Restrict what getaddrinfo(3) is willing to try to resolve.
authorflorian <florian@openbsd.org>
Thu, 17 Nov 2022 17:39:41 +0000 (17:39 +0000)
committerflorian <florian@openbsd.org>
Thu, 17 Nov 2022 17:39:41 +0000 (17:39 +0000)
commit1b04c78cb3ee7608c76cbb26114b603e2d854d11
tree54da78a7f35964237562c344a9bde2fd37d635bc
parentff827b62f389545cafa10fda63d504b800c320ec
Restrict what getaddrinfo(3) is willing to try to resolve.

Programs assume that a successful call to getaddrinfo(3) validates the
input as "safe", but that's not true. Characters like '$', '`', '\n'
or '*' can traverse the DNS without problems, but have special
meaning, for example a shell.

There is a function res_hnok() already in libc, but it validates if a
string is a host name, which is too strict in practice. For example
foo-.example.com is not a valid host name, but is used on the
Internet.

Posix has this to say:
"The getaddrinfo() function shall translate the name of a service
location (for example, a host name)"

It hints that the input should be a host name, but it does not
restrict it to it.

This introduces a function hnok_lenient() which restricts the input to
getaddrinfo(3) to the set [A-z0-9-_.]. Additionally two consecutive
dots ('.') are not allowed nor can the string start with - or '.'.

glibc introduced a similar restriction years ago, so this should not
cause problems.

It has been known in the DNS community for years, probably decades
that getaddrinfo(3) is too lenient what it accepts, but it has always
been kicked down the road as "not a DNS problem". Unfortunately this
information never made it out of the DNS community and no coordinated
effort happened to have this addressed in operating systems.

David Leadbeater recently demonstrated how ssh(1) and ftp(1) are too
trusting with what getaddrinfo(3) accepts. Both have been fixed
independently of this.

Input deraadt, eric
OK millert, deraadt
lib/libc/asr/asr_private.h
lib/libc/asr/asr_utils.c
lib/libc/asr/getaddrinfo_async.c
lib/libc/asr/gethostnamadr_async.c