Hello inetutils maintainers,
Security researcher here. A memory-safety bug in GNU inetutils talkd,
confirmed with ASAN on a real upstream build. (Note: I separately audited
telnetd/ftpd/rexecd/rlogind/rshd/uucpd and found them well-bounded â
BSD-origin hardened; only the talkd path below is affected.)
------------------------------------------------------------
# CVE #27 (åé, ASAN 确认) â inetutils talkd process_request: éç»ç»
CTL_MSG åæ®µ â å è¶ç读
**ç®æ **: GNU inetutils **2.7**ï¼ææ°ç为 2.8ï¼æ¬æºç¨ 2.7ï¼ä»£ç
ä¸ 2.8 `talkd/process.c` åæºï¼
`talkd/process.c:76`ï¼`process_request`ï¼
**ç±»å**: CWE-125 å è¶ç读ï¼syslog `%s` è¯»åæªå¼ºå¶ NUL
ç»ç»çå®é¿ç½ç»å段ï¼
**åè®®**: ntalkï¼BSD talkï¼UDPï¼**æ 认è¯**ï¼ä»»ä½è½å talkd UDP
端å£åå
ç主æºï¼
**OSS-Fuzz**: æªè¦çï¼inetutils æ talkd fuzzerï¼
**ç¶æ**: â
libFuzzer harness + ASAN 确认ï¼heap-buffer-overflow, READ of
size 41 @ process.c:76ï¼ã
â ï¸ çå® talkd daemon ç½ç»å¤ç°å¾
è¡¥ï¼é ASAN éç¼ talkd + UDP
åå
ï¼è§ä¸ï¼ã
## æè¦
ntalk çè¯·æ±æ¥ææ¯å®é¿ `CTL_MSG`ï¼84 åèï¼ç»æä½ï¼
```
vers(1) type(1) answer(1) pad(1) id_num(4)
addr(osockaddr 16) ctl_addr(osockaddr 16) pid(4)
l_name[12] r_name[12] r_tty[16] â ä¸ä¸ª char[] å®é¿åæ®µï¼æ
NUL ç»ç»
```
talkd ä¸»å¾ªç¯ `recvfrom(fd, &msg, sizeof msg,
...)`ï¼`talkd/talkd.c:166`ï¼ææ´ä¸ª 84 åè
UDP æ°æ®æ¥**åæ ·**å¡«å
¥ `CTL_MSG`ï¼**ä»ä¸**对
`l_name`/`r_name`/`r_tty` å¼ºå¶ NUL ç»ç»ã
éå `process_request()` æè¿äºåæ®µå½ C å符串åç» `syslog("%s",
...)`ï¼process.c:76ï¼ï¼
```c
if (acl_match (msg, sa_in) == ACL_DENY)
{
if ((logging || debug) && msg->type == LOOK_UP)
syslog (LOG_NOTICE, "dropping request: %s@%s",
msg->l_name, inet_ntoa (sa_in->sin_addr)); /* â
process.c:76 */
```
`syslog` ç `%s` éåèè¯»å° NUL 为æ¢ãå½
`l_name[12]`(åç§»44)ã`r_name[12]`(56)ã
`r_tty[16]`(68) **å
¨é¨å¡«æ»¡é NUL** æ¶ï¼`%s` ä» `l_name`
ä¸ç´è¯»å°ç»æä½æ«å°¾(åç§»84)å¹¶
**è¶è¿ 84 åèè¾¹ç**ï¼è¯» 41 åèï¼40 åèåæ®µ + 1
åèè¶çï¼ãè¥ `msg` æ¯æ°å¥½ 84 åèçå
åé
ï¼ææ ä¸ç´§è´´æªæ å°é¡µï¼ï¼å³å /æ è¶ç读ã
## ASAN 确认ï¼harnessï¼
```
==1201572==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x608000000174
READ of size 41 at 0x608000000174 thread T0
#2 0x54eaec in process_request .../talkd/process.c:76:2
SUMMARY: AddressSanitizer: heap-buffer-overflow ... in printf_common (syslog %s)
```
harnessï¼`fuzz_talkd.c`ï¼malloc **æ°å¥½ 84 åè**ï¼ASAN
红åºç´§è´´ç»æä½æ«å°¾ï¼ï¼å¡«å
¥ fuzz æ°æ®ï¼
å¼ºå¶ `vers=1`/`type=LOOK_UP`/`addr` æ=`AF_INET`ï¼`logging=1`ï¼è°çå®
`process.o` ç
`process_request`ã`syslog` æ¡©ç¨ `vsnprintf` æ¶è´¹
`%s`ï¼è§¦åè¶ç读ï¼ä½ä¸å `/dev/log`ã
`acl_match`/`do_announce`/table/print æ¡©æä»¥é离 `process_request`
èªèº«ä»£ç ââ
**bug å¨çå® `process.c` ç¼è¯äº§ç©é**ï¼éæ¡©ã
## PoC
`pocs/inetutils-talkd-ctm-lg-heap-oob.bin`ï¼84 åèï¼å³ä¸ä¸ªå®æ´
`CTL_MSG`ï¼ï¼
åç§» 44â83ï¼`l_name`+`r_name`+`r_tty`ï¼å
¨å¡« `0x41`('A')ãå¤ç°ï¼
```
ASAN_OPTIONS=detect_leaks=0 ./fuzz_talkd inetutils-talkd-ctm-lg-heap-oob.bin
# => heap-buffer-overflow READ of size 41 @ process.c:76
```
## å¯è¾¾æ§ï¼çå® daemonï¼
`process.c:76` è·¯å¾é满足ï¼â talkd 以 `-l`(logging) æ `-d`(debug)
å¯å¨ï¼å¸¸è§è¿ç»´é项ï¼ï¼
â¡ `acl_match` è¿å `ACL_DENY`ï¼å³é
ç½®äºæç»è§åï¼å¸¸è§äºéå¶
talk çé¨ç½²ï¼ã
é»è®¤æ ACL æ¶ `acl_match` è¿å `ACL_ALLOW`ï¼**ä¸**è§¦åæ¬ä½ç¹ã
**ä½å䏿 ¹å ï¼å®é¿å段ä¸å¼ºå¶ NUL
ç»ç»ï¼å½±åææå段æ¶è´¹è
ï¼å
¶ä¸æ´æè¾¾æçåä½**ï¼
- `talkd/announce.c:133` `len = sizeof(PATH_TTY_PFX) + strlen(request->r_tty) +
2;`
â `announce()` å¨ `do_announce` æ¾å°ç®æ ç»å½ç¨æ·æ¶**æ
æ¡ä»¶**è°ç¨ï¼**ä¸é logging/ACL**ï¼ï¼
`r_tty` æ¯ç»æä½**æåä¸ä¸ªå段**ï¼dense æ¶ `strlen`/ç´§éç
`sprintf("%s/%s",PFX,r_tty)`
(announce.c:140) ç´æ¥è¶è¿ 84 åèè¾¹çãæ»å»è
åä¸ä¸ªæå**ä»»ä¸å·²ç»å½ç¨æ·**ç ANNOUNCE
å³å¯è§¦åã
- `talkd/process.c:98` `syslog("%s@%s called by %s@%s", msg->r_name,
(r_tty[0]?msg->r_tty:..), msg->l_name, ..)`ï¼ANNOUNCE æå + loggingï¼ã
- `talkd/table.c` `find_request`/`insert_table` 对 `l_name`/`r_name` å
`strcmp`ï¼åæ ¹å ï¼è¶ç读ç¸é»å段ï¼ã
- `talkd/print.c` `print_request`ï¼debug æ¨¡å¼ `%s` æå°å段ï¼ã
â è¿æ¯**ä¸ç±»**缺é·ï¼recvfrom â å®é¿ char[] åæ®µ â å½ C
å符串ç¨ï¼æ ç»ç»ï¼ï¼ä¸æ¯åç¹ã
## çå® daemon ç½ç»å¤ç°ï¼é»å¡ â è¯å®è®°å½ï¼é bug èåï¼
å·²åï¼ç¨ `-fsanitize=address` éç¼ inetutils talkdï¼`talkd/talkd`ï¼497
个 `__asan` 符å·ï¼ï¼
launcher å¨ fd 0 䏿é 84B PoCï¼å·²éªè¯æ°æ®æ¥ roundtrip OKï¼ï¼ä»¥
`talkd -S -l -d` å¯å¨
ï¼`-S` strict_policy â `acl_match` æ ACL æä»¶æ¶è¿å `ACL_DENY`ï¼è§
`acl.c:430`ï¼ã
PoC åæ®µæ£ç¡®ï¼vers=1=TALK_VERSIONãtype=1=LOOK_UPãaddr/ctl_addr
æ=AF_INETãåç§»44-83 å
¨ `0x41`ï¼ï¼
è¿ `process.c:35/47/56` ä¸éæ£æ¥ï¼åºè¾¾ line 76ã
**ç»æï¼talkd è·è¿ recvfrom 循ç¯å¹¶é»å¡ï¼timeout 124ï¼ï¼æ ASAN
å´©æºã**
åå ï¼å·²å®ä½ï¼ï¼ASAN å¯å¨æ¶æ¥ `failed to intercept
'__isoc99_printf/sprintf/snprintf/vsnprintf/...'`
ââ printf ææ¦æªå¨**æªè£
ä¸**ã`syslog("%s", l_name)`
çè¶ç读åçå¨**æªè¢«ææ¡©ç glibc**
`vsnprintf` å
ï¼æ
æ ä¸ `msg` ç 1 åèè¶è¿çº¢åºè¯»**对 ASAN
ä¸å¯è§**ãharness è½å´©æ¯å 为 `msg`
为**å **ä¸ `malloc` æ°å¥½ 84Bï¼å 红åºä¸æ¯ + å©ä¸ç `vsnprintf`
æ¦æªå¨å½ä¸ï¼ï¼å è·¯å¾è¢« ASAN æå°ã
â è¿æ¯ **ASAN ç `%s`-æ è¶è¯»æ£æµç²åº**ï¼å·²ç¥å±éï¼å¯¹ glibc
`%s` åæ°è¯»åçæ£æ¥ä¾èµæ¦æªå¨ï¼
æ¦æªå¨å¤±è´¥å³æ¼æ¥ï¼ï¼**䏿¯ bug èå**ãbug ç宿§å·²ç±
harness å¨çå® `process.c` ç¼è¯äº§ç©ä¸
ç¡®è¯ï¼å è·¯å¾ ASAN 红åºå½ä¸ @
process.c:76ï¼ãè¦è¿ç¨çº§å¯è§å´©æºé让è¶è¯»è·¨é¡µï¼æ
䏿®µä¸å¯æ§ï¼
ææ¹ç¨ MSAN/æåæ ¡éªï¼æ¬ä¼è¯ä¸ä½ã
## ä¿®å¤æ¹å
`recvfrom` å对ä¸ä¸ªå®é¿åæ®µå¼ºå¶ NUL
ç»ç»ï¼æç®ãæå°è¡¥ä¸ï¼ä¸æ¬¡æ§å°ä½æ´ç±»ï¼ï¼
```c
/* talkd/talkd.c æ¶å
åï¼æ process_request å
¥å£ */
msg.l_name[sizeof(msg.l_name)-1] = '\0';
msg.r_name[sizeof(msg.r_name)-1] = '\0';
msg.r_tty [sizeof(msg.r_tty )-1] = '\0';
```
æææ `%s`/`strlen`/`strcmp`/`sprintf` æ¶è´¹ç¹æ¹ç¨å¸¦é¿åº¦
APIï¼`%.*s` / `strnlen` / `strncmp`ï¼ã
## è¯å®å£°æ / 䏥鿧
- **çå® OOB**ï¼ASAN å¨çå® `process.c` ç¼è¯äº§ç©ä¸ç¡®è¯ï¼æ ¹å
ï¼recvfrom ä¸ç»ç»å®é¿åæ®µï¼æ¸
æ°ã
-
**䏥鿧åä½**ï¼è¶ç读éå°ï¼æ°ååèï¼ï¼ä¸»è¦å±å®³æ¯è¯»ç¸é»ç»æä½å段/å
å
æ°æ®ï¼ä¿¡æ¯æ³é²ï¼ï¼
跨页æ¶å¯è½ DoSï¼talkd(ntalk) æ¯å¤èåè®®ï¼ç°ä»£ç³»ç»å¾å°é¨ç½²
talkdãå¯ä½ä¸ºä½å± CVE æ¥åï¼
ä½éé«å±ã
- **çå® daemon å¤ç°å·²åä½å ASAN ç²åºé»å¡**ï¼è§ä¸ãçå®
daemon ç½ç»å¤ç°ãââ PoC åæ®µæ£ç¡®ã
è·¯å¾å¯è¾¾ï¼ä½ glibc `%s` è¶è¯»å¯¹ ASAN ä¸å¯è§ï¼æ¦æªå¨æªè£
ä¸ï¼ï¼æ
æ å¯è§å´©æºãbug ç宿§ä»¥
harness å è·¯å¾ ASAN 红åºå½ä¸æ
ä¿ãå¦è¦å®æ¹è¿ç¨å¯è§å´©æºé跨页/MSANï¼è¶
åºæ¬ä¼è¯ã
- åæ ¹å å®¶æï¼announce.c:133 çï¼æä»£ç åææå®ï¼æªé个 ASAN
åç¬ç¡®è®¤ï¼announce.c ç¼è¯éæ´å¤
libinetutils å¤´ï¼æ¬ä¼è¯æªæåºï¼ã
------------------------------------------------------------
Thank you for your work on inetutils.
Best regards,
zhangph ([email protected])