一个影响三星Note 3、Galaxy S6手机的Bug——内核区域的URL过滤会出现什么问题?
作者:Roberto Paleari ( @rpaleari ) 和 Aristide Fattori ( @joystick )
ID: CVE-2016-2036
通知日期:20/10/2015
发布日期:20/01/2016
在研究三星的安卓内核时,我们歪打正着找到了一个名为secfilter的模块。这个模块的initialization程序吸引了我们的注意力,因为一些Netfilter hook在这里模块里被注册了。
... static struct nf_queue_handler sec_url_queue_handler = { .name = SEC_MODULE_NAME, .outfn = sec_url_filter_slow }; static struct nf_hook_ops sec_url_filter = { .hook = sec_url_filter_hook, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FIRST }; static struct nf_hook_ops sec_url_recv_filter = { .hook = sec_url_filter_recv_hook, .pf = PF_INET, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FIRST }; ... if ((add_send_hook =nf_register_hook( &sec_url_filter)) <0) break; if (nf_register_hook( &sec_url_recv_filter) <0) break; ... nf_register_queue_handler(PF_INET, &sec_url_queue_handler); ...
这些hook被配置成了拦截所有进入的(NF_INET_LOCAL_IN) 和所有传出的(NF_INET_LOCAL_OUT)包。被拦截后,匹配特定条件的输出的TCP包最终到达一个名为getURL()的内部函数,这个函数会检查TCP数据是否类似于一个HTTP请求,并解析包含的URL。
为什么三星手机会把URL参数传入Android内核呢?这是来自用户空间应用的程序访问机制的一部分。可能的利用应用包括家长控制应用,这类应用需要实现系统级的URL过滤。
它是如何工作的?
Netfilter hook总是存在的,但是URL过滤机制只在适当的ioctl()请求传给用户空间设备/dev/url/之后才启用。在我们的测试机中,该设备是secnetfilter组的访问成员:
shell@hlte:/ $ ls -l /dev/url crw-rw---- secnetfilter secnetfilter 226, 0 2014-01-04 19:36 url
反过来,访问secnetfilter组的权限通过com.sec.andtroid.SAMSUNG_GET_URL许可被授予给应用,同时创建保护级签名。一个拥有这个权限的app可以配置设备使其能够使用不同的监控模式:
FILTER_MODE_ON_BLOCK: 标准阻塞模式,检查URL的outgoing数据包最终被阻塞。 FILTER_MODE_ON_RESPONSE: 代替阻塞模式,从传出数据包中提取URL,但是回应会被阻塞并以一个自定义的HTTP/404代替。 FILTER_MODE_ON_BLOCK_REFER: 和FILTER_MODE_ON_BLOCK 相同,但是检查Referer头而不是请求的URL。 FILTER_MODE_ON_RESPONSE_REFER: 和 FILTER_MODE_ON_RESPONSE 相同,但是检查Referer头而不是请求URL。
如果实行任何阻塞模式,每个访问的URL会都会被放入队列然后被阻塞直到app停止阻塞它。
一个想要使用RUL过滤功能的app应该实现以下逻辑:
第一,app能够使用某个阻塞模式,例如通过写入以下二进制数据到/dev/rul:
<2-byte ver (0x00)><4-byte SET_FILTER_MODE cmd (0x01)><4 byte mode>
然后,app在/dev/url轮询直到一些数据可读。读取数据的格式如下:
<4-byte header><4-byte blocked URL ID><4 irrelevant bytes><4-byte URL length><n-byte URL>
最后,app检查URL,根据一些特定的应用逻辑做出决定,把决定告诉驱动,在/dev/url中写入下面的字节:
<2-byte ver (0x00)><4-byte SET_USER_SELECT cmd (0x01)><4-byte URL ID><4-byte choice (0x64 for block, 0xx65 for allow)>
内核模块通过直接引用从缓存中读取整数(如,filterMode = *(int *)data),因此数据必须是little-endian格式。当内核模块接收一个SET_USER_SELECT命令,他检查是否接收对应阻塞请求的ID(如,对应一个阻塞TCP流)并根据app决定作用于他。
我们目前只确定了一个名为 com.symantec.familysatety 应用程序,它使用了此权限,因此所有的URL过滤机制可能不是很广泛,或者么能它仍然处于开发的早期。
安全隐患
如前面所述,只有三星app store中的某些应用才能够获得SAMSUNG_GET_URL权限,这个模块应该引起广大三星用户的关注。他披上了"保护儿童"的外衣,但是它仍然是一个允许"授权"应用监控所有访问的URL。
总之,除了道德和隐私方面,仅仅从科技角度,这个模块都是相当令人担心的。确实,在URL过滤机制机制已经被"授权"app启动后,任何用户空间应用都可以在HTTP解析代码中触发一个空指针引用,然后导致系统崩溃。
触发这个bug非常简单,只要使用没有URL的HTTP请求就可以了,比如:
GET HTTP/1.1 Host: www.google.com
这样一个请求的实际目的并不相关,因为当URL过滤可以实行时,所有的outgoing HTTP流量都需要被检查。
从科技角度讲,三星通过他的 开源发布中心 开源了他们的Android内核代码。对于前面提到的空指针引用,有漏洞的代码就在drivers/secfilter/urlparser.c,函数getURL()。概括的说,该模块通过以下调用提取HTTP请求路径:
findStringByTag(node, &(node->url), dataStart, " HTTP/");
dataStart是一个char string,在http请求方法token之后指向。但是,当findStringByTag()处理有害请求时会为HTTP路径找到一个长度为零的string,并且留下未初始化的node->url。几行之后,node->url被废弃并且此时还是空的。
受影响设备
我们确认这个问题影响以下设备型号。其他的型号和固件版本可能也会被影响,但是我们还没有进行测试。
SM-N9005, Build N9005XXUGBOB6 (Note 3)
SM-G920F, Build G920FXXU2COH2 (Galaxy S6)
*原文: GitHub ,FireFrank编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)