Kto się boi duchów – resztki po GHOST
Ostatnie dni stały pod znakiem sensacyjnego, bo 14-letniego błędu w bibliotece glibc, która czyniła większość dystrybucji linuksowych podatnymi na zdalny atak. Jak to zwykle bywa, błąd został poprawiony niemal z dnia na dzień, a nawet i rok wcześniej (Google naprawiło glibc w Chrome OS i nikomu się nie pochwaliło). Na dodatek, większość współczesnych dystrybucji nie jest rozprowadzana z tym błędem, zatem i poprawki nie są potrzebne. Kto więc jest zagrożony i powinien się naprawiać?
Błąd o kryptonimie GHOST to typowe wykorzystanie przepełnienia bufora (buffer overflow). A można do niego doprowadzić wykorzystując luki w funkcji __nss_hostname_digits_dots() biblioteki glibc. Służy ona do translacji nazw DNS na adresy IP (i na odwrót). Tym samym podatne na ew. zdalny atak są wszystkie programy/usługi korzystające z protokołu DNS i funkcje gethostbyname*(). W momencie ogłoszenia luki podatne na nią były dystrybucje użytkujące starsze wersje glibc:
- RHEL (Red Hat Enterprise Linux) version 5.x, 6.x and 7.x
- CentOS Linux version 5.x, 6.x & 7.x
- Ubuntu Linux version 10.04, 12.04 LTS
- Debian Linux version 7.x
- Linux Mint version 13.0
- Fedora Linux version 19 or older
- SUSE Linux Enterprise 11 and older (also OpenSuse Linux 11 or older versions).
- SUSE Linux Enterprise Software Development Kit 11 SP3
- SUSE Linux Enterprise Server 11 SP3 for VMware
- SUSE Linux Enterprise Server 11 SP3
- SUSE Linux Enterprise Server 11 SP2 LTSS
- SUSE Linux Enterprise Server 11 SP1 LTSS
- SUSE Linux Enterprise Server 10 SP4 LTSS
- SUSE Linux Enterprise Desktop 11 SP3
- Arch Linux glibc version <= 2.18-1
Należy zaznaczyć, że najpopularniejsze Ubuntu 14.04/14.10 nie są podatne na wspomnianą przypadłość.
Aby sprawdzić, czy nasza maszyna jest podatna na tego rodzaju ataki, możemy wykorzystać poniższy kod:
#include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define CANARY "in_the_coal_mine" struct { char buffer[1024]; char canary[sizeof(CANARY)]; } temp = { "buffer", CANARY }; int main(void) { struct hostent resbuf; struct hostent *result; int herrno; int retval; /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/ size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1; char name[sizeof(temp.buffer)]; memset(name, '0', len); name[len] = '\0'; retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno); if (strcmp(temp.canary, CANARY) != 0) { puts("vulnerable"); exit(EXIT_SUCCESS); } if (retval == ERANGE) { puts("not vulnerable"); exit(EXIT_SUCCESS); } puts("should not happen"); exit(EXIT_FAILURE); }
Wystarczy pobrać, skompilować i uruchomić. Martwimy się, jeżeli wynikiem będzie komunikat „vulnerable”. W tym przypadku należy zaktualizować w swojej dystrybucji glibc.
W większości starszych dystrybucji (wspieranych) powinna wystarczyć typowa aktualizacja. Np. Ubuntu 10.04/12.04/Debian:
sudo apt-get clean
sudo apt-get update
sudo apt-get upgrade
I gotowe. Znaleziona luka z pewnością może wydać się sporym ciosem w bezpieczeństwo Linuksa, jednak należy pamiętać, że poprawki dla tego błędu pojawiły się już jakiś czas temu, choć sam błąd nie został uznany za krytyczny. Starsze dystrybucje otrzymały poprawki niemal z dnia na dzień.