searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

OGNL表达式注入

2023-05-29 07:10:37
58
0

一、什么是OGNL

现在有三个类分别是:CompanyBossEmployee;三个类含有的属性分别如下:

public class Company {
    public String name;
    public Boss boss;
}
public class Boss {
    public String name;
}
public class Employee {
    public String name;
    public Company company;

}

 

现在分别创建三个类的实例:companybossemployee;把boss的实例指定为companyboss属性,把company的实例指定为employeecompany属性,这样老板、公司、员工三者就存在依赖关系,通过这种依赖关系我们就能操作对象的属性和方法;

OGNL就是实现这种对象关系的导航语言,通过OGNL我们可以操作Java对象的任意对象属性和方法;

 二、OGNL的使用

以下测试OGNL版本均为:2.7.3

package com.l0cal.llll;

import ognl.Ognl;
import ognl.OgnlContext;

public class App {
    public static void main(String[] args) throws Exception {

        Company company = new Company();
        company.setName("360");
        company.setBoss(new Boss("laozhou"));

        Employee employee1 = new Employee();
        employee1.setName("lihua");
        employee1.setCompany(company);

        Employee employee2 = new Employee();
        employee2.setName("liming");
        employee2.setCompany(company);

        OgnlContext ognlContext = new OgnlContext();
        ognlContext.setRoot(employee1);
        ognlContext.put("e2",employee2);

        //获取Ognl根元素的相关值
        Object name = Ognl.getValue("name", ognlContext, ognlContext.getRoot());
        Object cname = Ognl.getValue("company.name", ognlContext, ognlContext.getRoot());
        System.out.println(name + " " + cname);

        //获取Ognl非根元素的相关值
        Object e2Name = Ognl.getValue("#e2.name", ognlContext, ognlContext.getRoot());
        Object ecn = Ognl.getValue("#e2.company.name", ognlContext, ognlContext.getRoot());
        Object bName = Ognl.getValue("#e2.company.boss.name", ognlContext, ognlContext.getRoot());
        System.out.println(e2Name + " " + ecn + " " + bName);

    }
}

可以实现实例属性的访问;

getValue()函数中三个参数分别是:表达式上下文root

  • 表达式:表示想干什么;(核心)
  • 上下文:对象运行的上下文、即:OGNL的操作在哪里
  • Root:对谁进行操作;

主要语法

  1. OGNL支持静态方法调用和值访问;格式:@[类全名]@[方法名|值名]

(系统过滤关键函数,只能截图)

  1. 支持方法的调用
  1. 支持运算法的操作;

表达式内容为Runtime@getRuntime()执行命令,通过debug发现表达式最终到OgnlRuntime.callAppropriateMethod()#method.invoke();

 

三、CVE-2022-26134 confluence OGNL漏洞分析

漏洞payload如下:

通过servlet-mapping请求处理class为:ConfluenceServletDispatcher.java

 
<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ConfluenceServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

有请求到达容器时,容器会调用servlet对象的service()方法;

该类继承ServletDispatcher.javaservlet对象的service()方法在该类中,service()函数内部调用serviceAction(),而在该函数中并调用getNameSpace(),然后调用getNamespaceFromServletPath.java,获取两/之间的内容;

 

serviceAction()中通过创建代理并传入namespace

 

在创建代理对象并进行初始化过程中传入namespace(我们的payload)

 
 

随后代理对象执行execute()方法,在该方法中调用了this.invocation.invoke()

 

跟进invoke(),该方法主要对拦截器的迭代,该类的有参构造方法中设置this.executed = false所以会执行流程会迭代拦截器,并执行this.proxy.getExecuteResult()方法,该方法在创建代理初始化过程中默认的值为true,因此会执行executeResult()函数;

execute() 函数中会通过 TextParseUtil.translateVariables()函数,并将 namespace 传入,并在此触发OGNL表达式,且表达式可控,造成RCE

com.opensymphony.xwork.util#findValue()

 

 

 

0条评论
0 / 1000
l0cal
3文章数
0粉丝数
l0cal
3 文章 | 0 粉丝
l0cal
3文章数
0粉丝数
l0cal
3 文章 | 0 粉丝
原创

OGNL表达式注入

2023-05-29 07:10:37
58
0

一、什么是OGNL

现在有三个类分别是:CompanyBossEmployee;三个类含有的属性分别如下:

public class Company {
    public String name;
    public Boss boss;
}
public class Boss {
    public String name;
}
public class Employee {
    public String name;
    public Company company;

}

 

现在分别创建三个类的实例:companybossemployee;把boss的实例指定为companyboss属性,把company的实例指定为employeecompany属性,这样老板、公司、员工三者就存在依赖关系,通过这种依赖关系我们就能操作对象的属性和方法;

OGNL就是实现这种对象关系的导航语言,通过OGNL我们可以操作Java对象的任意对象属性和方法;

 二、OGNL的使用

以下测试OGNL版本均为:2.7.3

package com.l0cal.llll;

import ognl.Ognl;
import ognl.OgnlContext;

public class App {
    public static void main(String[] args) throws Exception {

        Company company = new Company();
        company.setName("360");
        company.setBoss(new Boss("laozhou"));

        Employee employee1 = new Employee();
        employee1.setName("lihua");
        employee1.setCompany(company);

        Employee employee2 = new Employee();
        employee2.setName("liming");
        employee2.setCompany(company);

        OgnlContext ognlContext = new OgnlContext();
        ognlContext.setRoot(employee1);
        ognlContext.put("e2",employee2);

        //获取Ognl根元素的相关值
        Object name = Ognl.getValue("name", ognlContext, ognlContext.getRoot());
        Object cname = Ognl.getValue("company.name", ognlContext, ognlContext.getRoot());
        System.out.println(name + " " + cname);

        //获取Ognl非根元素的相关值
        Object e2Name = Ognl.getValue("#e2.name", ognlContext, ognlContext.getRoot());
        Object ecn = Ognl.getValue("#e2.company.name", ognlContext, ognlContext.getRoot());
        Object bName = Ognl.getValue("#e2.company.boss.name", ognlContext, ognlContext.getRoot());
        System.out.println(e2Name + " " + ecn + " " + bName);

    }
}

可以实现实例属性的访问;

getValue()函数中三个参数分别是:表达式上下文root

  • 表达式:表示想干什么;(核心)
  • 上下文:对象运行的上下文、即:OGNL的操作在哪里
  • Root:对谁进行操作;

主要语法

  1. OGNL支持静态方法调用和值访问;格式:@[类全名]@[方法名|值名]

(系统过滤关键函数,只能截图)

  1. 支持方法的调用
  1. 支持运算法的操作;

表达式内容为Runtime@getRuntime()执行命令,通过debug发现表达式最终到OgnlRuntime.callAppropriateMethod()#method.invoke();

 

三、CVE-2022-26134 confluence OGNL漏洞分析

漏洞payload如下:

通过servlet-mapping请求处理class为:ConfluenceServletDispatcher.java

 
<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.atlassian.confluence.servlet.ConfluenceServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

有请求到达容器时,容器会调用servlet对象的service()方法;

该类继承ServletDispatcher.javaservlet对象的service()方法在该类中,service()函数内部调用serviceAction(),而在该函数中并调用getNameSpace(),然后调用getNamespaceFromServletPath.java,获取两/之间的内容;

 

serviceAction()中通过创建代理并传入namespace

 

在创建代理对象并进行初始化过程中传入namespace(我们的payload)

 
 

随后代理对象执行execute()方法,在该方法中调用了this.invocation.invoke()

 

跟进invoke(),该方法主要对拦截器的迭代,该类的有参构造方法中设置this.executed = false所以会执行流程会迭代拦截器,并执行this.proxy.getExecuteResult()方法,该方法在创建代理初始化过程中默认的值为true,因此会执行executeResult()函数;

execute() 函数中会通过 TextParseUtil.translateVariables()函数,并将 namespace 传入,并在此触发OGNL表达式,且表达式可控,造成RCE

com.opensymphony.xwork.util#findValue()

 

 

 

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
1
1