写点什么

Struts2 漏洞分析之 Ognl 表达式特性引发的新思路

用户头像
H
关注
发布于: 2 小时前
Struts2漏洞分析之Ognl表达式特性引发的新思路

摘要

在 Ognl 表达式中,会将被括号“()”包含的变量内容当做 Ognl 表达式执行。Ognl 表达式的这一特性,引发出一种新的攻击思路。通过将恶意代码存储到变量中,然后在调用 Ognl 表达式的函数中使用这个变量来执行恶意的代码,从而实现攻击。

本文将会以 CVE-2011-3923 漏洞作为示例,描述这种利用思路的具体过程。但是,本文的内容绝不仅仅局限于这个漏洞,在实际的审计过程中,这种思路可以用来发现很多类似的漏洞。

背景介绍与原理分析

这个漏洞和 CVE-2010-1870 很相似,都是是通过 Ognl 表达式执行 java,来达到远程代码执行的效果。我们先来回顾下 CVE-2010-1870 漏洞,它是攻击者通过 get 方法提交 Ognl 表达式,直接来调用 java 的静态方法来实现代码执行。这个问题爆出来后,struts 官方加强了对于用户提交内容的审核,禁止使用“#”、“\”等特殊字符作为参数提交。

那么这样我们就没有办法远程执行 Ognl 表达式了吗?当然不,Ognl 给我们提供了另一种执行它的方法,我们来看下官方文档中一部分的内容:


Ognl 表达式给我们提供了“#fack()”这样调用上下文对象方法的功能,我们需要留意的是红色文字,大概的意思如下:如果你想要调用上下文环境中对象的方法,可以使用“(fact)()”这种格式来书写。

而在测试过程中发现,(one)(two)这种形式的 Ognl 表达式,会先将 one 当做另一个 Ognl 表达式先执行一遍,然后再继续他后面的工作。这样的话,如果程序在调用某一可以执行 Ognl 表达式的函数时,我们通过变量将恶意的表达式传入,那么,struts 所做的那些过滤便成为了一扇“透明的门”。

0x03 实例模拟与跟踪

在正常的调用中,我们找到了 setValue 这个函数,它的作用是根据 Ognl 表达式对目标进行赋值,在这个过程中 Ognl 表达式会执行。而 struts2 中通过在继承 ActionSupport 的类中,设置 setter 和 getter 方法,可以实现用户通过 get 和 post 方法直接为私有成员变量赋值。这种方法便会用到 setValue 这个函数。下面我们来搭建一个这样的类:


上面的这段代码只是简单的实现了接受参数“tang3”,并将它的内容打印到控制台中的功能。在跟踪它的过程中发现,用户提交的参数时,会通过调用 com.opensymphony.xwork2.interceptor.ParametersInterceptor 这个类中的 set Parameters 方法来获取参数,而这个方法会调用 setValue 函数,代码如下:

注意红色字体部分,name 参数是 Ognl 表达式部分,value 是被赋值的对象,而之前的 CVE-2010-1870 漏洞,也是通过这个函数执行的 Ognl 表达式。下面我们来看下如何结合前面讲到的内容来让这个函数执行我们需要的 Java 代码。

按照之前我们所说的 Ognl 表达式特性,我们应该构造这样的 url:

提交这样的 url 后,web server 将会做两件事,第一,将 Ognl 表达式内容存进了 tang3 变量中;第二,名为(tang3)(‘meh’)的 http 参数将会被当做另一个 Ognl 表达式执行,并且 action 属性 tang3 将会从 action 中恢复内容,即变成了()(‘meh’)。

因为 http 参数传入到变量中会自动进行 url 解码,那么我们便可以使用 url 编码“#”这样的特定字符,来绕过正则表达式的过滤。

在构造语句中还需要注意的一点就是,我们要确保 tang3 属性中的内容先被执行。所以这里需要一个小技巧,在提交参数时,使用 z[(tang3)(‘meh’)]=1 这种形式的参数,可以确保 tang3 变量被首先执行。下面我们构造一条可以弹出计算器的 url:

url 编码后:

效果如下图:


从最下面的红色框中,我们可以看出,控制台打印出的 tang3 变量的内容,就是我们刚才输入的代码。

总结

1.

这个漏洞的利用方法,存在局限性,目标代码需要有一个私有成员变量可以直接通过 http 参数赋值。同时,攻击者需要知道这个私有成员的名字。不过从代码审计的角度来看,可以很容易发现这种问题。但是,由于大部分使用 struts 框架搭建的网站都是闭源的,导致很难进行白盒测试。

这个问题在 struts2.3.1.2 版本之后便已经修复了,官方补丁的修复原文如下:

2.

The regex pattern inside the ParameterInterceptor was changed to provide a more narrow space of acceptable parameter names.

Furthermore the new setParameter method provided by the value stack will allow no more eval expression inside the param names.

修复方法就是,进一步减少 ParameterInterceptor 中白名单包含的内容,并且禁止参数名执行正则表达式

3.

Ognl 表达式的强大,能够明显的从 struts 所爆出的这些漏洞中看出。只要存在调用 Ognl 表达式的函数,都有可能出现代码执行问题。我在之前的《Struts2 漏洞浅析之 Ongl 代码执行分析》一文中,称 findValue 为 struts 中的 eval 函数,明显的有些狭隘了。Ognl 表达式才称得上是 eval 函数,在代码的编写的过程中要小心的处理它的表达式。

4.

再次重申在本文开始处所强调的,这篇文章并不仅仅局限于 CVE-2011-3923 这个漏洞,而且,它已经被修补了。本文的目的是,希望读者能够通过这个漏洞,了解到通过括号包裹变量,执行 Ognl 表达式这个特性,以此为我们在日后的审计增加一个思路。


用户头像

H

关注

还未添加个人签名 2021.07.04 加入

想白嫖网安学习资料的,扣我

评论

发布
暂无评论
Struts2漏洞分析之Ognl表达式特性引发的新思路