起因
和丁佬他们一起整了个小队去打了强网杯,然后就玩到了线下,有实物的rw赛制还是好玩
题目
赛题都放一个u盘里,然后还有个路由器的实体,有个说明文档,大致就是介绍题目的内容和上台演示的成功条件,由于比较菜,搞不来v8和VMware,就来搞这台路由器了
演示环境是不给后台密码的,所以我们需要挖的是一个远程利用的未授权RCE,这里拿到的路由器开了ssh,连上去可以知道这是小米路由器pro,然后把实机的固件dump下来确定版本后,去官网下原始固件来diff下看看是不是出题人塞东西或改的洞。
GoAhead漏洞分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| diff --git a/etc/mihttpd/mihttpd.conf b/etc/mihttpd/mihttpd.conf index 9fbe742..89d058f 100644 --- a/etc/mihttpd/mihttpd.conf +++ b/etc/mihttpd/mihttpd.conf @@ -153,13 +153,13 @@ http { upload_pass_form_field "^(?!nginx_file)"; upload_pass_args on; } - location /api-third-party/download/public { + location /api-third-party/download/public/ { alias /userdisk/data/; } - location /api-third-party/download/private { + location /api-third-party/download/private/ { alias /userdisk/appdata/; } - location /api-third-party/download/extdisks { + location /api-third-party/download/extdisks/ { alias /extdisks/; } diff --git a/etc/sysapihttpd/sysapihttpd.conf b/etc/sysapihttpd/sysapihttpd.conf index ab90d6c..16bf88c 100644 --- a/etc/sysapihttpd/sysapihttpd.conf +++ b/etc/sysapihttpd/sysapihttpd.conf @@ -129,19 +129,19 @@ http { proxy_pass http://127.0.0.1:5081; } - location /backup/log { + location /backup/log/ { alias /tmp/syslogbackup/; } location /api/service/plugin { rewrite ^/api/service/plugin/control /api-third-party/download/private/$arg_appid/control.html? permanent; } - location /api-third-party/download/public { + location /api-third-party/download/public/ { alias /userdisk/data/; } - location /api-third-party/download/private { + location /api-third-party/download/private/ { alias /userdisk/appdata/; } - location /api-third-party/download/extdisks { + location /api-third-party/download/extdisks/ { alias /extdisks/; } location /api-third-party/service { diff --git a/usr/lib/lua/traffic.lua b/usr/lib/lua/traffic.lua index 8bf1ad7..5c2569a 100644 --- a/usr/lib/lua/traffic.lua +++ b/usr/lib/lua/traffic.lua @@ -8,7 +8,7 @@ local dbDict local dhcpDict function cmdfmt(str) - return str:gsub("\\", "\\\\"):gsub("`", "\\`"):gsub("\"", "\\\""):gsub("%$", "\\$") + return str:gsub("\\", "\\\\"):gsub("`", "\\`"):gsub("\"", "\\\"") end function get_hostname_init() diff --git a/usr/lib/lua/xiaoqiang/module/XQBackup.lua b/usr/lib/lua/xiaoqiang/module/XQBackup.lua index 9330fb2..e8e3b2c 100644 --- a/usr/lib/lua/xiaoqiang/module/XQBackup.lua +++ b/usr/lib/lua/xiaoqiang/module/XQBackup.lua @@ -1,7 +1,7 @@ module ("xiaoqiang.module.XQBackup", package.seeall) -local DESFILE = "/tmp/cfg_backup.des" -local MBUFILE = "/tmp/cfg_backup.mbu" +local DESFILE = "/tmp/extmp/cfg_backup.des" +local MBUFILE = "/tmp/extmp/cfg_backup.mbu" local TARMBUFILE = "/tmp/cfgbackup.tar.gz" -- backup functions @@ -210,9 +210,10 @@ function save_info(keys, info) local dstr = json.encode(keys) local data = aes.encrypt(key, jstr) local filename = os.date("%Y-%m-%d--%X",os.time())..".tar.gz" + os.execute("mkdir -p /tmp/extmp >/dev/null 2>/dev/null") fs.writefile(MBUFILE, data) fs.writefile(DESFILE, dstr) - os.execute("cd /tmp; tar -czf "..backuppath..filename.." cfg_backup.des cfg_backup.mbu >/dev/null 2>/dev/null") + os.execute("cd /tmp/extmp; tar -czf "..backuppath..filename.." cfg_backup.des cfg_backup.mbu >/dev/null 2>/dev/null") os.execute("rm "..MBUFILE.." >/dev/null 2>/dev/null") os.execute("rm "..DESFILE.." >/dev/null 2>/dev/null") local url = lanip.."/backup/log/"..filename @@ -267,7 +268,8 @@ function extract(filepath) if not fs.access(tarpath) then return 1 end - os.execute("cd /tmp; tar -xzf "..tarpath.." >/dev/null 2>/dev/null") + os.execute("mkdir -p /tmp/extmp >/dev/null 2>/dev/null") + os.execute("cd /tmp/extmp; tar -xzf "..tarpath.." >/dev/null 2>/dev/null") os.execute("rm "..tarpath.." >/dev/null 2>/dev/null") if not fs.access(DESFILE) then return 2
|
发现把路径穿越还有一些其他的洞修了,然后删去了cmdfmt函数里防止$命令执行的过滤,那么重点就应该是在这个地方了,看一下traffic里的相关逻辑,能发现在trafficd_lua_ecos_pair_verify
调用了cmdfmt
接着找一下哪有调用这个文件的这个函数的文件
1 2 3
| iot@toi ~/C/r/d/rootfs> grep -r "trafficd_lua_ecos_pair_verify" usr/lib/lua/traffic.lua:function trafficd_lua_ecos_pair_verify(repeater_token) 匹配到二进制文件 usr/sbin/netapi
|
那么该去逆一波netapi里trafficd_lua_ecos_pair_verify的逻辑了
简单的逆完再结合到路由器里其他使用netapi的脚本后可以知道这是小米魔改dbus的tbus的一个服务
然后根据路由器里的脚本我们可以得到命令行版命令注入的poc
1
| tbus call netapi init {"data":"$(touch /tmp/nepire)"}
|
但我们需要的是远程的命令执行,我感觉这个好像用不了,同步了下进度就去看其他有监听端口的进程了
后来有人提醒我,这个进程有网络通信,直接重放命令可以执行,于是我又回来审这流量了
直接重放流量,发现可以成功执行,但重启设备后发现不行
重新抓流量对比发现有8个字节的不同,并且两个疑似相同的key不过一个是大端一个小端,在查看前面的流量中发现在返回包里存在该key,并且请求包的内容是固定的,那么就直接两步获取了,先获取key然后构造命令执行的请求包,写入authorized_keys,这样就能getshell了
由于路由器的www目录不能直接改,所以用mount把利用成功页面挂上去,至此完成整个利用