再开一个坑……算是刷buuctf系列的一个开篇吧。题目就这样随意过去了,主要是有些知识点进行记录,怕以后忘了。
GXYCTF2019 Ping Ping Ping
进去以后有提示用get输入IP,结合题目来看应该是命令执行。输入?ip=127.0.0.1;ls后验证猜想,用分号使得一句多行shell命令。
后来测试发现,空格和flag都被过滤了,无奈搜WP,发现IFS这个神奇的东西,于是
1 | payload:?ip=127.0.0.1;cat$IFS$1index.php |
解释一下IFS是个什么东西吧。
IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ``
<new‐
line>’’.
也就是说,IFS是个分隔符,可以用于在表达式或行之间进行分割。默认的三个值是空格、tab、换行。
那么,根据shell的特殊变量列表:
变量 | 含义 |
---|---|
$0 | 当前脚本文件名 |
$n | 传递给脚本或函数的参数。n是一个数字,代表第几个参数。例如,第一个参数是$1,第二个是$2 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数 |
$@ | 传递给脚本或函数的所有参数。用双引号包裹时,与$*略有不同 |
$$ | 当前shell进程ID。对于脚本而言,就是这些脚本所在的进程ID |
$? | 上个命令的退出状态,或函数的返回值 |
那么$IFS$1的含义就是,取IFS的第一个元素,即默认值空格,实现空格绕过,顺利读取index.php
1 |
|
刚刚还在疑惑为什么显示出来的index.php是不完整的,转眼F12发现被注释了一部分……
言归正传,根据正则,基本过滤了所有的尖括号引号等特殊符号,还过滤了包含空格、bash、flag,虽然我不是很懂为什么要过滤bash……
把flag过滤了,那么拿什么读取flag呢?这是我的知识盲区,只好求助于wp。
根据网上找到的资料,有这样几种绕过方法:
1.利用base64
1 | ?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh |
解释一下,echo后面那串字母是’cat flag.php’的base64加密密文,然后利用管道’|’传递给base64进行解密,再传递给sh执行(原来这里有点过滤bash的原因在了)
2.内联执行
1 | ?ip=127.0.0.1;cat$IFS$1`ls` |
就是将反引号里的ls执行,然后返回结果作为cat的参数,即可绕过flag的过滤
其它的有经过测试不可用的,有懒得测试的……就先记住这两个吧,其它的以后遇见了再看也不迟。
RoarCTF2019 Easy Calc
这题初遇的时候我其实是懵逼的,因为完全不知道如何着手,感觉像是命令执行,但是输入框输入字母就直接被过滤报错了,就很头疼。
后来看了WP,才发现原来那个AJAX送至的PHP文件可读……看见了calc.php,但没想到去读出来,惭愧
1 |
|
GET方法获得num,然后过滤空格、\t、\r、\n、单引号、双引号,反引号,左右中括号,美元符,斜杠,幂符号(在PHP里是异或运算符)
但是问题也就出在这里,当你用URL参数传num的时候,直接403forbidden,因为有WAF的存在,但是又不知道WAF规则……
看WP,发现一个字符串解析的特性,简单来说就是GET的参数传到WAF的解析和传到PHP的解析是不一致的。比如‘ num’,在WAF里处理是’空格‘+’num‘,但是在PHP里,空格会被忽略掉,因此可以绕过WAF而不影响其在PHP中的语义。参考链接:利用PHP的字符串解析特性Bypass
1 |
|
简单来说,通过在’foo’和’bar’两个字符串的前、中、后三个位置,不断循环测试255个ASCII码,然后通过是否被忽略来判断是否有特殊的字符解析。如果字符在某个位置被忽略了,就会输出对应的ASCII码和符号。
最后一个应该是在输出.chr($i).”)\n”时被截断了,因此直接下一行继续了。
可见,有些是可打印字符,有些是不可打印字符(%00),用这些字符套进num,就可以成功绕过,然后开始愉快地命令执行。值得一提的是,因为代码里是$o[“foo_bar”],因此{chr}在中间时应该是被替换成下划线了。
个人测试,空格+num和+num两个都是可以的,&不行,估计是被URL解析了。
1 | payload1:?+num=1;var_dump(scandir(char(47))) |
这里尝试过用echo和printf,但是echo被过滤了空格,而printf只输出了类型,于是还是用var_dump;
(最新测试,print_r用于打印数组,也可以显示结果)
1 | payload2:?+num=1;var_dump(file_get_contents(chr(47).f1aag)) |
chr(47)是右斜杠’/‘,即读出根目录下/f1aag的内容,顺利得到flag.
还有一种方法叫HTTP走私攻击,应该是非预期解……有空单开一篇,这个名词似乎图解HTTP遇见过,有空单独研究下。
- 本文作者: crlwebby
- 本文链接: https://crlwebby.github.io/security/CTF/buuctf-web-1/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!