Linuxのバむナリファむルの脆匱性を芋぀けお修正する-checksecナヌティリティずgccコンパむラを䜿甚



画像むンタヌネットアヌカむブブックの画像。Opensource.comによっお倉曎されたした。CC BY-SA 4.0



同じ゜ヌスコヌドをコンパむルした埌、異なるバむナリになっおしたう可胜性がありたす。これは、コンパむラヌの手に枡すフラグによっお異なりたす。これらのフラグの䞀郚を䜿甚するず、バむナリのセキュリティ関連のプロパティの数を有効たたは無効にできたす。



それらのいく぀かは、デフォルトでコンパむラヌによっお有効たたは無効にされたす。これが、私たちが気付いおいないバむナリファむルに脆匱性が発生する可胜性がある方法です。



Checksecは、コンパむル時に含たれおいたプロパティを刀別するための単玔なナヌティリティです。この蚘事で私はあなたに蚀うでしょう



  • checksecナヌティリティを䜿甚しお脆匱性を芋぀ける方法。
  • 芋぀かった脆匱性を修正するためにgccコンパむラを䜿甚する方法。


checksecのむンストヌル



Fedora OSおよびその他のRPMベヌスのシステムの堎合



$ sudo dnf install checksec
      
      





Debianベヌスのシステムの堎合はaptを䜿甚したす。



checksecによるクむックスタヌト



checksecナヌティリティは、単䞀のスクリプトファむルで構成されおいたすが、これは非垞に倧きくなりたす。この透過性のおかげで、バむナリの脆匱性を怜玢するためのどのシステムコマンドが内郚で実行されおいるかを知るこずができたす。



$ file /usr/bin/checksec

/usr/bin/checksec: Bourne-Again shell script, ASCII text executable, with very long lines

$ wc -l /usr/bin/checksec

2111 /usr/bin/checksec
      
      





ディレクトリブラりゞングナヌティリティlsでchecksecを実行しおみたしょう。



$ checksec --file=/usr/bin/ls

<strong>RELRO           STACK CANARY      NX            PIE             RPATH     RUNPATH      Symbols       FORTIFY Fortified       Fortifiable    FILE</strong>

Full RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   No Symbols        Yes   5       17              /usr/bin/ls

      
      





タヌミナルでコマンドを実行するず、このバむナリが持぀有甚なプロパティず持たないプロパティに関するレポヌトを受け取りたす。  



最初の行はテヌブルの先頭で、RELRO、STACK CANARY、NXなどのさたざたなセキュリティプロパティが䞀芧衚瀺されたす。2行目は、lsナヌティリティバむナリのこれらのプロパティの倀を瀺しおいたす。



こんにちはバむナリ



最も単玔なCコヌドからバむナリをコンパむルしたす。



#include <stdio.h>

int main()

{

        printf(«Hello World\n»);

        return 0;

}

      
      





これたでのずころ、-oを陀いお、コンパむラに単䞀のフラグを枡しおいないこずに泚意しおくださいこれは芁点の暪にありたすが、コンパむル結果を出力する堎所を瀺しおいるだけです。



$ gcc hello.c -o hello

$ file hello

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, not stripped

$ ./hello

Hello World
      
      





次に、バむナリに察しおchecksecナヌティリティを実行したす。䞀郚のプロパティはプロパティずは異なりたす



ls (     ):

$ checksec --file=./hello

<strong>RELRO           STACK CANARY      NX            PIE             RPATH     RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE</strong>

Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   85) Symbols       No    0       0./hello

      
      





Checksecを䜿甚するず、さたざたな出力圢匏を䜿甚できたす。これは、-outputオプションで指定できたす。JSON圢匏を遞択し、jqナヌティリティを䜿甚しお出力をよりわかりやすくしたす 。



$ checksec --file=./hello --output=json | jq

{

  Â«./hello»: {

    Â«relro»: «partial»,

    Â«canary»: «no»,

    Â«nx»: «yes»,

    Â«pie»: «no»,

    Â«rpath»: «no»,

    Â«runpath»: «no»,

    Â«symbols»: «yes»,

    Â«fortify_source»: «no»,

    Â«fortified»: «0»,

    Â«fortify-able»: «0»

  }

}

      
      





脆匱性の分析checksecず排陀gcc



䞊で䜜成されたバむナリファむルには、たずえば、その脆匱性の皋床を決定するいく぀かのプロパティがありたす。このファむルのプロパティをlsバむナリ䞊蚘にもリストされおいたすのプロパティず比范し、checksecナヌティリティを䜿甚しおこれを行う方法を説明したす。 



さらに、アむテムごずに、芋぀かった脆匱性を排陀する方法を瀺したす。



1.デバッグシンボル



簡単に始めたしょう。特定のシンボルは、コンパむル時にバむナリに含たれたす。これらのシンボルは゜フトりェア開発で䜿甚されたす。デバッグずバグ修正に必芁です。



デバッグシンボルは通垞、開発者が䞀般的な䜿甚のためにリリヌスするバむナリのバヌゞョンから削陀されたす。これは、プログラムの動䜜にはたったく圱響したせん。このクリヌンアップ単語ストリップで瀺される は、文字が削陀された埌にファむルが軜くなるため、スペヌスを節玄するために行われるこずがよくありたす。たた、プロプラむ゚タリ゜フトりェアでは、攻撃者がバむナリ圢匏で文字を読み取っお独自の目的に䜿甚できるため、これらの文字は削陀されるこずがよくありたす。



Checksecは、デバッグシンボルがバむナリに存圚するこずを瀺しおいたすが、lsファむルには存圚したせん。 



$ checksec --file=/bin/ls --output=json | jq | grep symbols

    Â«symbols»: «no»,

$ checksec --file=./hello --output=json | jq | grep symbols

    Â«symbols»: «yes»,
      
      







fileコマンドを実行するず、同じこずが衚瀺されたす。文字は削陀されたせん。



$ file hello

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, <strong>not stripped</strong>
      
      





checksecのしくみ



--debugオプションを指定しおこのコマンドを実行しおみたしょう。



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

      
      





checksecナヌティリティは1぀の長いスクリプトであるため、Bash関数を䜿甚しお調べるこずができたす。スクリプトがhelloファむルに察しお実行するコマンドを衚瀺しおみたしょう。



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





echo_messageに特に泚意しおください-バむナリにデバッグシンボルが含たれおいるかどうかに関するメッセヌゞの出力



+ readelf -W --symbols ./hello

+ grep -q '\.symtab'

+ echo_message '\033[31m96) Symbols\t\033[m  ' Symbols, ' symbols=«yes»' '«symbols»:«yes»,'
      
      





checksecナヌティリティは、特別なフラグ--symbolsを指定したreadelfコマンドを䜿甚しお、バむナリファむルを読み取りたす。バむナリ内のすべおのデバッグシンボルを出力したす。 



$ readelf -W --symbols ./hello
      
      





.symtabセクションの内容から、芋぀かったシンボルの数を確認できたす。



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





コンパむル埌にデバッグシンボルを削陀する方法



ストリップナヌティリティはこれを支揎したす。



$ gcc hello.c -o hello

$
 

$ file hello

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, for GNU/Linux 3.2.0, <strong>not stripped</strong>

$
 

$ strip hello

$
 

$ file hello

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, for GNU/Linux 3.2.0, <strong>stripped</strong>
      
      





コンパむル時にデバッグシンボルを削陀する方法



コンパむルするずきは、-sフラグを䜿甚したす。



$ gcc -s hello.c -o hello

$

$ file hello

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=247de82a8ad84e7d8f20751ce79ea9e0cf4bd263, for GNU/Linux 3.2.0, <strong>stripped</strong>

      
      





checksecナヌティリティを䜿甚しお、シンボルが削陀されたこずを確認するこずもできたす。



$ checksec --file=./hello --output=json | jq | grep symbols

    Â«symbols»: «no»,

      
      





2.カナリア



カナリア情報提䟛者は、バッファヌず制埡デヌタの間のスタックに栌玍される「秘密の」倀です。これらは、バッファオヌバヌフロヌ攻撃から保護するために䜿甚されたすこれらの倀が倉曎された堎合は、アラヌムを鳎らす䟡倀がありたす。アプリケヌションが起動されるず、そのアプリケヌション甚に独自のスタックが䜜成されたす。この堎合、それはプッシュ操䜜ずポップ操䜜を備えた単なるデヌタ構造です。攻撃者は悪意のあるデヌタを準備しおスタックに曞き蟌む可胜性がありたす。この堎合、バッファがオヌバヌフロヌし、スタックが損傷する可胜性がありたす。将来的には、これはプログラムのクラッシュに぀ながるでしょう。カナリア倀の分析により、ハッキングが発生したこずをすばやく理解しおアクションを実行できたす。



$ checksec --file=/bin/ls --output=json | jq | grep canary

    Â«canary»: «yes»,

$

$ checksec --file=./hello --output=json | jq | grep canary

    Â«canary»: «no»,

$

 ,    canary,  checksec   :

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





カナリアをオンにする



これを行うには、コンパむル時に-stack-protector-allフラグを䜿甚したす。



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

$ checksec --file=./hello --output=json | jq | grep canary

    Â«canary»: «yes»,

      
      





これで、checksecは、カナリアメカニズムがオンになっおいるこずを明確な良心で教えおくれたす。



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

     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (3)

    83: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@@GLIBC_2.4

$

      
      





3.PIE



有効なPIEプロパティを䜿甚するず、絶察アドレスに関係なく、実行可胜コヌドをメモリに任意に配眮できたす



。PIEPosition Independent Executable-䜍眮に䟝存しない実行可胜コヌド。プロセスのアドレス空間のどこにどの領域のメモリがあるかを予枬する機胜は、攻撃者の手に枡りたす。ナヌザヌプログラムは、PIEオプションでコンパむルされおいない限り、事前定矩されたプロセス仮想メモリアドレスからロヌドおよび実行されたす。 PIEを䜿甚するず、オペレヌティングシステムは実行可胜コヌドのセクションをメモリの任意のチャンクにロヌドできるため、解読がはるかに困難になりたす。



$ checksec --file=/bin/ls --output=json | jq | grep pie

    Â«pie»: «yes»,

$ checksec --file=./hello --output=json | jq | grep pie

    Â«pie»: «no»,

      
      





倚くの堎合、PIEプロパティは、ラむブラリをコンパむルするずきにのみ含たれたす。以䞋の出力では、helloはLSB実行可胜ファむルずしおマヌクされ、暙準ラむブラリlibc.soファむルはLSB共有オブゞェクトずしおマヌクされおいたす。



$ file hello

hello: ELF 64-bit <strong>LSB executable</strong>, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, not stripped

$ file /lib64/libc-2.32.so

/lib64/libc-2.32.so: ELF 64-bit <strong>LSB shared object</strong>, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4a7fb374097fb927fb93d35ef98ba89262d0c4a4, for GNU/Linux 3.2.0, not stripped

      
      





Checksecは、次のようにこの情報を取埗したす。



$ readelf -W -h ./hello | grep EXEC

  Type:                              EXEC (Executable file)

      
      





ラむブラリに察しお同じコマンドを実行するず、EXECの代わりにDYNが衚瀺されたす。



$ readelf -W -h /lib64/libc-2.32.so | grep DYN

  Type:                              DYN (Shared object file)

      
      





PIEをオンにしたす



プログラムをコンパむルするずきは、次のフラグを指定する必芁がありたす。



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





PIEプロパティが有効になっおいるこずを確認するには、次のコマンドを実行したす。



$ checksec --file=./hello --output=json | jq | grep pie

    Â«pie»: «yes»,

$
      
      





これで、バむナリファむルhelloのタむプがEXECからDYNに倉曎されたす。



$ file hello

hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bb039adf2530d97e02f534a94f0f668cd540f940, for GNU/Linux 3.2.0, not stripped

$ readelf -W -h ./hello | grep DYN

  Type:                              DYN (Shared object file)

      
      





4.NX



オペレヌティングシステムずプロセッサツヌルを䜿甚するず、仮想メモリペヌゞぞのアクセス暩を柔軟に構成できたす。NXNo Executeプロパティを有効にするこずで、デヌタがプロセッサ呜什ずしお解釈されるのを防ぐこずができたす。倚くの堎合、バッファオヌバヌフロヌ攻撃では、攻撃者はコヌドをスタックにプッシュしおから実行しようずしたす。ただし、これらのメモリセグメントでコヌドが実行されないようにするこずで、このような攻撃を防ぐこずができたす。gccを䜿甚した通垞のコンパむルでは、このプロパティはデフォルトで有効になっおいたす。



$ checksec --file=/bin/ls --output=json | jq | grep nx

    Â«nx»: «yes»,

$ checksec --file=./hello --output=json | jq | grep nx

    Â«nx»: «yes»,

      
      





Checksecは、再床readelfコマンドを䜿甚しお、NXプロパティに関する情報を取埗したす。この堎合、RWはスタックが読み取り/曞き蟌みであるこずを意味したす。ただし、この組み合わせにはE文字が含たれおいないため、このスタックからコヌドを実行するこずは犁止されおいたす。



$ readelf -W -l ./hello | grep GNU_STACK

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

      
      





NXを無効にする 



NXプロパティを無効にするこずはお勧めしたせんが、次のように行うこずができたす。



$ gcc -z execstack hello.c -o hello

$ checksec --file=./hello --output=json | jq | grep nx

    Â«nx»: «no»,

      
      





コンパむル埌、スタックのアクセス蚱可がRWEに倉曎されたこずがわかりたす。



$ readelf -W -l ./hello | grep GNU_STACK

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10
      
      





5. RELRO



動的にリンクされたバむナリでは、特別なGOTグロヌバルオフセットテヌブルを䜿甚しお、ラむブラリから関数を呌び出したす。このテヌブルは、ELFExecutable Linkable Formatバむナリによっお参照されたす。RELRORelocation Read-Only保護が有効になっおいる堎合、GOTは読み取り専甚になりたす。これにより、テヌブルレコヌドを倉曎するいく぀かのタむプの攻撃から保護できたす。



$ checksec --file=/bin/ls --output=json | jq | grep relro

    Â«relro»: «full»,

$ checksec --file=./hello --output=json | jq | grep relro

    Â«relro»: «partial»,

      
      





この堎合、RELROプロパティの1぀だけが有効になっおいるため、checksecは倀「partial」を出力したす。Checksecは、readelfコマンドを䜿甚しお蚭定を衚瀺したす。 



$ readelf -W -l ./hello | grep GNU_RELRO

  GNU_RELRO      0x002e10 0x0000000000403e10 0x0000000000403e10 0x0001f0 0x0001f0 R   0x1

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





フルプロテクションをオンにするFULL RELRO



これを行うには、コンパむル時に適切なフラグを䜿甚する必芁がありたす。



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

$ checksec --file=./hello --output=json | jq | grep relro

    Â«relro»: «full»,

      
      





これで、バむナリはFULLRELROの名誉称号を取埗したした。



$ readelf -W -l ./hello | grep GNU_RELRO

  GNU_RELRO      0x002dd0 0x0000000000403dd0 0x0000000000403dd0 0x000230 0x000230 R   0x1

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

 0x0000000000000018 (BIND_NOW)    
      
      



      

その他のchecksec機胜



セキュリティのトピックは際限なく研究するこずができたす。この蚘事で簡単なchecksecナヌティリティに぀いお話しおいおも、すべおを網矅するこずはできたせん。ただし、さらにいく぀かの興味深い可胜性に぀いお説明したす。



耇数のファむルをチェックする



ファむルごずに個別のコマンドを実行する必芁はありたせん。耇数のバむナリに察しお1぀のコマンドを䞀床に実行できたす。



$ checksec --dir=/usr/bin
      
      





プロセスの確認



checksecナヌティリティを䜿甚するず、プロセスのセキュリティを分析するこずもできたす。次のコマンドは、システムで実行䞭のすべおのプログラムのプロパティを衚瀺したすこれを行うには、-proc-allオプションを䜿甚する必芁がありたす。 



$ checksec --proc-all
      
      





名前を指定しお、チェックするプロセスを1぀遞択するこずもできたす。



$ checksec --proc=bash
      
      





カヌネルチェック



同様に、システムのカヌネルの脆匱性を分析できたす。



$ checksec --kernel
      
      





事前に譊告されおいたす



セキュリティプロパティを詳现に調査し、それぞれが正確に䜕に圱響し、どのような皮類の攻撃を防ぐこずができるかを理解しおください。あなたを助けるためにChecksec






Macleodのクラりドサヌバヌ は高速で安党です。



䞊蚘のリンクを䜿甚するか、バナヌをクリックしお登録するず、任意の構成のサヌバヌをレンタルした最初の月が10割匕になりたす。






All Articles