RSS Feed
更好更安全的互联网
  • WebLogic coherence UniversalExtractor 反序列化 (CVE-2020-14645) 漏洞分析

    2020-11-03

    作者:DEADF1SH_CAT@知道创宇404实验室
    时间:2020年8月3日

    前言

    Oracle七月发布的安全更新中,包含了一个Weblogic的反序列化RCE漏洞,编号CVE-2020-14645,CVS评分9.8。

    image-20200801182009244

    该漏洞是针对于CVE-2020-2883的补丁绕过,CVE-2020-2883补丁将MvelExtractorReflectionExtractor列入黑名单,因此需要另外寻找一个存在extract且方法内存在恶意操作的类,这里用到的类为com.tangosol.util.extractor.UniversalExtractor,存在于Coherence组件。

    CVE-2020-2883

    先来回顾一下CVE-2020-2883的两个poc调用链

    其本质上,都是通过ReflectionExtractor调用任意方法,从而实现调用Runtime对象的exec方法执行任意命令,但补丁现在已经将ReflectionExtractor列入黑名单,那么只能使用UniversalExtractor重新构造一条利用链,这里使用poc2的入口即CommonsCollections4链的入口进行构造。

    CVE-2020-14645

    为了方便一些纯萌新看懂,此处将会从0开始分析反序列化链(啰嗦模式警告),并且穿插一些poc构造时需要注意的点,先来看看调用栈。

    image-20200801234349005

    从头开始跟进分析整个利用链,先来看看PriorityQueue.readObject()方法。

    image-20200801234303677

    第792会执行for循环,将s.readObject()方法赋给queue对象数组,跟进heapify()方法。

    image-20200801234406139

    这里会取一半的queue数组分别执行siftDown(i, (E) queue[i]);,实质上PriorityQueue是一个最小堆,这里通过siftDown()方法进行排序实现堆化,那么跟进siftDown()方法。

    image-20200801234425033

    这里有个对于comparator的判定,我们暂时不考虑comparator的值是什么,接下来会使用到,我们先跟进siftDownUsingComparator()方法。

    image-20200801234433087

    重点关注comparator.compare()方法,那么我们先来看看comparator是怎么来的。

    image-20200801234441593

    是在PriorityQueue的构造函数中被赋值的,并且这里可以看到,queue对象数组也是在这里被初始化的。那么结合上述所分析的点,我们需要构造一个长度为2的queue对象数组,才能触发排序,进入siftDown()方法。同时还要选择一个comparator,这里选用ExtractorComparator。继续跟进ExtractorComparator.compare()方法。

    image-20200801234503470

    这里将会调用this.m_extractor.extract()方法,让我们看看this.m_extractor是怎么来的。

    image-20200801221007825

    可以看到,this.m_extractor的值是与传入的extractor有关的。这里需要构造this.m_extractorChainedExtractor,才可以调用ChainedExtractorextract()方法实现串接extract()调用。因此,首先需要构造这样一个PriorityQueue对象:

    继续跟进ChainedExtractor.extract()方法,可以发现会遍历aExtractor数组,并调用其extract()方法。

    image-20200801234521152

    此处aExtractor数组是通过ChainedExtractor的父类AbstractCompositeExtractorgetExtractors()方法获取到父类的m_aExtractor属性值。

    image-20200801234540446

    所以,poc中需要这样构造m_aExtractor

    m_aExtractor具体的值需要怎么构造,需要我们继续往下分析。先回到我们所要利用到的UniversalExtractor,跟进其extract()方法。

    image-20200801234615723

    此处由于m_cacheTarget使用了transient修饰,无法被反序列化,因此只能执行else部分,跟进extractComplex()方法。

    image-20200801234732346

    这里看到最后有method.invoke()方法,oTargetaoParam都是我们可控的,因此我们需要看看method的处理,跟进findMethod方法。

    image-20200801234829234

    可以看到第477行可以获取任意方法,但是要进入if语句,得先使fExactMatchtruefStaticfalse。可以看到fStatic是我们可控的,而fExactMatch默认为true,只要没进入for循环即可保持true不变,使cParams为空即aclzParam为空的Class数组即可,此处aclzParamgetClassArray()方法获取。

    image-20200801235221510

    显而易见,传入一个空的Object[]即可。回到extractComplex()方法,此时我们只要我们进入第192行的else语句中,即可调用任意类的任意方法。但此时还需要fProperty的值为false,跟进isPropertyExtractor()方法。

    image-20200801235942238

    可惜m_fMethod依旧是使用transient修饰,溯源m_fMethod的赋值过程。

    image-20200802000213645
    image-20200802000409329
    image-20200802000425863

    可以看到,由于this对象的原因,getValueExtractorCanonicalName()方法始终返回的是null,那么跟进computeValuExtractorCanonicalName()方法。

    image-20200802000543790

    此处不难理解,如果aoParam不为null且数组长度大于0就会返回null,因此我们调用的方法必须是无参的(因为aoParam必须为null)。接着如果方法名sName不以 () 结尾,则会直接返回方法名。否则会判断方法名是否以 VALUE_EXTRACTOR_BEAN_ACCESSOR_PREFIXES数组中的前缀开头,是的话就会截取掉并返回。

    image-20200802002321123

    回到extractComplex方法中,在if条件里会对上述返回的方法名做首字母大写处理,然后拼接BEAN_ACCESSOR_PREFIXES数组中的前缀,判断clzTarget类中是否含有拼接后的方法。这时发现无论如何我们都只能调用任意类中getis开头的方法,并且还要是无参的。

    image-20200802005549067

    整理下我们可以利用的思路:

    • 调用init()方法,对this.method进行赋值,从而使fProperty的值为false,从而进入else分支语句,实现调用任意类的任意方法。然而这个思路马上就被终结了,因为我们根本调用不了非getis开头的方法!!!
    • transient修饰的m_cacheTargetextractComplex方法中被赋值
    image-20200802011653243

    ExtractorComparator.compare()方法中,我们知道extract方法能被执行两次,因此在第二次执行时,能够在UniversalExtractor.extract方法中调用targetPrev.getMethod().invoke(oTarget, this.m_aoParam)方法。但是这种方法也是行不通的,因为getMethod()获取的就是图上红框的中的method,很显然method依旧受到限制,当我们调用非 get 和 is 开头的方法时,findMethod 会返回 null

    • 只能走方法被限制的路线了,寻找所有类中以 get 和 is 开头并且可利用的无参方法

    复现过Fastjson反序列化漏洞的小伙伴,应该清楚Fastjson的利用链寻找主要针对getset方法,这时候就与我们的需求有重合处,不难想到JdbcRowSetImpl的JNDI注入,接下来一起回顾一下。

    image-20200802012325020

    connect方法中调用了lookup方法,并且DataSourceName是可控的,因此存在JNDI注入漏洞,看看有哪些地方调用了connect方法。

    image-20200802012358277

    有三个方法调用了connect方法,分别为preparegetDatabaseMetaDatasetAutoCommit方法,逐一分析。

    • prepare()
    image-20200802012523723

    一开始就调用了connect方法,继续回溯哪里调用了prepare方法。

    image-20200802012552220

    execute方法,应该是用于执行sql查询的

    image-20200802012907664

    这个应该是用于获取参数元数据的方法,prepare()方法应该都是用于一些与sql语句有关的操作方法中。

    • getDatabaseMetaData()
    image-20200802012946090
    • setAutoCommit()
    image-20200802012958970

    必须让this.conn为空,对象初始化时默认为null,因此直接进入else语句。其实this.conn就是connect方法,用于保持数据库连接状态。

    回到connect方法,我们需要进入else语句才能执行lookup方法。有两个前提条件,this.conn为空,也就是执行connect方法时是第一次执行。第二个条件是必须设置DataSourceName的值,跟进去该参数,发现为父类BaseRowSetprivate属性,可被反序列化。

    那么,对于WebLogic这个反序列化利用链,我们只要利用getDatabaseMetaData()方法就行,接下来看看该怎么一步步构造poc。先从JdbcRowSetImpl的JNDI注入回溯构造:

    接着构造UniversalExtract对象,用于调用JdbcRowSetImpl对象的方法

    紧接着将UniversalExtract对象装载进文章开头构造的chainedExtractor对象中

    此处,还有一个小点需注意,一个在文章开头部分构造的PriorityQueue对象,需要构造一个临时Extractor对象,用于创建时的comparator,此处以ReflectionExtractor为例。其次,PriorityQueue对象需要执行两次add方法。

    回到PriorityQueue对象的readObject方法

    image-20200802022513752

    首先需要能进入for循环,for循环就得有size的值,size值默认为0,private属性,可以通过反射直接设置,但是不想通过反射怎么办,回溯赋值过程。

    image-20200802022659383

    offer方法处获得赋值,而offer方法又是由add方法调用。(注意此处会执行siftUp方法,其中会触发comparator的compare方法,从而执行extract方法)。

    image-20200802023215593

    不难理解,每add一次,size加1,根据上述heapify方法,只会从开头开始取一半的queue数组执行siftDown方法。所以size至少为2,需要执行两次add方法,而不是add(2)一次。

    至此,poc的主体就构造完成,其余部分就不在此阐述了,当然构造方式有很多,此处为方便萌新,分析得比较啰嗦,poc也比较杂乱,大家可以自行构造属于自己的poc。如果想要了解简洁高效的poc,可以参考一下Y4er师傅的poc[3]。

    体会

    初次接触完整的反序列化漏洞分析,在整个分析过程中收获到很多东西。笔者得到的不仅仅只是知识上的收获,在调试过程中也学到了很多调试技巧。另外本文看起来可能会比较啰嗦冗余,但其初衷是想要站在读者的角度去思考,去为了方便一些同样刚入门的人阅读起来,能够更加浅显易懂。学安全,我们经常会碰壁,对于一些知识会比较难啃。有些人遇到就选择了放弃,然后却因此原地踏步。不妨就这样迎难而上,咬着牙啃下去,到最后,你会发现,你得到的,远远比你付出的要多。可能对部分人不太有效、毕竟因人而异,但这是自己在学习过程中所体会到的,也因此想要分享给大家这么一个建议。相信在未来,自己对于反序列化漏洞的理解以及挖掘思路,能够有更深刻的认知,同时激发出自己不一样的思维碰撞。

    References

    [1] Oracle 7月安全更新

    https://www.oracle.com/security-alerts/cpujul2020.html

    [2] T3反序列化 Weblogic12.2.1.4.0 JNDI注入

    https://mp.weixin.qq.com/s/8678EM15rZSeFBHGDfPvPQ

    [3] Y4er的poc

    https://github.com/Y4er/CVE-2020-14645

    [4] Java反序列化:基于CommonsCollections4的Gadget分析

    https://www.freebuf.com/articles/others-articles/193445.html

    [5] Oracle WebLogic 最新补丁的绕过漏洞分析(CVE-2020-2883)

    https://blog.csdn.net/systemino/article/details/106117659


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1280/

    作者:江 | Categories:漏洞分析 | Tags:
  • 基于网络空间搜索引擎的通用漏洞挖掘

    2020-11-03

    作者:知道创宇404实验室
    时间:2020年8月4日

    FIT 2019 大会上,黑哥发表《基于网络空间搜索引擎的通用漏洞挖掘》主题演讲,介绍了知道创宇旗下网络空间搜索引擎 “ZoomEye 钟馗之眼”的诞生、特点与使用,尤其是以404实验室研究实例讲述了利用ZoomEye进行网络空间漏洞挖掘的方法。有兴趣的同学可以按照黑哥提出的网络空间漏洞挖掘套路进行实战演练,还可以利用ZoomEye通过调用API实现自动化平台等等,更多实现方式等待你去发现。附上演讲议题PDF下载:https://images.seebug.org/archive

    另外还有一个好消息,ZoomEye API接口输出数据不再有限制!HW行动在即,“ZoomEye 钟馗之眼”发布了重大更新,取消原有 API 接口(包括数据下载功能)最高随机输出 40% 数据的限制,全面支持 100% 的数据输出服务。此次更新打破了ZoomEye自上线以来的一个限制,对使用者更友好,近期我们还将发布一些新功能及细节优化,敬请期待!

    访问ZoomEye:https://www.zoomeye.org/

    作者:江 | Categories:公司活动 | Tags:
  • Shiro-550 PoC 编写日记

    2020-11-03

    作者:w7ay @ 知道创宇404实验室
    时间:2020年8月11日

    深刻认识到不会java搞这类poc的困难,只能做一个无情的搬砖机器。

    目标是编写Pocsuite3 python版本的Shiro-550 PoC,最好不要依赖其他东西。

    本文没有新奇的观点,只是记录日常 =_=

    Shiro识别

    看到@pmiaowu开源的burp shiro检测插件 https://github.com/pmiaowu/BurpShiroPassiveScan

    image-20200803161651145

    看了下源码,主要有三种判断方式

    1. 原始cookie key带了rememberMe
    2. 原始请求返回cookie中value带有deleteMe
    3. 以上条件都不满足时,发送cookierememberMe=1

    检测Shiro key

    l1nk3r师傅 的 基于原生shiro框架 检测方法

    简述下如何不依赖java环境来检测poc。

    可得到生成的反序列二进制payload(最好使用jdk6来编译,能够兼容之后的版本)

    将这段payload内置到poc里即可。

    通过python函数生成最终检测payload

    其中key是shiro需要检测的key,bb是生成的payload,当key正确时,不会返回deleteMe

    image-20200803162703060
    image-20200803162647250

    回显payload

    一开始看的是宽字节安全的burp插件:https://github.com/potats0/shiroPoc

    但在本地环境下测试没有成功,之后猜测可能是gadgets或java版本的问题

    看他的exploitType代码

    image-20200810141000382

    类似于java的汇编代码?确认过眼神是看不懂的。

    然后在GitHub上找到一个开源的exp https://github.com/Ares-X/shiro-exploit/blob/master/shiro.py

    它将gadget base64之后硬编码到了python中,正好符合我的需求。

    image-20200810141813620

    经过测试用CommonsCollections1就可以在我本地环境复现了。

    到这里就可以写poc了,但我还想看看这些硬编码的payload是怎么来的。

    更细节

    那些硬编码的文件是反序列化的文件,我想找到Tomcat的通用回显的源码。@longofo告诉我可以通过CA FE BA BE(cafebaby)来确定class的特征,将它和后面的数据保存为class文件。

    image-20200807175522519

    然后拖到idea反编译后就能看到源码了

    就算解出了源码,看的也不是太懂,可能是根据java的各种魔法来实现的吧 - = 于是就转而开始写poc了。

    没想到写完poc的第二天,xray的作者就给出检测细节和源码。

    通过比对源码:https://github.com/frohoff/ysoserial/compare/master...zema1:master

    可以找到tomcat的全版本回显的payload

    至于为什么要那么写,可能也是因为某种魔法,我暂时还不明白。

    和一些特别的链

    ysoserial 中的 CommonsCollections4 只能用于 CC4.0 版本,我把这个利用链进行了改进使其支持了 CC3 和 CC4 两个版本,形成了上面说的 K1/K2 两条链,这两条链就是我们处理 Shiro 这个环境的秘密武器。经过这些准备,我们已经从手无缚鸡之力的书生变为了身法矫健的少林武僧,可以直击敌方咽喉,一举拿下目标。万事具备,只欠东风。

    PoC演示

    一路下来迷迷糊糊啥也不明白真实太菜了,只能在一些大佬的肩膀上搬搬砖这样子了。

    PoC集成了识别,检测key,命令执行回显以及shell反弹的操作。

    检测识别key

    image-20200810153335261

    攻击模式执行任意命令

    image-20200810153612164

    shell反连

    image-20200810153921731

    最后也顺便给w13scan - 被动扫描器增加了一份Shiro插件。

    image-20200810154343285

    感谢看完全程,不说了,学习java去。

    image-20200810154429552

    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1290/

    作者:江 | Categories:技术分享 | Tags:
  • 从代码角度看各类子域名收集工具

    2020-11-03

    作者:w7ay @ 知道创宇404实验室
    时间:2020年8月12日

    开源的域名收集工具有很多,本文会从代码的角度去看各类开源的域名收集工具的技术特点,以及各有哪些优缺点,来帮助大家,在合适的时候选择合适的利用工具。

    这里选取了常用和知名的工具,包括subDomainBrute,Sublist3r,ESD,OneForAll,dnsprobe,subfinder,shuffledns,massdns

    subDomainBrute

    Github:https://github.com/lijiejie/subDomainsBrute

    最早使用是lijiejie的子域名爆破工具,也是学习python时最早看的源码。

    看了下commit,最早发布是在2015年,另外最近的一次更新使它支持了Python3。

    subDomainBrute是通过纯DNS爆破来找到子域名,为了最大提升效率,subDomainBrute用协程+多进程的方式进行爆破。

    对于python3,使用asyncio,aiodns库进行异步dns的发包,但对于python2,使用的是dnspython gevent库,应该是历史原因导致的。

    Dns server test

    对于爆破dns来说,有足够多且快的dns server是关键(爆破一段时间后,可能会有dns不再回应请求)

    可以自己配置dns server在dict/dns_servers.txt文件中,subDomainBrute会在程序启动时测试DNS。

    首先测试dns server

    image-20200811164059789

    测试 public-dns-a.baidu.com 返回 180.76.76.76 是正确的dns

    测试 test.bad.dns.lijiejie.com 抛出异常则为正确的dns,如果有返回结果,则不正常。

    泛域名

    subDomainBrute没有泛域名处理,如果存在泛域名解析,程序就会直接退出。

    image-20200811164721033

    Sublist3r

    Github https://github.com/aboul3la/Sublist3r

    Sublist3r也是2015年发布的,在暴力破解的基础上还会通过接口枚举来获取域名。

    它的爆破模块用的是 https://github.com/TheRook/subbrute

    SubBrute是一个社区驱动的项目,旨在创建最快,最准确的子域枚举工具。SubBrute背后的神奇之处在于它使用开放式解析器作为一种代理来规避DNS速率限制(https://www.us-cert.gov/ncas/alerts/TA13-088A)。该设计还提供了一层匿名性,因为SubBrute不会将流量直接发送到目标的名称服务器。

    提供了一层匿名性 => 用很多代理DNS来进行DNS请求

    它只有多进程来运行爆破程序,如果在Windows下,它只会使用线程

    可能是觉得在Windows下难以操控多线程吧。

    但这样一来它的效率就太慢了。

    它支持的搜索引擎

    用随机数来判断是否泛解析

    同样它也不支持泛解析的支持。

    唯一有优势的就是它能作为一个python包存在,通过pip就能快速安装使用,或者把它集成在代码中。

    ESD

    Github:https://github.com/FeeiCN/ESD

    相比于的暴力收集手段,esd在很多方面有独特的想法。

    支持泛解析域名

    基于RSC(响应相似度对比)技术对泛解析域名进行枚举(受网络质量、网站带宽等影响,速度会比较慢)

    基于aioHTTP获取一个不存在子域名的响应内容,并将其和字典子域名响应进行相似度比对。 超过阈值则说明是同个页面,否则则为可用子域名,并对最终子域名再次进行响应相似度对比。

    更快的速度

    基于AsyncIO异步协程技术对域名进行枚举(受网络和DNS服务器影响会导致扫描速度小幅波动,基本在250秒以内)

    基于AsyncIO+aioDNS将比传统多进程/多线程/gevent模式快50%以上。 通过扫描qq.com,共170083条规则,找到1913个域名,耗时163秒左右,平均1000+条/秒

    更全的字典

    融合各类字典,去重后共170083条子域名字典

    • 通用字典
      • 单字母、单字母+单数字、双字母、双字母+单数字、双字母+双数字、三字母、四字母
      • 单数字、双数字、三数字
    • 域名解析商公布使用最多的子域名
      • DNSPod: dnspod-top2000-sub-domains.txt
    • 其它域名爆破工具字典
      • subbrute: names_small.txt
      • subDomainsBrute: subnames_full.txt

    更多的收集渠道

    • 收集DNSPod接口泄露的子域名
    • 收集页面响应内容中出现的子域名
    • 收集跳转过程中的子域名
    • 收集HTTPS证书透明度子域名
    • 收集DNS域传送子域名
    • 收集搜索引擎子域名
    • 收集zoomeye、censys、fofa、shodan的接口结果

    DNS服务器

    • 解决各家DNS服务商对于网络线路出口判定不一致问题
    • 解决各家DNS服务商缓存时间不一致问题
    • 解决随机DNS问题,比如fliggy.com、plu.cn等
    • 根据网络情况自动剔除无效DNS,提高枚举成功率

    很多实现都值得学习,这里贴出一些值得学习的代码。

    域传输漏洞实现

    HTTPS证书透明度获取子域名

    纯socket实现的check dns server

    基于文本相似度过滤泛解析域名

    这个代码跨度很大,下面是简化版本

    其他

    ESD只能用文本相似度来过滤泛解析,但以此会导致机器的内存,CPU都暴涨,机器性能小不建议使用。

    另外ESD似乎不能在windows下使用,因为看最后保存的路径写死了是/tmp/esd

    image-20200811173500596

    其他感觉没有不兼容的地方,解决了这个路径Windows应该就可以用了。

    另外

    • 解决各家DNS服务商对于网络线路出口判定不一致问题
    • 解决各家DNS服务商缓存时间不一致问题
    • 解决随机DNS问题,比如fliggy.com、plu.cn等

    这三个不知道怎么解决的,可能代码躲在了哪个角落,没发现。

    OneForAll

    OneForAll https://github.com/shmilylty/OneForAll

    OneForAll的更新很勤快,我写这篇文章时,发现1小时前就有新的提交。

    image-20200811180837960

    OneForAll的功能也很多,被动搜索域名,子域爆破,子域接管,端口探测,指纹识别,导出等等。

    被动搜索

    OneForAll集成了很多收集域名的web接口,每个接口为一个py文件,py文件中最后都会基于common/module.py Module这个类,这个类提供了很多需要通用方法,如网页的请求,匹配域名,保存结果以及运行时需要的各类方法。

    比较令人注意的是匹配域名的方法,因为很多web的接口返回格式都不太一样,要每个插件都处理一遍这样的格式吗?不必,OneForAll编写了通用域名匹配函数,即通过正则对最终结果匹配。

    泛解析处理

    通过DNS泛解析域名时返回的TTL相同。

    参考的 http://sh3ll.me/archives/201704041222.txt

    泛解析一直都是域名爆破中的大问题,目前的解决思路是根据确切不存在的子域名记录(md5(domain).domain)获取黑名单 IP,对爆破 过程的结果进行黑名单过滤。 但这种宽泛的过滤很容易导致漏报,如泛解析记录为 1.1.1.1,但某存在子域名也指向 1.1.1.1,此时这个子域名便可能会被黑名单过 滤掉。 胖学弟提到,可以将 TTL 也作为黑名单规则的一部分,评判的依据是:在权威 DNS 中,泛解析记录的 TTL 肯定是相同的,如果子域名 记录相同,但 TTL 不同,那这条记录可以说肯定不是泛解析记录。最终的判断代码如下:

    这个方法是否好,我也不知道。

    爆破流程

    brute.py简写版爆破流程

    域名接管

    OneForAll的域名接管主要是针对一些公共服务的域名接管,根据其指纹识别的内容

    原理是获取域名的cname,如果cname和上述指纹匹配,并且访问后返回内容也匹配即说明目前无人使用,可以创建一个相同域名。

    但创建都需要手动,OneForAll只提供了一个GIthub的自动创建脚本modules/autotake/github.py,但没有看到任何地方调用它。

    OneForAll的域名接管只针对在线服务商。

    原先以为会对每个普通域名查询cname,然后查询cname的域名是否注册,但是没有。

    指纹识别

    OneForAll的指纹识别使用的是 https://github.com/webanalyzer/rules

    作者定义了通用指纹识别的规则

    并且集成转化了fofa,wappalyzer,whatweb的指纹,感觉挺不错的。

    指纹识别具体的文件在modules/banner.py,根据指纹识别的规则,基本上访问一次首页就能识别到指纹。唯一不解的是作者只使用了多进程来识别,为什么前面是协程+多进程,指纹识别这里只用进程了,感觉效率会大大受影响。

    image-20200812114924375

    其他

    OneForAll 基于Python3,官方要求Python3.8以上,依赖项requirements.txt有38行,这样对使用者不太友好(Python要求版本太高,依赖太多,很容易报错)。

    dnsprobe

    dnsprobe https://github.com/projectdiscovery/dnsprobe

    dnsprobe是go语言编写的dns查询工具,因为go语言隐藏了协程的细节,使用简单的编程便可以实现并发编程。同时用go语言静态编译可以运行在各种平台,也极大方便了使用者。

    dnsprobe的作者也很能注意到效率的瓶颈点,例如如果是大字典的dns爆破,读取这个字典就要花费不少时间,而dnsprobe是边读边爆破,上述分析的工具都没有注意到这个点。

    image-20200812135541025

    但是用Python做到还是很不容易的,使用python的协程后,需要把所有函数都变为协程,才能发挥协程的威力,如果要实现边读边扫描,要将读取文件变为协程,以及扫描变为协程。

    为此需要安装一个额外的包

    subfinder

    subfinder https://github.com/projectdiscovery/subfinder

    同属projectdiscovery项目下的子域名发现工具subfinder,它的定位是通过各种接口来发现有效子域名。

    subfinder is built for doing one thing only - passive subdomain enumeration, and it does that very well.

    subfinder仅用于做一件事-被动子域枚举,它做得很好。

    它的接口列表

    subfinder是go写的,那么是如何加载这些接口的呢

    subfinder的每个接口都需要实现Source这个接口

    image-20200812152013318

    接着定义Agent实现一个map类,map的内容为每个接口的Source

    image-20200812152145720

    接着搜索域名时只需要遍历这个map,执行其中的Run方法即可。

    image-20200812152304342

    配合

    通过在线接口获取域名后批量dns查询域名保存为domain.txt文件

    shuffledns

    https://github.com/projectdiscovery/shuffledns

    shuffledns就是调用的massdns,将返回结果处理了一下。OneForAll和shuffledns都使用了massdns那么就来看看它。

    massdns

    https://github.com/blechschmidt/massdns

    Massdn 是一个简单的高性能 DNS 存根解析器,针对那些寻求解析数百万甚至数十亿个大量域名的用户。在没有特殊配置的情况下,使用公开可用的解析器,massdn 能够每秒解析超过350,000个名称。

    C语言编写,第一次提交记录在2016年。

    粗略的看了下代码,massdns使用socket发包,然后用epoll,pcap,busy-wait polling等技术来接收。

    去年我写了篇《从 Masscan, Zmap 源码分析到开发实践》(https://paper.seebug.org/1052/),当时我就想过用"无状态扫描"技术来对DNS爆破,当时只用pcap模块来进行发送和接收

    image-20200812160929189

    理论速度是可以到70w/s的。

    最近准备再改改然后开源出来~

    总结

    原本计划还有OWASP Amass的,这个就留给下篇吧。

    总结一下

    • subDomainBrute老牌DNS爆破工具,使用让人感觉很稳很友好,依赖较少,很好安装。
    • ESD 域名收集方法很多,对接的web接口比较少,支持python调用,用于集成到扫描器应该不错。
    • OneForAll依赖较多,功能比较全面,但功能还是有些欠缺,有些地方效率考虑的不够好。适合对一个新的域名爆破,结果比较多。

    对于子域名收集,我推荐的组合是subfinderdnsprobe,它们都是go语言,直接下载二进制就能跑,subfinder用于收集网上接口(但接口似乎没有OneForAll多),dnsprobe用于爆破/验证域名。

    用linux哲学,跑的可以更优雅~

    另外进行DNS爆破时,DNS解析器的设定非常重要,它决定了爆破的质量和数量,推荐1w字典就增加一个DNS服务器。

    在写文章的时候可能会有些错误或者不到的地方,可以在paper评论区回复和我讨论~


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1292/

    作者:江 | Categories:技术分享 | Tags:
  • ISC 议题 | 从数据动态视角看网络空间测绘

    2020-11-03

    作者:知道创宇404实验室
    时间:2020年8月14日

    2020第八届互联网安全大会(ISC)上, 知道创宇404实验室总监隋刚发表《从数据动态视角看网络空间测绘》的主题演讲,从多个案例入手具体分析,阐明了网络空间测绘的实质性意义。另外也通过汇总 ZoomEye 近 6年的线上IPv4测绘数据,从数据分析的角度看网络空间的变化情况,借此看到一些新的观点和相应的支撑数据。

    有兴趣的同学可以点击这里回看视频,以及下载演讲议题PDF:https://paper.seebug.org/papers/Archive/

    作者:江 | Categories:公司活动 | Tags:
  • 从反序列化到类型混淆漏洞——记一次 ecshop 实例利用

    2020-11-03

    作者:LoRexxar'@知道创宇404实验室
    时间:2020年3月31日
    English Version: https://paper.seebug.org/1268

    本文初完成于2020年3月31日,由于涉及到0day利用,所以于2020年3月31日报告厂商、CNVD漏洞平台,满足90天漏洞披露期,遂公开。


    前几天偶然看到了一篇在Hackerone上提交的漏洞报告,在这个漏洞中,漏洞发现者提出了很有趣的利用,作者利用GMP的一个类型混淆漏洞,配合相应的利用链可以构造mybb的一次代码执行,这里我们就一起来看看这个漏洞。

    https://hackerone.com/reports/198734

    以下文章部分细节,感谢漏洞发现者@taoguangchen的帮助。

    GMP类型混淆漏洞

    漏洞利用条件

    • php 5.6.x
    • 反序列化入口点
    • 可以触发__wakeup的触发点(在php < 5.6.11以下,可以使用内置类)

    漏洞详情

    gmp.c

    zend_object_handlers.c

    从gmp.c中的片段中我们可以大致理解漏洞发现者taoguangchen的原话。

    __wakeup等魔术方法可以导致ZVAL在内存中被修改。因此,攻击者可以将**object转化为整数型或者bool型的ZVAL,那么我们就可以通过Z_OBJ_P访问存储在对象储存中的任何对象,这也就意味着可以通过zend_hash_copy覆盖任何对象中的属性,这可能导致很多问题,在一定场景下也可以导致安全问题。

    或许仅凭借代码片段没办法理解上述的话,但我们可以用实际测试来看看。

    首先我们来看一段测试代码

    在代码中我展示了多种不同情况下的环境。

    让我们来看看结果是什么?

    我成功修改了第一个声明的对象。

    但如果我将反序列化的类改成b会发生什么呢?

    很显然的是,并不会影响到其他的类变量

    如果我们给class b加一个__Wakeup函数,那么又会产生一样的效果。

    但如果我们把wakeup魔术方法中的变量设置为2

    返回的结果可以看出来,我们成功修改了第二个声明的对象。

    但如果我们把ryat改为4,那么页面会直接返回500,因为我们修改了没有分配的对象空间。

    在完成前面的试验后,我们可以把漏洞的利用条件简化一下。

    如果我们有一个可控的反序列化入口,目标后端PHP安装了GMP插件(这个插件在原版php中不是默认安装的,但部分打包环境中会自带),如果我们找到一个可控的__wakeup魔术方法,我们就可以修改反序列化前声明的对象属性,并配合场景产生实际的安全问题。

    如果目标的php版本在5.6 <= 5.6.11中,我们可以直接使用内置的魔术方法来触发这个漏洞。

    真实世界案例

    在讨论完GMP类型混淆漏洞之后,我们必须要讨论一下这个漏洞在真实场景下的利用方式。

    漏洞的发现者Taoguang Chen提交了一个在mybb中的相关利用。

    https://hackerone.com/reports/198734

    这里我们不继续讨论这个漏洞,而是从头讨论一下在ecshop中的利用方式。

    漏洞环境

    • ecshop 4.0.7
    • php 5.6.9

    反序列化漏洞

    首先我们需要找到一个反序列化入口点,这里我们可以全局搜索unserialize,挨个看一下我们可以找到两个可控的反序列化入口。

    其中一个是search.php line 45

    这是一个前台的入口,但可惜的是引入初始化文件在反序列化之后,这也就导致我们没办法找到可以覆盖类变量属性的目标,也就没办法进一步利用。

    还有一个是admin/order.php line 229

    后台的表单页的这个功能就满足我们的要求了,不但可控,还可以用urlencode来绕过ecshop对全局变量的过滤。

    这样一来我们就找到了一个可控并且合适的反序列化入口点。

    寻找合适的类属性利用链

    在寻找利用链之前,我们可以用

    来确定在反序列化时,已经声明定义过的类。

    在我本地环境下,除了PHP内置类以外我一共找到13个类

    从代码中也可以看到在文件头引入了多个库文件

    这里我们主要关注init.php,因为在这个文件中声明了ecshop的大部分通用类。

    在逐个看这里面的类变量时,我们可以敏锐的看到一个特殊的变量,由于ecshop的后台结构特殊,页面内容大多都是由模板编译而成,而这个模板类恰好也在init.php中声明

    回到order.php中我们寻找与$smarty相关的方法,不难发现,主要集中在两个方法中

    而这里我们主要把视角集中在display方法上。

    粗略的浏览下display方法的逻辑大致是

    比较重要的代码会在make_compiled这个函数中被定义

    当流程走到这一步的时候,我们需要先找到我们的目标是什么?

    重新审视cls_template.php的代码,我们可以发现涉及到代码执行的只有几个函数。

    get_para只在select中调用,但是没找到能触发select的地方。

    然后是pop_vars

    恰好配合GMP我们可以控制$this->_temp_key变量,所以我们只要能在上面的流程中找到任意地方调用这个方法,我们就可以配合变量覆盖构造一个代码执行。

    在回看刚才的代码流程时,我们从编译后的PHP文件中找到了这样的代码

    order_info.htm.php

    在遍历完表单之后,正好会触发pop_vars

    这样一来,只要我们控制覆盖cls_template变量的_temp_key属性,我们就可以完成一次getshell

    最终利用效果

    Timeline

    • 2020.03.31 发现漏洞。
    • 2020.03.31 将漏洞报送厂商、CVE、CNVD等。
    • 2020.07.08 符合90天漏洞披露期,公开细节。

    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1267/

    作者:江 | Categories:漏洞分析 | Tags:
  • F5 BIG-IP hsqldb(CVE-2020-5902)漏洞踩坑分析

    2020-11-03

    作者:Longofo@知道创宇404实验室
    时间:2020年7月10日
    English Version: https://paper.seebug.org/1272/

    F5 BIG-IP最近发生了一次比较严重的RCE漏洞,其中主要公开出来的入口就是tmsh与hsqldb方式,tmsh的利用与分析分析比较多了,如果复现过tmsh的利用,就应该知道这个地方利用有些鸡肋,后面不对tmsh进行分析,主要看下hsqldb的利用。hsqldb的利用poc已经公开,但是java hsqldb的https导致一直无法复现,尝试了各种方式也没办法了,只好换其他思路,下面记录下复现与踩坑的过程。

    利用源码搭建一个hsqldb http servlet

    如果调试过hsqldb,就应该知道hsqldb.jar的代码是无法下断点调试的,这是因为hsqldb中类的linenumber table信息没有了,linenumber table只是用于调式用的,对于代码的正常运行没有任何影响。看下正常编译的类与hqldb类的lineumber table区别:

    使用javap -verbose hsqlServlet.class命令看下hsqldb中hsqlServlet.class类的详细信息:

    使用javap -verbose Test.class看下自己编译的类信息:

    可以看到自己编译的类中,每个method中都有一个 LineNumberTable,这个信息就是用于调试的信息,但是hsqldb中没有这个信息,所以是无法调试下断点的,hsqldb应该在编译时添加了某些参数或者使用了其他手段来去除这些信息。

    没办法调试是一件很难受的事情,我现在想到的有两种:

    1. 反编译hsqldb的代码,自己再重新编译,这样就有linenumber信息了,但是反编译再重新编译可能会遇到一些错误问题,这部分得自己手动把代码修改正确,这样确实是可行的,在后面f5的hsqldb分析中可以看到这种方式
    2. 代码开源,直接用源码跑

    hsqldb的代码正好是开源的,那么这里就直接用源码来开启一个servlet吧。

    环境

    • hsqldb source代码是1.8的,现在新版已经2.5.x了,为了和f5中的hsqldb吻合,还是用1.8的代码吧
    • JDK7u21,F5 BIG-IP 14版本使用的JDK7,所以这里尽量和它吻合避免各种问题

    虽然开源了,但是拖到idea依然还有些问题,我修改了一些代码,让他正常跑起来了,修改好的代码放到github上了,最后项目结构如下:

    使用http方式利用hsqldb漏洞(ysoserial cc6,很多其他链也行):

    利用requests发包模拟hsqldb RCE

    java hsqldb https问题无法解决,那就用requests来发https包就可以了,先模拟http的包。

    抓取上面利用java代码发送的payload包,一共发送了三个,第一个是连接包,连接hsqldb数据库的,第二、三包是执行语句的包:

    根据代码看下第一个数据包返回的具体信息,主要读取与写入的信息都是由Result这个类处理的,一共20个字节:

    • 1~4:总长度00000014,共20字节
    • 5~8:mode,connection为ResultConstants.UPDATECOUNT,为1,00000001
    • 9~12:databaseID,如果直接像上面这样默认配置,databaseID在服务端不会赋值,由jdk初始化为0,00000000
    • 13~16:sessionID,这个值是DatabaseManager.newSession分配的值,每次连接都是一个新的值,本次为00000003
    • 17~20:connection时,为updateCount,注释上面写的 max rows (out) or update count (in),如果像上面这样默认配置,updateCount在服务端不会赋值,由jdk初始化为0,00000000

    连接信息分析完了,接下来的包肯定会利用到第一次返回包的信息,把他附加到后面发送包中,这里只分析下第二个发送包,第三个包和第二个是一样的,都是执行语句的包:

    • 1~4:总长度00000082,这里为130
    • 5~8:mode,这里为ResultConstants.SQLEXECDIRECT,0001000b
    • 9~12:databaseID,为上面的00000000
    • 13~16:sessionID,为上面的00000003
    • 17~20:updateCount,为上面的00000000
    • 21~25:statementID,这是客户端发送的,其实无关紧要,本次为00000000
    • 26~30:执行语句的长度
    • 31~:后面都是执行语句了

    可以看到上面这个处理过程很简单,通过这个分析,很容易用requests发包了。对于https来说,只要设置verify=False就行了。

    反序列化触发位置

    这里反序列化触发位置在:

    其实并不是org.hsqldb.util.ScriptTool.main这个地方导致的,而是hsqldb解析器语法解析中途导致的反序列化。将ScriptTool随便换一个都可以,例如org.hsqldb.sample.FindFile.main

    F5 BIG-IP hsqldb调试

    如果还想调试下F5 BIG-IP hsqldb,也是可以的,F5 BIG-IP里面的hsqldb自己加了些代码,反编译他的代码,然后修改反编译出来的代码错误,再重新打包放进去,就可以调试了。

    F5 BIG-IP hsqldb回显

    • 既然能反序列化了,那就可以结合Template相关的利用链写到response
    • 利用命令执行找socket的fd文件,写到socket
    • 这次本来就有一个fileRead.jsp,命令执行完写到这里就可以了

    hsqldb的连接安全隐患

    从数据包可以看到,hsqldb第一次返回信息并不多,在后面附加用到的信息也就databaseID,sessionID,updateCount,且都只为4字节(32位),但是总有数字很小的连接排在前面,所以可以通过爆破出可用的databaseID、sessionID、updateCount。不过对于本次的F5 BIG-IP,直接用上面默认的就行了,无需爆破。

    总结

    虽然写得不多,写完了看起来还挺容易,不过过程其实还是很艰辛的,一开始并不是根据代码看包的,只是发了几个包对比然后就写了个脚本,结果跑不了F5 BIG-IP hsqldb,后面还是调试了F5 hsqldb代码,很多问题需要解决。同时还看到了hsqldb其实是存在一定安全隐患的,如果我们直接爆破databaseID,sessionID,updateCount,也很容易爆破出可用的databaseID,sessionID,updateCount。


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1271/

    作者:江 | Categories:漏洞分析 | Tags:
  • 开源=安全?RVN 盗币事件复盘

    2020-11-03

    作者:ACce1er4t0r@知道创宇404区块链安全研究团队
    时间:2020年7月22日

    在7月15号,v2ex上突然出现了一个这样标题的帖子:三行代码就赚走 4000w RMB,还能这么玩?

    帖子内容里,攻击者仅仅只用了短短的几行代码,就成功的获利千万RMB,那么他是怎么做到的呢?

    让我们来回顾一下这次事件。

    事件回顾

    2020年1月16日,开源项目Ravencoin接到这么一则pull request

    image.png

    代码中,提交者将原本定义模糊的报错细分,让人们能够更直观的了解究竟出了什么错误,看起来是在优化项目,但是,事实真是这样么?

    2020年6月29日,Solus Explorer开发团队一位程序员在修bug后同步数据时发现了一个suspected transactions with unbalanced VOUTs被Explorer标记出,之后他检查RVN时发现RVN大约被增发了约275,000,000,并发现了大量可疑地reissue asset Transaction,这些交易不仅仅有Asset Amount,而且获得了RVN。在他发现这一事件后,马上和他的团队一起将事件报告给Ravencoin团队。

    2020年7月3日,Ravencoin团队向社区发布紧急更新

    2020年7月4日,13:26:27 (UTC),Ravencoin团队对区块强制更新了新协议,并确认总增发量为 301,804,400 RVN,即为3.01亿RVN.

    2020年7月5月,Ravencoin团队宣布紧急事件结束

    2020年7月8日,Ravencoin团队公布事件

    image.png

    事件原理

    在解释原理前,我们不妨先重新看看WindowsCryptoDev提交的代码

    这是一段Ravencoin中用于验证的逻辑代码。

    简单来说,提交者改变了CheckTransaction对Asset验证的判断,将原本isAsset && txout.nValue != 0的条件更改为下面的条件:

    1. isAsset && nType == TX_TRANSFER_ASSET && txout.nValue != 0
    2. isAsset && nType == TX_NEW_ASSET && txout.nValue != 0

    这段代码本身利用了开源社区PR的风格(在开源社区中,如果开发者发现提交的PR无关实际逻辑,则不会过度关注代码影响),看似只是细化了交易过程中返回的报错,使得正常使用功能的交易者更容易定位到错误,实则,通过忽略else语句,导致一个通用的限制条件被细化到了nType的两种常见情况下

    而代码中nTypt可能的值有如下:

    由于代码的改变,当nType == TX_REISSUE_ASSET时,txout.nValue可以不为0。

    通过对比正常的交易和存在问题的交易,我们也能验证这一观点。

    image.png

    在正常的Reissue操作中,我们需要向 Address RXReissueAssetXXXXXXXXXXXXXXVEFAWu支付100RVN,之后我们可以得到一个新的Amount为0的Address,如果新的Address的Amount不为0,那么将会返回bad-txns-asset-tx-amount-isn't-zero的错误信息(代码被更改前,修复后会返回bad-txns-asset-reissued-amount-isn't-zero的错误信息)

    image.png

    而攻击者修改了判断条件,导致了在CheckTransaction时并不会检测TX_REISSUE_ASSET,所以能够在Address的Amount不为0的情况下通过判断,最终实现增发RVN。

    看完代码后,我们点开这位叫做WindowsCryptoDev的用户的GitHub主页

    这是个在2020年1月15日新建的账号,为了伪造身份,起了个WindowsCryptoDev的id,并且同天建了个叫Windows的repo,最后的活动便是在1月16号向Ravencoin提交PR。

    而对于这个PR,项目团队的反馈也能印证我们的猜测。


    整个攻击流程如下:

    1. 2020年1月15日,攻击者伪造身份
    2. 1月16日,攻击者提交pull request
    3. 1月16日,当天pull request被合并
    4. 5月9日,攻击者开始通过持续制造非法Reissue Asset操作增发RVN,并通过多个平台转卖换为其他虚拟货币
    5. 6月29日,Solus Explorer开发团队一位程序员发现问题并上报
    6. 7月3日,Ravencoin团队向社区发布紧急更新,攻击者停止增发RVN
    7. 7月4日,13:26:27 (UTC),Ravencoin团队对区块强制更新了新协议
    8. 7月5月,Ravencoin团队宣布紧急事件结束
    9. 7月8日,Ravencoin团队公布事件

    至此,事件结束,最终,攻击者增发了近3亿的RVN。

    总结

    随着互联网时代的发展,开源文化逐渐从小众文化慢慢走向人们的视野中,人们渐渐开始认为开源社区给项目带来源源不断的活力,开源使得人人都可以提交请求、人人都可以提出想法,可以一定层度上提高代码的质量、增加社区的活跃度,形成一种正反馈,这使开源社区活力无限。

    但也因此,无数不怀好意的目光也随之投向了开源社区,或是因为攻击者蓄谋已久,抑或是因为贡献者无心之举,一些存在问题的代码被加入到开源项目中,他们有的直接被曝光被发现被修复,也有的甚至还隐藏在核心代码中深远着影响着各种依赖开源项目生存着的软件、硬件安全。

    开源有利亦有弊,攻击者也在渗透着越来越多开发过程中的不同维度,在经历了这次事件之后,你还能随意的接受开源项目中的PR吗?

    REF

    [1] 三行代码就赚走 4000w RMB,还能这么玩?

    https://s.v2ex.com/t/690286

    [2] commit

    https://github.com/RavenProject/Ravencoin/commit/d23f862a6afc17092ae31b67d96bc2738fe917d2

    [3] Solus Explorer - Address: Illegal Supply

    https://rvn.cryptoscope.io/address/?address=Illegal%20Supply

    [4] Ravencoin — Emergency Update

    https://medium.com/@tronblack/ravencoin-emergency-update-dece62255fd9/https://medium.com/@tronblack/ravencoin-emergency-update-dece62255fd9

    [5] Ravencoin — Emergency Ended

    https://medium.com/@tronblack/ravencoin-emergency-ended-3f3181a0f6d2/https://medium.com/@tronblack/ravencoin-emergency-ended-3f3181a0f6d2

    [6] The anatomy of Ravencoin exploit finding

    https://medium.com/@cryproscope/the-anatomy-of-ravencoin-exploit-finding-8fa4fe7547a9/https://medium.com/@cryproscope/the-anatomy-of-ravencoin-exploit-finding-8fa4fe7547a9

    [7] RavencoinVulnerability — WTF Happened?

    https://medium.com/@tronblack/ravencoin-post-vulnerability-fix-fb3a4bd70b7b/https://medium.com/@tronblack/ravencoin-post-vulnerability-fix-fb3a4bd70b7b


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1275/

    作者:江 | Categories:安全科普 | Tags:
  • CVE-2020-1362 漏洞分析

    2020-11-03

    作者:bybye@知道创宇404实验室
    时间:2020年7月24日

    漏洞背景

    WalletService 服务是 windows 上用来持有钱包客户端所使用的对象的一个服务,只存在 windows 10 中。

    CVE-2020-1362 是 WalletService 在处理 CustomProperty 对象的过程中出现了越界读写,此漏洞可以导致攻击者获得管理员权限,漏洞评级为高危。

    微软在 2020 年 7 月更新对漏洞发布补丁。

    环境搭建

    1. 复现环境:windows 10 专业版 1909 (内部版本号 18363.815)
    2. 设置 WalletService 服务启动类型为自动
    3. 调试环境:windbg -psn WalletService 即可。

    漏洞原理与分析

    漏洞点是设置 CustomProperty 对象的 Group 的 get 方法和 set 方法没有检查边界。

    1. get 方法的 a2 参数没有检查边界导致可以泄露堆上的一些地址。
    2. set 方法的 a2 参数没有检查边界,可以覆盖到对象的虚表指针,从而控制程序流。

    漏洞利用过程

    创建 CustomProperty 对象

    WalletService 服务由 WalletService.dll 提供,WalletService.dll 实际上是一个动态链接库形式的 Com 组件,由 svchost.exe 加载。我们可以在自己写的程序(下面称为客户端)中使用 CoCreateInstance() 或者 CoGetClassObject() 等函数来创建对象,通过调用获得的对象的类方法来使用服务提供的功能。

    如何创建出漏洞函数对应的对象呢?最简单的办法是下载 msdn 的符号表,然后看函数名。

    我们想要创建出 CustomProperty 对象,ida 搜索一下,发现有两个创建该对象的函数:Wallet::WalletItem::CreateCustomProperty() 和 Wallet::WalletXItem::CreateCustomProperty()。

    img

    所以我们创建一个 CustomProperty 需要一个 WalletXItem 对象或者 WalletItem 对象,那么使用哪个呢?继续用 ida 搜索 CreateWalletItem 或者 CreateWalletXItem,会发现只有 CreateWalletItem。

    img

    那到这里我们需要一个 WalletX 对象,继续用 ida 搜索会发现找不到 CreateWalletX,但是如果搜索 WalletX,会发现有个 WalletXFactory::CreateInstance(),如果有过 Com 组件开发经验的同学就会知道,这个是个工厂类创建接口类的函数,上面提到的 CoCreateInstance() 函数会使 WalletService 调用这个函数来创建出接口类返回给客户端。

    img

    那么如何调用 WalletXFactory::CreateInstance() 并创建出 WalletX 对象呢?我们需要在客户端使用 CoCreateInstance() 。

    1. 首先,我们需要 WalletXFactory 的 CLSID,可以使用 OLEViewDotNet 这个工具查看。
    2. 其次,我们需要一个 WalletX 的 IID,这个可以用 ida 直接看 WalletXFactory::CreateInstance() 这个函数。

    有了 WalletXFactory 的 CLSID 和 WalletX 的 IID,然后在客户端调用 CoCreateInstance(),WalletService 就会调用 CLSID 对应的工厂类 WalletXFactory 的 CreateInstance(), 创建出 IID 对应的 WalletX 对象,并返回对象给客户端。

    然后按照上面的分析,使用 WalletX::CreateWalletItem() 创建出 WalletItem 对象,然后使用 WalletItem::CreateCustomProperty() 创建出 CustomProperty 对象。

    对于上面的步骤有疑问的同学可以去学一学 Com 组件开发,尤其是进程外组件开发。

    伪造虚表,覆盖附表指针

    由于同一个动态库,在不同的进程,它的加载基址也是一样的,我们可以知道所有dll里面的函数的地址,所以可以获得伪造的虚表里面的函数地址。

    那么把虚表放哪里呢?直接想到的是放堆上。

    但如果我们继续分析,会发现,CustomProperty 类里面有一个 string 对象,并且可以使用 CustomProperty::SetLabel() 对 string 类进行修改,所以,我们可以通过修改 string 类里面的 beg 指针 和 end 指针,然后调用 CustomProperty::SetLabel() 做到任意地址写。

    img

    有了任意地址写,我们选择把虚表放在 WalletService.dll 的 .data 节区,以避免放在堆上可能破坏堆上的数据导致程序崩溃。

    控制程序流到 LoadLibrary 函数

    使用伪造 vtable 并覆盖虚表指针的办法,我们可以通过调用虚函数控制 WalletService 的程序流到任意地址了。

    那么怎么提权呢?在 windows 服务提权中,通常的办法是把程序流控制到可以执行 LoadLibrary() 等函数来加载一个由我们自己编写的动态链接库,因为在加载 dll 的时候会执行 dll 里面的 DllMain(),这个方法是最强大的也是最实用的。

    这里使用漏洞提交者的方法,把虚表的某个地址覆盖成 dxgi.dll 里面的 ATL::CComObject\::`vector deleting destructor(),因为这个函数调用的 LoadLibraryExW() 会使用一个全局变量作为想要加载的 dll 的路径。

    img

    我们可以通过上面的 SetLabel() 进行任意地址写,修改上图的全局变量 Src,使其指向我们自己实现的动态链接库的路径,然后调用对应的虚表函数,使程序流执行到 LoadLibrarExW() 即可。

    实现一个动态链接库

    在 DllMain() 里面写上我们希望以高权限执行代码,然后调用虚表里面对应的函数是 WalletService 的程序流运行到 LoadLibraryEx() 即可。

    注意,因为 windows 服务运行在后台,所以需要在 DllMain() 里面使用命名管道或者 socket 等技术来进行回显或者交互,其次由于执行的是 LoadLibraryExW(),所以这里的 dll 路径要使用宽字符。

    其它

    在控制虚表函数程序流到 LoadLibraryExW() 时,需要绕过下面两个 check。

    第一个是需要设置 this+0x80 这个地址的值,使得下面的 and 操作为 true。

    image-20200724111317787

    第二个是要调整 qword_C5E88 和 qword_C5E80 是下面的变量 v4 指向具有写权限的内存。

    image-20200724111819875

    漏洞利用结果

    可以获得管理员权限

    image-20200724121314068

    补丁前后对比

    可以看到,打了补丁之后,get 方法和 set 方法都对 a2 参数添加了边界检测。

    img
    img

    参考链接

    [1] PoC链接
    [2] 微软更新公告
    [3] nvd漏洞评级


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1276/

    作者:江 | Categories:漏洞分析 | Tags:
  • Look for traces of APT attacks through the ZoomEye history api

    2020-11-02

    Author: Heige(a.k.a Superhei) of KnownSec 404 Team 
    Date: May 25,2020

    Chinese version:https://paper.seebug.org/1219/

    We had released ZoomEye’s historical data API query interface in ZoomEye 2020 that had launched in January this year: https://medium.com/@80vul/zoomeye-2020-has-started-8414d6aaf38. Next, I will introduce some examples of using ZoomEye History API to capture the traces of APT team attacks.

    Instructions for using the historical query API interface: https://www.zoomeye.org/doc#history-ip-search ,Of course we have also updated our ZoomEye SDK support history api: https://github.com/knownsec/ZoomEye.

    Before the cases are explained, I must explain the ZoomEye online data update mode again: it is the overwrite update mode. Many malware teams, including many apt teams, will abandon the C2 server immediately after it is discovered. So this also causes the data on ZoomEye to be cached without being updated and overwritten.

    The first case is about Darkhotel APT group

    I have already mentioned it in this tweet, of course, here needs to explain a "bug" in this tweet ,Although this “bug” has nothing to do with the issue discussed today : The vulnerability used in this attack should be CVE-2019-1367 instead of CVE-2020-0674 (Here we need to thank the friends who discussed together)

    In this Darkhotel attack, they attacked the ip website service and implanted ie 0day to carry out Watering Hole attack. So we queried all historical data of this IP on ZoomEye:

    List all scan time records and ports about this IP

    Query the time and port of the IE 0day implanted into the Watering Hole attack :

    It turned out that this Watering Hole attack continued from at least '2019-10-06 05:24:44' to '2020-01-28 10:58:02' , This also shows that Darkhotel APT group attacked this IP website as early as 2019-10-06.

    We continue to analyze the port service of this IP in 2019 :

    Very typical Tomcat-based JSP operating environment, and once opened 8009 ajp port. Many attack events prove that tomcat manages weak passwords, security vulnerabilities and other issues, making security very vulnerable,Perhaps this is also the method used in this attack.

    The second case is about APT-C-01(a.k.a Green Spot)

    Qi An Xin Threat Intelligence Center released a detailed analysis report on APT-C-01 in 2018: https://www.virusbulletin.com/virusbulletin/2019/11/vb2019-paper-vine-climbing-over-great-firewall-longterm-attack-against-china/ (En)https://ti.qianxin.com/uploads/2018/09/20/6f8ad451646c9eda1f75c5d31f39f668.pdf(Ch)

    "The loader program will first try to connect to a common URL to check network connectivity. If there is no connection, it will try to connect every five seconds until the network is connected. Then it downloads the payload from hxxp://updateinfo.servegame.org/tiny1detvghrt.tmp"

    We put our focus on the payload download URL hxxp://updateinfo.servegame.org/tiny1detvghrt.tmp>,Through the ping command, we can no longer find the IP address of this domain name resolution :

    From the Chinese version of the report, we see a screenshot that shows that can opendir

    This means we can find the target by searching "tiny1detvghrt.tmp" on ZoomEye ,Very lucky we found it :

    Once again, after the APT attack was discovered, these IPs were directly abandoned.

    We get the IP(165.227.220.223) of the domain(updateinfo.servegame.org) name and continue to query the historical records through the ZoomEye history api interface

    Let's look at the time interval for tiny1detvghrt.tmp deployment : from at least '2017-11-21 19:09:14' to '2018-05-20 00:55:48'

    Let's look at the time node before tiny1detvghrt.tmp deployment: 2017-10-04 05:17:38

    From the file naming method and file size, it can be inferred that this time node, the attacker should be a drill before the attack.

    Final summary

    The cyberspace search engine is very useful in the tracking of cyberattack threats by using active detection methods. It rechecks the attacker's attack methods, purposes, and processes through the timeline of historical records. Finally, I would like to thank all the friends who support ZoomEye. As the world's leading search engine for cyberspace mapping, ZoomEye has been working hard!


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1220/

    作者:江 | Categories:技术分享 | Tags: