本篇主要介绍cloud_token的计算方式和远程命令执行漏洞的代码分析。cloud_token是开启远程ssh的token,如果知道cloud_token就可以远程开启ssh服务。
按照上文的模拟环境运行方式,打开 541K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5c8X3I4G2j5$3q4D9i4K6u0V1M7%4y4Z5i4K6u0r3 连接。出现远程开启ssh服务的页面。

正常情况下local token的输入框显示的是路由器local token的值,因为是模拟环境,没有板载信息,所以显示的为空。这里提供一组历史数据:
uuid就是路由器的固件信息,每个路由器都不同,获取的路径是 010K9s2c8@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代码如下: 6a4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5J5y4#2)9J5k6e0m8Q4x3X3f1H3i4K6u0W2x3g2)9J5c8X3I4G2j5$3q4D9i4K6u0V1M7%4y4Z5i4K6u0r3j5i4m8A6i4K6y4r3L8h3g2@1K9r3!0V1i4K6y4p5N6X3q4D9K9h3c8Q4x3U0k6S2L8i4m8Q4x3@1u0V1j5i4c8S2i4K6y4p5i4K6N6o6L8s2x3`.

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
被易之生生编辑
,原因: