ASA-2019-00011 – systemd: Out-of-bounds read ao analisar uma mensagem do syslog criada


For the English version of this alert, click here.

Allele Security Alert

ASA-2019-00011

Identificador(es)

ASA-2019-00011, CVE-2018-16866

Título

Out-of-bounds read ao analisar uma mensagem do syslog criada

Fabricante(s)

Lennart Poettering

Produto(s)

systemd

Versão(ões) afetada(s)

systemd v221 até v240

Versão(ões) corrigida(s)

systemd lançado com os seguintes commits:

journal: fix syslog_parse_identifier()
https://github.com/systemd/systemd/commit/a6aadf4ae0bae185dc4c414d492a4a781c80ffe5

journal: do not remove multiple spaces after identifier in syslog message
https://github.com/systemd/systemd/commit/8595102d3ddde6d25c282f965573a6de34ab4421

Prova de conceito

Desconhecida

Descrição

Um out-of-bounds read foi descoberto no systemd-journald na maneira como ela analisa mensagens de log que terminam com dois pontos ‘:’. Um atacante local pode usar essa vulnerabilidade para divulgar dados da memória de processo.

Detalhes técnicos

Foi descoberto um out-of-bounds read no journald que pode ser transformado em um memory leak:

File: v238/src/journal/journald-syslog.c
---
31 #define WHITESPACE " \t\n\r"
...
194 size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
195 const char *p;
...
197 size_t l, e;
...
203 p = *buf;
204
205 p += strspn(p, WHITESPACE);
206 l = strcspn(p, WHITESPACE);
207
208 if (l <= 0 ||
209 p[l-1] != ':')
210 return 0;
211
212 e = l;
...
240 if (strchr(WHITESPACE, p[e]))
241 e++;
242 *buf = p + e;
243 return e;
244 }
---

Se enviarmos uma mensagem do syslog para o journald (em *buf), e se o último caractere desta mensagem for um ‘:’ (antes do terminador ‘\0’), então:

– na linha 240, p[e] é o terminador ‘\0’ da nossa mensagem;

– na linha 240, strchr(WHITESPACE, p[e]) retorna um ponteiro para o terminador ‘\0’ da cadeia WHITESPACE (como mencionado em man strchr: “O byte nulo de terminação é considerado parte da cadeia, de forma que se c é especificado como ‘\0’, essas funções retornam um ponteiro para o terminador. “);

– na linha 241, e é incrementado;

– na linha 242, *buf aponta fora dos limites, para o primeiro caracter após o terminador ‘\0’ da nossa mensagem;

– mais tarde, a string fora do limite em *buf (supostamente o corpo da nossa mensagem do syslog) é escrita (vazada) para o journald.

Consequentemente, podemos ler esta string fora dos limites:

– diretamente do journald (se “Storage” do journald for “persistent” ou “auto” e /var/log/ journal/ existe), porque o journald suporta ACLs de arquivos estendidos (Access Control Lists):

$ id
uid=1000(john) gid=1000(john) groups=1000(john) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ ls -l /var/log/journal/*/user-$UID.journal
-rw-r-----+ 1 root systemd-journal 8388608 Nov 20 09:35 
/var/log/journal/2562d1eced654f44a3d3a217d66b9ff3/user-1000.journal

$ getfacl /var/log/journal/*/user-$UID.journal
...
user:john:r--

$ ./infoleak

$ journalctl --all --user --lines=1 --identifier=infoleak | hexdump -C
...
00000050 2e 20 2d 2d 0a 4e 6f 76 20 32 30 20 31 36 3a 30 |. --.Nov 20 16:0|
00000060 30 3a 33 36 20 6c 6f 63 61 6c 68 6f 73 74 2e 6c |0:36 localhost.l|
00000070 6f 63 61 6c 64 6f 6d 61 69 6e 20 69 6e 66 6f 6c |ocaldomain infol|
00000080 65 61 6b 5b 33 35 34 38 5d 3a 20 78 fb 1e 78 54 |eak[3548]: x..xT|
00000090 7f 0a |..|

– ou (se o “Storage” do journald é “volatile“, ou “auto” e /var/log/journal/ não existe) de um tty que gravamos para /var/run/utmp, porque journald escreve (“walls“) mensagens de emergência (LOG_EMERG) para o tty de cada usuário logado:

$ ./infoleak
...
00003510 0a 07 0d 0d 0a 42 72 6f 61 64 63 61 73 74 20 6d |.....Broadcast m|
00003520 65 73 73 61 67 65 20 66 72 6f 6d 20 73 79 73 74 |essage from syst|
00003530 65 6d 64 2d 6a 6f 75 72 6e 61 6c 64 40 6c 6f 63 |emd-journald@loc|
00003540 61 6c 68 6f 73 74 2e 6c 6f 63 61 6c 64 6f 6d 61 |alhost.localdoma|
00003550 69 6e 20 28 54 75 65 20 32 30 31 38 2d 31 31 2d |in (Tue 2018-11-|
00003560 32 30 20 31 36 3a 32 35 3a 34 36 20 43 53 54 29 |20 16:25:46 CST)|
00003570 3a 0d 0d 0a 0d 0d 0a 69 6e 66 6f 6c 65 61 6b 5b |:......infoleak[|
00003580 33 38 37 32 5d 3a 20 78 6b a2 e1 2f 7f 0d 0d 0a |3872]: xk../....|

Esta vulnerabilidade foi introduzida no systemd v221:

commit ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8
Date: Wed Jun 10 22:33:44 2015 -0700
...
- e += strspn(p + e, WHITESPACE);
+ if (strchr(WHITESPACE, p[e]))
+ e++;

e foi inadvertidamente corrigido em agosto de 2018:

commit a6aadf4ae0bae185dc4c414d492a4a781c80ffe5
Date: Wed Aug 8 15:06:36 2018 +0900
...
- if (strchr(WHITESPACE, p[e]))
- e++;
+ e += strspn(p + e, WHITESPACE);
commit 8595102d3ddde6d25c282f965573a6de34ab4421
Date: Fri Aug 10 11:07:54 2018 +0900
...
- e += strspn(p + e, WHITESPACE);
+ /* Single space is used as separator */
+ if (p[e] != '\0' && strchr(WHITESPACE, p[e]))
+ e++;

Créditos

Qualys Research Labs

Referência(s)

System Down: A systemd-journald exploit
https://seclists.org/oss-sec/2019/q1/54

journal: fix syslog_parse_identifier()
https://github.com/systemd/systemd/commit/a6aadf4ae0bae185dc4c414d492a4a781c80ffe5

journal: do not remove multiple spaces after identifier in syslog message
https://github.com/systemd/systemd/commit/8595102d3ddde6d25c282f965573a6de34ab4421

CVE-2018-16866
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16866

CVE-2018-16866
https://nvd.nist.gov/vuln/detail/CVE-2018-16866

Se encontrou algum erro neste alerta ou deseja uma análise compreensiva, entre em contato.

Última modificação: 31 janeiro 2019