iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
Security

從以卵擊石到堅若磐石之 Web API 安全性全攻略系列 第 29

Day29-保護鯨魚人人有責(四)

前言

前幾天不管是講怎麼把 Dockerfile 寫好、還是做弱點掃描,基本上都是在確保 Docker image 本身的安全性。而今天要講的則是在啟動一個 image 時,要加上哪些參數或設定才可以讓安全性再往上提高一個層次

不要在 container 中使用 root user

只要用過一陣子 Docker 應該就會知道,預設情況下我們在跑 docker run image 時 Docker Daemon 會用 root user 幫我們把 container 跑起來,而且在 container 中也是以 root 的身份執行程式

那這樣有什麼問題呢?因為底層的 Docker Daemon 或是 Linux kernel 可能會有漏洞,所以攻擊者可以藉由應用程式的漏洞,先取得在 container 內的 root 權限,再藉著 Linux kernel 的漏洞成功得到你機器上的 root 權限也就可以在你的機器上做任何想做的事

因為被取得 root 權限實在是太嚴重了,所以其中一個解決方法就是在啟動 container 時指定隨意一個 user ID,這樣即便駭客成功進入 container 也沒辦法拿到 root 權限

docker run --user 3000 <image>

而如果你是用 docker-compose 來啟動的話,也是直接在設定裡面加上 user 屬性就好了,輕輕鬆鬆就提高了安全性

services:
  api-server:
    restart: always
    image: server
    user: "3000"
    ports:
      - "4000:4000"

限制 container 能做的事

為了方便管理權限,Linux kernel 從 2.1 開始引入了 capability 的概念,他把 root 的特殊權限細分為非常多類,譬如說 CAP_CHOWN 是允許改變檔案的所有權、CAP_KILL 是可以對任意 process 發送 signal、CAP_NET_ADMIN 是可以管理防火牆跟路由等等網路設定

而 Docker daemon 預設在啟動 container 時也會給他其中一些權限,雖然說有權限好辦事,但 container 有了那些權限之後如果沒有好好管理反而會提高風險,因此如果只是一個普通的 API Server 沒有特別的需求的話,我會建議在啟動 container 時就直接加上 --cap-drop ALL 來取消所有特權,除非你的 server 哪天真的需要管理防火牆(幾乎沒有這種需求吧),那可以再用 --cap-add CAP_NET_ADMIN <image> 單獨把網路管理的權限開起來

docker run --cap-drop ALL <image> # 關掉所有權限
docker run --cap-drop ALL --cap-add CAP_NET_ADMIN <image> # 只給網管權限

而 docker-compose 的話也很簡單,只要設定一下 cap-addcap-drop 屬性就好了~

services:
  api-server:
    image: server
    ports:
      - "4000:4000"
    cap_drop:
      - ALL
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN

用 read only 模式把 container 跑起來

如果你的 API server 跑起來之後不會需要修改或新增檔案(大多數 API server 應該都是這樣),那可以直接加上 --read-only 用唯讀模式把 container 跑起來,如此一來即便你的 container 被入侵了,那駭客也沒辦法在裡面修改任何檔案、程式碼,所以就可以降低損害(有很多攻擊都是透過修改 production 程式碼或是 nginx 設定達成的)

docker run --read-only <image>

如下圖,如果你成功入侵一個 read-only 的 container,並且嘗試要新增一個叫做 newFile 的檔案,就會馬上噴出 Read-only file system 錯誤,你能做的就只有看看 container 裡面有哪些東西

而 docker-compose 設定起來也很簡單,只要加上一個 read_only 屬性就好了哦~

services:
  api-server:
    image: server
    ports:
      - "4000:4000"
    read_only: true

雖然 read only 聽起來好像限制了很多功能,但其實很適合現在大多數的 API Server。尤其現在為了方便水平擴展,上傳頭貼、照片這類的功能基本上都是傳到 s3,資料庫很多也是用 RDS 之類的服務,完全不會需要在 container 內寫入檔案,所以除非有什麼困難,不然真的很推薦把 read only 模式開起來

小結

今天講了幾個要把 image 跑起來時可以設定的小地方,因為用 docker run 要加上一堆參數很冗長、一不小心還可能忘記,所以在 production 上建議至少都要用 docker-compose 來啟動(當然 Swarm 或 K8s 也可以),這樣一來只要把以上那些設定加進去 yaml 裡面,container 跑起來就超安全的哦

關於 Docker 的內容就講到今天,如果對於這幾天 Docker 相關的內容有什麼疑問歡迎在下方留言,都沒問題的話明天就是總結了~謝謝大家~


上一篇
Day28-保護鯨魚人人有責(三)
下一篇
Day30-結語
系列文
從以卵擊石到堅若磐石之 Web API 安全性全攻略30

尚未有邦友留言

立即登入留言