简介
原题复现:https://github.com/glzjin/buuctf_2018_online_tool (环境php5.6.40)
考察知识点:escapeshellarg
和escapeshellcmd
使用不当导致rce
线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题
过程
简单审计
菜狗打开页面 看到源码 看到两个函数不知道 看wp吧。。。
1 php 2 3 print_r($_SERVER['HTTP_X_FORWARDED_FOR']); 4 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 5 $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; 6 print("1"); 7 } 8 9 if(!isset($_GET['host'])) { 10 highlight_file(__FILE__); 11 } else { 12 $host = $_GET['host']; 13 $host = escapeshellarg($host); 14 $host = escapeshellcmd($host); 15 $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']); 16 echo 'you are in sandbox '.$sandbox; 17 @mkdir($sandbox); 18 chdir($sandbox); 19 echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host); 20 }
先学了解两个陌生的函数
escapeshellcmd
escapeshellcmd — shell 元字符转义
escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。
反斜线(\)会在以下字符之前插入: `|*?~<>^()[]{}$\, \x0A 和 \xFF。 ' 和 " 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
php var_dump(escapeshellcmd("xiaohua da wang")); echo "
"; var_dump(escapeshellcmd("xiaohua 'da' wang")); echo "
"; var_dump(escapeshellcmd("xiaohua '''da' 'wang")); echo "
";
结果:仅转义了单个出现的单引号
escapeshellarg
escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数
escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。对于用户输入的部分参数就应该使用这个函数。shell 函数包含exec(), system() 执行运算符 。
php var_dump(escapeshellarg("xiaohua da wang")); echo '
'; var_dump(escapeshellarg("xiaohua 'da' wang")); echo '
'; var_dump(escapeshellarg("xiaohua '''da' wang")); echo '
';
结果: 只要出现单引号就进行转义
所以说escapeshellcmd
和不同之处在于escapeshellarg,前者仅会对落单了的单引号进行转义,而后者会对所有单引号进行转义,前者会对一些特殊字符进行转义如:
& # ; ` | * ? ~ < > ^ ( ) [ ] { } $
php var_dump(escapeshellcmd("& # ; ` | * ? ~ < > ^ ( ) [ ] { } $")); echo "
";
参考学习:https://paper.seebug.org/164/
传入的参数是:172.17.0.2' -v -d a=1 经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。 经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php 最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。
nmap参数:https://blog.csdn.net/qq_26090065/article/details/80285088
在nmap命令中 有一个参数-oG可以实现将命令和结果写到文件
最终payload
这个命令就是我们的输入可控!然后写入到文件
?host=' -oG xiaohua.php '
显示生成的文件夹名 我们拼凑下访问
http://6b6aa4fa-cc55-4b5d-8dd9-9ba66a236355.node3.buuoj.cn/4d484018dc3b664c4cc70a3ef2b8e7a3/xiaohua.php
参考学习:Online Tool(BUUCTF 2018)
PHP escapeshellarg()+escapeshellcmd() 之殇