68

使用Docker快速搭建漏洞分析环境

 5 years ago
source link: http://x3fwy.bitcron.com/post/use-docker-to-analysis-vulnerability?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

起因

需求源于痛苦。很多人可能已经深有体会,搭建环境的时间可能会远大于真正做事时间。我最近在看一些Java的漏洞,但我不是Java开发者,并没有现成的Java环境。而且最近我没有自己的电脑用,需要管理员权限的操作我都不能执行。用着并不熟悉的IDEA,拉下来的代码编译无数遍都没有通过。检查了各种配置无果后,萌生了一个想法:为什么不能把我在开发中经常用到的Docker拿过来用做Java代码编译和部署,并且可以进行远程断点调试?而且我们可以通过不同的镜像去切换不同的JDK和Maven版本,岂不爽哉?闲话少说,行不行跟我一起试试看就知道了。

准备

  • Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口...官方的话就不继续说了,有关Docker的具体用法请看 官方文档

  • 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生命周期的两个命令: cleaninstall

NbyMrmz.png!web

那么,移步Docker Hub,找一下Maven相关的镜像

NRVf6rN.png!web

恰好,Docker Hub中的运行示例使用的正是 cleaninstall 这两个命令。直接拿过来跑一下试试。

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

uiaAJnE.png!web

看起来不错,已经开始跑了。让它先跑着,我们研究下其他的。

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吗?回头看已经成功了。

FVBFbuN.png!web

现在我们运行 docker-compose up 让服务跑起来。

eIJZVrV.png!web

可以在这里看到镜像构建过程和服务运行状态。现在在浏览器中访问http://localhost:8080 就可以看到Tomcat主页

aQzYnmU.png!web

点击 Manager App 可以看到刚刚部署的showcase项目,可直接点击访问。

fmeE7ve.png!web

BzyUV3U.png!web

远程调试

服务跑起来后,使用IDEA打开 src/ 目录,在菜单中依次点击 RUN —— Edit Configurations ,弹出页面点击 + 号添加一个 Remote 配置,命名为 tomcat-docker

yEZr6n3.png!web

修改Debug端口为8000如下图设置:

yIbeIjq.png!web

保存后依次点击菜单中 RUN —— debug "tomcat-docker" ,Console中输出如下内容即连接远程调试成功。

yYvM3uv.png!web

确认没有问题了就可以打断点触发漏洞了。以 S2-045 为例,断点打在 struts2-core-2.5.10.jar!/org/apache/struts2/interceptor/FileUploadInterceptor.class

JFnq2i7.png!web

断点打好后,来一段 payload 触发断点,因为没有管理员权限,我使用Postman代替Brupsuite。

IjInquJ.gif

现在差不多了。但是有一个不大的问题,我要跑两个命令,一个是 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

至此全部搞定。不过,我只是抛个砖~

参考


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK