iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0

今天我們來聊聊因為 sudo 設定錯誤導致一般使用者變成特權帳號 root 的案例,我們先了解什麼是 sudo?

如果你在 Linux 裡面輸入

man sudo

你會看到 sudo 在官方文件的說明是這樣的
lab-01

因此可以知道,sudo 是一個讓使用者在授權範圍內,以另一個使用者的身分執行特定指令的工具。它的目的,是讓低權限帳號在有正當需求時,不必直接取得完整的高權限帳號,也能完成需要較高權限的操作,例如使用 sudo dnf install httpd 安裝 Apache HTTP Server。

正因為 sudo 是一個切換執行身分的工具,因此每當攻擊者取得初始 shell 後,sudo -l 幾乎是最早執行的枚舉動作之一。

先看一下這個 Lab 的設定

在開始之前,先把靶機的 sudo 設定攤開來,方便大家自己重現。

user ALL=(root)      NOPASSWD: /usr/bin/less /var/log/lab06/app.log
user ALL=(root)      NOPASSWD: /opt/lab06/maintenance.sh
user ALL=(svcbackup) NOPASSWD: /usr/bin/cat
項目 內容
Starting Privilege user,一般帳號,無 root
Target 取得 root shell
Prerequisite maintenance.sh 對 group ops06 可寫;/tmp 未以 nosuid 掛載
Expected Result id 顯示 uid=0(root)

⚠️ 風險提醒:此操作建議在虛擬機上面執行,並先建立快照方便還原。

第一步:枚舉自己的 sudo 權限

sudo -l 這個指令會去解析 /etc/sudoers/etc/sudoers.d/*,列出目前使用者被授權的 sudo 權限。承接昨天的權限模型,我們先用 id 確認自己的身分,再用 sudo -l 看看手上有哪些權限。

id
sudo -l

lab-02

先看 id

uid=1000(user) gid=1000(user) groups=1000(user),1001(opsadmin),1004(ops06)

這裡有兩件事先記著,第二條會用到:

  • user 的 uid 是 1000、身分是一般帳號 user不是 root
  • user 屬於 ops06 群組(groups=…,1004(ops06))—— 這代表凡是「group 為 ops06 且群組可寫」的檔案,我都改得動

接著看 sudo -l,可以知道 user 這個帳號能用 sudo 做三件事:

  1. 不需輸入密碼,用 root 的身分執行 less 查看 /var/log/lab06/app.log
  2. 不需輸入密碼,用 root 的身分執行 /opt/lab06/maintenance.sh
  3. 不需輸入密碼,用 svcbackup 的身分執行 cat

這三條裡有兩個提權風險 + 一個身分橫移,我們一條一條看。


一、透過 less 進行提權

less 是很多工程師在查看 log 的好夥伴,比 more 好用的地方在於可以往回捲動。其中 less 的官方說明有提到一個功能:
lab-03

這個功能的意思是 less 可以呼叫一個 shell 來執行命令(俗稱 shell escape),一邊查 log 一邊操作的時候很方便。既然 sudoers 讓 less 以 root 身分執行,那麼從 less 裡面逃逸出來的 shell,自然也是 root 的 shell,使用者就間接拿到了最高權限。

我們先利用 less 開啟檔案:
lab-04

接著我們輸入 !id 按下 Enter,會發現 UID / GID 都顯示成 root:
lab-05

再用同樣的方式執行 !/bin/bash,就成功拿到一個 root shell:
lab-06
lab-07


二、可寫入腳本 + sudo:把 root 的執行權交給別人

我們再來看 /opt/lab06/maintenance.sh 的權限:

ls -l /opt/lab06/maintenance.sh

lab-08

這裡我們可以看到檔案 owner 是 root,但 group ops06 卻有寫入權(w。這邊的風險在於:這是一個「內容我能改」而且「我能用 sudo 叫它以 root 身分跑」的腳本。當我把命令寫進去、再用 sudo 觸發它時,那行命令就會以 root 執行。

實際操作:

echo 'cp /bin/bash /tmp/rootbash; chmod u+s /tmp/rootbash' >> /opt/lab06/maintenance.sh
sudo /opt/lab06/maintenance.sh      # root 會執行你加的那行
/tmp/rootbash -p                    # -p 保留 euid=0 ⇒ root shell

lab-09

解釋一下上面的 payload:

  • 因為 user 可以對腳本寫入,所以我們注入一行,把 /bin/bash 複製到 /tmp/rootbash
  • /tmp/rootbash 執行 chmod u+s 設定 SUID,讓它之後被執行時 euid = 檔案 owner(也就是 root)
  • 執行 sudo /opt/lab06/maintenance.sh,這一步由 root 執行整個腳本,包含我們注入的那行,所以 /tmp/rootbash 是以 root 身分被建立、SUID 也設定成功
  • 最後執行 /tmp/rootbash -p 取得 root shell

為什麼一定要加 -p

我們來看下面這張表

概念 意義 在這個情境
ruid(real uid) 你「真正是誰」 仍然是 user
euid(effective uid) 核心用「誰的身分」做權限檢查 SUID 讓它變成 owner root

也就是說,SUID 讓 /tmp/rootbash 執行時 euid=root、ruid=user。而 bash 有一個內建的自我保護機制:

man bash:若 shell 啟動時 effective uid 不等於 real uid,且未提供 -p 選項,bash 會主動把 euid 降回 ruid,並且不讀取啟動檔。

所以如果不加 -p,bash 一啟動就把自己降權回 user,SUID 就白設了。-p 就是在跟 bash 說「別降權」。

Prerequisite 提醒:如果 /tmp 是以 nosuid 掛載,SUID 位元會被核心忽略,這招會直接失效。可以先確認:

findmnt -no OPTIONS /tmp

三、利用 svcbackup 身分讀檔

第三條乍看比較單純:用 svcbackup 的身分跑 cat,可以看到 svcbackup 讀得到、但 user 讀不到的檔案。
lab-10

在這邊可以多問問自己:「svcbackup 這個帳號,能讀到什麼 user 讀不到的高價值檔案?」備份服務帳號常見的目標:

sudo -u svcbackup cat /home/svcbackup/.ssh/id_rsa    # 私鑰 → 橫向到其他主機
sudo -u svcbackup cat /opt/backup/backup.sh          # 腳本內硬編碼的 DB / 雲端憑證
sudo -u svcbackup cat /var/backups/*.sql             # 資料庫備份 → 資料外洩

小結

今天我們簡單的實作了三種 sudo 設定錯誤,讓我們看到 sudo 需要被嚴格管理的重要性。其實就算不靠 sudo,Linux 上還有很多提權管道。今天提到的 SUID 明天會完整展開,還會加上 SGID 的提權方式。那我們期待下一天的主題-SUID / SGID:一個執行權限如何把普通使用者送上 Root。


上一篇
Day 05|Linux 權限模型:提權枚舉前,先看懂自己能做什麼
下一篇
Day 07|SUID / SGID:一個執行權限如何把普通使用者送上 Root
系列文
我以前被社會打穿,現在輪到我研究怎麼把系統打穿:資安工程師的 30 天紅隊轉職實驗7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言