漏洞简介
· OpenWrt LuCI是一款用于OpenWrt(Linux发行版)的图形化配置界面。
· OpenWrt LuCI 0.10及之前版本中的admin/status/realtime/bandwidth_status和admin/status/realtime/wireless_status端点存在命令注入漏洞。该漏洞源于外部输入数据构造可执行命令过程中,网络系统或产品未正确过滤其中的特殊元素。攻击者可利用该漏洞执行非法命令。
环境搭建
· 由于OpenWrt中自带LuCI,只需要使用虚拟机正常运行OpenWrt即可,在这里使用VMware运行OpenWrt虚拟机。
· OpenWrt版本:Chaos Calmer OpenWrt 15.05.1
· 下载地址:https://archive.openwrt.org/chaos_calmer/15.05.1/x86/generic/openwrt-15.05.1-x86-generic-combined-ext4.img.gz
安装成功后成功访问LuCI主页:
设置登陆密码后成功登陆:
为了直接分析LuCI源码,在虚拟机中找到LuCI的地址并使用tar打包:
由于openwrt中没有文件下载工具,而LuCI已经把目录映射了,直接将打包文件移动至http映射目录下,走http下载LuCI源码:
POC
传入Payload: http://192.168.153.4/cgi-bin/luci/admin/status/realtime/bandwidth_status/eth0$(id>cmd):
成功执行命令:
漏洞分析
· LuCI采用了典型的MVC三层架构,并使用Lua脚本开发;在解析请求时,首先进入admin/status.lua中的controller入口进行路由,然后调用相应的model进行处理。
而漏洞的触发点是在controller的bandwidth_status函数中,该函数将用户传入的字符串直接格式化到命令中并执行,造成了RCE。
· 代码具体执行过程如下: 使用HTTP访问路径/admin/status/realtime/bandwidth_status(或wireless_status)/[param],首先进入index entry进行路由,在路由中使用dispatcher的call函数调用了action_bandwidth函数: Controller/index.lua:
dispatcher.lua中的call函数:
然后,进入action_bandwidth函数,url解析路由之后的部分将被当做参数传入,未过滤而使用%q直接将参数格式化到字符串中。%q将在iface外包裹双引号。
使用io.popen执行命令,在bash下,双引号中的$()或“会执行,从而达到命令执行的目的:
此处相当于执行命令:sh -c luci-bwc –i “eth0$(id>cmd)” 2>/dev/null:
使用EXP执行ping命令后,可以在openwrt下查看到执行的命令:
exp脚本
脚本已上传:https://github.com/HACHp1/LuCI_RCE_exp 执行效果:
斜杠绕过
在执行的命令中需要斜杠(/)时,由于路径解析的问题,斜杠无法使用,此时可以考虑使用bash内置变量来代替。
遇到的坑
· 最开始的时候考虑使用${HOME:0:1}来替代。然后发现并不能成功。但是直接在命令行中、重新开一个lua脚本执行、直接在lua交互处执行却都可以执行。
· 最后发现问题竟然是在LuCI中$HOME变量没有值,但是在正常情况是有值的,在此处卡的时间很长。
解决办法
在LuCI中,${PATH:0:1}是没有被更改的,可以直接使用。测试payload为:ls ${PATH:0:1}。
漏洞修复方案分析
查看源码修复漏洞的地方,新的源码使用gsub将iface中的单引号去掉,并在最外层加上了单引号,这样整个iface参数就仅作为字符串而不会被执行:
在源码中输出一下:
Iface参数被单引号包裹,作为r参数传入luci-bwc,不会执行ls命令:
写在最后
· 整个漏洞与半年前爆出的thinkphp RCE都与路由解析和controller相关,可见MVC构建的controller处比较容易出现安全漏洞。由于MVC模型的特性,Controller是MVC模式函数调用的入口,如果攻击者能够控制controller或者能够注入并利用controller,就容易出现漏洞。
参考资料
· https://www.jianshu.com/p/bfb93c4e8dc9
· https://forum.openwrt.org/t/vulnerable-releases-for-cve-2019-12272/38564
· https://blog.csdn.net/ballack_linux/article/details/81331527
· https://github.com/openwrt/luci/commit/9e4b8a91384562e3baee724a52b72e30b1aa006d