0x0 不安全的C函数
从事二进制漏洞的研究人员几乎都接触过strcpy和sprintf导致的缓冲区溢出漏洞,而在漏洞的修复建议中,都建议进行边界检查,同时使用strncpy和snprintf。snprintf的正确用法如下:
snprintf(dst,sizeof(dst),"%s",src);
在正确使用strncpy和snprintf的前提下,肯定是没有问题的,不过笔者也见过如下使用snprintf的开发人员:
snprintf(dst, strlen(src), "%s", src);
当然,这种完全属于使用不当的低级错误不值得讨论。笔者在研究路由器固件的过程中,意外的发现了一个漏洞,是在正确使用snprintf的情况下,由于代码整体的逻辑不够严谨,从而导致了权限绕过。在这里展示出来与大家分享一下这个有趣的漏洞。
0x1 路由器web权限控制
近几年,各种路由器漏洞层出不穷,除了常见的是命令注入和缓冲区溢出漏洞,还有一类路由器漏洞就是权限绕过。一般的权限绕过分如下几种:
(1) 厂商留有隐藏的调试或者维护接口;
(2) 通过漏洞能够获取用户名+密码;
(3) 通过特殊构造的数据包可以无需用户名和密码实现任意请求。
在网上搜索一下,以上三种情况都有不少的案例,本文讨论的漏洞为第(3)种情况。为了能更好的理解,这里先简单介绍下路由器web方面的权限控制。
通常来看,大多数路由器的权限设定将htm/asp/php等页面需要登录才能访问,而css/js/png等资源是无需登录即可访问的。之后的逻辑通过sprintf函数将uri格式化到”/www/%s”或者”/web/%s”来生成路径,之后再访问对应的资源生成response。简单的示意图(省略了无关逻辑)如下:
熟悉漏洞的读者很容易发现,如果没有额外的校验,这里的sprintf很可能存在超长URI导致的缓冲区溢出漏洞。从安全的角度讲,应当将sprintf更换成snprintf,正确的使用snprintf即可避免此类缓冲区溢出漏洞。
0x2 正确使用snprintf就一定安全吗?
使用snprintf之后的逻辑如下图:
可以看到,根据栈空间的大小,snprintf的第二个参数可以手工设置为小于栈空间的值,这样无论如何也不会造成缓冲区溢出漏洞。snprintf对于超过设定长度的字符串后续部分,是采用了丢弃的处理,以0x50为例,如果源字符串超过0x50,那么会在0x4F的位置截断。聪明的读者或许已经发现,如果构造如/AAAAA......AAAAuser.htm.js使得.js落在了截断位置,那么就可以实现无需登录访问AAAAA......AAAAuser.htm文件了。
等等,即便能绕过登陆访问htm后缀的文件,但是AAAAA......AAAAuser.htm并不存在,又有何用。这里有个小技巧,将A换成/试试,linux系统对于多个连续的/是会忽略的。
0x3 实战NetGear R7000路由器
存在漏洞的"NETGEAR R7000"路由器固件版本为V1.0.7.12_1.2.5(其他低版本未验证,最新版本已经修复)。Shodan上搜索"NETGEAR R7000",通过访问https://ip/ currentsetting.htm页面可看到固件版本。此页面为少数几个不用登陆即可访问的htm页面,其他功能性的页面都需要登录才能访问。以Adv_USB.htm为例:
可以看到返回包为401,需要登录。通过上一节的分析,精确控制/的数量,使得恰好从.js截断后的请求如下:
完美绕过!!!
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法