PHP反序列化
一、概述
在理解這個漏洞之前,需要先搞清楚php中的serialize(),unserialize()這兩個函數
序列化serialize()
序列化通俗點就是把一個對象變成可以傳輸的字符串,比如下面是一個對象。
class S{ public $test="pikachu"; } $s=new S(); //創建一個對象 serialize($s); //把這個對象進行序列化 序列化后得到的結果是這個樣子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";} O:代表object 1:代表對象名字長度為一個字符 S:對象的名稱 1:代表對象里面有一個變量 s:數據類型 4:變量名稱的長度 test:變量名稱 s:數據類型 7:變量值的長度 pikachu:變量值
反序列化unserialize()
就是把被序列化的字符串還原為對象,然后再接下來的代碼中繼續使用。
$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}"); echo $u->test; //得到的結果為pikachu
序列化和反序列化本身沒有問題,但是如果反序列化的內容是用戶可以控制的,且后台不正當的使用了PHP中的魔法函數就會導致安全問題。
常見的幾個魔法函數: __construct()當一個對象創建時被調用 __destruct()當一個對象銷毀時被調用 __toString()當一個對象被當作一個字符串使用 __sleep() 在對象在被序列化之前運行 __wakeup將在序列化之后立即被調用 漏洞舉例: class S{ var $test = "pikachu"; function __destruct(){ echo $this->test; } } $s = $_GET['test']; @$unser = unserialize($a); payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
二、PHP反序列化漏洞
①觀察源碼返現這里有個借口可以接受一個反序列化的對象,對傳進來的參數沒有進行任何過濾
②我們利用詳細的代碼生成一個反序列化的字符串。
<?php class S{ var $test = "<script>alert('xss')</script>"; } echo '<br>'; $a = new S(); echo serialize($a); ?>
③新建文檔,通過url訪問
我這里是localhost/pikachu-master/test.php
④我們右鍵查看頁面源代碼
⑤把<br>后的O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";} 復制放入關卡中,就可以進行XSS攻擊了
XXE
一、概述
XXE -"xml external entity injection"
既"xml外部實體注入漏洞"。
概括一下就是"攻擊者通過向服務器注入指定的xml實體內容,從而讓服務器按照指定的配置進行執行,導致問題"
也就是說服務端接收和解析了來自用戶端的xml數據,而又沒有做嚴格的安全控制,從而導致xml外部實體注入。
具體的關於xml實體的介紹,網絡上有很多,自己動手先查一下。
現在很多語言里面對應的解析xml的函數默認是禁止解析外部實體內容的,從而也就直接避免了這個漏洞。
以PHP為例,在PHP里面解析xml用的是libxml,其在≥2.9.0的版本中,默認是禁止解析xml外部實體內容的。
xml是一種可拓展的標記語言,可以用來存儲數據,例如:我們經常看到一些.xml的文件;它還可以用來傳輸數據,我們可以直接將數據以xml的格式放在請求當中,發給服務器。
具體的關於xml實體的介紹,網絡上有很多,自己動手先查一下。
第一部分:XML聲明部分
<?xml version="1.0"?>
第二部分:文檔類型定義 DTD
<!DOCTYPE note[
<!--定義此文檔是note類型的文檔-->
<!ENTITY entity-name SYSTEM "URI/URL">
<!--外部實體聲明-->
]>
第三部分:文檔元素
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
其中,DTD(Document Type Definition,文檔類型定義),用來為 XML 文檔定義語法約束,可以是內部申明也可以使引用外部DTD現在很多語言里面對應的解析xml的函數默認是禁止解析外部實體內容的,從而也就直接避免了這個漏洞。
① 內部申明DTD格式
<!DOCTYPE 根元素 [元素申明]>
② 外部引用DTD格式
<!DOCTYPE 根元素 SYSTEM "外部DTD的URI">
③ 引用公共DTD格式
<!DOCTYPE 根元素 PUBLIC "DTD標識名" "公共DTD的URI">
外部實體引用 Payload
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<x>&f;</x>
二、XXE漏洞
①先輸入一個payload
<?xml version = "1.0"?>
<!DOCTYPE note [
<!ENTITY hacker "ESHLkangi">
]>
<name>&hacker;</name>
將我們定義的實體內容打印在了前端
②構造讀取文件的payload
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "file:///C://2.txt">
]>
<x>&f;</x>
SSRF
一、概述
SSRF(Server-Side Request Forgery:服務器端請求偽造)
其形成的原因大都是由於服務端提供了從其他服務器應用獲取數據的功能,但又沒有對目標地址做嚴格過濾與限制
導致攻擊者可以傳入任意的地址來讓后端服務器對其發起請求,並返回對該目標地址請求的數據
數據流:攻擊者----->服務器---->目標地址
根據后台使用的函數的不同,對應的影響和利用方法又有不一樣
PHP中下面函數的使用不當會導致SSRF:
file_get_contents()
fsockopen()
curl_exec()
如果一定要通過后台服務器遠程去對用戶指定("或者預埋在前端的請求")的地址進行資源請求,則請做好目標地址的過濾。
二、SSRE(curl)
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中發現了詩的來源,然后我在本機鏈接虛擬機的pikachu,更改URL訪問了虛擬機pikachu-master下的1.txt文件,文件的內容為GOOD MAN
URL:(虛擬機IP為192.168.233.138)
http://192.168.233.138/pikachu-master/vul/ssrf/ssrf_curl.php?url=http://192.168.233.138/pikachu-master/1.txt
三、SSRF(file_get_content)
我們接着點擊鏈接,發現和剛才一樣
看一下源碼
//讀取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; } ?>
與上面實驗不同的是這個使用了file_get_contents
讀取PHP文件的源碼:php://filter/read=convert.base64-encode/resource=ssrf.php
內網請求:http://x.x.x.x/xx.index
那么file_get_contents里面帶有php:// filter 我們用這個就可以來讀取php源碼
我們構造這樣的url
localhost/pikachu-master/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base64-encode/resource=ssrf.php