在BMZCTF中,有一道题是shell_exec,在尝试做了该题后,又翻看了现有的write-up,发现现有的write-up语焉不详,对于不原理和微操讲解不细,因此写了这篇文章,主要是在前人的基础上对此题进行进一步描述,主要针对刚接触此领域的小白用户,希望能够对他们理解这道题提供帮助。
首先,打开本题,可以看到如下界面:

进行测试,发现输入一个IP地址或者域名后,可以PING测试对应的IP,然后把结果反馈到界面上来。
之后,查看页面源代码(不要问我为什么要查看页面源代码,做CTF题查看页面源代码应该是本能的反应),可以发现如下提示:

可以看出,题目将以POST的形式上传名为IP的变量,并且将其作为目标地址,把PING测试的结果显现出来。因此,可以断定,这道题是一道命令执行相关的题目。
在这里,有些人不明白2>&1的作用,查询后,得到的标准答案是将标准错误重定向到标准输出,为了保证小白们可以理解这句话,在这里我稍微解释一下。
在Linux中,一条命令可以被正常运行,也有可能出错(出错的原因可能是尝试打开不存在的文件、给定的参数错误等,在这里即PING后面的host错误)。在命令行模式下,命令正常运行时会给予一个输出,出错时会给予一个反馈,表面上看上去都会显示一些信息,但是在本质上,正常运行时输出的是正常运行时的结果,而程序错误时输出的是错误提示。这就好像在写C语言程序时,正常的C程序会显示正常的运行结果,但是错误的C程序会报错一样。将标准错误重定向到标准输出,意思就是如果程序出错,那么将出错信息作为程序正常运行时的输出处理。2>&1这条附加命令,在命令行情况下加与不加不会有明显的区别,但是本质上,就是这条语句是否被正确执行的根本性区别。
回到这道题,既然是在命令执行上做文章,首先想到的就是构造特殊形式的payload,把自己想要执行的命令附加在id参数中,然后执行命令,拿到flag。
最简单的命令拼接的方式是管道符(&&,||等)、分号(;)但是经过实验,都被后台的WAF拦截,经过实验发现,反引号(``)和$()的方式可以使得我们的命令正常执行而不被拦截。
反引号和$(),本质上都属于命令嵌套,本意是Linux为了执行嵌套式的命令而设计的一种命令模式,比如我如果想echo whoami指令执行后的结果,在Linux中直接执行:
echo whoami
是不可以的!
但是,我们可以这样:
echo `whoami`
或者是:
echo $(whoami)
Linux系统就会先执行whoami命令,然后将其执行后的结果显示出来。
因此,在这里我们可以利用命令嵌套,来执行我们想要的代码,只需要用反引号或者是$符号把我们想要执行的命令作为嵌套命令即可。
明确了如何嵌套我们的想要执行的命令,经过实验发现题目还设置了防火墙,对特定的格式进行了过滤,比如“cat”、“flag”以及空格等,这里,针对这些过滤,我们可以通过替代的方式绕过,比如说经过实验,可以使用${IFS}替换空格,可以使用head替换cat,也可以使用%9插在字符串中间,起到防范的作用,这样,我们精心构造的payload就可以拿到flag了!
最后,我把我拿到flag的payload公布一下:
ip=www.baidu.come.$(ec$9ho$IFS$9s$9h$IFS$9d.txt$IFS$9|s$9h$IFS$9>f.txt)

执行成功后,访问f.txt,就可以看到flag了!!!

本文详细解析了一道CTF比赛中的shell_exec题目,通过查看源代码发现命令执行漏洞。介绍了2>&1的作用,即重定向错误输出到标准输出。讨论了如何利用反引号和$()进行命令嵌套,以及如何规避过滤限制获取flag。最终给出了成功拿到flag的payload示例。

1519

被折叠的 条评论
为什么被折叠?



