TP-Link Archer AXE75漏洞复现

新发布lua命令执行加密解密
2025-08-06 11:46
11687

漏洞情报

CVE-2024-53375:TP-Link Archer系列路由器存在一个已认证的远程代码执行(RCE)漏洞。该漏洞存在于TP-Link提供的HomeShield功能中的"tmp_get_sites"函数内。即使未启用HomeShield功能,此漏洞仍可被利用。

本文采用Archer AXE75(EU)_V1_1.2.2 Build 20240827固件进行分析、复现和挖掘

信息收集

拿到固件,binwalk解包,进入squashfs-root目录下

Snipaste_2025-07-28_13-40-04.png

看到是ARM架构32位

我们找到web服务器usr/sbin/uhttpd

uhttpd分析

main函数

找到uhttpd的main函数。该函数用于启动一个轻量级Web服务器

以下按代码逻辑顺序分析各部分功能和实现细节,跳过不需要部分,命令行参数解析部分重点展开。

命令行参数解析

while ( 1 )
{
    v11 = getopt(argc, (char *const *)argv, "fSDRC:K:N:E:I:p:s:h:c:l:L:d:r:m:n:x:i:t:T:A:u:U:");
    v12 = v11;
    if ( v11 <= 0 )
        break;
    switch ( v11 )
    {
        case 'A': ... case 'C': ... case 'D': ... /* 其他选项 */
        default:
            v37 = "Usage: %s -p [addr:]port [-h docroot]
" /* 使用说明 */
            v36 = *argv;
            goto LABEL_91;
    }
}
  • 功能:解析命令行参数,配置服务器的运行参数。
  • 逻辑
    • 使用getopt循环处理选项,选项字符串为"fSDRC:K:N:E:I:p:s:h:c:l:L:d:r:m:n:x:i:t:T:A:u:U:"
    • 将当前选项存入v11(并复制到v12),若v11 <= 0,退出循环。
    • 使用switch根据选项字符执行对应逻辑。
    • 无效选项打印使用说明并退出。
  • 选项字符串
    • 无参数选项:f, S, D, R, l, L
    • 带参数选项:C:, K:, N:, E:, I:, p:, s:, h:, c:, d:, r:, m:, n:, x:, i:, t:, T:, A:, u:, U:
    • optarg存储带参数选项的值。
各选项详细分析

以下部分分析switch中的选项逻辑和功能:

-A:设置最大活动连接数

case 'A':
    v46 = atoi((const char *)optarg);
    p_tm_isdst = &filename[93].tm_isdst;
    goto LABEL_108;
LABEL_108:
    *p_tm_isdst = v46;
    continue;
  • 功能:设置服务器的最大活动连接数。
  • 逻辑:将optarg转换为整数(atoi),存储在filename[93].tm_isdst
  • 细节:影响服务器的并发处理能力,复用struct tm字段存储配置。

-R:启用RFC1918过滤

case 'R':
    p_tm_year = &filename[93].tm_yday;
    goto LABEL_104;
  • 功能:启用RFC1918私有地址过滤。
  • 逻辑:设置filename[93].tm_yday=1
  • 细节:限制私有IP访问。

-T:设置网络超时

case 'T':
    v46 = atoi((const char *)optarg);
    p_tm_isdst = &filename[93].tm_wday;
    goto LABEL_108;
  • 功能:设置网络超时时间(秒)。
  • 逻辑:将optarg转换为整数,存储在filename[93].tm_wday
  • 细节:默认30秒。

-U:设置ubus socket路径

case 'U':
    v48 = (int)optarg;
    p_tm_min = (struct tm *)&filename[94].tm_min;
    goto LABEL_110;
LABEL_110:
    p_tm_min->tm_sec = v48;
    continue;
  • 功能:覆盖ubus socket路径。
  • 逻辑:将optarg存储在filename[94].tm_min
  • 细节:默认路径为/var Rats/ubus.sock

-h:设置文档根目录

case 'h':
    if ( realpath((const char *)optarg, (char *)filename) )
        continue;
    v39 = (const char *)optarg;
    v40 = (FILE *)stderr;
    v41 = _errno_location();
    v42 = strerror(*v41);
    fprintf(v40, "Error: Invalid directory %s: %s
", v39, v42);
    goto LABEL_82;
  • 功能:指定文档根目录。
  • 逻辑
    • 使用realpath解析optargfilename,验证路径。
    • 如果无效,打印错误并退出。
  • 细节:默认根目录为.

-n:设置最大并发请求数

case 'n':
    v46 = atoi((const char *)optarg);
    p_tm_isdst = &filename[93].tm_gmtoff;
    goto LABEL_108;
  • 功能:设置最大并发请求数。
  • 逻辑:将optarg转换为整数,存储在filename[93].tm_gmtoff
  • 细节:默认值8。

-p-s:绑定端口(普通或TLS)

case 'p':
case 's':
    memset(v107, 0, sizeof(v107));
    v16 = (const char *)optarg;
    v17 = strrchr((const char *)optarg, 58);
    if ( v17 )
    {
        v18 = v17 - v16;
        v19 = *(unsigned __int8 *)v16 == 91;
        if ( v16 >= v17 )
            v19 = 0;
        if ( v19 && *(v17 - 1) == 93 )
        {
            v18 -= 2;
            v20 = v16 + 1;
            if ( v18 >= 0x80 )
                v18 = 128;
        }
        else
        {
            v20 = v16;
            if ( v18 >= 0x80 )
                v18 = 128;
        }
        v16 = v17 + 1;
        memcpy(v107, v20, v18);
    }
    if ( v12 != 115 )
        goto LABEL_38;
    if ( sub_149F8(filename) )
    {
        fprintf((FILE *)stderr, "Notice: TLS support is disabled, ignoring '-s %s'
", optarg);
        continue;
    }
    v98 = 1;
LABEL_38:
    v101 = 1;
    if ( v107[0] )
        v21 = v107;
    else
        v21 = 0;
    pai[0] = 0;
    v22 = getaddrinfo(v21, v16, &req, pai);
    /* 后续网络初始化逻辑 */
  • 功能
    • -p:绑定普通HTTP端口。
    • -s:绑定HTTPS端口(需TLS支持)。
  • 逻辑
    • 解析optarg格式为[addr]:port(支持IPv6)。
    • 分割地址(存入v107)和端口(存入v16)。
    • 对于-s,检查TLS支持,若不支持则忽略并设置v98=1
    • 调用getaddrinfo解析地址,创建套接字,绑定端口。
  • 细节
    • 支持IPv4/IPv6,地址为空时绑定所有接口。
    • TLS端口需-C-K配合。

-r:设置认证领域

case 'r':
    v48 = optarg;
    p_tm_min = (struct tm *)&filename[93].tm_min;
    goto LABEL_110;
  • 功能:设置基本认证的领域名称。
  • 逻辑:将optarg存储在filename[93].tm_min
  • 细节:默认"Protected Area"

-t:设置脚本超时

case 't':
    v46 = atoi((const char *)optarg);
    p_tm_isdst = &filename[94].tm_wday;
    goto LABEL_108;
  • 功能:设置CGI/Lua/ubus脚本超时时间(秒)。
  • 逻辑:将optarg转换为整数,存储在filename[94].tm_wday
  • 细节:默认60秒。

-x:设置CGI处理URL前缀

case 'x':
    v48 = optarg;
    p_tm_min = (struct tm *)&filename[93].tm_zone;
    goto LABEL_110;
  • 功能:指定CGI处理器的URL前缀。
  • 逻辑:将optarg存储在filename[93].tm_zone
  • 细节:默认/cgi-bin

默认情况

default:
    v37 = "Usage: %s -p [addr:]port [-h docroot]
" /* 详细使用说明 */
    v36 = *argv;
    goto LABEL_91;
LABEL_91:
    fprintf(v38, v37, v36);
    goto LABEL_82;
  • 功能:处理无效选项,打印使用说明并退出。
  • 逻辑:输出程序用法,设置退出状态v35=1
参数验证
if ( v9 <= 1 )
    v13 = v98;
else
    v13 = 0;
if ( v13 )
{
    v14 = "Error: Missing private key or certificate file
";
    v15 = (FILE *)stderr;
    goto LABEL_81;
}
if ( !v96 )
{
    v14 = "Error: No sockets bound, unable to continue
";
    v15 = (FILE *)stderr;
    goto LABEL_81;
}
  • 功能:验证命令行参数完整性。
  • 逻辑
    • 如果启用了-sv98=1)且v9<=1(缺少证书或私钥),报错退出。
    • 如果v96=0(无成功绑定的套接字),报错退出。
  • 细节
    • v9确保TLS配置完整(需-C-K)。
    • v96记录绑定的套接字数量。

网络初始化

v25 = pai[0];
v97 = 0;
while ( 2 )
{
    if ( v25 )
    {
        v26 = socket(v25->ai_family, v25->ai_socktype, v25->ai_protocol);
        v27 = v26;
        if ( setsockopt(v26, 1, 2, &v101, 4u) )
            goto LABEL_53;
        if ( filename[93].tm_isdst > 0 )
        {
            v104 = 3;
            tm_isdst = filename[93].tm_isdst;
            optval = 1;
            if ( setsockopt(v27, 1, 9, &v101, 4u)
              || setsockopt(v27, 6, 4, &optval, 4u)
              || setsockopt(v27, 6, 5, &tm_isdst, 4u)
              || setsockopt(v27, 6, 6, &v104, 4u) )
            {
                v29 = (FILE *)stderr;
                v30 = _errno_location();
                v31 = strerror(*v30);
                fprintf(v29, "Notice: Unable to enable TCP keep-alive: %s
", v31);
            }
        }
        if ( v25->ai_family == 10 && setsockopt(v27, 41, 26, &v101, 4u) == -1 )
            goto LABEL_53;
        if ( bind(v27, v25->ai_addr, v25->ai_addrlen) == -1 )
            goto LABEL_54;
        if ( listen(v27, 64) == -1 )
            goto LABEL_54;
        v32 = uh_listener_add(v27, filename);
        if ( v32 )
        {
            if ( v12 == 115 )
                p_tm_mon = &filename[94].tm_mon;
            else
                p_tm_mon = 0;
            if ( v12 == 115 )
                p_tm_mon = (int *)p_tm_mon[6];
            *(_DWORD *)(v32 + 52) = p_tm_mon;
            v34 = fcntl(v27, 1);
            fcntl(v27, 2, v34 | 1);
            uh_ufd_add(v32, sub_14858, 65);
            ++v97;
        }
        else
        {
            fputs("uh_listener_add(): Failed to allocate memory
", (FILE *)stderr);
        }
        if ( v27 > 0 )
            close(v27);
LABEL_51:
        v25 = v25->ai_next;
        continue;
    }
    break;
}
freeaddrinfo(pai[0]);
v96 += v97;
  • 功能:创建TCP套接字,绑定地址和端口,启动监听。
  • 逻辑
    • 使用getaddrinfo解析地址(从-p-s)。
    • 为每个地址创建套接字,设置SO_REUSEADDR和TCP keep-alive(若启用)。
    • 调用bindlisten,最大连接数64。
    • 使用uh_listener_add注册监听器到事件循环。
    • 增加v97(成功绑定计数),释放地址信息。
    • 更新v96(总绑定计数)。
  • 细节
    • 支持IPv4/IPv6,TCP keep-alive增强连接稳定性。
    • uh_ufd_add将套接字加入事件循环,回调函数为sub_14858,后续如果想进一步分析http服务从这里入手。

服务器配置

uh_get_operation_mode(&dword_2B45C);
uh_get_local_addr(&dword_2B45C);
uh_get_admin_config(&dword_2B45C);
if ( filename[93].tm_gmtoff <= 0 )
    filename[93].tm_gmtoff = 8;
if ( filename[93].tm_wday <= 0 )
    filename[93].tm_wday = 30;
if ( !uh_index_files )
{
    if ( byte_2B41C[0] )
    {
        memset(pai, 0, 0x80u);
        sprintf((char *)pai, "index.%shtml", byte_2B41C);
        uh_index_add(pai);
    }
    uh_index_add("index.html");
    uh_index_add("index.htm");
    uh_index_add("default.html");
    uh_index_add("default.htm");
}
if ( filename[94].tm_wday <= 0 )
    filename[94].tm_wday = 60;
if ( !filename[93].tm_zone )
    filename[93].tm_zone = "/cgi-bin";
  • 功能:设置服务器运行模式、地址和默认配置。
  • 逻辑

试读结束,发布七天后转为公开

公开时间:2025年8月13日 11:46:02

提前解锁全文,需花费 50 积分

登录解锁全文
分享到

参与评论

0 / 200

全部评论 1

Aiyflowers的头像
李克用(856年10月24日—908年2月23日),字翼圣,本姓朱邪,后赐姓李氏,祖籍陇右金城, 出生于神武川新城(今山西省应县),沙陀族。唐末至五代初年军阀,后唐王朝奠基人。后唐庄宗李存勖之父。iotseczone优秀创作者
2025-08-07 11:16
KDEV的头像
我嘞个五代十国啊
2025-08-07 13:50
投稿
签到
联系我们
关于我们