iT邦幫忙

2023 iThome 鐵人賽

1

Yes

  • Docker 的容器預設使用 root (id=0)身分去執行程式,也因此即使在不使用特權容器的情況下,該帳號仍然擁有一些權限可以做事情,像是 apt 安裝套件、安裝驅動程式之類的,或是存取 root 權限的檔案。/images/emoticon/emoticon16.gif

  • 而 Non-Root User 容器的概念就是指定容器使用低權限的身分去執行程式,如此一來即便駭客拿下容器的控制權也只有一般使用的身分,無法再進一步執行高權限的動作,相關資料可以參考Docker Security Cheat Sheet - RULE #2 - Set a user

  • Non-Root User 的作法是在撰寫 Dockerfile 的時候,新增使用者身分並且切換過去,Dockerfile 調整如下。至於裡面用到的 suid_test 檔案內容可以參考 Day14 - Pwnkit 如果沒有 SUID,那跟鹹魚有什麼分別?

    FROM aeifkz/my-ubuntu:v1.0
    
    ADD suid_test /tools
    
    RUN chown root:root /tools/suid_test && chmod 4755 tools/suid_test
    
    RUN useradd -u 8877 aeifkz
    USER aeifkz
    
    CMD ["python3","/tools/reverse_server.py"]
    
  • 編譯 image 檔案並且執行。

    docker build --no-cache --tag non-root . ;
    docker run --rm -it non-root bash;
    
    #看一下身分是誰?
    whoami ; 
    
    #測試套件資訊更新,會失敗
    apt update ; 
    
    #透過程式提權
    /tools/suid_test ; 
    
    #看一下身分,所以代表還是可以提權
    whoami ; 
    
    #測試套件資訊更新,會成功
    apt update ; 
    
    # 當然還是可以用 root 身分連進去,只是要用 -u 參數指定 uid
    docker exec -it -u 0 [container_name] bash;
    
  • 利用此容器測試之前練過的容器逃逸手法,會發現在不討論提權的情況下,這個防禦機制能夠阻擋蠻多的攻擊手法,所以算是相當值得投資的一塊/images/emoticon/emoticon34.gif。但萬一在容器中存在可以提權的弱點時(ex: /tools/suid_test),還是可以於提權後再使用原本的攻擊手法。

攻擊手法 Non Root User 能否阻擋?
privileged + host pid Y
--cap-add=ALL + host pid Y
privileged Y
(CVE-2022-0492) unshare + cgroup 特權逃逸手法 Y
安裝 linux_module Y
docker.sock 掛載 Y
  • 這邊有個觀念要小小的勘誤一下,也就是 (CVE-2022-0492) unshare + cgroup 特權逃逸手法這個部分,剛好可以藉由 Non-Root User 這個防禦機制來做個小驗證。

    # 有檔案應該就是 cgroup v2 版本
    cat /sys/fs/cgroup/cgroup.controllers ;
    
    # 調整 GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=0"
    sudo vim /etc/default/grub ;
    
    sudo update-grub ;
    sudo shutdown -r now ;
    
    
    # 啟動容器並且不啟動安全防護機制 seccomp、apparmor
    docker run --rm -it --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" aeifkz/my-ubuntu:v.non-root bash ;
    
    # 目前該容器不是特權容器
    cat /proc/$$/status | grep CapEff ;
    
    # 複習一下 cgroup 逃逸手法前半段
    mkdir /tmp/cgroup ;
    mount -t cgroup -o rdma cgroup /tmp/cgroup ;  
    
    # 偷看一下目前的 uid 對應,格式為 ID-inside-ns   ID-outside-ns   length
    # ID-inside-ns 表示在容器顯示的UID
    # ID-outside-ns 表示容器外映射的真實的UID
    # length 表示映射的範圍
    cat /proc/$$/uid_map ;
    
    # 透過 CVE-2022-0492 漏洞呼叫 
    unshare -UrmC --propagation=unchanged bash ;
    
    # 看起來全部的能力都有,而且也是 root 帳號
    whoami ;
    cat /proc/$$/status | grep CapEff ;
    
    # 如果剛剛沒提權,這邊連 apt update 都不能做
    apt update ;
    
    # unshare 建立新的 namespace 就可以呼叫 mount
    mount -t cgroup -o rdma cgroup /tmp/cgroup ;
    
    # 測試驅動程式逃逸手法看看,會發現無法成功安裝驅動程式
    insmod test.ko ; 
    
    # 最後再偷看一次目前的 uid 對應
    cat /proc/$$/uid_map ;
    
    # 退回容器
    exit ;
    
  • 其實 unshare 下的參數有幫忙建立一個新的 user namespace,這部分會在 user remapping 的防禦手法再做說明,但即便在新的 namespace 有 root 身分,但仍然無法進行高權限的操作。

  • 也因此從現在這個角度來看期中考的判斷流程還是有瑕疵的/images/emoticon/emoticon20.gif,因為當初第一步是先判斷 /proc/$$/status 內回傳的內容去判斷容器擁有的能力,但透過 unshare 開出新的 namespace 可能會造成誤判。所以要判斷 privileged container 的方式包含如參考資料所示 :

  1. capabilities: removing any capability restrictions
  2. devices: the host devices will be visible
  3. seccomp: removing restrictions on allowed syscalls
  4. apparmor/selinux: policies aren't applied
  5. cgroups: I don't believe the container is limited within a cgroup (個人認為 mount | grep cgroup)
  • 作業10-1 : 又來到我們的大型翻車現場,這車足足翻了有一年了我現在才發現。首先這次 Day01 - 開賽 (含作業1) 請各位建立的 Linux kernel - v5.16.20(Ubuntu) 其實這版是無法使用 CVE-2022-0492 這個弱點的,請參考資訊解釋一下為何不能? 以及更新內核版本後試著利用弱點進行逃逸會遇到甚麼問題? /images/emoticon/emoticon33.gif

  • 作業10-2 : 既然翻車了就要撥亂反正,請建立以下環境並試著參考New Linux Vulnerability CVE-2022-0492 Affecting Cgroups: Can Containers Escape?實踐利用 CVE-2022-0492 弱點後接續 cgroups 的逃逸手法,並試著比較跟作業10-1環境的差異/images/emoticon/emoticon33.gif。建立環境參考如下 :

    1. Linux : Ubuntu 18.04.6 LTS (調整為使用此版本) - kernel 版本 v4.15.10 (影響 CVE-2022-0492)
    2. Docker : 18.03.1-ce (影響 cgroups 逃逸手法)
  • 今日總結 :

    • 本日回顧 :
      • 大概介紹了 Non-Root user 的想法以及實作方式,也針對了之前介紹過的逃逸手法進行防禦測試。在不提權的情況下測試結果還不錯,因此建議可以針對這部分費點心力進行防禦,只不過如果容器內有提權漏洞的話就會全數破功就是了。
    • 次日預告 :
      • 明天會針對容器的啟動的安全參數進行說明及測試,以及介紹使用 no-new-privileges 來避免容器內的提權。

上一篇
Day 33 - 作業 9 解答 - 測試 cap-add ALL 以及 host pid 的逃逸手法 (SELinux)
下一篇
Day 34 - 作業 10-1 解答 - 尋找具有 CVE-2022-0492 的漏洞版本及測試
系列文
怕痛的我把 Docker、K8s 攻擊、防禦、偵測力點滿就對了63
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言