TL;DR. I denne artikel undersøger vi sikkerhedsskemata (hardening schemes), der fungerer out-of-the-box i fem populære Linux-distributioner. For hver af dem har vi taget den standard kerne-konfiguration, installeret alle pakker og analyseret beskyttelsesskemaerne i de indlejrede binære filer. Distributionerne der undersøges er OpenSUSE 12.4, Debian 9, CentOS, RHEL 6.10 og 7, samt Ubuntu 14.04, 12.04 og 18.04 LTS.
Resultaterne bekræfter, at selv grundlæggende ordninger som stack canaries og position-independent code endnu ikke anvendes af alle. Situationen er endnu værre for compilerne, når det kommer til beskyttelse mod sårbarheder som stack clash, som kom i fokus i januar efter offentliggørelsen . Men alt er ikke håbløst. En betydelig del af binærerne implementerer grundlæggende beskyttelsesmetoder, og deres antal vokser fra version til version.
Undersøgelsen viste, at det største antal beskyttelsesmetoder er implementeret i Ubuntu 18.04 på OS- og applikationsniveau, efterfulgt af Debian 9. På den anden side implementeres der også grundlæggende beskyttelsesskemaer i OpenSUSE 12.4, CentOS 7 og RHEL 7, og beskyttelse mod stack clash anvendes endnu bredere med et langt mere tætsiddende sæt af standardpakker.
Introduktion
Det er svært at sikre høj kvalitet af software. På trods af det enorme antal avancerede værktøjer til statisk kodeanalyse og dynamisk analyse under kørsel, samt betydelige fremskridt i udviklingen af compilere og programmeringssprog, lider moderne software stadig af sårbarheder, der konstant udnyttes af angrebere. Situationen er endnu værre i økosystemer, der inkluderer forældet kode. I sådanne tilfælde står vi ikke kun over for det evige problem med at finde potentielle udnyttelige fejl, men er også begrænset af strenge krav om bagudkompatibilitet, som ofte kræver at begrænse, og endnu værre, sårbar eller buggede kode.
Her kommer metoderne til beskyttelse eller forstærkning af programmer (hardening) ind i billedet. Nogle typer fejl kan vi ikke forhindre, men vi kan gøre livet sværere for angriberen og delvist løse problemet ved at forhindre eller hindre. udnyttelse disse fejl. Denne beskyttelse anvendes i alle moderne operativsystemer, men metoderne varierer meget i kompleksitet, effektivitet og ydeevne: fra stack canaries og til fuldgyldige beskyttelser og . I denne artikel vil vi se på, hvilke beskyttelsesmetoder der anvendes i de mest populære Linux-distributioner i standardkonfigurationen, samt undersøge egenskaberne ved binære filer, der distribueres gennem pakkehåndteringssystemerne for hver distribution.
CVE og sikkerhed
Vi har alle set artikler med titler som "Årets mest sårbare applikationer" eller "De mest sårbare operativsystemer". Normalt indeholder de statistikker om det samlede antal registreringer af sårbarheder af typen , hentet fra fra og andre kilder. Disse applikationer eller operativsystemer rangeres derefter efter antallet af CVE. Desværre, selvom CVE er meget nyttige til at spore problemer og informere leverandører og brugere, siger de ikke meget om den reelle sikkerhed af software.
Som et eksempel vil vi se på det samlede antal CVE over de seneste fire år for Linux-kernen og fem af de mest populære server-distributioner, nemlig Ubuntu, Debian, Red Hat Enterprise Linux og OpenSUSE.

Fig. 1
Hvad fortæller denne graf os? Betyder et højere antal CVE, at en distribution er mere sårbar end en anden? Svaret er nej. For eksempel vil du i denne artikel se, at Debian implementerer strengere beskyttelsesmekanismer sammenlignet med for eksempel OpenSUSE eller RedHat Linux, og alligevel har Debian flere CVE. Men de betyder ikke nødvendigvis svækket sikkerhed: selv tilstedeværelsen af CVE indikerer ikke, om en sårbarhed kan udnyttes. Alvorlighedsscorer giver en indikation af, hvor sandsynligt det er, at en sårbarhed kan blive udnyttet, men i sidste ende afhænger udnytteligheden i høj grad af beskyttelsen i de berørte systemer samt ressourcerne og evnerne hos angriberne. Desuden siger fraværet af CVE-rapporter ikke noget om andre uregistrerede eller ukendte Sårbarheder. Forskellen i CVE kan forklares ikke ved kvaliteten af softwaren, men af andre faktorer, herunder de ressourcer, der er afsat til testning, eller størrelsen af brugerbasen. I vores eksempel kan det større antal CVE for Debian simpelthen indikere, at Debian leverer flere softwarepakker.
Selvfølgelig giver CVE-systemet nyttig information, der gør det muligt at skabe relevante beskyttelser. Jo bedre vi forstår årsagerne til programsvigt, desto lettere bliver det at identificere mulige angrebsmetoder og udvikle de relevante mekanismer. opdagelse og reaktion. Figur 2 viser kategorier af sårbarheder for alle distributioner over de sidste fire år (). Det er straks tydeligt, at de fleste CVE falder ind under følgende kategorier: tjenestenægtelse (DoS), udførelse af kode, buffer-overløb, hukommelseskorruption, lækage (ekskfiltrering) af oplysninger og privilegieforskydning. Selvom mange CVE er blevet registreret flere gange i forskellige kategorier, forbliver de samme problemer stort set uændrede år efter år. I næste del af artiklen vil vi vurdere brugen af forskellige beskyttelsesskemaer til at forhindre udnyttelse af de nævnte sårbarheder.

Figur 2
Opgaver
I denne artikel har vi til hensigt at besvare følgende spørgsmål:
- Hvor sikker er de forskellige Linux-distributioner? Hvilke beskyttelsesmekanismer findes i kernen og applikationerne i brugerrummet?
- Hvordan har accepten af beskyttelsesmekanismer ændret sig over tid for de forskellige distributioner?
- Hvad er de gennemsnitlige afhængigheder af pakker og biblioteker for hver distribution?
- Hvilke beskyttelser er implementeret for hver binærfil?
Valg af distributioner
Det viser sig at være svært at finde præcise statistikker over installationer af distributioner, da antallet af downloads i de fleste tilfælde ikke angiver antallet af faktiske installationer. Ikke desto mindre udgør Unix-mulighederne flertallet af serversystemer (69,2% på webservere, ifølge W3techs og andre kilder), og deres andel stiger konstant. Derfor har vi fokuseret vores forskning på distributioner, der er tilgængelige direkte fra leverandøren på platformen . Vi valgte specifikt følgende operativsystemer:
Distribution/version
Kernel
Byg
OpenSUSE 12.4
4.12.14-95.3-default
#1 SMP Wed Dec 5 06:00:48 UTC 2018 (63a8d29)
Debian 9 (stretch)
4.9.0-8-amd64
#1 SMP Debian 4.9.130-2 (2018-10-27)
CentOS 6.10
2.6.32-754.10.1.el6.x86_64
#1 SMP Tue Jan 15 17:07:28 UTC 2019
CentOS 7
3.10.0-957.5.1.el7.x86_64
#1 SMP Fri Feb 1 14:54:57 UTC 2019
Red Hat Enterprise Linux Server 6.10 (Santiago)
2.6.32-754.9.1.el6.x86_64
#1 SMP Wed Nov 21 15:08:21 EST 2018
Red Hat Enterprise Linux Server 7.6 (Maipo)
3.10.0-957.1.3.el7.x86_64
#1 SMP Thu Nov 15 17:36:42 UTC 2018
Ubuntu 14.04 (Trusty Tahr)
4.4.0–140-generic
#166~14.04.1-Ubuntu SMP Sat Nov 17 01:52:43 UTC 20…
Ubuntu 16.04 (Xenial Xerus)
4.15.0–1026-gcp
#27~16.04.1-Ubuntu SMP Fri Dec 7 09:59:47 UTC 2018
Ubuntu 18.04 (Bionic Beaver)
4.15.0–1026-gcp
#27-Ubuntu SMP Thu Dec 6 18:27:01 UTC 2018
Tabel 1
Analyse
Vi gennemgår standardkernens konfiguration samt egenskaberne for de pakker, der er tilgængelige gennem pakkemanagersystemet i hver distribution fra starten. På denne måde ser vi kun på pakker fra de standard spejle for hver distribution, mens vi ignorerer pakker fra ustabile repositories (som ‘testing’ spejle i Debian) og tredjepartspakker (som Nvidia-pakker fra standard spejle). Derudover ser vi ikke på brugercompilerede kerner eller konfigurationer med øget sikkerhed.
Analyse af kernens konfiguration
Vi har anvendt en analyzescript baseret på . Vi ser på de indbyggede sikkerhedsindstillinger for de nævnte distributioner og sammenligner dem med listen fra (KSPP). For hver konfigurationsparameter beskriver tabel 2 den ønskede indstilling: der er afkrydsning for de distributioner, der opfylder KSPP's anbefalinger (forklaring af termer ses ; i kommende artikler vil vi fortælle, hvordan mange af disse beskyttelsesmetoder blev til, og hvordan man kan hacke systemet, når de ikke er til stede).

Generelt har nye kerner mere strenge indstillinger fra starten. For eksempel har CentOS 6.10 og RHEL 6.10 på kerne 2.6.32 ikke de fleste kritiske funktioner, der er implementeret i nye kerner, såsom , strenge RWX tilladelser, adresse-randomisering eller copy2usr beskyttelse. Det skal bemærkes, at mange af konfigurationsmulighederne i tabellen mangler i ældre versioner af kernen og ikke er anvendelige i praksis - derfor angives der stadig mangel på tilstrækkelig beskyttelse. På samme måde, hvis en konfigurationsparameter mangler i denne version, men for sikkerhed skal denne parameter deaktiveres, så betragtes det som en fornuftig konfiguration.
En anden ting at overveje ved fortolkning af resultaterne: nogle kernekonfigurationer, der øger angrebsfladen, kan samtidig bruges til sikkerhed. Sådanne eksempler inkluderer uprobes og kprobes, kernelmoduler samt BPF/eBPF. Vores anbefaling er at anvende de nævnte mekanismer for at sikre reel beskyttelse, da de ikke er triviale at bruge, og deres udnyttelse forudsætter, at ondsindede aktører allerede har fået fodfæste i systemet. Men hvis disse indstillinger er aktiveret, skal systemadministratoren aktivt overvåge misbrug.
Når vi nærmere undersøger optagelserne i tabel 2, ser vi, at moderne kerner tilbyder flere muligheder for at beskytte mod udnyttelse af sårbarheder såsom informationslækager og stack/heap-overløb. Dog bemærker vi, at selv de nyeste populære distributioner endnu ikke har implementeret mere kompleks beskyttelse (for eksempel med patches ) eller moderne beskyttelse mod genbrug af kode (for eksempel, ). Hvad der er endnu værre, selv disse mere avancerede beskyttelsesmidler beskytter ikke mod det fulde spektrum af angreb. Derfor er det vitale for systemadministratorer at supplere rimelige konfigurationer med løsninger, der tilbyder detektion og forebyggelse af exploits under kørsel.
Applikationsanalyse
Det er ikke overraskende, at forskellige distributioner har forskellige pakkeegenskaber, kompilationsindstillinger, biblioteksafhængigheder osv. Forskelle findes selv for distributioner og pakker med få afhængigheder (for eksempel coreutils i Ubuntu eller Debian). For at vurdere forskellene har vi downloadet alle tilgængelige pakker, udtrukket deres indhold og analyseret binære filer og afhængigheder. For hver pakke sporede vi de andre pakker, som den afhænger af, og for hver binærfil sporede vi dens afhængigheder. I dette afsnit opsummerer vi konklusionerne.
Distributioner
I alt har vi downloadet 361.556 pakker til alle distributioner, idet vi kun har udvundet pakker fra standardspejle. Vi har ignoreret pakker uden eksekverbare ELF-filer, såsom kildekoder, skrifttyper osv. Efter filtrering er der tilbageholdt 129.569 pakker, som indeholder i alt 584.457 binære filer. Fordelingen af pakker og filer blandt distributionerne vises i Fig. 3.

Fig. 3
Det kan bemærkes, at jo mere moderne distributionen er, jo flere pakker og binære filer indeholder den, hvilket er logisk. Samtidig inkluderer pakkerne Ubuntu og Debian væsentligt flere binære filer (både eksekverbare og dynamiske moduler og biblioteker) end CentOS, SUSE og RHEL, hvilket potentielt øger angrebsoverfladen for Ubuntu og Debian (det skal bemærkes, at tallene afspejler alle binærfiler fra alle versioner af pakken, altså nogle filer analyseres flere gange). Dette er især vigtigt i betragtning af afhængighederne mellem pakkerne. En sårbarhed i binærfilerne fra én pakke kan påvirke mange dele af økosystemet, ligesom en sårbar biblioteksfil kan påvirke alle binære filer, der importerer den. Som et udgangspunkt ser vi på fordelingen af antallet af afhængigheder pr. pakke i forskellige OS:
Fig. 4
I næsten alle distributioner har 60% af pakkerne mindst 10 afhængigheder. Desuden har nogle pakker betydeligt flere afhængigheder (over 100). Det samme gælder for omvendte pakkeafhængigheder: som forventet anvendes flere pakker af mange andre pakker i distributionen, derfor er sårbarheder i disse få udvalgte pakker forbundet med høj risiko. Som et eksempel er der i den følgende tabel nævnt 20 pakker med det maksimale antal omvendte afhængigheder i SLES, CentOS 7, Debian 9 og Ubuntu 18.04 (i hver celle er angivet pakken og antallet af omvendte afhængigheder).

Tabel 3
Interessant faktum. Selvom alle de analyserede OS'er er bygget til x86_64-arkitekturen, og de fleste pakker er defineret som x86_64 og x86, indeholder pakkerne ofte binære filer til andre arkitekturer, som vist i Fig. 5.

Fig. 5
I det næste afsnit dykker vi ned i karakteristikaene ved de analyserede binære filer.
Statistik for beskyttelse af binære filer
Som det absolutte minimum skal du studere et grundlæggende sæt af beskyttelsesmetoder for eksisterende binære filer. Flere Linux-distributioner leveres med scripts, der udfører sådanne kontroller. For eksempel har Debian/Ubuntu sådan et script. Her er et eksempel på dets funktion:
$ hardening-check $(which docker)
/usr/bin/docker:
Position Independent Executable: yes
Stack protected: yes
Fortify Source functions: no, only unprotected functions found!
Read-only relocations: yes
Immediate binding: yesScriptet kontrollerer fem :
- Position Independent Executable (PIE): angiver, om tekstafsnittet af programmet kan flyttes i hukommelsen for at opnå randomisering, hvis ASLR er aktiveret i kernen.
- Stack Protected: er stackkanarier aktiveret til at beskytte mod stak-kollisionsangreb.
- Fortify Source: erstattes usikre funktioner (f.eks. strcpy) med deres mere sikre alternativer, og runtime-kald kontrolleres med deres usikre alternativer (f.eks. memcpy i stedet for __memcpy_chk).
- Read-only relocations (RELRO): er forsiden af relocation-table markeret som 'kun til læsning', hvis de blev aktiveret før programkørslen.
- Immediate binding (øjeblikkelig binding): tillader linkeren ved kørsel at løse alle relokationer før programmet kører (svarende til fuld RELRO).
Er de ovennævnte mekanismer tilstrækkelige? Desværre nej. Der er kendte måder at omgå alle ovenstående beskyttelser, men jo strammere beskyttelsen er, desto sværere bliver det for en angriber. For eksempel er sværere at anvende, når PIE og øjeblikkelig binding er aktiveret. Tilsvarende kræver fuld ASLR yderligere arbejde for at skabe et fungerende exploit. Dog er sofistikerede angribere allerede forberedt på sådanne forsvarsforanstaltninger: fraværet af dem vil i praksis fremskynde hackingen. Derfor er det ekstremt vigtigt, at disse foranstaltninger betragtes som nødvendige. mindst.
Vi ønskede at undersøge, hvor mange binære filer i de betragtede distributioner der er beskyttet af disse samt tre andre metoder:
- Ikke-udførelsebit () forhindrer udførelse i ethvert område, der ikke bør være udførbart, for eksempel i stakkens heap osv.
- angiver søgestien, der anvendes af den dynamiske loader til at finde de relevante biblioteker. Den første er obligatorisk for any modern system: its absence allows attackers to arbitrarily write payloads into memory and execute them as is. For the second, incorrect execution path configurations assist in introducing unreliable code, which can lead to a number of issues (for example, , samt ).
- Stack collision protection provides defense against attacks that cause the stack to overlap with other memory areas (for example, the heap). Given recent exploits that exploit , we deemed it appropriate to include this mechanism in our dataset.
So, without further ado, let's get to the numbers. Tables 4 and 5 provide a summary of the analysis of executable files and libraries from various distributions, respectively.
- As can be seen, NX protection is implemented everywhere, with few exceptions. Notably, its usage is somewhat lower in the Ubuntu and Debian distributions compared to CentOS, RHEL, and OpenSUSE.
- Stack canaries are missing in many places, especially in distributions with older kernels. Some progress is observed in the latest distributions of CentOS, RHEL, Debian, and Ubuntu.
- With the exception of Debian and Ubuntu 18.04, most distributions have poor PIE support.
- Stack collision protection is poorly implemented in OpenSUSE, CentOS 7, and RHEL 7, and is virtually absent in the others.
- All distributions with modern kernels have some support for RELRO, with Ubuntu 18.04 leading and Debian coming in second.
As mentioned earlier, the metrics in this table are averages across all versions of the binary file. If we look only at the latest versions of the files, the numbers will be different (for example, see ). Moreover, most distributions typically check the protection of only a few functions in binary code when calculating statistics, whereas our analysis specifies the true percentage of fortified functions. Therefore, if a binary has 5 out of 50 functions protected, we will assign it a score of 0.1, which corresponds to 10% fortified functions.

Table 4. Protection characteristics for executable files shown in Fig. 3 (implementation of corresponding functions as a percentage of the total number of executable files)

Tabel 5. Beskyttelsesegenskaber for biblioteker vist i fig. 3 (implementering af de relevante funktioner i procent af det samlede antal biblioteker)
Er der fremgang? Bestemt: det kan ses fra statistikken for de enkelte distributioner (for eksempel, ), samt fra de ovenfor nævnte tabeller. Som eksempel vises i fig. 6 implementeringen af beskyttelsesmekanismer i tre på hinanden følgende Ubuntu LTS 5 distributioner (vi har udeladt statistikken for beskyttelse mod stakoverløb). Vi bemærker, at fra version til version støtter flere og flere filer stakcanarier, og desuden leveres der gradvist flere binære filer med fuld RELRO-beskyttelse.
Fig. 6
Desværre har en række eksekverbare filer i forskellige distributioner stadig ikke nogen af de ovennævnte beskyttelser. For eksempel, hvis man ser på Ubuntu 18.04, kan man bemærke binæren ngetty (en erstatning for getty), såvel som skalene mksh og lksh, interpreter picolisp, pakkerne nvidia-cuda-toolkit (en populær pakke til GPU-accelererede applikationer, såsom maskinlæringsrammer) og klibc-utils. Tilsvarende leveres binæren mandos-client (et administrationsværktøj, der muliggør automatisk genstart af maskiner med krypterede filsystemer), samt rsh-redone-client (en genimplementering af rsh og rlogin) uden NX-beskyttelse, selvom de har SUID-rettigheder :(. Derudover har flere suid-binære filer ikke grundlæggende beskyttelse, såsom stakcanarier (for eksempel binærfilen Xorg.wrap fra Xorg-pakken).
Resumé og afsluttende bemærkninger
I denne artikel fremhæver vi flere sikkerhedsegenskaber ved moderne Linux-distributioner. Analysen viser, at den seneste distribution af Ubuntu LTS (18.04) i gennemsnit har det stærkeste niveau af OS- og applikationsbeskyttelse blandt distributioner med relativt nye kerner, såsom Ubuntu 14.04, 12.04 og Debian 9. Dog leverer de overvejede distributioner CentOS, RHEL og OpenSUSE i vores datasæt som standard et mere tæt sæt pakker, og de seneste versioner (CentOS og RHEL) har en højere procentdel af implementering af beskyttelse mod stack-kollidering sammenlignet med konkurrenter baseret på Debian (Debian og Ubuntu). Når vi sammenligner versionerne CentOS og RedHat, bemærker vi store forbedringer i implementeringen af stack canaries og RELRO fra version 6 til 7, men i gennemsnit er der implementeret flere funktioner i CentOS end i RHEL. Generelt bør alle distributioner have særlig fokus på PIE-beskyttelse, som, undtagen Debian 9 og Ubuntu 18.04, er implementeret i mindre end 10% af de binære filer i vores datasæt.
Endelig skal det bemærkes: selvom vi udførte undersøgelsen manuelt, findes der mange sikkerhedsværktøjer (for eksempel, , , ), som udfører analyser og hjælper med at undgå usikre konfigurationer. Desværre garanterer selv stærk beskyttelse med rimelige konfigurationer ikke fraværet af exploits. Derfor er vi fast overbevist om, at det er afgørende at sikre , med fokus på udnyttelsesmønstre og forhindring af dem.
Kilde: habr.com
