首页
社区
课程
招聘
[原创]QQFuzzy可行性尝试二--被忽略的漏洞总结
发表于: 2018-4-13 15:46 6051

[原创]QQFuzzy可行性尝试二--被忽略的漏洞总结

2018-4-13 15:46
6051

0x00

第一篇地址: https://bbs.pediy.com/thread-225630.htm
首先,感谢看雪,感谢上文 @dalao 兄的邀请,以及其他几位兄弟的捧场。
然后,特别感谢 milo兄关于QQ的指点,及这篇的审校。

 

最后,如第一篇所言,随手报了3个,均被忽略,赞tx!

 

刚开始专攻Exploit,对漏洞的评估有不足,感谢TSRC的 qwerty 的回复。

 

这里做个总结,希望各位老司机多多批评指正。

0x01

目前的代码主要组成是从Android QQ来的,版本7.2.0。

0x02 报告总结

  • 漏洞一: YY的DOS攻击
    不到20分钟就给我忽略了,20分钟就忽略了,忽略,了,,,我这算是审核最快的报告吗???
    大兄弟!老心!扎铁了!!!我仿佛看到了红旗在飘你们内心在奸笑!!!/[手动愤怒]
    milo兄给我发了这篇(http://www.qcloud.com/blog/?p=1457),于是我又看了看其他文章,这一个就不多说了。
    尽管我仍然认为是可实施的。

  • 漏洞二:反序列化对畸形数据包检测不足 (针对server,没实质危害)
    这个在提交TSRC之前,纯属猜测服务端在反序列化时会触发,由于担心server是C的怕造成crash没测就提了。
    被忽略之后,便使用获取好友功能测试了下,会返回脏数据,可能完全没有数据格式(即客户端无法解析,由于我是1:1还原的,所以判断这里可能就是返回了乱码)。

    之后milo兄告诉我了tars ( https://github.com/Tencent/Tars ),读了下源码,如果QQ Server使用的版本和GitHub上的版本是一样的,那可以确认问题是存在的。

    原理:
    客户端发送逻辑:

    socket sockQQ; // QQ 的 tcp 连接
    CBizObject objExample ; // 最终业务功能的对象  比如获取好友列表,
    uchar *szOriData = JceSerial(objExample); // 使用 jce 将对象序列化为字节流   在这里将序列化的数据处理成畸形的
    uchar *szSendData = encodeRequest(szoriData); // 将序列化的数据加密   
    send(sockQQ, szSendData, len(szSendData)); // tcp send 数据
    

    服务端接收逻辑:

    socket sockQQ; // QQ 的 tcp 连接
    uchar *szBuf ; // 用来接收数据的缓冲区
    recv(sockQQ, szBuf, MAX_BUFFER_LEN, 0); // 按协议头部的长度接收该长度的数据
    uchar *szDecode = decodeRequest(szBuf); // 解密接收的数据
    CBizObject objExample ; // 将要反序列化为的业务对象
    objExample = JceDeserial(szDecode); // 畸形数据包将在这里触发异常
    

    序列化函数的类: https://github.com/Tencent/Tars/blob/master/java/core/src/main/java/com/qq/tars/protocol/tars/TarsOutputStream.java

    反序列化的类: https://github.com/Tencent/Tars/blob/master/java/core/src/main/java/com/qq/tars/protocol/tars/TarsInputStream.java

    在Android版本中分别对应 JceOutputStream 和 JceInputStream.

    举个例子:大家看 JceInputStream 的 readHead

    public static int readHead(HeadData hd, ByteBuffer bb) {
          byte b = bb.get();  // 比如构造的数据在该执行这里的时候就已经到尾部,那一定会抛异常
          hd.type = (byte) (b & 15);
          hd.tag = ((b & (15 << 4)) >> 4);
          if (hd.tag == 15) {
              hd.tag = (bb.get() & 0x00ff);
              return 2;
          }
          return 1;
      }
    

    构造畸形数据包的方式很多,最简单的方式可能是直接修改 JceOutputStream 来生成。

    剩下的就是攻击思路的问题,比如构造格式正常但逻辑却异常的数据包过掉Server,使数据可以到达好友客户端。
    比如根据序列化原理,构造个可以被放大的包(打个比方原始数据占100字节内存,反序列化后占10000字节内存,反正意思就是这个意思),再配合第一个YY的DOS攻击。

    使server异常的攻击都没有什么实质危害,但畸形数据到客户端就难说了。

    .

  • 漏洞三:QQ钱包支付密码猜解 (这个我觉得是有点风险的)

    原理

    QQ钱包支付是使用https,证书校验方式只是 https://zhuanlan.zhihu.com/p/22426761 中描述部分,强度应该还需要加强。
    我的话不够权威,来个比较权威的,省去大家的质疑时间: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

    在这里我再补充下我的理解,不了解HTTPS原理的兄弟先去熟悉下HTTPS,这里就不占用篇幅了。

    然后我们思考个问题: 纯净的Android手机 HTTPS 一定是安全的吗?对,纯净的。
    一定吗?
    一定吗??
    一定吗???

    我认为不一定。

    现在我们来回想一下,HTTPS之所以大家都在说足够安全的前提是什么?
    前提就两条:1,可信的证书链    2,足够强的算法和密钥

    算法肯定够强啊,秘钥也肯定够啊,1024都是最低标配了吧,所以第二条是可以保证的。

    可是,可信的证书链能保证吗?怎么保证的呢?
    这一点,在Android里,要分2个角度说,一个是系统层面,一个是webview层面。

    首先说webview。
    在Android里,不论是Webview组件apk,还是Chrome,包括火狐等浏览器,都是把根证书与apk打包在一起的。
    比如Webview组件apk,大家可以把这个apk(包名:com.google.android.webview)拖出来,解压,找最大的那个so文件,ida打开,翻一翻就可以找到一堆的证书了。
    比如PC版的chrome,证书是放在一个dll里的。
    也就是说,webview、浏览器这种,保证证书链可信的方式是:升级。不升级就无法保证。

    然后说系统。
    系统的证书是放在了 /system/etc/security/cacerts/,我记得这个路径好像是写死的,大家去翻翻Android 源码,我上一次看得时候记得有一处是写死的这个路径,另外一处还是几处是拼接的,但结果是一样的,有时间的同学可以去确认下。
    所以,系统是怎么保证证书可信的呢?对的,也是升级。
    比如小米手机是升级补丁的时候会升掉,这一点还不错。
    我算是华为的半个粉丝了,可是我可以说MATE1我首发时购买,直到用了5年扔掉,一次升级提示都没有过吗....

    所以说,如果手机没升级、webview没升级,证书链就不一定可信,证书链不可信,那HTTPS就保证不了安全性。
    那有实例吗?有的,很多,随便搜几个:
    https://www.wired.com/2011/03/comodo-compromise/
    https://docs.microsoft.com/zh-cn/security-updates/SecurityAdvisories/2011/2607712
    http://www.williamlong.info/archives/3690.html
    https://blog.mozilla.org/security/2015/03/23/revoking-trust-in-one-cnnic-intermediate-certificate/

    说到这里,我们也就明白了,若要HTTPS请求安全,除了降级攻击这种常规防御之外,还要保证证书链可信。

    HTTPS有不可信的可能了,就打开了攻击中最重的那个大门。

    支付密码猜解

    第一步完成之后,我们看下如何猜解支付密码。业务功能是发红包。

    原理:

    完整的支付过程包含7个https请求,在请求的过程中使用的加密算法有2种,一层是DES,一层是RSA。
    其中,Des的KeyTable中一共包含16个key,每次发起请求时生成0-15之间的随机数(DesKeyIndex),根据此随机数选择将要使用的key。
    RSA加密使用的公钥是固定的,但也包含类似des的机制(RsaKeyIndex),随机数是0-13。

    HTTPS请求中的加密的数据,首先会用RSA进行加密,之后再使用DES进行二次加密。
    HTTPS返回的结果使用DES解密,解密的des key与请求时加密的des key一致。

    在每个https请求中,加密的数据是放在 req_text 字段中。

    公式:

    origin_req_text = RSA(iRandomRsaKeyIndex, password)
    req_text = DES_Encode(iRandomDesKeyIndex,  origin_req_text)
    

    由于 req_text 抓包时可直接获取,Des 的 KeyTable 已知,故使用Des解密函数将所有的Des Key遍历一遍解密req_text,解密不乱码的就是 origin_req_text ,懒得动脑可采用这个方式。

    origin_req_text 解密后,就可看到其包含的p字段和 timestamp 字段,p字段中包含密码信息。
    p的公式:

    p = RSA(rsaKeyIndex + lrand48盐 + timestamp + 密码md5)
    

    由于 lrand48 生成的是伪随机数,且没有设置种子(srand48),故lrand48盐可预测。

    同时由于p已知,RSA公钥已知,timestamp 已知,rsaKeyIndex范围是0-13,密码是6位纯数字,故遍历000000-999999密码即可。

    伪码

    for (int iPwd = 0; iPwd < 999999; iPwd++){ // 密码遍历 0-999999
       string strPwd = ConvertPwd2Str(iPwd); // 转为6位字符串 比如 1->000001
       vector<long int> vecRand48; // 预测的随机数表
       for (int iRand48Index = 0; iRand48Index < vecRand48.size(); iRand48Index){ // 遍历随机数表
         for (int rsaKeyIndex = 0; rsaKeyIndex < 13; rsaKeyIndex ++){ // 遍历 RsaKeyIndex
           if (RSA(rsaKeyIndex, vecRand48[iRand48Index], timestamp , MD5(strPwd)) == p){
              // 对比计算出来的值和p,如果相等,猜解成功
          }
      }      
    }
    

    由于QQ进程常驻,假如1年没有重启过,而绝大多数人不会没完没了的发红包,假设每天发1000个红包,那预测的随机数 365*1000*128 = 46720000. 应该可以覆盖大部分用户了吧?
    由此来看,即便全部跑一遍运算量也不太大,而如果配合最常用密码可能大幅降低运算量。

    验证

    首先看请求,抓个包,我们看看链接的样子:

    截图的第一个部分是原始请求,密码在req_text字段中。
    第二个部分是req_text解密后的内容,密码在p字段中,同时我们可以看到timestamp字段,也就是得到了time盐。
    p字段的还原代码:

    加密函数在: libcftutils_v1.2.5.so 中, 函数是: encrypt_pass

    倒数第三行的 Encrypt 是RSA加密函数,第一个参数是rsaKeyIndex,固定值0,固定值0,固定值0.....公钥一共13个,只使用第0个.....

    至此可知:在加密公式中的rsaKeyIndex,最悲观的情况下也就是 13个值,具体到字节上,占一个字节

    srand48查找所有引用,会发现所有的调用的地方都是在出现异常的时候才会触发。

    lrand48可预测性,在这里,按我的理解,未设置种子的情况下,只要攻击方生成的队列够长,就能找到一样的,我测试了多台MacBook、Android手机,随机数序列都是一样的。

    我的烂电脑实测运算10000次生成p字段内容13秒。

    谢谢大家

    广告:有安全团队缺打杂的不? UVE6IDE1NDY5MTExMjE= 字体无法再小了...

[课程]FART 脱壳王!加量不加价!FART作者讲授!

最后于 2018-4-13 15:57 被eightmg编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 18
活跃值: (561)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
看了下,个人觉得忽略的没毛病,都不是安全问题。
2018-4-13 15:52
0
雪    币: 343
活跃值: (1056)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
ele7enxxh 看了下,个人觉得忽略的没毛病,都不是安全问题。
学习中
2018-4-13 15:58
0
游客
登录 | 注册 方可回帖
返回
//