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: 14 agosto 2019

Não somos responsáveis por qualquer perda de dados, corrupção de dispositivos ou qualquer outro tipo de problema devido ao uso de qualquer informação mencionada em nossos alertas de segurança.