51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

CVE-2018-8893:

看到某大佬在群里发了一个 CVE 通告,打开网页有看到:

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

正好想找点事做,遂做一波分析。
首先定位到 plugin_edit.php 文件,在 /zb_user/plugin/AppCentre/plugin_edit.php ,看下代码:

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

注意到红框框里的代码,是一个判断的流程,本意是判断输入的插件的 ID 只能是数字或字母,并且长度只能在3到30个之间,但是这个正则引起了我的注意,他的正则是:

^[A-Za-z0-9_]{3,30}

它这个正则的意思是:以字母或数字开头,匹配3到30个。 然后,然后就没了。所以只要前3个字符是数字或字幕就能通过它正则的检查了,比如我输入:test<?php phpinfo();?> ,虽然后面出现了各种符合和空格,但是前面的 test 符合了它的正则,所以这个正则依然能匹配到,就能通过它正则的检测了,如图:

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

而正确的正则应该是:

^[A-Za-z0-9_]{3,30}$

注意最后加了一个$符号,意思是匹配以字幕或数字开头,并且以数字或字母结束,长度在3到30个字符之间:

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

所以这个正则的判断就可以绕过了。 然后怎么 Getshell 呢? 看上面代码的两个箭头,有两处有写入文件的操作,就在这里。 结合上面的代码代码可以知道它的逻辑是从一个既有的插件的文件模板里把对应的文件复制到新建的插件文件夹里面,文件夹的名字就是插件的ID,再把模板中一些插件的信息替换一下写入到新建插件的目录里。
好了,那看下最主要的需要复制过去的模板文件 main.html (/zb_user/plugin/AppCentre/tpl/main.html):

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

两处箭头所指的就是要替换的插件信息,替换逻辑在上面的 plugin_edit.php 的58到61行:

$file = file_get_contents('tpl/main.html');
            $file = str_replace("<%appid%>", $app->id, $file);
            $path = $zbp->usersdir . 'plugin/' . $app->id . '/' . trim($_POST['app_path']);
            @file_put_contents($path, $file);

就是单纯的把 <%appid%> 替换为新建插件的 ID 值。那么就开始构造了,构造的目标就是把一句话木马写进去,并且符合 PHP 的语法保证能让这个脚本文件跑起来,而因为上面绕过了正则检测,所以能写入除了字母和数字以外的字符。 但是这里有存在一个问题:仔细观察需要替换的两处位置会发现第一个需要替换的地方在语法上比第二处多了一个右括号,这就意味着无论怎么构造,要符合两处替换位置的语法是不可能的,如果符合第一处的语法,第二处肯定不符合,反之亦然(反正我没想到,不知道大佬们有什么姿势没有?)。
那就换一个思路,既然需要符合两处替换位置的语法不可能,那就让它符合一处的就好了,想到利用 ?> 闭合掉 PHP 的代码解析,让第二处替换位置不再当作 PHP 代码执行而是当作普通的文本,最终构造出的 payload:

AppCentre') || eval($_POST[z]))?>

替换后的代码如下(注意代码高亮的变化):

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

此时第二处替换的位置就已经不被解析为 PHP 的代码而是普通的文本了,此时已经把一句话木马写入到 main.php 文件中了,Getshell达成,测试一下:

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

证明成功 Getshell 了,注意下上面圈起来的部分,因为写入的 payload 有问号,而问号在 URL 中是当作 GET 参数的开始符号,所以这里需要进行编码,否则会找不到路径。

Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)

结合这个操作有 CSRF 漏洞,就可以构造如下 payload 来通过 CSRF 来 Getshell:

  

赞(3)
未经允许不得转载:工具盒子 » Z-Blog两处Getshell分析(附EXP)(CVE-2018-8893、CVE-2018-9169、CVE-2018-9153)