你可能已经听说过,Whatsapp在他们的客户端发现了一个安全问题,这个问题在wild被积极利用。该漏洞利用不需要目标接听电话,这真的很可怕。
WhatsApp VOIP堆栈中的缓冲区溢出漏洞允许通过发送到目标电话号码的特制SRTCP数据包远程执行代码。
这个细节不多,调查可能仍在进行。我非常希望听到报告WhatsApp如何检测到滥用行为。
我们知道SRTCP存在问题,SRTCP是用于媒体传输的控制协议。这可能意味着两点:
- 解密RTCP数据包是一个问题,即在SRTCP层。
- RTCP解析器中存在一个问题。
SRTCP非常简单,因此RTCP解析器中的错误更可能发生。正如我去年所说,我很惊讶Natalie Silvanovichs fuzzer在webrtc.org RTCP解析器中没有发现任何问题。
实际上,我们掌握了一些二进制差异检验点研究提供的事实,他们分析了修订版的不同之处。
他们发现了两件有趣的事:
- 在RTCP模块中有一个额外的大小检查,确保少于1480字节。
- 在呼叫应答之前处理RTCP
让我们谈谈RTCP
RTCP是实时控制协议,是RFC 3550中描述的一种相当复杂的协议。它提供有关RTP媒体流如何执行的反馈,例如丢包。 UDP数据报可以将多个单独的RTCP数据包复用到所谓的复合数据包中。当使用SRTCP加密RTCP复合数据包时,所有数据包都与一个通常为12个字节的身份验证标记一起加密。
为了使多路分解复合分组成为可能,每个单独的RTCP分组在16比特字段中指定其长度。例如,发件人报告数据包就像这样开始:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ header |V=2|P| RC | PT=SR=200 | length |
长度字段定义为:
长度:16位
这个RTCP数据包的长度以32位字减去1, 包括标题和任何填充。 (一个偏移使 零成为有效长度并避免扫描复合RTCP数据包时有可能发生的无限循环,同时计算32位字避免对4的倍数进行有效性检查。)
这是……相当复杂。特别是这个定义意味着RTCP解析器必须根据数据报的长度和数据包中的剩余字节来验证长度字段。某些RTCP数据包甚至还有其他内部长度字段。
对于复合数据包中的第一个数据包,长度验证通常由实现SRTCP的库(如libSRTP)完成。请注意,WhatsApp可能会使用PJSIP和PJMEDIA,至少在2015年我见到他们使用。
第二个数据包的长度检查需要由RTCP库完成。并且仍然有点不清楚长度字段是否针对剩余字节进行了验证。尽管如此,1480似乎是一个非常奇怪的数字。起初我认为这是有道理的,因为它是1492减去SRTCP标签的12个字节,但UDP的最大有效载荷大小为1472字节,而不是1492.所以现在我最终再次感到困惑……
不要处理来自陌生人的数据
这里还有另一个问题。正如“纽约时报”的一篇文章所说,受害者似乎接到了电话,但他们从未回答过。断点分析确认了在修订版本中(仍然)触发了RTCP代码。这并不好,至少使攻击更容易。
自2015年来,WhatsApp已经花了相当多的时间来优化呼叫建立时间。在用户接听实际呼叫之前建立媒体连接是理论上优化事物的好方法。这种想法并不是全新的,即使像XMPP这样的标准,Jingle建议不要在没有某种信任关系的情况下使用它:
响应客户端不应该向发起者返回“会话接受”操作,直到响应者明确同意继续进行会话(除非发起者位于其会话被自动接受的实体列表上)。
即使在隐私方面,这也很难做到,因为必须至少避免暴露IP地址。 WhatsApp可能通过他们的中继优先方法来确保这一点。
总结
RTCP处理中的这种错误本身就很糟糕。在接受呼叫之前同时处理数据,这变得更加糟糕并且被积极利用。端到端的模糊测试(甚至像前面提到的像Fred这样的简单模糊器)可能都已经发现了问题。当前的补丁看起来像一个修补程序,我希望代码进一步改变。
不处理不在联系人列表中的人的媒体是我期望的另一个改变,并且使用wireshark很容易观察到。
Tim Panton发现了正确的话:
我对编写WhatsApp bug的程序员深表同情。 RTCP / DTLS是一种可怕的协议。我盯着RFC看了几天,弄清楚如何获得加密的有效载荷长度。
原文标题:The WhatsApp RTCP exploit – what might have happened?
作者:“Philipp Hancke“