命令注入(Command Injection): 是指通过提交恶意构造的参数破坏命令语句结构, 从而达到执行恶意命令的目的
前面的基础课程中, 我们提到命令注入需要三个条件:
1. 是否调用系统命令?
2. 函数 / 参数是否可控?
3. 是否拼接输入?
具体怎么应用, 我们在接下去的实战中学习和体会
DVWA 实战:
1. 打开 phpStudy 或 xampp, 运行 Apach 和 MySQL;
2. 浏览器进入 DVWA 主界面, 在左侧栏选择 DVWA Security 安全等级为 Low, 然后进入 Command Injection;
3. 我们输入一个 IP 提交后, 发现返回了对这个 IP 进行 Ping 的结果
注: 如果返回乱码, 可以试试如下方法:
找到 DVWA 目录下 / dvwa/includes 里的 dvwaPage.inc.php 文件, 把字符集 utf-8 改为 gb2312 , 保存一下便可
- // Send Headers + main html code
- Header( Cache-Control: no-cache, must-revalidate); // HTTP/1.1
- //Header( Content-Type: text/html;charset=utf-8 ); // TODO- proper XHTML headers...
- Header( Content-Type: text/html;charset=gb2312 ); // TODO- proper XHTML headers...
- Header( Expires: Tue, 23 Jun 2009 12:00:00 GMT ); // Date in the past
其实就跟我们自己进 Windows 的 cmd 里 ping 是一样的因此, 我们猜想后台肯定也是调用了系统的命令, 并且将输入的参数进行拼接:
- // Get input
- $target = $_REQUEST[ ip ];
- // Determine OS and execute the ping command.
- if( stristr( php_uname( s ), Windows NT ) ) {
- // Windows
- $cmd = shell_exec( ping . $target );
- }
- else {
- // *nix
- $cmd = shell_exec( ping -c 4 . $target );
- }
因此, 这边的提交操作满足了命令注入的三个条件, 存在命令注入漏洞
4. 如果我们输入 123.125.114.144 && net user, 那么会得到如下信息:
一个简单的命令注入漏洞就这样被利用了, 只需要常见的命令连接符 (&,&&,|,|" ,; 等) 和系统命令, 如果输入的命令更具威胁性, 那么这个危害就更大了, 例如在 Linux 下输入 127.0.0.1&&cat /etc/shadow 甚至可以读取 shadow 文件
5. 接下去我们把安全等级调到 medium, 发现报错了: 错误的参数 net 我们来看看后台的代码, 发现对 && ; 进行过滤, 本质上是黑名单的方式
- // Set blacklist
- $substitutions = array(
- && => ,
- ; => ,
- );
但是黑名单的过滤有限, 我们可以利用 & 来攻击漏洞, 输入 123.125.114.144 & net user 即可, 另外, 既然会把关键连接符过滤, 何不反过来利用, 构造 &;& 连接符, 这样当; 被过滤后,&& 发挥了功效
6. 接下去我们看看 high 等级的命令注入, 发现上述方法也失效了, 查看后台代码, 发现对更多的命令连接符进行了过滤
- // Set blacklist
- $substitutions = array(
- & => ,
- ; => ,
- | => ,
- - => ,
- $ => ,
- ( => ,
- ) => ,
- ` => ,
- || => ,
- );
本质上仍然是黑名单的方式, 所以仍然存在局限性例如代码中的 | 后面有个空格, 因此, 我们直接输入 123.125.114.144|net user 即可
另外, 对于无回显的情况, 可以使用延时命令查看响应速度 (如 Windows 下的 ping 127.0.0.1 -n 5 > nul 或 Linux 下的 sleep 5) 或搭建服务器查看是否有接收到请求 (Windows 下的 ping,telnet 或者 Linux 下的 wget,curl 等) 等方法;
7. 最后我们来看看 impossible 等级的命令注入, 发现用上述的方法不可行, 而且报错信息也更改了: ERROR: You have entered an invalid IP 查看后台代码, 发现对参数 ip 进行了严格的限制, 只有数字. 数字. 数字. 数字的输入才会被接收执行, 有效的修复了命令注入漏洞
- // Get input
- $target = $_REQUEST[ ip ];
- $target = stripslashes( $target );
- // Split the IP into 4 octects
- $octet = explode( ".", $target );
- // Check IF each octet is an integer
- if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
- // If all 4 octets are ints put the IP back together.
- $target = $octet[0] . . . $octet[1] . . . $octet[2] . . . $octet[3];
实战心得:
使用白名单对用户输入的命令进行限制, 尽量不要使用黑名单, 最好是要遵守对一切输入不可信任的原则, 对输入进行严格的校验
来源: http://www.bubuko.com/infodetail-2505934.html