GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Identifizieren Sie Sicherheitseigenschaften unter Linux mit checksec

Das Kompilieren des Quellcodes erzeugt eine Binärdatei. Während der Kompilierung können Sie dem Compiler Flags bereitstellen, um bestimmte Eigenschaften der Binärdatei zu aktivieren oder zu deaktivieren. Einige dieser Eigenschaften sind sicherheitsrelevant.

Checksec ist ein raffiniertes kleines Tool (und Shell-Skript), das neben anderen Funktionen die Sicherheitseigenschaften identifiziert, die in eine Binärdatei eingebaut wurden, als sie kompiliert wurde. Ein Compiler aktiviert möglicherweise einige dieser Eigenschaften standardmäßig, und Sie müssen möglicherweise bestimmte Flags bereitstellen, um andere zu aktivieren.

Dieser Artikel erklärt, wie man checksec verwendet, um die Sicherheitseigenschaften einer Binärdatei zu identifizieren, einschließlich:

  1. Die zugrunde liegenden Befehle, die checksec verwendet, um Informationen zu den Sicherheitseigenschaften zu finden
  2. So aktivieren Sie Sicherheitseigenschaften mit der GNU Compiler Collection (GCC) beim Kompilieren einer Beispielbinärdatei

Checksec installieren

Um checksec auf Fedora und anderen RPM-basierten Systemen zu installieren, verwenden Sie:

$ sudo dnf install checksec 

Verwenden Sie für Debian-basierte Distributionen das entsprechende apt Befehl.

Das Shell-Skript

Checksec ist ein Single-File-Shell-Skript, wenn auch ein ziemlich großes. Ein Vorteil ist, dass Sie das Skript schnell durchlesen und alle Systembefehle verstehen können, die ausgeführt werden, um Informationen über Binärdateien oder ausführbare Dateien zu finden:

$-Datei /usr/bin/checksec
/usr/bin/checksec:Bourne-Again-Shell-Skript, ausführbarer ASCII-Text, mit sehr langen Zeilen

$ wc -l /usr /bin/checksec
2111 /usr/bin/checksec

Nehmen Sie checksec für ein Laufwerk mit einer Binärdatei, die Sie wahrscheinlich täglich ausführen:das allgegenwärtige ls Befehl. Das Format des Befehls ist checksec --file= gefolgt vom absoluten Pfad des ls binär:

 $ checksec --file =/ usr / bin / ls 
Relro-Stapel Kanarische NX-Pie REPPPLATE RUNPATH-Symbole Festung befestigungsfähige felifierbare Datei
Full Relro Canary gefunden NX-fähiger Pie Aktiviert Nein RPPath Kein Laufpfad Keine Symbole Ja 5       17              /usr/bin/ls

Wenn Sie dies in einem Terminal ausführen, sehen Sie eine Farbcodierung, die zeigt, was gut ist und was wahrscheinlich nicht. Ich sage "wahrscheinlich", denn selbst wenn etwas rot ist, bedeutet das nicht unbedingt, dass die Dinge schrecklich sind - es könnte nur bedeuten, dass die Distributionsanbieter beim Kompilieren der Binärdateien Kompromisse eingegangen sind.

Die erste Zeile stellt verschiedene Sicherheitseigenschaften bereit, die normalerweise für Binärdateien verfügbar sind, wie RELRO , STACK CANARY , NX , und so weiter (ich erkläre es weiter unten im Detail). Die zweite Zeile zeigt den Status dieser Eigenschaften für die angegebene Binärdatei (ls , in diesem Fall). Beispiel:NX enabled bedeutet, dass einige Eigenschaften für diese Binärdatei aktiviert sind.

Eine Beispiel-Binärdatei

Für dieses Tutorial verwende ich das folgende "Hello World"-Programm als Beispielbinärdatei.

#include 

int main()
{
        printf("Hello World\n");
        return 0;
}
 

Beachten Sie, dass ich gcc nicht angegeben habe mit allen zusätzlichen Flags während der Kompilierung:

$ gcc hello.c -o hallo
 
$ file hallo
hello:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch verknüpft, Interpreter / lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, für GNU/Linux 3.2.0, nicht entfernt

$ ./hello
Hello World

Führen Sie die Binärdatei durch checksec. Einige der Eigenschaften sind anders als bei ls Befehl oben (auf Ihrem Bildschirm werden diese möglicherweise rot angezeigt):

 $ CheckSec --file =. / Hallo 
Relro-Stapelkanarare NX Pie RPPath-Laufwerk-Symbole anständig befestigungsfähige felifierbare Datei
Partial Relro No Canary gefunden 0./Hallo
$

Ändern des Ausgabeformats

Checksec erlaubt verschiedene Ausgabeformate, die Sie mit --output festlegen können . Ich wähle das JSON-Format und leite die Ausgabe an jq weiter Dienstprogramm für hübsches Drucken.

Um mitzumachen, stellen Sie sicher, dass Sie jq haben installiert, da dieses Tutorial dieses Ausgabeformat verwendet, um schnell nach bestimmten Eigenschaften aus der Ausgabe zu suchen und yes zu melden oder no jeweils:

$ checksec --file=./hello --output=json | jq
{
  "./hello":{
    "relro":"partial",
    "canary":"no",
    "nx":" ja",
    "pie":"nein",
    "rpath":"nein",
    "runpath":"nein",
    "symbols":"ja" ,
    "fortify_source":"no",
    "fortified":"0",
    "fortify-able":"0"
  }
}

Durch die Sicherheitseigenschaften gehen

Mehr zur Sicherheit

  • Der defensive Programmierleitfaden
  • Webinar:Automatisierung der Systemsicherheit und Compliance mit einem Standardbetriebssystem
  • 10 Ebenen der Linux-Containersicherheit
  • SELinux-Malbuch
  • Weitere Sicherheitsartikel

Die obige Binärdatei enthält mehrere Sicherheitseigenschaften. Ich werde diese Binärdatei mit ls vergleichen binär oben, um zu untersuchen, was aktiviert ist, und zu erklären, wie checksec diese Informationen gefunden hat.

1. Symbole

Ich fange erstmal mit dem einfachen an. Während der Kompilierung werden bestimmte Symbole in die Binärdatei aufgenommen, hauptsächlich zum Debuggen. Diese Symbole sind erforderlich, wenn Sie Software entwickeln, und erfordern mehrere Zyklen zum Debuggen und Beheben von Problemen.

Diese Symbole werden normalerweise aus der endgültigen Binärdatei entfernt (entfernt), bevor sie zur allgemeinen Verwendung freigegeben wird. Dies wirkt sich in keiner Weise auf die Ausführung der Binärdatei aus; es läuft genauso wie mit den Symbolen. Das Strippen wird oft durchgeführt, um Platz zu sparen, da die Binärdatei nach dem Strippen der Symbole etwas leichter ist. In Closed-Source- oder proprietärer Software werden Symbole häufig entfernt, da diese Symbole in einer Binärdatei es etwas einfacher machen, auf das Innenleben der Software zu schließen.

Laut checksec sind Symbole in dieser Binärdatei vorhanden, aber sie waren nicht in ls binär. Sie können diese Informationen auch finden, indem Sie die file ausführen Befehl im Programm – Sie sehen not stripped in der Ausgabe gegen Ende:

$ checksec --file=/bin/ls --output=json | jq | grep-Symbole
    "symbols":"no",

$ checksec --file=./hello --output=json | jq | grep symbole
    "symbols":"yes",

$ file hallo
hallo:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch verknüpft , Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, für GNU/Linux 3.2.0, nicht entfernt

Wie hat checksec diese Informationen gefunden? Nun, es bietet ein praktisches --debug Option, um anzuzeigen, welche Funktionen ausgeführt wurden. Daher sollte Ihnen das Ausführen des folgenden Befehls zeigen, welche Funktionen innerhalb des Shell-Skripts ausgeführt wurden:

$ checksec --debug --file=./hello 

In diesem Lernprogramm suche ich nach den zugrunde liegenden Befehlen, mit denen diese Informationen gefunden werden. Da es sich um ein Shell-Skript handelt, können Sie immer Bash-Funktionen nutzen. Dieser Befehl gibt jeden Befehl aus, der innerhalb des Shell-Skripts ausgeführt wurde:

$ bash -x /usr/bin/checksec --file=./hello 

Wenn Sie durch die Ausgabe scrollen, sollten Sie eine echo_message sehen gefolgt von der Kategorie der Sicherheitseigenschaft. Hier ist, was checksec darüber berichtet, ob die Binärdatei Symbole enthält:

+ readelf -W --symbols ./hello
+ grep -q '\.symtab'
+ echo_message '\033[31m96) Symbols\t\033[m  ' Symbole, ' Symbole ="ja"' '"symbole":"ja",'

Um dies zu vereinfachen, verwendet checksec das readelf Dienstprogramm zum Lesen der Binärdatei und bietet einen speziellen --symbols Flag, das alle Symbole innerhalb der Binärdatei auflistet. Dann sucht es nach einem speziellen Wert, .symtab , das die Anzahl der gefundenen Einträge (Symbole) angibt. Sie können die folgenden Befehle an der oben kompilierten Test-Binärdatei ausprobieren:

$ readelf -W --symbols ./hello
$ readelf -W --symbols ./hello | grep -i symtab

So entfernen Sie Symbole

Sie können Symbole nach der Kompilierung oder während der Kompilierung entfernen.

  • Beitragskompilierung: Nach der Kompilierung können Sie den strip verwenden Dienstprogramm auf der Binärdatei, um die Symbole zu entfernen. Bestätigen Sie, dass es funktioniert hat, indem Sie die file verwenden Befehl, der die Ausgabe jetzt als stripped anzeigt :
    $ gcc hello.c -o hallo
    $
    $ file hallo
    hallo:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV) , dynamisch verknüpft, Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, für GNU/Linux 3.2.0, nicht entfernt
    $
    $ strip hallo
    $
    $ file hallo
    hallo:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch gelinkt, Interpreter /lib64/ld-linux-x86-64.so .2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, für GNU/Linux 3.2.0, entfernt
    $

So entfernen Sie Symbole während der Kompilierung

Anstatt Symbole nach der Kompilierung manuell zu entfernen, können Sie den Compiler bitten, dies für Sie zu tun, indem Sie das -s angeben Argument:

$ gcc -s hallo.c -o hallo
$
$ file hallo
hallo:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch gelinkt , Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=247de82a8ad84e7d8f20751ce79ea9e0cf4bd263, für GNU/Linux 3.2.0, entfernt
$

Nach dem erneuten Ausführen von checksec können Sie diese symbols sehen werden als no angezeigt :

$ checksec --file=./hello --output=json | jq | grep-Symbole
    "symbols":"no",
$

2. Kanarienvogel

Kanarienvögel sind bekannte Werte, die zwischen einem Puffer und Steuerdaten auf dem Stack platziert werden um Pufferüberläufe zu überwachen. Wenn eine Anwendung ausgeführt wird, werden ihr zwei Arten von Speicher zugewiesen. Einer davon ist ein Stapel , die einfach eine Datenstruktur mit zwei Operationen ist:push , das Daten auf den Stack legt, und pop , wodurch Daten in umgekehrter Reihenfolge aus dem Stack entfernt werden. Schädliche Eingaben könnten den Stapel mit speziell präparierten Eingaben überlaufen oder beschädigen und das Programm zum Absturz bringen:

$ checksec --file=/bin/ls --output=json | jq | grep canary
    "canary":"yes",
$
$ checksec --file=./hello --output=json | jq | grep canary
    "canary":"no",
$

Wie findet checksec heraus, ob die Binärdatei mit einem Canary aktiviert ist? Mit der obigen Methode können Sie es eingrenzen, indem Sie den folgenden Befehl im Shell-Skript ausführen:

$ readelf -W -s ./hello | grep -E '__stack_chk_fail|__intel_security_cookie' 

Canary aktivieren

Zum Schutz vor diesen Fällen stellt der Compiler den -stack-protector-all bereit Flag, das der Binärdatei zusätzlichen Code hinzufügt, um nach solchen Pufferüberläufen zu suchen:

$ gcc -fstack-protector-all hello.c -o hallo

$ checksec --file=./hello --output=json | jq | grep canary
    "canary":"yes",

Checksec zeigt, dass die Eigenschaft jetzt aktiviert ist. Sie können dies auch überprüfen mit:

$ readelf -W -s ./hello | Grep-t '__stack_chk_fail | __intel_security_cookie' 
2:000000000000000000 0 Func global Standard und __stack_chk_fail@glibc_2.4 (3)
83:000000000000000000 0 func global default und __stack_chk_fail @@ glibc_2.4
$

3. TORTE

PIE steht für positionsunabhängige ausführbare Datei. Wie der Name schon sagt, handelt es sich um Code, der unabhängig von seiner absoluten Adresse irgendwo im Speicher zur Ausführung abgelegt wird:

$ checksec --file=/bin/ls --output=json | jq | grep pie
    "pie":"ja",

$ checksec --file=./hello --output=json | jq | grep pie
    "pie":"nein",

Häufig wird PIE nur für Bibliotheken und nicht für eigenständige Befehlszeilenprogramme aktiviert. In der Ausgabe unten hello wird als LSB executable angezeigt , wohingegen die libc Standardbibliothek (.so )-Datei ist als LSB shared object gekennzeichnet :

$ Datei Hallo
Hallo:ELF 64-Bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch verlinkt, Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[ sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, für GNU/Linux 3.2.0, nicht entfernt

$ file /lib64/libc-2.32.so
/lib64/libc-2.32.so:ELF 64-bit Gemeinsam genutztes LSB-Objekt, x86-64, Version 1 (GNU/Linux), dynamisch verknüpft, Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4a7fb374097fb927fb93d35ef98ba89262d0c4a4, für GNU/Linux 3.2.0, nicht gestrippt

Checksec versucht diese Informationen zu finden mit:

$ readelf -W -h ./hallo | grep EXEC
  Typ:                             EXEC (ausführbare Datei)

Wenn Sie denselben Befehl in einer gemeinsam genutzten Bibliothek anstelle von EXEC versuchen , sehen Sie ein DYN :

$ readelf -W -h /lib64/libc-2.32.so | grep DYN
  Typ:                             DYN (Shared Object File)

PIE aktivieren

Um PIE in einem Testprogramm zu aktivieren, senden Sie die folgenden Argumente an den Compiler:

$ gcc -pie -fpie hello.c -o hello 

Sie können mit checksec:

überprüfen, ob PIE aktiviert ist
$ checksec --file=./hello --output=json | jq | grep pie
    "pie":"ja",
$

Es sollte als ausführbare PIE-Datei angezeigt werden, deren Typ sich von EXEC geändert hat zu DYN :

$ file hallo
hallo:ELF 64-Bit LSB Pie ausführbar, x86-64, Version 1 (SYSV), dynamisch verknüpft, Interpreter /lib64/ld-linux-x86-64.so.2, BuildID [sha1]=bb039adf2530d97e02f534a94f0f668cd540f940, für GNU/Linux 3.2.0, nicht entfernt

$ readelf -W -h ./hello | grep DYN
  Typ:                             DYN (Shared Object File)

4. NX

NX steht für „nicht ausführbar“. Es wird oft auf CPU-Ebene aktiviert, sodass ein Betriebssystem mit aktiviertem NX bestimmte Speicherbereiche als nicht ausführbar markieren kann. Pufferüberlauf-Exploits legen häufig Code auf dem Stack ab und versuchen dann, ihn auszuführen. Wenn Sie diesen beschreibbaren Bereich jedoch nicht ausführbar machen, können Sie solche Angriffe verhindern. Diese Eigenschaft ist standardmäßig während der regulären Kompilierung mit gcc aktiviert :

$ checksec --file=/bin/ls --output=json | jq | grep nx
    "nx":"ja",

$ checksec --file=./hello --output=json | jq | grep nx
    "nx":"ja",

Checksec ermittelt diese Informationen mit dem folgenden Befehl. RW gegen Ende bedeutet, dass der Stack lesbar und beschreibbar ist; da es kein E gibt , es ist nicht ausführbar:

$ readelf -W -l ./Hallo | grep GNU_STACK
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

NX für Demozwecke deaktivieren

Es wird nicht empfohlen, aber Sie können NX deaktivieren beim Kompilieren eines Programms mit dem -z execstack Argument:

$ gcc -z execstack hallo.c -o hallo

$ checksec --file=./hello --output=json | jq | grep nx
    "nx":"nein",

Nach dem Kompilieren wird der Stack ausführbar (RWE ), wodurch schädlicher Code ausgeführt werden kann:

$ readelf -W -l ./Hallo | grep GNU_STACK
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

5. RELRO

RELRO steht für Relocation Read-Only. Eine ELF-Binärdatei (Executable Linkable Format) verwendet eine Global-Offset-Tabelle (GOT), um Funktionen dynamisch aufzulösen. Wenn diese Sicherheitseigenschaft aktiviert ist, macht sie das GOT innerhalb der Binärdatei schreibgeschützt, was irgendeine Form von Verschiebungsangriffen verhindert:

$ checksec --file=/bin/ls --output=json | jq | grep relro
    "relro":"full",

$ checksec --file=./hello --output=json | jq | grep relro
    "relro":"teilweise",

Checksec findet diese Informationen mit dem folgenden Befehl. Hier wird eine der RELRO-Eigenschaften aktiviert; Daher zeigt die Binärdatei "teilweise" an, wenn sie über checksec verifiziert wird:

$ readelf -W -l ./Hallo | grep GNU_RELRO
  GNU_RELRO      0x002e10 0x0000000000403e10 0x0000000000403e10 0x0001f0 0x0001f0 R   0x1

$ readelf -W -d ./hello | grep BIND_NOW

Vollständiges RELRO aktivieren

Um das vollständige RELRO zu aktivieren, verwenden Sie beim Kompilieren mit gcc die folgenden Befehlszeilenargumente :

$ gcc -Wl,-z,relro,-z,jetzt hallo.c -o hallo

$ checksec --file=./hello --output=json | jq | grep relro
    "relro":"voll",

Jetzt ist auch die zweite Eigenschaft aktiviert, wodurch das Programm vollständig RELRO wird:

$ readelf -W -l ./Hallo | grep GNU_RELRO
  GNU_RELRO      0x002dd0 0x0000000000403dd0 0x0000000000403dd0 0x000230 0x000230 R   0x1

$ readelf -W -d ./hello | grep BIND_NOW
 0x0000000000000018 (BIND_NOW)          

6. Stärken

Fortify ist eine weitere Sicherheitseigenschaft, die jedoch in diesem Artikel nicht behandelt wird. Ich werde lernen, wie checksec Fortify in Binärdateien überprüft und wie es mit gcc aktiviert wird als Übung für Sie.

$ checksec --file=/bin/ls --output=json | jq | grep -i forti
    "fortify_source":"yes",
    "fortified":"5",
    "fortify-able":"17"

$ checksec --file=./hello --output=json | jq | grep -i forti
    "fortify_source":"no",
    "fortified":"0",
    "fortify-able":"0"

Weitere Checksec-Funktionen

Das Thema Sicherheit ist endlos, und obwohl es hier nicht möglich ist, alles abzudecken, möchte ich doch noch ein paar weitere Funktionen von checksec erwähnen Befehle, mit denen es ein Vergnügen ist, damit zu arbeiten.

Mit mehreren Binärdateien ausführen

Sie müssen Checksec nicht jede Binärdatei einzeln zur Verfügung stellen. Stattdessen können Sie einen Verzeichnispfad angeben, in dem sich mehrere Binärdateien befinden, und checksec überprüft sie alle auf einmal:

$ checksec --dir=/usr/bin 

Prozesse

Neben Binärdateien arbeitet checksec auch an Programmen während der Ausführung. Der folgende Befehl findet die Sicherheitseigenschaften aller laufenden Programme auf Ihrem System. Sie können --proc-all verwenden wenn Sie möchten, dass alle laufenden Prozesse überprüft werden, oder Sie können einen bestimmten Prozess anhand seines Namens auswählen:

$ checksec --proc-all

$ checksec --proc=bash

Kernel-Eigenschaften

Zusätzlich zu den in diesem Artikel beschriebenen Userland-Anwendungen von checksec können Sie damit auch die in Ihrem System integrierten Kernel-Eigenschaften überprüfen:

$ checksec --kernel 

Probieren Sie es aus

Checksec ist ein guter Weg, um zu verstehen, welche Userland- und Kernel-Eigenschaften aktiviert sind. Gehen Sie jede Sicherheitseigenschaft im Detail durch und versuchen Sie, die Gründe für die Aktivierung jeder Funktion und die Arten von Angriffen zu verstehen, die sie verhindert.


Linux
  1. 13 Linux-Sicherheits-Tutorials

  2. 50 UNIX / Linux Sysadmin-Tutorials

  3. Kali Linux auf Android mit Linux Deploy

  4. Beispiele für die Verwendung des Befehls dmsetup unter Linux

  5. Beispiel für die Verwendung von getnstimeofday im Linux-Kernel

Installieren Sie MongoDB mit Vagrant unter Linux

15 Dinge, die Sie vor der Verwendung von Kali Linux wissen sollten

Verwenden der SSH-Portweiterleitung als Sicherheitstool unter Linux

Verwenden des Watch-Befehls unter Linux

Cut auf Linux Terminal verwenden

Linux vs. Windows-Sicherheit