使用Docker快速搭建漏洞分析環境
起因
需求源於痛苦。很多人可能已經深有體會,搭建環境的時間可能會遠大於真正做事時間。我最近在看一些Java的漏洞,但我不是Java開發者,並沒有現成的Java環境。而且最近我沒有自己的電腦用,需要管理員許可權的操作我都不能執行。用著並不熟悉的IDEA,拉下來的程式碼編譯無數遍都沒有通過。檢查了各種配置無果後,萌生了一個想法:為什麼不能把我在開發中經常用到的Docker拿過來用做Java程式碼編譯和部署,並且可以進行遠端斷點除錯?而且我們可以通過不同的映象去切換不同的JDK和Maven版本,豈不爽哉?閒話少說,行不行跟我一起試試看就知道了。
準備
- Docker
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的Linux機器上,也可以實現虛擬化,容器是完全使用沙箱機制,相互之間不會有任何介面...官方的話就不繼續說了,有關Docker的具體用法請看 ofollow,noindex" target="_blank">官方文件 。
- IDEA
這是一個我也不咋熟悉的IDE,在本文中只用來做遠端除錯。
- 含有漏洞的showcase
本文以 S2-045
為例,需要下載struts-2.5.10的showcase,下載地址: https://archive.apache.org/dist/struts/
檔案結構
+- debug_in_docker/ +- src/ |+- [showcase files] ! +- tomcat/ |+- context.xml |+- tomcat-users.xml |+- run.sh | +- docker-compose.yml | +- Dockerfile | +- run.sh
從檔案結構中可以看出,我將含有漏洞的showcase程式碼拿出來放在一個新資料夾,tomcat資料夾主要是Tomcat的一些配置和執行指令碼。Dockerfile用於構建部署環境需要的映象,docker-compose.yml用於執行映象,run.sh為整個系統的執行指令碼。我會在搭建思路中一一講解它們。
搭建思路
Maven Build
Struts2的showcase是一個可以用Maven編譯和執行的專案。我在使用IDEA編譯的時候使用了Maven生命週期的兩個命令: clean
和 install
。
那麼,移步Docker Hub,找一下Maven相關的映象
恰好,Docker Hub中的執行示例使用的正是 clean
和 install
這兩個命令。直接拿過來跑一下試試。
cd debug_in_docker/src docker run -it --rm --name my-maven-project -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.3-jdk-8 mvn clean install
看起來不錯,已經開始跑了。讓它先跑著,我們研究下其他的。
Tomcat Server
我們需要構建一個Tomcat伺服器映象並且把我們Bulid好的程式部署上去並進行遠端除錯,那我們來寫一個Dockerfile吧。這裡我借鑑 docker/labs 這個專案。我跟著它的步驟走了一遍整個流程,然後進行了一些優化。
首先是Tomcat的配置。我希望能在Tomcat的主頁通過 Manager App
看到我所有部署好的專案,需要更改兩個Tomcat配置。
- tomcat/context.xml
<?xml version="1.0" encoding="UTF-8"?> <Context antiResourceLocking="false" privileged="true" > <!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> --> <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/> </Context>
這個配置檔案主要把 ...RemoteAddrValve...
註釋掉用於允許遠端訪問管理頁面。
- tomcat/tomcat-users.xml
<?xml version='1.0' encoding='cp1252'?> <tomcat-users> <user username="system" password="manager" roles="admin-gui,manager-gui" /> <role rolename="manager-script"/> <user username="admin" password="admin" roles="manager-script"/> </tomcat-users>
這個配置檔案用來設定管理頁面的賬號和密碼。
- tomcat/run.sh
#!/bin/sh exec ${CATALINA_HOME}/bin/catalina.sh jpda run
這個shell檔案用來啟動Tomcat並啟動遠端除錯。
現在回到Dockerfile,我們使用 tomcat
作為基礎映象,然後把我們剛剛搞的Tomcat配置檔案和 run.sh
放到它們應該在的位置並且給run.sh執行許可權。然後在映象內 webapps/
中為 struts2-showcase
建立一個資料夾。設定一下遠端除錯的相關環境變數,引出8080埠,執行 run.sh
。
- Dockerfile
FROM tomcat # sets up user accounts and access permit for the Tomcat manager GUI # and script access for Maven deployments ADD tomcat/tomcat-users.xml $CATALINA_HOME/conf/ ADD tomcat/context.xml $CATALINA_HOME/webapps//manager/META-INF/ # ADD tomcat/catalina.sh $CATALINA_HOME/bin/ ADD tomcat/run.sh $CATALINA_HOME/bin/run.sh RUN chmod +x $CATALINA_HOME/bin/run.sh # create mount point for volume with application RUN mkdir $CATALINA_HOME/webapps/struts2-showcase # add tomcat jpda debugging environmental variables #ENV JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n" ENV JPDA_ADDRESS="8000" ENV JPDA_TRANSPORT="dt_socket" # start tomcat with remote debugging EXPOSE 8080 CMD ["run.sh"]
寫好Dockerfile後,我們寫一個docker-compose來為容器執行做準備。
- docker-compose.yml
version: "3" services: webserver: build: . image: debug-webserver volumes: - ./src/target/struts2-showcase:/usr/local/tomcat/webapps/struts2-showcase ports: - "8080:8080" - "8000:8000" restart: always
docker-compose就簡單多了,主要就是引出對應的埠和把使用Maven Build好的 target
資料夾掛載到容器內新建的 struts2-showcase
資料夾中,完成部署的同時方便遠端除錯。
執行
還記得剛才我們用 docker run
跑的build嗎?回頭看已經成功了。
現在我們執行 docker-compose up
讓服務跑起來。
可以在這裡看到映象構建過程和服務執行狀態。現在在瀏覽器中訪問http://localhost:8080 就可以看到Tomcat主頁
點選 Manager App
可以看到剛剛部署的showcase專案,可直接點選訪問。
遠端除錯
服務跑起來後,使用IDEA開啟 src/
目錄,在選單中依次點選 RUN —— Edit Configurations
,彈出頁面點選 +
號新增一個 Remote
配置,命名為 tomcat-docker
。
修改Debug埠為8000如下圖設定:
儲存後依次點選選單中 RUN —— debug "tomcat-docker"
,Console中輸出如下內容即連線遠端除錯成功。
確認沒有問題了就可以打斷點觸發漏洞了。以 S2-045
為例,斷點打在 struts2-core-2.5.10.jar!/org/apache/struts2/interceptor/FileUploadInterceptor.class
中
斷點打好後,來一段 payload
觸發斷點,因為沒有管理員許可權,我使用Postman代替Brupsuite。
現在差不多了。但是有一個不大的問題,我要跑兩個命令,一個是 docker run maven
用於build專案。一個是 docker-compose up
用於將build好的專案部署到伺服器中並開啟遠端除錯,那麼有沒有辦法用一個命令呢?我試了寫兩個 services
的 docker-compose 即使增加 depends_on
或者 links
,docker-compose也並不知道build有沒有完成。官方提供了一個 解決方案 是在服務A執行完成後建立一個檔案,服務B一直監控是否存在這個檔案,如果不存在就一直等待,存在繼續跑。這個方案應該可行但是過於麻煩了,而且在這個官方方案的投票中踩遠大於頂,很有意思。有興趣的可以去看下。我沒有參考官方方案,直接寫個shell指令碼吧。
- run.sh
#!/bin/sh docker run -it --rm --name build-maven-project -v "$(pwd)"/src:/usr/src/mymaven -w /usr/src/mymaven maven:3.3-jdk-8 mvn clean install docker-compose up
至此全部搞定。不過,我只是拋個磚~