這篇文章出人意料地登上了黑客新聞的頭版,并在那里引發了一場富有成效的討論。我將試著總結一下主要的要點:
- 漏洞掃描器往往有很多誤報
- 一些報告的發現已經可以在上游和后端修復
- 有些可能完全不相關,因為它們特定于某些深奧的架構
- 在鏡像倉庫(例如Docker Hub)中,官方基礎鏡像從不(或很少)更新
- 隨著容器使用的增加,為操作系統打補丁的負擔實際上從管理員和操作人員轉移到了開發人員身上
- 但并不是每個開發者都意識到這一點
- 有些人建議在每個Dockerfile的開頭添加RUN apt-get update && apt-get -y upgrade,我嘗試了一下,在完全成熟的Debian 10發行版中,它提供了非常小的效果
- 但其他人反駁說,這會導致不可復制的構建,以及由于反向端口改變依賴的默認行為而導致的潛在風險
- 這導致了一個公平的控制源存儲庫的建議
- 當然,這會讓事情變得更復雜
- 這就是為什么最典型的解決方案似乎是簡單地,忽略了這個問題
- 盡管掃描結果很好,但Alpine鏡像并不總是很好
- 因為據報道musl libc比glibc慢,并不是每個依賴庫都為這個平臺提供構建
以下是原文。
我最近在破解容器時注意到,Docker開始在構建輸出中突出Docker掃描命令。我已經忽略它的存在有一段時間了,所以是時候嘗試一下了。
掃描官方Python鏡像
Docker掃描命令使用一個第三方工具,稱為Snyk Container。顯然,這是某種漏洞掃描器。所以,我決定,主要是為了好玩,掃描我的一個鏡像。這是一件非?;镜氖虑椋?/p>
# latest stable at the time
FROM python:3.9
RUN pip install Flask
COPY server.py server.py
ENV FLASK_APP=server.py
ENV FLASK_RUN_PORT=5000
ENV FLASK_RUN_HOST=0.0.0.0
EXPOSE 5000
CMD ["flask", "run"]
我運行docker build -t python-flask,然后容器掃描python-flask。令我非常驚訝的是,產生大量的輸出!下面是一段摘錄:
Testing python-flask...
? Low severity vulnerability found in unbound/libunbound8
Description: Improper Input Validation
Info: https://snyk.io/vuln/SNYK-DEBIAN10-UNBOUND-534899
Introduced through: mysql-defaults/default-libmysqlclient-dev@1.0.5
From: mysql-defaults/default-libmysqlclient-dev@1.0.5 > mariadb-10.3/libmariadb-dev-compat@1:10.3.27-0+deb10u1 > mariadb-10.3/libmariadb-dev@1:10.3.27-0+deb10u1 > gnutls28/libgnutls28-dev@3.6.7-4+deb10u6 > gnutls28/libgnutls-dane0@3.6.7-4+deb10u6 > unbound/libunbound8@1.9.0-2+deb10u2
? Low severity vulnerability found in tiff/libtiff5
Description: Out-of-Bounds
Info: https://snyk.io/vuln/SNYK-DEBIAN10-TIFF-1079067
Introduced through: imagemagick@8:6.9.10.23+dfsg-2.1+deb10u1, imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1
From: imagemagick@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/imagemagick-6.q16@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-6@8:6.9.10.23+dfsg-2.1+deb10u1 > tiff/libtiff5@4.1.0+git191117-2~deb10u2
From: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > tiff/libtiff-dev@4.1.0+git191117-2~deb10u2 > tiff/libtiff5@4.1.0+git191117-2~deb10u2
From: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > tiff/libtiff-dev@4.1.0+git191117-2~deb10u2 > tiff/libtiffxx5@4.1.0+git191117-2~deb10u2 > tiff/libtiff5@4.1.0+git191117-2~deb10u2
and 3 more...
...
? High severity vulnerability found in gcc-8
Description: Insufficient Entropy
Info: https://snyk.io/vuln/SNYK-DEBIAN10-GCC8-469413
Introduced through: gcc-defaults/g++@4:8.3.0-1, libtool@2.4.6-9, imagemagick@8:6.9.10.23+dfsg-2.1+deb10u1, meta-common-packages@meta
From: gcc-defaults/g++@4:8.3.0-1 > gcc-8@8.3.0-6
From: libtool@2.4.6-9 > gcc-8@8.3.0-6
From: gcc-defaults/g++@4:8.3.0-1 > gcc-8/g++-8@8.3.0-6 > gcc-8@8.3.0-6
and 23 more...
? High severity vulnerability found in djvulibre/libdjvulibre21
Description: NULL Pointer Dereference
Info: https://snyk.io/vuln/SNYK-DEBIAN10-DJVULIBRE-481572
Introduced through: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1
From: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > djvulibre/libdjvulibre-dev@3.5.27.1-10 > djvulibre/libdjvulibre21@3.5.27.1-10
From: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-6-extra@8:6.9.10.23+dfsg-2.1+deb10u1 > djvulibre/libdjvulibre21@3.5.27.1-10
From: imagemagick/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > imagemagick/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1 > djvulibre/libdjvulibre-dev@3.5.27.1-10
and 1 more...
? High severity vulnerability found in bluez/libbluetooth3
Description: Double Free
Info: https://snyk.io/vuln/SNYK-DEBIAN10-BLUEZ-1018718
Introduced through: bluez/libbluetooth-dev@5.50-1.2~deb10u1
From: bluez/libbluetooth-dev@5.50-1.2~deb10u1 > bluez/libbluetooth3@5.50-1.2~deb10u1
From: bluez/libbluetooth-dev@5.50-1.2~deb10u1
Package manager: deb
Project name: docker-image|python-flask
Docker image: python-flask
Platform: linux/amd64
Tested 431 dependencies for known vulnerabilities, found 358 vulnerabilities.
For more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp
共發現漏洞358個,其中高級別54個,中級別48個。
仔細查看掃描報告后,我發現的大部分漏洞可能與Debian有關(參見信息:https://snyk.io/vuln/SNYK-DEBIAN10-…稍高一點,報告中很多項目都有)。
顯然,python:3.9鏡像是基于成熟的Debian 10發行版。
老實說,這是令人興奮的!我知道容器越厚,潛在的攻擊面就越高。但無論如何,我沒想到會有這么大的規模。
好的,讓我們試著把鏡像瘦身……
FROM python:3.9-slim
RUN pip install Flask
COPY server.py server.py
ENV FLASK_APP=server.py
ENV FLASK\_RUN\_PORT=5000
ENV FLASK\_RUN\_HOST=0.0.0.0
EXPOSE 5000
CMD ["flask", "run"]
掃描python:3.9-slim的鏡像給了我更好的結果:
Package manager: deb
Project name: docker-image|python-flask-slim
Docker image: python-flask-slim
Platform: linux/amd64
Tested 94 dependencies for known vulnerabilities, found 69 vulnerabilities.
共發現69個漏洞,其中高級別14個,中級別8個。
我們能做得更好嗎?讓我們嘗試python: 3.9-alpine:
FROM python:3.9-alpine
RUN pip install Flask
COPY server.py server.py
ENV FLASK_APP=server.py
ENV FLASK_RUN_PORT=5000
ENV FLASK_RUN_HOST=0.0.0.0
EXPOSE 5000
CMD ["flask", "run"]
終于,0已知的漏洞!
Package manager: apk
Project name: docker-image|python-flask-alpine
Docker image: python-flask-alpine
Platform: linux/amd64
? Tested 37 dependencies for known issues, no vulnerable paths found.
掃描無發布的Python鏡像
另一個可能解決膨脹容器問題的方案是谷歌所謂的“非發行版”Docker鏡像。項目描述說它是“語言聚焦Docker鏡像,減去操作系統”。盡管這在Python的情況下很難實現,因為它的標準庫依賴于一些高級操作系統功能。
我花了一段時間才想出一個可以工作的非發行版Python鏡像。大多數示例都展示了如何使用一些簡單的腳本。然而,安裝Flask(或任何其他依賴項)比我預期的要困難得多。由于gcr,Python的無發行版容器需要多階段的構建過程。gcr.io/distroless/python3鏡像既沒有PIP,也沒有easy_install。首先,我試圖利用構建鏡像中的虛擬環境,然后將其復制到運行時鏡像中,并修改PATH變量。但它并沒有很好地工作,因為基本的非發行版鏡像在文件系統布局上做了一些自以為是的布局:
所以,我最終得到了以下Dockerfile,允許我在非發行版的Python鏡像中安裝Flask:
# Build image
FROM python:3.7-slim AS build-env
RUN python -m pip install Flask
# Runtime image
FROM gcr.io/distroless/python3
COPY --from=build-env /usr/local/bin/flask /usr/local/bin/flask
COPY --from=build-env /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages
WORKDIR /app
COPY server.py server.py
# Important line!
ENV PYTHONPATH=/usr/local/lib/python3.7/site-packages
ENV FLASK_APP=server.py
ENV FLASK_RUN_PORT=5000
ENV FLASK_RUN_HOST=0.0.0.0
EXPOSE 5000
CMD ["/usr/local/bin/flask", "run"]
掃描它與Docker掃描輸出以下結果:
Package manager: deb
Project name: docker-image|python-flask-distroless
Docker image: python-flask-distroless
Platform: linux/amd64
Tested 25 dependencies for known vulnerabilities, found 37 vulnerabilities.
所以,只有37個漏洞:6個嚴重程度高,8個中等。聽起來好像比原始的python:3.9鏡像減少了90%!它甚至比python:3.9-slim中的漏洞更少。
因此,我們的基于Alpine的Python鏡像是一個贏家!
掃描Go鏡像
我喜歡完全從零開始構建容器鏡像的想法,避免將任何distr內容放入其中。但為此,你需要一種對靜態構建有深刻支持的語言,例如Go:
FROM scratch
COPY hello /
CMD ["/hello"]
得出以下結果……沒錯,這就是它!
Testing go-scratch...
Package manager: linux
Project name: docker-image|go-scratch
Docker image: go-scratch
Platform: linux/amd64
? Tested go-scratch for known vulnerabilities, no vulnerable paths found.
沒有distr并不意味著沒有漏洞。但它確實降低了攻擊的可能性。
相反的結論
根據我的經驗,膨脹的鏡像通常是使用默認的From bloated_base,或者因為人們為了將來的調試/故障排除故意將額外的工具放入鏡像的結果。
第一種可能是Docker過去大規模營銷活動的結果。為了普及容器,你需要給人們一些看起來很酷和方便的東西。而且能夠在一秒鐘內從你的開發機器上啟動一個成熟的Linux distr(某種程度上),即使在今天看起來也很酷。一些本地的修補和/或實驗從docker run -it ubuntu中獲益良多。然而,我希望它從來沒有被用于生產。但是從一個成熟的Debian,CentOS,或者Ubuntu開始,Dockerfile的例子實在是太多了,至少要避免將其中一些滲透到我們的生產環境中。
第二個原因看起來更合理。但我有一種感覺,這只是第一眼看到的感覺。理想情況下,應該有另一種方法來調試你的容器化服務。這種方法不需要將所有潛在需要的工具打包到一個容器中。最近添加的kubectl調試功能很好地證明了這一假設。它允許將臨時容器注入運行中的Pod中,這樣的容器可以擁有調試所需的所有東西。
更小的容器不僅僅意味著更快的構建和更小的磁盤和網絡利用率,它們還意味著更安全。
原文鏈接:https://iximiuz.com/en/posts/thick-container-vulnerabilities/
本文鏈接:http://m.abandonstatusquo.com/40760.html
網友評論comments