路由器研究

admin 2022年5月12日09:09:50评论4 views字数 2552阅读8分30秒阅读模式

描述

之前以为对路由器进行研究,需要先买一个路由器。之后对路由器的固件进行了解之后,才知道直接从官网下载对应的固件文件,然后用Linux系统即可搭建环境。

准备

待研究的路由器一个带有binwalk命令的系统。去想研究的路由器官网下载带有漏洞的历史固件:

路由器研究

源码获

binwalk -Me filename.bin

路由器研究

源码在squashfs-root目录下,打包,然后拖到本机tar -cvf squashfs-root.tar squashfs-root,其实,这就是一个小型的Linux系统。

路由器研究

目录结构

前端

lua写的路由器主要分两块,一块是web前端代码,在/www/目录下边。

路由器研究

前端文件访问均不需要权限,主要包括js、css、json和图片等文件。可以翻翻js文件、json文件,可能会包含当前路由器的固件和硬件版本信息,针对性的分析。

后端

另一块是后端逻辑代码,在usrliblualuci下面。

路由器研究

后端代码主要通过控制器来访问,控制器文件放在usrliblualucicontroller目录下,admin内的都是需要管理员权限才能访问的功能,其他文件不需要权限即可访问。

url和文件对应关系

stok=后面对应的值,对应usrliblualucicontroller下面相应位置的lua文件。比如路径:/cgi-bin/luci/;stok=/locale?form=lang对应usrliblualucicontrollerlocale.lua文件。

分析思路

全局搜索危险函数

相对于路由器,主要关注权限控制、命令执行、文件操作、XSS等漏洞。危险函数有如下,其他更多的自己探索。

popen()
exec()
open()
` `
execute()

拿popen来举例

路由器研究

可以看到,找到很多。不过也是有选择的分析,后边参数写死的就不用看了。选择第一个深入分析。没有对e参数进行过滤,但是也没有e参数的来源,还需要进一步跟踪。

function exec(e)  
   local e = r.popen(e)  
   local n = e:read("*a")  
   e:close()  
   return n  
end

继续跟进,全局搜索exec的调用。注意这里的exec不是原生库的exec函数。而是sys文件内的exec,后面可能的调用s.exec

路由器研究

这个命令执行的命令行拼接了变量a,跟进aa的值来自n.file_namen在第六行被重新赋值。

function unknown_ap_list_get()  
   local e = {}  
   local a  
   local _  
   local e = {}  
   local n, l = n.jcsUI2uac("unsupport_ap_get", n.JCS_OP_TYPE_GET, true, {})  
   if n == nil or n.ret ~= 0 or n.file_name == nil or n.unrecognize_ap == nil then  
return t.ENONE, e, #e  
   else  
a = n.file_name  
   end  
local l, o = io.open(a, "r")  
   if l == nil then  
r(o)  
       return t.ENONE, e, #e  
   else  
_ = l:read("*a")  
       l:close()  
   end  
e = i.decode(_)  
   if n.unrecognize_ap > 0 then  
local n = {}  
       n.model_name = "unknown"  
n.hardware_ver = "unknown"  
e[#e + 1] = n  
   end  
e = s.format_tbl_arry_with_secname_cnt(e, "unknown_ap_list")  
   luci.sys.exec("rm -f " .. a)  
   return t.ENONE, e, #e  
end

跟进函数jcsUI2uac

function jcsUI2uac(c, n, e, a)  
   return t(c, n, e, a, '/tmp/jcs.ui.srv.uac')  
end

继续跟进函数t,大致意思就是读取一个pid文件,最后返回文件内容和消息文件内容不可控这条路算是断了下面分析其他地方。

local function t(_, t, f, p, u)  
   local a = u .. i.getpid() .. '.luaclt'  
local n = i.open(a)  

·······

d, e = i.rcve(n, 180)  

······

s = o.decode(d)  
       if not s then  
e = c .. 'Decode pkt failed'  
end  
end r(n, a)  
   return s, e  
end

另一个sys.exec的调用

if N == true then  
l = "ping -c 1 -W %d -s %d %q 2>&1" % { e, i, t }  
   n = luci.sys.exec(l)  
else  
l = "ping -I %s -c 1 -W %d -s %d %q 2>&1" % { h, e, i, t }  
   n = luci.sys.exec(l)  
end

可以看到变量ht直接拼接进命令行,跟进变量tt从参数C传入。

local function V(c)  
   local t = c.addr or ""  
local r = c.num or ""  
local i = c.size or ""  
local e = c.timeout or ""  
local h = c.interface or ""

跟进V()调用,当diag_type为ping时,调用V()

function start_diagnose(e)  
   local o = e.diag_type  
   local n  
   if o == "ping" then  
n = V(e)  
   elseif o == "tracert" then  
n = u(e)  
   else

继续跟进start_diagnose(e)调用,下面就是构造请求了。

register_keyword_action("diagnose", "start", "start_diagnose")

总结

当然,也可能会存在一些逻辑漏洞,比如绕过登陆限制,直接获取管理员权限。或者登陆模块比较脆弱,比如没有二次验证,密码未加密,密码简单等等。

原文始发于微信公众号(云智信安云窟实验室):路由器研究

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月12日09:09:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   路由器研究https://cn-sec.com/archives/1000487.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息