Linux中的保護機制
在編寫漏洞利用程式碼的時候,需要特別注意目標程式是否開啟了NX、PIE等機制,例如存在NX的話就不能直接執行棧上的資料,存在PIE 的話各個系統呼叫的地址就是隨機化的。
一:canary(棧保護)
棧溢位保護是一種緩衝區溢位攻擊緩解手段,當函式存在緩衝區溢位攻擊漏洞時,攻擊者可以覆蓋棧上的返回地址來讓shellcode能夠得到執行。當啟用棧保護後,函式開始執行的時候會先往棧裡插入cookie資訊,當函式真正返回的時候會驗證cookie資訊是否合法,如果不合法就停止程式執行。攻擊者在覆蓋返回地址的時候往往也會將cookie資訊給覆蓋掉,導致棧保護檢查失敗而阻止shellcode的執行。在Linux中我們將cookie資訊稱為canary。
gcc在4.2版本中新增了-fstack-protector和-fstack-protector-all編譯引數以支援棧保護功能,
因此在編譯時可以控制是否開啟棧保護以及程度,例如:
1、gcc -o test test.c // 預設情況下,不開啟Canary保護
2、gcc -fno-stack-protector -o test test.c //禁用棧保護
3、gcc -fstack-protector -o test test.c //啟用堆疊保護,不過只為區域性變數中含有 char 陣列的函式插入保護程式碼
4、gcc -fstack-protector-all -o test test.c //啟用堆疊保護,為所有函式插入保護程式碼
二:NX(no execute)
NX即No-eXecute(不可執行)的意思,NX(DEP)的基本原理是將資料所在記憶體頁標識為不可執行,當程式溢位成功轉入shellcode時,程式會嘗試在資料頁面上執行指令,此時CPU就會丟擲異常,而不是去執行惡意指令。
gcc編譯器預設開啟了NX選項,如果需要關閉NX選項,可以給gcc編譯器新增-z execstack引數。 例如:
1、gcc -o test test.c // 預設情況下,開啟NX保護
2、gcc -z execstack -o test test.c // 禁用NX保護
3、gcc -z noexecstack -o test test.c // 開啟NX保護
在Windows下,類似的概念為DEP(資料執行保護)
三:PIE(position-independent executables)
位置獨立的可執行區域。這樣使得在利用緩衝溢位和移動作業系統中存在的其他記憶體崩潰缺陷時採用面向返回的程式設計(return-oriented programming)方法變得難得多。一般情況下NX(Windows平臺上稱其為DEP)和地址空間分佈隨機化(ASLR)會同時工作。記憶體地址隨機化機制(address space layout randomization),有以下三種情況:
0 - 表示關閉程式地址空間隨機化。
1 - 表示將mmap的基址,stack和vdso頁面隨機化。
2 - 表示在1的基礎上增加棧(heap)的隨機化。
liunx下關閉PIE的命令如下:
sudo -s echo 0 > /proc/sys/kernel/randomize_va_space
gcc編譯命令:
1、gcc -o test test.c // 預設情況下,不開啟PIE
2、gcc -fpie -pie -o test test.c // 開啟PIE,此時強度為1
3、gcc -fPIE -pie -o test test.c // 開啟PIE,此時為最高強度2
4、gcc -fpic -o test test.c // 開啟PIC,此時強度為1,不會開啟PIE
5、gcc -fPIC -o test test.c // 開啟PIC,此時為最高強度2,不會開啟PIE
四:RELRO( read only relocation)
在Linux系統安全領域,資料可以寫的儲存區就會是攻擊的目標,尤其是儲存函式指標的區域。 所以在安全防護的角度來說盡量減少可寫的儲存區域對安全會有極大的好處。GCC, GNU linker以及Glibc-dynamic linker一起配合實現了一種叫做relro的技術:。大概實現就是由linker指定binary的一塊經過dynamic linker處理過 relocation之後的區域為只讀.設定符號重定向表格為只讀或在程式啟動時就解析並繫結所有動態符號,從而減少對GOT(Global Offset Table)攻擊。RELRO為” Partial RELRO”,說明我們對GOT表具有寫許可權。
gcc編譯:
gcc -o test test.c // 預設情況下,是Partial RELRO
gcc -z norelro -o test test.c // 關閉,即No RELRO
gcc -z lazy -o test test.c // 部分開啟,即Partial RELRO
gcc -z now -o test test.c // 全部開啟
五 總結
各種安全選擇的編譯引數如下:
- NX:-z execstack / -z noexecstack (關閉 / 開啟)
- Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (關閉 / 開啟 / 全開啟)
- PIE:-no-pie / -pie (關閉 / 開啟)
- RELRO:-z norelro / -z lazy / -z now (關閉 / 部分開啟 / 完全開啟)
參考資料:
https://www.cnblogs.com/Spider-spiders/p/8798628.html