首页
社区
课程
招聘
[原创]极路由远程命令执行漏洞-漏洞分析
发表于: 2025-10-27 12:25 2807

[原创]极路由远程命令执行漏洞-漏洞分析

2025-10-27 12:25
2807

本篇主要介绍cloud_token的计算方式和远程命令执行漏洞的代码分析。cloud_token是开启远程ssh的token,如果知道cloud_token就可以远程开启ssh服务。

按照上文的模拟环境运行方式,打开 3d8K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5c8X3I4G2j5$3q4D9i4K6u0V1M7%4y4Z5i4K6u0r3 连接。出现远程开启ssh服务的页面。

SSH页面

正常情况下local token的输入框显示的是路由器local token的值,因为是模拟环境,没有板载信息,所以显示的为空。这里提供一组历史数据:

uuid就是路由器的固件信息,每个路由器都不同,获取的路径是 7fdK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5c8X3y4Y4K9g2)9J5k6r3u0A6L8W2)9J5c8Y4c8#2M7X3u0G2i4K6u0r3M7s2u0G2P5s2W2Q4x3V1k6J5L8%4g2@1k6i4u0Q4y4h3k6A6L8X3k6G2

通过查看nginx的配置文件,可以找到local_ssh的解析路径为 /usr/lib/lua/luci/local_ssh/local_ssh.lua;

然后使用luadec对local_ssh.lua和local_ssh_util.lua进行反编译,luadec需要使用luadec-openwrt的版本。

可以使用luadec直接反编译,也可以使用luadec -dis 先转为lua的反汇编形式,再使用AI转为lua代码;

local_ssh.lua的反编译代码如下:

local_ssh_util.lua的反编译代码如下:

local_token的计算方式是:base64(mac_address,ssh,current_time,hmac_token),主要代码如下:

cloud_token的计算方式是: lua_hmac_sha1_with_uuid(mac_address,ssh,current_time+1),主要代码如下:

lua_hmac_sha1_with_uuid 的函数在libauth.so中,主要代码如下:

调用的hmac_sha1_with_uuid函数在libauth.so中,主要代码如下:

tw_get_uuid(v9)是获取固件信息的fac_uuid,也就是固件的uuid。在libtw.so.0.1.0中,代码如下:

然后调用SHA1对uuid进行哈希运算做为HMAC的密钥,HMAC使用的是sha1模式进行哈希运算。

根据以上的分析结果生成计算cloud_token的python代码如下:

远程命令执行的漏洞分析比较简单,漏洞代码就位于以上的local_ssh.lua中。漏洞代码如下:

在method=valid时,对于传来的data参数没有做任何的过滤就直接传进了exec_cmd进行了执行。

远程命令执行的POC代码如下: b48K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5c8X3I4G2j5$3q4D9i4K6u0V1M7%4y4Z5i4K6u0r3j5i4m8A6i4K6y4r3L8h3g2@1K9r3!0V1i4K6y4p5N6X3q4D9K9h3c8Q4x3U0k6S2L8i4m8Q4x3@1u0V1j5i4c8S2i4K6y4p5i4K6N6o6L8s2x3`.

POC页面

local_token:RDRFRTA3MjI0MjFFLHNzaCwxNjEyNTA5ODU1NTI4LN/Gtg9ilqUoIsFFNGeHCHIA237Q
 
uuid:f1f01c50-a881-11e4-9b37-d4ee0722421e
 
cloud_token:5Jj4IhbY/K+QpS3n1rGfMFI3A58=
local_token:RDRFRTA3MjI0MjFFLHNzaCwxNjEyNTA5ODU1NTI4LN/Gtg9ilqUoIsFFNGeHCHIA237Q
 
uuid:f1f01c50-a881-11e4-9b37-d4ee0722421e
 
cloud_token:5Jj4IhbY/K+QpS3n1rGfMFI3A58=
ls /usr/lib/lua/luci/local_ssh
local_ssh.lua       local_ssh_util.lua
ls /usr/lib/lua/luci/local_ssh
local_ssh.lua       local_ssh_util.lua
local json = require("hiwifi.json")
local utils = require("openapi.utils.utils")
local string = string
local tostring = tostring
 
module("luci.local_ssh.local_ssh")
 
local function dispatcher(request)
    local response = ""
    local result = {}
     
    if not request then
        request = {}
    end
     
    local method = request.method
     
    if method == "get" then
        local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua get")
        result["code"] = 0
        result["data"] = cmd_result
    elseif method == "valid" then
        if request.data ~= nil then
            local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua valid " .. tostring(request.data))
            if not cmd_result then
                cmd_result = ""
            end
            cmd_result = tostring(cmd_result)
             
            if string.find(cmd_result, "Success:") then
                result["code"] = 0
                result["data"] = cmd_result
            else
                result["code"] = 1
                result["data"] = cmd_result
            end
        else
            -- 当request.data为nil时的处理
            result["code"] = 1
            result["data"] = ""
        end
    elseif method == "stop" then
        local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua stop")
        result["code"] = 0
        result["data"] = cmd_result
    else
        result["code"] = 1
        result["data"] = "Error: Method does not exist"
    end
     
    response = json.encode(result)
    return response
end
 
dispatcher = dispatcher
local json = require("hiwifi.json")
local utils = require("openapi.utils.utils")
local string = string
local tostring = tostring
 
module("luci.local_ssh.local_ssh")
 
local function dispatcher(request)
    local response = ""
    local result = {}
     
    if not request then
        request = {}
    end
     
    local method = request.method
     
    if method == "get" then
        local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua get")
        result["code"] = 0
        result["data"] = cmd_result
    elseif method == "valid" then
        if request.data ~= nil then
            local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua valid " .. tostring(request.data))
            if not cmd_result then
                cmd_result = ""
            end
            cmd_result = tostring(cmd_result)
             
            if string.find(cmd_result, "Success:") then
                result["code"] = 0
                result["data"] = cmd_result
            else
                result["code"] = 1
                result["data"] = cmd_result
            end
        else
            -- 当request.data为nil时的处理
            result["code"] = 1
            result["data"] = ""
        end
    elseif method == "stop" then
        local cmd_result = utils.exec_cmd("sudo /usr/lib/lua/luci/local_ssh/local_ssh_util.lua stop")
        result["code"] = 0
        result["data"] = cmd_result
    else
        result["code"] = 1
        result["data"] = "Error: Method does not exist"
    end
     
    response = json.encode(result)
    return response
end
 
dispatcher = dispatcher
local tw = require("tw")
local auth = require("auth")
local socket = require("socket")
local util = require("luci.util")
local nixio = require("nixio")
local protocol = require("luci.http.protocol")
 
local math_floor = math.floor
local current_time = math_floor(socket.gettime() * 1000)
local mac_address = tw.get_mac()
 
local service_name = "ssh"
local token = ""
local base_string = tostring(mac_address) .. "," .. service_name .. "," .. tostring(current_time)
local encoded_token = ""
local timestamp_file = "/tmp/local_ssh_ms"
 
-- 读取时间戳文件
local file_handle = io.open(timestamp_file, "r")
local stored_timestamp = 0
 
if file_handle ~= nil then
    local timestamp = file_handle:read("*n")
    if timestamp then
        stored_timestamp = timestamp
    else
        stored_timestamp = 0
    end
    file_handle:close()
else
    -- 文件不存在,创建新文件
    file_handle = io.open(timestamp_file, "a")
    stored_timestamp = 0
    file_handle:close()
end
 
local command = arg[1]
local input_data = arg[2] or ""
 
local popen_handle, port_number
 
if command == "get" then
    -- 获取SSH状态
    file_handle = assert(io.open(timestamp_file, "w"))
    file_handle:write(current_time)
    file_handle:close()
     
    local hmac_token = auth.lua_hmac_sha1_with_uuid(base_string, string.len(base_string))
    if hmac_token then
        token = hmac_token
    else
        token = ""
    end
     
    encoded_token = nixio.bin.b64encode(base_string .. "," .. token)
    print(encoded_token)
    os.exit(0)
     
elseif command == "valid" then
    -- 验证令牌
    local validation_string = tostring(mac_address) .. "," .. service_name .. "," .. tostring(stored_timestamp + 1)
    local hmac_token = auth.lua_hmac_sha1_with_uuid(validation_string, string.len(validation_string))
    if hmac_token then
        token = hmac_token
    else
        token = ""
    end
     
    encoded_token = nixio.bin.b64encode(token)
     
    if input_data == encoded_token then
        -- 令牌验证成功,重启SSH服务
        os.execute("/etc/init.d/dropbear restart; hwf-at 10 /usr/lib/lua/luci/local_ssh/local_ssh_util.lua check_connected")
        os.remove(timestamp_file)
         
        -- 获取SSH端口号
        popen_handle = io.popen("s=`netstat -lntp|grep dropbear | grep '0.0.0.0' | grep -v '127.0.0.1'|awk '{print $4}'`; echo ${s##*:}")
         
        if popen_handle == nil then
            print("Error: port file does not exist")
            os.exit(1)
        end
         
        port_number = popen_handle:read("*n")
         
        if port_number == nil then
            print("Error: port does not exist")
            os.exit(1)
        end
         
        popen_handle:close()
        print("Success: ssh port is " .. port_number)
        os.exit(0)
    else
        print("Error: valid token error")
        os.exit(1)
    end
     
elseif command == "stop" then
    -- 停止SSH服务
    popen_handle = io.popen("pidof dropbear | wc -w")
    local process_count = popen_handle:read("*n")
    popen_handle:close()
     
    if process_count <= 1 then
        os.execute("/etc/init.d/dropbear stop")
    else
        -- 如果还有连接,5秒后重试
        os.execute("hwf-at 5 /usr/lib/lua/luci/local_ssh/local_ssh_util.lua stop")
    end
     
elseif command == "check_connected" then
    -- 检查SSH连接状态
    popen_handle = io.popen("pidof dropbear | wc -w")
    local process_count = popen_handle:read("*n")
    popen_handle:close()
     
    if process_count <= 1 then
        -- 没有连接,10秒后再次检查
        os.execute("hwf-at 10 /usr/lib/lua/luci/local_ssh/local_ssh_util.lua check_connected")
    else
        -- 有连接,180秒后尝试停止
        os.execute("hwf-at 180 /usr/lib/lua/luci/local_ssh/local_ssh_util.lua stop")
    end
     
else
    print("Error: method does not exist")
    os.exit(1)
end
local tw = require("tw")
local auth = require("auth")
local socket = require("socket")
local util = require("luci.util")
local nixio = require("nixio")
local protocol = require("luci.http.protocol")
 
local math_floor = math.floor
local current_time = math_floor(socket.gettime() * 1000)
local mac_address = tw.get_mac()
 
local service_name = "ssh"
local token = ""
local base_string = tostring(mac_address) .. "," .. service_name .. "," .. tostring(current_time)
local encoded_token = ""
local timestamp_file = "/tmp/local_ssh_ms"
 
-- 读取时间戳文件
local file_handle = io.open(timestamp_file, "r")
local stored_timestamp = 0
 
if file_handle ~= nil then
    local timestamp = file_handle:read("*n")
    if timestamp then
        stored_timestamp = timestamp
    else
        stored_timestamp = 0
    end
    file_handle:close()
else
    -- 文件不存在,创建新文件
    file_handle = io.open(timestamp_file, "a")
    stored_timestamp = 0
    file_handle:close()
end
 
local command = arg[1]
local input_data = arg[2] or ""
 
local popen_handle, port_number
 
if command == "get" then
    -- 获取SSH状态
    file_handle = assert(io.open(timestamp_file, "w"))
    file_handle:write(current_time)
    file_handle:close()
     
    local hmac_token = auth.lua_hmac_sha1_with_uuid(base_string, string.len(base_string))
    if hmac_token then
        token = hmac_token
    else
        token = ""
    end
     
    encoded_token = nixio.bin.b64encode(base_string .. "," .. token)
    print(encoded_token)
    os.exit(0)
     
elseif command == "valid" then
    -- 验证令牌
    local validation_string = tostring(mac_address) .. "," .. service_name .. "," .. tostring(stored_timestamp + 1)
    local hmac_token = auth.lua_hmac_sha1_with_uuid(validation_string, string.len(validation_string))
    if hmac_token then
        token = hmac_token
    else
        token = ""
    end
     
    encoded_token = nixio.bin.b64encode(token)
     
    if input_data == encoded_token then
        -- 令牌验证成功,重启SSH服务
        os.execute("/etc/init.d/dropbear restart; hwf-at 10 /usr/lib/lua/luci/local_ssh/local_ssh_util.lua check_connected")
        os.remove(timestamp_file)
         
        -- 获取SSH端口号
        popen_handle = io.popen("s=`netstat -lntp|grep dropbear | grep '0.0.0.0' | grep -v '127.0.0.1'|awk '{print $4}'`; echo ${s##*:}")
         
        if popen_handle == nil then
            print("Error: port file does not exist")
            os.exit(1)
        end
         
        port_number = popen_handle:read("*n")
         
        if port_number == nil then
            print("Error: port does not exist")
            os.exit(1)
        end
         
        popen_handle:close()
        print("Success: ssh port is " .. port_number)
        os.exit(0)
    else

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-10-27 16:11 被易之生生编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 472
活跃值: (5316)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
不错 cloud_token代码弄出来,不怕网站关闭了。。。
2025-10-29 20:45
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
极路由都倒闭了吧
2025-11-12 15:47
0
游客
登录 | 注册 方可回帖
返回