目录
1、知识铺垫
(1)文件描述符
(2)/dev/null
2、代码审计
3、命令分隔
(1)使用分号 ;
(2)使用逻辑或 ||
(3)使用 && 或者 &
4、%0a 换行符截断
命令执行,需要严格的过滤
1、知识铺垫
(1)文件描述符
标准输入(stdin):文件描述符为 0,用于读取输入数据。
标准输出(stdout):文件描述符为 1,用于输出普通的结果或信息。
标准错误(stderr):文件描述符为 2,用于输出错误信息。
(2)/dev/null
/dev/null 是类 Unix 操作系统中的一个特殊文件,被称为“空设备”或“黑洞”,它是一个字符设备文件,其主要作用是丢弃所有写入它的数据,同时任何从它读取的操作都会立即返回EOF(文件结束符)。
2、代码审计
system($c." >/dev/null 2>&1");
将 get 请求传递的 c 的内容与后面内容进行拼接后作为 system 函数的参数;
>/dev/null 是一个重定向操作符,用于将标准输出(stdout)重定向到 /dev/null,这意味着命令的标准输出将不会显示在终端或网页上,也不会写入任何文件;
2>&1 是另一个重定向操作符,它将标准错误(stderr)重定向到标准输出(stdout),>&1 表示将标准错误重定向到标准输出所指向的地方(即 /dev/null),这意味着命令的所有错误信息也会被丢弃。
直接传入系统命令没有回显:
针对这种回显被重定向到了黑洞的情况,下面给出一些处理方法。
3、命令分隔
使用管道符,这里又有四种方法
(1)使用分号 ;
对于命令分隔,分号只适用于 Linux 系统,不适用于 Windows 系统。
构造 payload:
?c=ls;
执行成功
(2)使用逻辑或 ||
关于管道符的详细介绍和用法可以参考我之前写的 DVWA 靶场的命令注入:
DVWA 靶场之 Command Injection(命令执行)原理介绍、分隔符测试、后门写入与源码分析、修复建议_dvwa command injection-CSDN博客https://myon6.blog.csdn.net/article/details/136291307对于两个或,前面为真,只执行前面的,后面命令不会执行;而对于一个或, 无论第一个命令执行为真还是假,都是直接执行第二个命令。
这里我们只希望执行 ls 而不希望执行重定向的效果,构造 payload:
其实无论后面重定向的命令执行与否对我们前面命令的执行都不影响,我们只需要确保第一个命令执行了就行。
?c=ls||
执行成功
(3)使用 && 或者 &
对于两个与,当第一个命令执行失败(为假),那么第二个命令也不会被执行;
对于一个与,前面的语句为假则直接执行后面的,前面可真可假,后面命令都会执行;
我们也不用管后面的,确保前面命令被执行即可。
但是这里与符号传入前需要先 URL 编码,我也不知道为啥,虽然说是在 url 里面传的,但是为啥或符号不需要呢?不懂,有知道的可以解释下谢谢。
直接传与符号没有回显:
编码后传入,构造 payload:
?c=ls%26
或者:
?c=ls%26%26
4、%0a 换行符截断
构造 payload:
?c=ls%0a
最后就直接拿 flag 吧,反向显示 flag.php:
?c=tac flag.php%0a
拿到 flag:ctfshow{77a306ca-d797-4143-a52e-bbc73ca89b22}