跳至內容

Arch 打包準則/安全

出自 Arch Linux 中文维基
Arch 打包準則

32 位安全CLRCMakeDKMSEclipseElectronFree PascalGNOMEGoHaskellJava交叉編譯工具KDELispMesonMinGW內核模塊Node.jsNonfreeOCamlPerlPHPPythonRRubyRustShellVCSWebWine字體

本文描述了適用於 Arch Linux 軟體包的打包安全指引。對於 C/C++ 項目,可以為編譯器和連結器應用安全加固選項。Arch Linux 默認會啟用 PIEFORTIFY_SOURCE、棧保護、nxrelro

用法

可以使用 checksec 檢查強化加固保護選項:

$ checksec --file=/usr/bin/cat
提示:Namcap 也可以報告本文描述的一些安全問題。

RELRO

RELRO 是用於加固 ELF 二進制文件和進程的一種通用緩解技術。在程序加載時,連結器需要寫入幾個 ELF 內存區段,但在將控制權交給程序前,可以將這些區段設為只讀,由此防止攻擊者覆蓋掉部分 ELF 區段。有兩種 RELRO 模式:

  • 部分 RELRO(-Wl,-z,relro):程序加載後部分區段被設為只讀,但 GOT(.got.plt)仍為可寫。
  • 完全 RELRO(-Wl,-z,now):程序加載時解析所有動態符號,使得整個 GOT 都可被設為只讀。

如果應用匯報使用了部分 RELRO,需檢查構建工具是否使用了我們傳遞的 LDFLAGS,以及是否允許覆寫 LDFLAGS。對於 Go 軟體包,需檢查構建方法是否將 build.go 作為了純 golang Makefile 替代使用,該方法不允許傳遞 LDFLAGS。

Haskell

暫不清楚如何為 Haskell 實現完全 RELRO。

Go

參見 Go 語言軟體打包準則#Flags and build options

Stack canary

Stack canary(又稱棧警惕標誌)由編譯器添加在棧的緩衝區和控制數據之間。如果該已知值被破壞,就代表出現了緩衝區溢出,運行中的程序就會報出段錯誤(segfaults),以防止執行潛在的錯誤代碼。

gcc 包默認通過 --enable-default-ssp 編譯選項啟用了棧保護。

NX

C/C++

可執行空間保護會將內存區域標記為非可執行,使得在該區域執行機器碼時會出現報錯。該功能使用了類似 NX 位(No-eXecute bit,禁止執行位)的硬體功能,有時也會使用軟體模擬這些特性。

PIE

C/C++

gcc 包默認通過 --enable-default-pie 選項為 C/C++ 啟用了該特性。

Golang

將以下標誌傳遞給 go build

export GOFLAGS='-buildmode=pie'
export CGO_CPPFLAGS="-D_FORTIFY_SOURCE=3"
export CGO_LDFLAGS="-Wl,-z,relro,-z,now"

Haskell

將以下標誌傳遞給 runhaskell Setup.hs configure

--ghc-option='-pie'

RPATH/RUNPATH

RUNPATH/RPATH 為包含該參數的對象提供了更多的搜索路徑(適用於可執行文件和共享對象):

$ objdump -x /usr/bin/perl | grep -E 'RPATH|RUNPATH'

如果 RPATH 的值包含了攻擊者可控制的路徑,那就有可能通過對應目錄下的惡意庫執行代碼(例如 CVE-2006-1566CVE-2005-4280)。更多信息請參考 Debian:RpathIssue

RPATH 是通過向 LDFLAGS 傳遞類似 -Wl,-rpath -Wl,/usr/local/lib 的參數,然後由連結器負責設置的。如果要設置 RUNPATH,請將 --enable-new-dtags 添加到連結器標誌中。

FORTIFY

Fortify source 是一個宏,可以為執行內存和字符串操作的函數添加緩衝區溢出保護。它會檢測是否有攻擊者嘗試通過負責更多的字節來溢出緩衝區,並停止程序的運行。該保護項已在默認 CPPFLAGS 中啟用:

makepkg.conf
CPPFLAGS="-D_FORTIFY_SOURCE=3"

更多信息請參考 makepkg#配置

systemd 服務

此頁面或章節適合移動到 systemd/Sandboxing

附註: 內容主題與 systemd#應用程式環境沙盒 相同,兩者可被匯總到單獨頁面,草稿可參考 User:NetSysFire/systemd sandboxing。(在 Talk:Security#systemd unit hardening and system.conf tweaks 討論)


如果上游不提供 systemd 服務文件,使得需隨軟體包附帶,請檢查是否需要使用以下 systemd 服務加固功能。Systemd 提供並為服務啟用了分析安全特性的方法:

$ systemd-analyze security reflector.service

文件訪問

可以通過限制文件系統訪問來加固服務。

為執行的進程配置一個新的文件系統命名空間,並在內部掛載私有 /tmpvar/tmp 目錄,使得其不與命名空間外部的進程共享。該方法適用於會向 /tmp 目錄寫入數據的程序:

PrivateTmp=true

ProtectSystem 參數對於執行中進程有三種只讀掛載方式,其中 「full」 選項會將 /usr/boot/etc 目錄掛載為只讀。ProtectHome 會使進程無法訪問 /home/root/run/user 目錄:

ProtectSystem=strict
ProtectHome=true

PrivateDevices 會為執行中的進程配置新的 /dev 命名空間,其中只包含類似 /dev/null/dev/zero/dev/random 的 API 偽設備,不包含任何物理設備、系統內存、系統埠和其它設備。該選項可以防止進程直接向物理設備進行寫入,systemd 還會為 @raw-io 集添加系統調用過濾器:

PrivateDevices=true

以下選項會使執行中進程無法修改可通過 /proc/sys/sys 等路徑訪問的內核變量。ProtectControlGroups 會使 /sys/fs/cgroup 層次結構變為只讀:

ProtectKernelTunables=true
ProtectControlGroups=true

以下方法可禁止訪問部分文件路徑:

InaccessiblePaths=/etc

更多信息請參考 systemd.exec(5)

用戶

確保執行中的進程和其子進程無法通過 execve(2) 獲得新權限:

NoNewPrivileges=true

內存

禁止創建同時為可寫和可執行的內存映射、將映射修改為可執行和創建可執行共享內存。該方法會將進程沙箱化,防止攻擊者向可執行的內存部分寫入數據。注意,該方法與使用 JIT 的應用不兼容:

MemoryDenyWriteExecute=true

系統調用

鎖定 personality(2) 系統調用,使內核執行域無法被修改:

LockPersonality=true

還可以限制服務的系統調用,以下命令將顯示 systemd 可以過濾的系統調用:

$ systemd-analyze syscall-filter

可以使用預定義組,以下示例為使用推薦的系統服務調用白名單配置起點:

SystemCallFilter=@system-service

還可以按架構來限制系統調用,例如限制在 64 位設備上執行 32 位二進制文件(即非原生架構二進制文件):

SystemCallArchitectures=native

網絡

如果進程不需要訪問網絡,可以為進程配置一個新的網絡命名空間,並只配置迴環接口,以此完全禁用網絡訪問:

PrivateNetwork=true

如果需要網絡,還可以限制 socket(2) 系統調用可使用的地址族類型,以只允許 UNIX socket 為例:

RestrictAddressFamilies=AF_UNIX

也可以對只需連接到 localhost(本機)或特定 IP 段的情況進行限制,以只允許 localhost 為例:

IPAddressAllow=localhost
IPAddressDeny=any

更多網絡過濾相關的信息請參考 systemd.resource-control(5)

其它

為執行的進程配置新的 UTS 命名空間,並禁止修改主機名或域名:

ProtectHostname=true