在開始介紹 User Remapping 之前先來看個簡單的資訊,步驟參考如下 :
docker run --rm -it aeifkz/my-ubuntu:v1.0 bash ;
wget https://github.com/genuinetools/amicontained/releases/download/v0.4.9/amicontained-linux-amd64 && chmod +x amicontained-linux-amd64 ;
# 這邊會顯示
# Has Namespaces:
# pid: true
# user: false
./amicontained-linux-amd64 ;
ls -al /proc/self/ns | grep user ;
exit ;
# 這邊會發現容器內與容器外的 user 是同一個 namespace
ls -al /proc/self/ns | grep user ;
那有沒有種可能是跟之前講的 unshare 一樣可以創造出一個新的 user namespace,讓容器內以為那個帳號是 root 但在容器外其實只是個普通帳號呢? 答案是有的,也就是今天要講的防禦機制 - user remapping。相關資料可以參考Isolate containers with a user namespace、容器安全之启用用户命名空间(user namespace)。以下就用 Ubuntu 系統來試著開啟該防禦機制,步驟如下所示 :
建立群組以及使用者
# 透過指令幫建一個 user account
sudo adduser low_user ;
# 這邊會新增一筆對應資料,例如 : low_user:165536:65536
cat /etc/subuid ;
cat /etc/subgid ;
這個 low_user:165536:65536 的格式為之後產生的 uid 區段為 [165536,165536+65536-1],之後套用到容器後則為映射到容器內部的 uid 區段 [0,0+65536-1]。接著修改 /etc/docker/daemon.json 的套用 user remapping 設定數值。
{
"userns-remap": "low_user"
}
重啟 docker 服務,進行一連串的測試
# 觀察一下目前的 image 狀態
docker images ;
sudo systemctl restart docker ;
# 再次觀察一下目前的 image 狀態,會被清空
docker images ;
#開啟系統 port 正常,這點還蠻奇怪的
docker run -p 80:80 --rm -it aeifkz/my-ubuntu:v1.0 bash ;
# exit 結束容器後,看一下 docker 執行權限
ps aux | grep docker ;
# 進入容器觀察一下差別
docker run -p 80:80 --rm -it aeifkz/my-ubuntu:v1.0 bash ;
# 驗證功能
apt update ;
wget https://github.com/genuinetools/amicontained/releases/download/v0.4.9/amicontained-linux-amd64 && chmod +x amicontained-linux-amd64 ;
# 工具告訴我們現在針對 Has Namespaces: user: true
./amicontained-linux-amd64 ;
# 可以透過這個檔案看目前的 uid_map 對應
cat /proc/self/uid_map ;
# 隨便造一個檔案
touch i_am_non_root_container ;
# 去宿主機的 /var/lib/docker 底下(要切換到root)
sudo find /var/lib/docker -name "i_am_non_root_container" ;
# 依照找到的檔案看一下 owner 是誰,會發現是 low_user
sudo ls -al /var/lib/docker/165536.165536/overlay2/75bb79ab2636837133d88fb4b77a0ac5e8e7de2014eb0ce3217b7c56116ac5ed/merged/i_am_non_root_container ;
#開啟特權容器失敗
docker run -p 80:80 --rm -it --privileged aeifkz/my-ubuntu:v1.0 bash ;
透過觀察會發現設定 user remapping 的幾個特性 :
因為 user remapping 的關係所以實際上在宿主機運作的並非是真實的 root 帳號,接著來測試之前講過容器逃逸手法,看看有幾個可以防禦成功?
攻擊手法 | user remapping 能否阻擋? |
---|---|
privileged + host pid | Y |
--cap-add=ALL + host pid | Y |
privileged | Y |
(CVE-2022-0492) unshare + cgroup 特權逃逸手法 | Y (作業11-1) |
安裝 linux_module | Y |
docker.sock 掛載 | Y (作業11-2) |
作業11-1 : 試著練習用之前建立的 Ubuntu 18.04 環境測試 (CVE-2022-0492) unshare + cgroup 特權逃逸手法 看看是否會成功? 並解釋其原因。
作業11-2 : 在宿主機中 docker.sock 的 owner 是 root,而做完 user remapping 後進入容器的權限也是 root,請測試為何該機制可以防禦住 docker.scok 掛載的攻擊並做解釋。
今日總結 :