iT邦幫忙

2023 iThome 鐵人賽

DAY 3
1

Yes

  • 虛擬機器(virtual machine),可建立一個環境模擬完整硬體的功能,可在上面安裝與宿主機器不同的作業系統,進而形成一個隔離環境進行測試。常見的免費軟體有VMware Workstation Player、VirtualBox。

  • 容器化本質上是一種沙盒技術,透過將作業系統的應用程式進行隔離,讓該應用程式誤以為擁有作業系統所有資源,但不同容器間卻是彼此隔離的。實踐容器化技術大多以Docker為主,除此之外還有LXD、Podman等等。

  • 相關架構圖參考如下,
    https://ithelp.ithome.com.tw/upload/images/20230910/20148308mm2z5Xyp1w.png
    來源: Difference between VM vs Docker

  • 在解說原理前先來觀察一下容器的內部情況。

步驟如下 :

  1. docker run --rm -it aeifkz/my-ubuntu:v1.0 bash ;
  • 執行之後彷彿進入到一個新世界,可以試著下幾個指令進行觀察宿主機與容器的差別。

步驟如下 :

  1. ps aux | wc -l #process - 左邊為容器, 右邊為宿主機
    https://ithelp.ithome.com.tw/upload/images/20230910/20148308gqJ8vrn6P1.jpg
  2. ls /tmp -al | wc -l #file system - 左邊為容器, 右邊為宿主機
    https://ithelp.ithome.com.tw/upload/images/20230910/20148308FZcpOeLsub.jpg
  3. whoami # user - 左邊為容器, 右邊為宿主機
    https://ithelp.ithome.com.tw/upload/images/20230910/20148308aFUzEOUQHV.jpg
  • 是不是稍微可以感受到資源隔離的感覺,從宿主端、容器端會觀察到不同的結果,彷彿容器與宿主機是兩個不同的機器裡面。但實際上容器技術只是將目標 process 隔離出來,讓其彷彿處於一個獨立的執行環境中。與虛擬機的差別在於虛擬機需要多模擬一層 Guest OS,所以虛擬機的效能較差,但虛擬機的隔離性比較好。容器的效能比較好,但是隔離性較差。

  • 接下來感受一下所謂容器隔離性差的這件事情,這邊可以從 process 跟 file system 的角度切入看看。

# 容器內睡個 87878787 秒
sleep 87878787 ;

#在宿主機上觀察一下,會發現這個 8787 是用 root 權限在睡的
ps aux | grep 87878 ;


# 容器內在 /tmp 底下建立個 87878787 檔案
echo "I am 87" > /tmp/87878787 ;

#在宿主機上觀察一下,會發現這個檔案躺在 /var/lib/docker/overlay2 的某個資料夾內
sudo find /var/lib/docker/overlay2 -name "87878787" ;
  • 上述的方式如果把用虛擬機去取代容器的話,無法得到相同的結果,甚至從宿主機的指令也無法看到虛擬機內部的狀態。這也就是為什麼大家都說虛擬機的隔離性比容器來的好。

  • 那接下來就要開始簡單介紹 Linux 使用的隔離技術為何。資源隔離的概念會包含兩個面向,一個是隔離了哪些資源,另一個則是如何限制資源的使用量。而在 Linux 中則是透過 namespcae 以及 cgroup 來達到上述講的兩個目的。此篇就從 namespace 觀念說起,並且簡單透過 unshare 指令來作觀念驗證。

  • namespace 是一種 Linux 的隔離機制,目前有個隔離類型包含 Cgroup、IPC、Network、Mount、PID、Time、User以及 UTS。

  • 其中 PID 的掛載以及隔離部分可以參考 Day 13: Mount Namespace 的坑,這篇系列探討相當的完整。/images/emoticon/emoticon42.gif

  • 至於本次會透過 unshare 指令模擬出一個類似容器環境的方式,相關資料都是參考 使用Linux Namespace把进程一步一步隔离起来

  • pid namespace 步驟如下 :

cp `which unshare` ./ ;

#並非使用 root 執行,因此需要針對該程式增加權限
sudo setcap 'cap_sys_admin+ep' ./unshare ; 

# --pid 代表要建立一個獨立的 pid namespace,mount-proc 則是將這個獨立的process 資料掛載到 /proc 底下
# 如此一來 ps aux 才會看到真正的結果
./unshare --pid --mount-proc --fork bash ; 

ps aux ;
exit ;
  • 雖然目前 pid 的部分已經隔離了,但是檔案系統仍然是使用宿主機的檔案系統,因此必須利用 docker 匯出容器目前的檔案系統狀態作為掛載對象,然後再利用 unshare 將其掛載上去。
  • mount namespace 步驟如下 :
docker run -it --name my-nginx nginx bash ;
apt update && apt-get install procps net-tools -y ;
exit ;
docker export my-nginx --output=nginx.tar ;
mkdir nginx ;
tar -xvf nginx.tar -C nginx/;
sudo setcap 'cap_sys_admin+ep cap_sys_chroot+ep' ./unshare ;
./unshare --mount --root nginx --pid --mount-proc --fork bash ;

# 可以觀察 bash 的狀態
ps aux ; 
  • 透過在容器以及宿主機執行 ls /proc/$$/ns -al 可以觀察到當前執行 process 的各項 namespace,可以發現上述環境的 mount、pid、pid_fork 的 namespace 是有差異的。
    https://ithelp.ithome.com.tw/upload/images/20230910/20148308s3rMTyVF1L.jpg

  • 做到這邊差不多就利用 unshare 隔離出 pid、mount namespace 的執行狀態出來,算是針對容器的隔離概念有點小小的了解,下一次則是要開始學習如何逃逸出容器的隔離環境,進而得到操控宿主機的能力。

  • 今日總結 :

    • 本日回顧 :
      • 針對容器隔離觀念做介紹,一開始先用例子讓大家了解容器隔離性較差的部分。後面則使用 unshare 做出一個類似容器隔離的環境。主要的目的是想讓大家了解其實所謂的容器就是把特定Process做隔離以及資源的限制,實際上Process還是利用作業系統的kernel在執行。
    • 次日預告 :
      • 既然容器的隔離性比虛擬機來的差,所以自然逃逸的手法相對來的豐富許多。接下來就針對容器的 root 能力以及啟動設定造成可以被逃逸來做為說明。排序的部分會從開放權限大到小來逐一演示。

上一篇
Day02 - (新手向) 容器基本操作介紹
下一篇
Day04 - (攻擊) 容器逃逸手法 nsenter
系列文
怕痛的我把 Docker、K8s 攻擊、防禦、偵測力點滿就對了63
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言