[Linux] 用 GCC 編譯 ELF 檔案時,加上 PIE/SSP 編譯選項加強安全性
最近公司在推行幫 Linux ELF 檔案加上 PIE/SSP 的編譯選項,
這兩個是什麼東西呢?
PIE 是 Position Indenpendent Executable,
SSP 是 Stack Smash Protection,
其實感覺很像是 Windows 上的 DEP/ASLR~
我們可以安裝 hardening-check 這個套件,來檢查 PIE/SSP 有沒有打開:
yum install hardening-check
執行 hardening-check <ELF 檔案>,就能檢查 PIE/SSP 是否有打開~
舉例來說,這個 HelloWorld 都沒有開:
testuser@localhost ~ hardening-check HelloWorld HelloWorld: Position Independent Executable: no, normal executable! Stack protected: no, not found! Fortify Source functions: no, only unprotected functions found! Read-only relocations: yes Immediate binding: no, not found!
要打開 PIE,可以在 GCC 加上 -fPIE -pie 編譯選項。
要打開 SSP,可以加上下面任一種 -fstack-protector* 的 GCC 鏈結選項:
- -fstack-protector
- -fstack-protector-strong
- -fstack-protector-all
SSP 三種選項的差別是覆蓋率的不同,
-fstack-protector 最少但最快,-fstack-protector-all 最多但也最慢,
所以我通常是選中庸的 -fstack-protector-strong~
(實際的差別可以參考 GCC Stack Protector options)
重新編譯之後,再來檢查一次,
可以發現 PIE/SSP 都是 yes 了:
testuser@localhost ~ hardening-check HelloWorld HelloWorld: Position Independent Executable: yes Stack protected: yes Fortify Source functions: no, only unprotected functions found! Read-only relocations: yes Immediate binding: no, not found!
要注意的是 PIE 是針對執行檔才有意義的,
如果對一個 shared library (DLL) 檢查 PIE,
hardening-check 會忽略相關檢查,但 SSP 仍然是可以檢查的:
testuser@localhost ~ hardening-check libTest.so libTest.so: Position Independent Executable: no, regular shared library (ignored) Stack protected: no, not found! Fortify Source functions: no, only unprotected functions found! Read-only relocations: yes Immediate binding: no, not found!
心得:每個模組都改這個編譯選項很累啊…
2018/11/29 補註:
並不是每個檔案只要加上這些編譯選項,
hardening-check 就一定能檢查出來…
舉例來說,當一個 cpp 檔案裡沒有定義自己的函式時,
編譯器就沒有地方可以加上 SSP 的保護措施,
所以 hardening-check 自然也檢查不出來了~
參考資料:
When and how to use GCC’s stack protection feature?