问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
CVE-2024-41667 OpenAM FreeMarker 模板注入分析
漏洞分析
OpenAM是一个开放式的访问管理解决方案。在版本15.0.3及之前的版本中,存在一个模板注入漏洞(CVE-2024-41667)。RealmOAuth2ProviderSettings.java中的`getCustomLoginUrlTemplate`方法由于使用了用户输入而容易受到模板注入攻击。
前言 -- OpenAM是一个开放式的访问管理解决方案。在版本15.0.3及之前的版本中,存在一个模板注入漏洞(CVE-2024-41667)。RealmOAuth2ProviderSettings.java中的`getCustomLoginUrlTemplate`方法由于使用了用户输入而容易受到模板注入攻击。虽然开发者意图实现自定义URL以处理登录,以覆盖默认的PingOne Advanced Identity Cloud登录页面,但他们没有对`CustomLoginUrlTemplate`进行限制,使其可以自由设置。 影响版本:<= 15.0.3 环境搭建 ---- ```yml //docker-compose.yml version: '3' services: openam: image: openidentityplatform/openam:15.0.3 ports: - "5005:5005" - "8080:8080" command: /opt/java/openjdk/bin/java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager --add-exports java.base/sun.security.x509=ALL-UNNAMED --add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED --add-exports java.xml/com.sun.org.apache.xerces.internal.dom=ALL-UNNAMED -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dcom.iplanet.services.configpath=/usr/openam/config -Dcom.sun.identity.configuration.directory=/usr/openam/config -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start ``` docker-compose 启动之后访问<http://127.0.0.1:8080/openam/>,默认配置搭建即可,调试端口为5005 ![image-20240829111300913.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-caa38bd5164673fbfd8927734a96150eab9a2def.png) 漏洞复现 ---- 登录到后台 ![image-20240829114932966.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-6de13e8880bdcf0103f050d506d6c68607da52d4.png) 创建了一个Connect Client ![image-20240829121408200.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-a1f41c63340f8a5038a35a991231107a3317cc53.png) ![image-20240829121434435.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-0924f96d4d931edd8b590c7a0cefda8e65e0cb4d.png) 点击刚才创建的Client配置信息,修改Redirection URIs和Scope的值 ![image-20240829144902182.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-dd5ea4e34c7f988dd9cacc800f666a4458666f9f.png) 配置一个OAuth2 Provider,在Custom Login URL Template 处填入payload ```php <#assign value="freemarker.template.utility.Execute"?new()>${value("touch /tmp/vuln")} ``` ![image-20240829121553319.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-d3ab70e77338e7d8fdb0f6e693169dae45b3cec6.png) ![image-20240829121629286.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-e586fea8b10c90bba13ef328d14578cec7ed1c97.png) ![image-20240829144822825.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-ba821a50c8f76d8c41792f8af948036081c7b07d.png) 在给出的 [POC](https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-7726-43hg-m23v)中在请求时需要加上csrf参数来绕过CSRF检测,这里只要退出openAM平台的登录再发送请求就不用添加csrf参数,这样并不会影响payload的执行,只是页面不会跳转到 [https://baidu.com](https://baidu.com/) ```php http://127.0.0.1:8080/openam/oauth2/realms/root/authorize?client_id=1&scope=employeenumber&redirect_uri=https://baidu.com&response_type=code&max_age=200 ``` ![image-20240829150138114.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-a3fb33ebf84a0ff89cf366aed4a520e695dbc4f3.png) 执行之后,进入到docker容器中,在/tmp目录下可以看到已经成功创建了文件 ![image-20240829141854086.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-df6db700d21f2e76dc2371fff13c8155e31903f8.png) 分析过程 ---- ### 路由分析 根据openam-server-only模块下的web.xml文件可以知道当访问/oauth2/realms/root/authorize接口时,会交由RestEndpointServlet处理 ![image-20240828173419208.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-78e13ca96b6442db8361d39dadcd873db2a74d0b.png) 跟进到org.forgerock.openam.rest.RestEndpointServlet,在该Servlet中不存在doGet()和doPost(),容器会调用到service方法 在该方法中,会判断ServletPath的值调用到不同的方法,这里会进入到restletOAuth2ServiceServlet.service() ![image-20240828173950868.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-610ac52ac40dc14b5552b532139c18eec75b6eba.png) 在service()方法中,初始化了一个HttpServerHelper对象,这是Restlet框架下的一个类,它充当了Restlet应用于HTTP服务器之间的桥梁,用来处理HTTP请求并将其转换为Restlet请求 ![image-20240828174347971.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-ca1806c18a37905638502afd926c9328dd4b2d93.png) 继续向下执行到关键代码处,将断点下在依赖org.restlet-2.4.0.jar包下的org.restlet.routing.Router#handle()方法下,该方法主要用来处理请求并控制请求的流向 程序会接受request对象作为参数,调用this.getNext()来根据上下文返回下一个处理器,如果不存在next下一个处理器的话会将请求的状态设置为404 ![image-20240829103820852.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-da4580d573fd4baf400e01bc307ab994a63605ad.png) 访问接口<http://127.0.0.1:8080/openam/oauth2/realms/root/authorize>,观察next的值 ![image-20240829104306081.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-41728bd3d9ea42e68b86323adfd362fc136200d2.png) ![image-20240829104649198.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-57132b8b6058a41ca23bbe8d57208c8b8aa255f4.png) ![image-20240829104708347.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-c2d88f6a991bdf28982a5e499d4f6ed63c8b8d01.png) ![image-20240829104728498.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-d54301e0fced5f24532d5226cb402f3732d7eba3.png) 在Restlet 程序初始化时,会通过一系列的工厂类进行路由注册并将其抽象成树状结构(如下图),假设用户访问的接口为/openam/test/stop,在/openam/test父树下不存在/stop这个子树,那么就证明/openam/test/stop这个请求是不合法的,程序就会返回404 ![image-20240829105819218.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-57a8668f4c2b503d929f2d5947246703ee43b99e.png) 跟进到this.getNext(),可以查看到某个父控制器下面的所有子树控制器,这是/openam/oauth2父控制器下的所有子控制器 ![image-20240829112705316.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-8ac5dfdac5ab3fbbd1fcf2c1eebe0271b99000f2.png) POC中的漏洞接口为/openam/oauth2/realms/root/authorize,通过上面的this.routes可以知道,实际上/openam/oauth2/authorize接口也是可以调用到漏洞类的 /authorize路由的注册实现在org.forgerock.openam.oauth2.rest.OAuth2RouterProvider#get(),可以看到当调用到authorize控制器时会交给AuthorizeResource类处理 ![image-20240829151229853.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-e1868375aeff87ee7a906d40f8ce3f456c80a252.png) 所以当访问/openam/oauth2/realms/root/authorize,最终的业务逻辑由AuthorizeResource#authorize()处理 ### 漏洞分析 在该方法中首先调用requestFactory.create()将原始的http请求转换成OAuth2Request类型的,接着调用到authorizationService.authorize() ![image-20240829151729099.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-04679e5231a75c882fccfab634d162fdd9d03022.png) 在该方法中程序会获取请求时参数的值,调用validateAuthorizationScope()验证传入的值与配置的值是否一致 ![image-20240829155612722.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-79bda2f637f3648d38b3ca468e93bbed80dbcad0.png) 跟进到validate(),由于获取到的token的值为null,会进入到下面的else语句中 ![image-20240829155009514.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-ce0eeb3f1f46a55b881014c8ad1ea8a400c79dca.png) isRefreshToken()用来检查传入的 OAuth2 请求是否是一个刷新令牌请求,这里返回的值为false,所以会进入到authenticationRequired() ![image-20240829155027233.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-22f9a0ef2be63396a4f3b0c928ad970f796a64e1.png) 最终会进入到getCustomLoginUrlTemplate()中,首先从设置中获取自定义登录 URL 模板字符串loginUrlTemplateString,接着使用该字符串创建一个模板对象返回 ![image-20240829155057611.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-02a1b21cbe28df9c36350a4c326db5fa78f30c8a.png) ![image-20240829155133830.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-9a1ecc74445cf1cb2a3b88fb3f3274520e77647e.png) 漏洞修复 ---- 设置了一个新的类解析器,用于控制模板中可以使用的类 <https://github.com/OpenIdentityPlatform/OpenAM/commit/fcb8432aa77d5b2e147624fe954cb150c568e0b8> ![image-20240829161427965.png](https://shs3.b.qianxin.com/attack_forum/2024/09/attach-210763a837cdc5fa91efa3f2cb91ef4813bd2235.png) 参考 -- <https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-7726-43hg-m23v>
发表于 2024-09-10 08:00:00
阅读 ( 6052 )
分类:
Web应用
0 推荐
收藏
0 条评论
请先
登录
后评论
kakakakaxi
7 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!