GNU/Linux >> Belajar Linux >  >> Linux

Identifikasi properti keamanan di Linux menggunakan checksec

Kompilasi kode sumber menghasilkan biner. Selama kompilasi, Anda dapat memberikan flag ke kompiler untuk mengaktifkan atau menonaktifkan properti tertentu pada biner. Beberapa properti ini relevan dengan keamanan.

Checksec adalah alat kecil yang bagus (dan skrip shell) yang, di antara fungsi lainnya, mengidentifikasi properti keamanan yang dibangun ke dalam biner saat dikompilasi. Kompilator mungkin mengaktifkan beberapa properti ini secara default, dan Anda mungkin harus memberikan tanda khusus untuk mengaktifkan yang lain.

Artikel ini menjelaskan cara menggunakan checksec untuk mengidentifikasi properti keamanan pada biner, termasuk:

  1. Perintah dasar yang digunakan checksec untuk menemukan informasi tentang properti keamanan
  2. Cara mengaktifkan properti keamanan menggunakan GNU Compiler Collection (GCC) saat mengompilasi biner sampel

Instal checksec

Untuk menginstal checksec di Fedora dan sistem berbasis RPM lainnya, gunakan:

$ sudo dnf install checksec 

Untuk distro berbasis Debian, gunakan yang setara dengan apt perintah.

Skrip shell

Checksec adalah skrip shell file tunggal, meskipun agak besar. Keuntungannya adalah Anda dapat membaca skrip dengan cepat dan memahami semua perintah sistem yang berjalan untuk menemukan informasi tentang binari atau yang dapat dieksekusi:

$ file /usr/bin/checksec
/usr/bin/checksec:Bourne-Again shell script, teks ASCII dapat dieksekusi, dengan garis yang sangat panjang

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

Ambil checksec untuk drive dengan biner yang mungkin Anda jalankan setiap hari:ls yang ada di mana-mana memerintah. Format perintahnya adalah checksec --file= diikuti oleh path absolut dari ls biner:

 $ checksec --file =/ usr / bin / ls 
relro tumpukan canary nx pie rahkan runpath simbol fortify fortified file borden 5       17              /usr/bin/ls

Ketika Anda menjalankan ini di terminal, Anda melihat kode warna yang menunjukkan apa yang baik dan apa yang mungkin tidak. Saya katakan "mungkin" karena meskipun ada sesuatu yang berwarna merah, itu tidak selalu berarti hal-hal yang buruk—itu mungkin hanya berarti vendor distro membuat beberapa pengorbanan saat mengkompilasi binari.

Baris pertama menyediakan berbagai properti keamanan yang biasanya tersedia untuk biner, seperti RELRO , STACK CANARY , NX , dan seterusnya (saya jelaskan secara rinci di bawah). Baris kedua menunjukkan status properti ini untuk biner yang diberikan (ls , pada kasus ini). Misalnya, NX enabled berarti beberapa properti diaktifkan untuk biner ini.

Biner sampel

Untuk tutorial ini, saya akan menggunakan program "hello world" berikut sebagai contoh biner.

#include 

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

Perhatikan bahwa saya tidak memberikan gcc dengan tanda tambahan apa pun selama kompilasi:

$ gcc hello.c -o hello
 
$ file hello
hello:ELF 64-bit LSB yang dapat dieksekusi, x86-64, versi 1 (SYSV), tertaut secara dinamis, penerjemah / lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, untuk GNU/Linux 3.2.0, tidak dilucuti

$ ./hello
Halo Dunia

Jalankan biner melalui checksec. Beberapa properti berbeda dengan ls perintah di atas (di layar Anda, ini mungkin ditampilkan dengan warna merah):

 $ checksec --file =. / / hello 0./halo
$

Mengubah format keluaran

Checksec memungkinkan berbagai format keluaran, yang dapat Anda tentukan dengan --output . Saya akan memilih format JSON dan menyalurkan output ke jq utilitas untuk pencetakan cantik.

Untuk mengikuti, pastikan Anda memiliki jq diinstal karena tutorial ini menggunakan format output ini untuk dengan cepat mengambil properti tertentu dari output dan melaporkan yes atau no pada setiap:

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

Menelusuri properti keamanan

Selengkapnya tentang keamanan

  • Panduan pengkodean defensif
  • Webinar:Mengotomatiskan keamanan sistem dan kepatuhan dengan sistem operasi standar
  • 10 lapisan keamanan kontainer Linux
  • Buku mewarnai SELinux
  • Artikel keamanan lainnya

Biner di atas mencakup beberapa properti keamanan. Saya akan membandingkan biner itu dengan ls biner di atas untuk memeriksa apa yang diaktifkan dan menjelaskan bagaimana checksec menemukan informasi ini.

1. Simbol

Saya akan mulai dengan yang mudah dulu. Selama kompilasi, simbol-simbol tertentu disertakan dalam biner, sebagian besar untuk debugging. Simbol-simbol ini diperlukan saat Anda mengembangkan perangkat lunak dan memerlukan beberapa siklus untuk men-debug dan memperbaiki berbagai hal.

Simbol-simbol ini biasanya dilucuti (dihapus) dari biner terakhir sebelum dirilis untuk penggunaan umum. Ini tidak mempengaruhi eksekusi biner dengan cara apapun; itu akan berjalan seperti halnya dengan simbol. Stripping sering dilakukan untuk menghemat ruang, karena biner agak lebih ringan setelah simbol dilucuti. Dalam perangkat lunak sumber tertutup atau berpemilik, simbol sering kali dihilangkan karena memiliki simbol ini dalam biner membuatnya agak mudah untuk menyimpulkan cara kerja bagian dalam perangkat lunak.

Menurut checksec, simbol ada dalam biner ini, namun tidak ada di ls biner. Anda juga dapat menemukan informasi ini dengan menjalankan file perintah pada program—Anda melihat not stripped di output menjelang akhir:

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

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

$ file halo
halo:LSB 64-bit ELF yang dapat dieksekusi, x86-64, versi 1 (SYSV), tertaut secara dinamis , interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, untuk GNU/Linux 3.2.0, tidak dihapus

Bagaimana checksec menemukan informasi ini? Nah, ini menyediakan --debug yang praktis opsi untuk menunjukkan fungsi mana yang dijalankan. Oleh karena itu, menjalankan perintah berikut akan menunjukkan kepada Anda fungsi mana yang dijalankan dalam skrip shell:

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

Dalam tutorial ini, saya mencari perintah dasar yang digunakan untuk menemukan informasi ini. Karena ini adalah skrip shell, Anda selalu dapat memanfaatkan fitur Bash. Perintah ini akan menampilkan setiap perintah yang dijalankan dari dalam skrip shell:

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

Jika Anda men-scroll output, Anda akan melihat echo_message diikuti oleh kategori properti keamanan. Berikut adalah laporan checksec tentang apakah biner berisi simbol:

+ readelf -W --symbols ./hello
+ grep -q '\.symtab'
+ echo_message '\033[31m96) Simbol\t\033[m  ' Simbol, ' simbol ="ya"' '"simbol":"ya",'

Untuk menyederhanakan ini, checksec menggunakan readelf utilitas untuk membaca biner dan menyediakan --symbols khusus flag yang mencantumkan semua simbol dalam biner. Kemudian ia mengambil nilai khusus, .symtab , yang memberikan jumlah entri (simbol) yang ditemukannya. Anda dapat mencoba perintah berikut pada biner uji yang Anda kompilasi di atas:

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

Cara menghapus simbol

Anda dapat menghapus simbol setelah kompilasi atau selama kompilasi.

  • Kompilasi pos: Setelah kompilasi, Anda dapat menggunakan strip utilitas pada biner untuk menghapus simbol. Konfirmasikan itu berfungsi menggunakan file perintah, yang sekarang menampilkan output sebagai stripped :
    $ gcc hello.c -o hello
    $
    $ file hello
    hello:ELF 64-bit LSB dapat dieksekusi, x86-64, versi 1 (SYSV) , terkait secara dinamis, penerjemah /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, untuk GNU/Linux 3.2.0, tidak dilucuti
    $
    $ strip hello
    $
    $ file hello
    hello:ELF 64-bit LSB executable, x86-64, versi 1 (SYSV), tertaut secara dinamis, interpreter /lib64/ld-linux-x86-64.so .2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, untuk GNU/Linux 3.2.0, dihilangkan
    $

Cara menghapus simbol selama kompilasi

Alih-alih menghapus simbol secara manual setelah kompilasi, Anda dapat meminta kompiler untuk melakukannya untuk Anda dengan memberikan -s argumen:

$ gcc -s hello.c -o hello
$
$ file hello
hello:ELF 64-bit LSB yang dapat dieksekusi, x86-64, versi 1 (SYSV), terhubung secara dinamis , interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=247de82a8ad84e7d8f20751ce79ea9e0cf4bd263, untuk GNU/Linux 3.2.0, dihilangkan
$

Setelah menjalankan kembali checksec, Anda dapat melihat symbols ditampilkan sebagai no :

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

2. burung kenari

Canary adalah nilai yang diketahui yang ditempatkan di antara buffer dan data kontrol di tumpukan untuk memantau buffer overflows. Ketika sebuah aplikasi dijalankan, dua jenis memori diberikan padanya. Salah satunya adalah tumpukan , yang merupakan struktur data dengan dua operasi:push , yang menempatkan data ke dalam tumpukan, dan pop , yang menghapus data dari tumpukan dalam urutan terbalik. Masukan berbahaya dapat meluap atau merusak tumpukan dengan masukan yang dibuat khusus dan menyebabkan program mogok:

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

Bagaimana cara checksec mengetahui apakah biner diaktifkan dengan kenari? Menggunakan metode di atas, Anda dapat mempersempitnya dengan menjalankan perintah berikut di dalam skrip shell:

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

Aktifkan kenari

Untuk melindungi dari kasus ini, kompilator menyediakan -stack-protector-all flag, yang menambahkan kode ekstra ke biner untuk memeriksa buffer overflows tersebut:

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

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

Checksec menunjukkan bahwa properti sekarang diaktifkan. Anda juga dapat memverifikasi ini dengan:

$ readelf -W -s ./hello | grep -E '__stack_chk_fail|__intel_security_cookie'
     2:0000000000000000     0 FUNC    DEFAULT GLOBAL  UND __stack_chk_fail@GLIBC_2.4 (3)
   0000_OBNCAL  0000@ $

3. PIE

PIE adalah singkatan dari executable posisi-independen. Seperti namanya, itu adalah kode yang ditempatkan di suatu tempat di memori untuk dieksekusi terlepas dari alamat absolutnya:

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

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

Seringkali, PIE diaktifkan hanya untuk perpustakaan dan bukan untuk program baris perintah yang berdiri sendiri. Pada output di bawah ini, hello ditampilkan sebagai LSB executable , sedangkan, libc pustaka standar (.so ) file ditandai dengan LSB shared object :

$ file hello
halo:ELF 64-bit LSB yang dapat dieksekusi, x86-64, versi 1 (SYSV), tertaut secara dinamis, juru bahasa /lib64/ld-linux-x86-64.so.2, BuildID[ sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, untuk GNU/Linux 3.2.0, tidak dilucuti

$ file /lib64/libc-2.32.so
/lib64/libc-2.32.so:ELF 64-bit objek bersama LSB, x86-64, versi 1 (GNU/Linux), tertaut secara dinamis, juru bahasa /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4a7fb374097fb927fb93d35ef98ba89262d0c4a4, untuk GNU/Linux 3.2.0, tidak dilucuti

Checksec mencoba menemukan informasi ini dengan:

$ readelf -W -h ./hello | grep EXEC
  Jenis:                             EXEC (File yang dapat dieksekusi)

Jika Anda mencoba perintah yang sama pada pustaka bersama alih-alih EXEC , Anda akan melihat DYN :

$ readelf -W -h /lib64/libc-2.32.so | grep DYN
  Jenis:                             DYN (Berkas objek bersama)

Aktifkan PIE

Untuk mengaktifkan PIE pada program pengujian, kirim argumen berikut ke kompiler:

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

Anda dapat memverifikasi PIE diaktifkan menggunakan checksec:

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

Itu harus ditampilkan sebagai PIE yang dapat dieksekusi dengan jenis yang diubah dari EXEC ke DYN :

$ file hello
hello:ELF 64-bit LSB pie executable, x86-64, versi 1 (SYSV), tertaut secara dinamis, interpreter /lib64/ld-linux-x86-64.so.2, BuildID [sha1]=bb039adf2530d97e02f534a94f0f668cd540f940, untuk GNU/Linux 3.2.0, tidak dilucuti

$ readelf -W -h ./hello | grep DYN
  Jenis:                             DYN (Berkas objek bersama)

4. NX

NX adalah singkatan dari "non-executable." Ini sering diaktifkan pada tingkat CPU, sehingga sistem operasi dengan NX diaktifkan dapat menandai area memori tertentu sebagai tidak dapat dieksekusi. Seringkali, eksploitasi buffer-overflow menempatkan kode pada tumpukan dan kemudian mencoba mengeksekusinya. Namun, membuat area yang dapat ditulis ini tidak dapat dieksekusi dapat mencegah serangan tersebut. Properti ini diaktifkan secara default selama kompilasi reguler menggunakan gcc :

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

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

Checksec menentukan informasi ini dengan perintah di bawah ini. RW menjelang akhir berarti tumpukan dapat dibaca dan ditulis; karena tidak ada E , itu tidak dapat dieksekusi:

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

Nonaktifkan NX untuk tujuan demo

Ini tidak disarankan, tetapi Anda dapat menonaktifkan NX saat mengkompilasi program dengan menggunakan -z execstack argumen:

$ gcc -z execstack hello.c -o hello

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

Setelah kompilasi, tumpukan menjadi dapat dieksekusi (RWE ), yang memungkinkan kode berbahaya untuk dieksekusi:

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

5. RELRO

RELRO adalah singkatan dari Relokasi Read-Only. Biner Executable Linkable Format (ELF) menggunakan Global Offset Table (GOT) untuk menyelesaikan fungsi secara dinamis. Saat diaktifkan, properti keamanan ini membuat GOT dalam biner hanya-baca, yang mencegah beberapa bentuk serangan relokasi:

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

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

Checksec menemukan informasi ini dengan menggunakan perintah di bawah ini. Di sini, salah satu properti RELRO diaktifkan; oleh karena itu, biner menunjukkan "sebagian" saat memverifikasi melalui checksec:

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

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

Aktifkan RELRO penuh

Untuk mengaktifkan RELRO penuh, gunakan argumen baris perintah berikut saat mengompilasi dengan gcc :

$ gcc -Wl,-z,relro,-z,sekarang hello.c -o hello

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

Sekarang, properti kedua juga diaktifkan, membuat program RELRO penuh:

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

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

6. Perkuat

Fortify adalah properti keamanan lain, tetapi di luar cakupan artikel ini. Saya akan belajar bagaimana checksec memverifikasi fortify di binari dan bagaimana itu diaktifkan dengan gcc sebagai latihan untuk Anda atasi.

$ 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"

Fitur checksec lainnya

Topik keamanan tidak pernah berakhir, dan meskipun tidak mungkin untuk membahas semuanya di sini, saya ingin menyebutkan beberapa fitur lagi dari checksec perintah yang membuatnya menyenangkan untuk digunakan.

Berjalan melawan banyak biner

Anda tidak harus memberikan setiap biner ke checksec satu per satu. Sebagai gantinya, Anda dapat memberikan jalur direktori tempat beberapa binari berada, dan checksec akan memverifikasi semuanya untuk Anda sekaligus:

$ checksec --dir=/usr/bin 

Proses

Selain binari, checksec juga bekerja pada program selama eksekusi. Perintah berikut menemukan properti keamanan dari semua program yang berjalan di sistem Anda. Anda dapat menggunakan --proc-all jika Anda ingin memeriksa semua proses yang berjalan, atau Anda dapat memilih proses tertentu dengan menggunakan namanya:

$ checksec --proc-all

$ checksec --proc=bash

Properti kernel

Selain aplikasi userland checksec yang dijelaskan dalam artikel ini, Anda juga dapat menggunakannya untuk memeriksa properti kernel yang dibangun ke dalam sistem Anda:

$ checksec --kernel 

Cobalah

Checksec adalah cara yang baik untuk memahami properti userland dan kernel apa yang diaktifkan. Pelajari setiap properti keamanan secara mendetail, dan coba pahami alasan pengaktifan setiap fitur dan jenis serangan yang dicegahnya.


Linux
  1. Debug Linux menggunakan ProcDump

  2. 13 tutorial keamanan Linux

  3. Menggunakan Perintah ripgrep (rg) di Linux

  1. 50 Tutorial Sysadmin UNIX / Linux

  2. Kali Linux di Android menggunakan Linux Deploy

  3. Contoh penggunaan perintah dmsetup di Linux

  1. Contoh penggunaan getnstimeofday di kernel Linux

  2. Pindahkan folder di Linux menggunakan perintah mv

  3. IPC menggunakan Sinyal di linux