freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

漏洞分析 | JumpServer未授权访问漏洞(CVE-2023-42442)
2024-01-25 15:42:28

漏洞概述

JumpServer是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统,帮助企业以更安全的方式管控和登录所有类型的资产,实现事前授权、事中监察、事后审计,满足等保合规要求。

网宿安全演武实验室监测到JumpServer存在未授权访问漏洞(CVE-2023-42442)。由于JumpServer某接口未做授权限制,允许任何未经身份验证的用户获取session信息,最终结合目录权限绕过下载录像文件,其中可能包含敏感信息,如密码、历史命令等。

受影响版本

受影响版本:v3.0.0 - v3.6.3

漏洞分析

JumpServer使用了Django Rest Framework的权限模型来验证用户权限,而此次漏洞成因是自定义权限出了问题,所以先了解一下如何正确地实现自定义权限。

BasePermission是Django Rest Framework提供的基类。开发者可以通过继承permissions.BasePermission 来创建自定义的权限类,并且通常要实现has_permission、has_object_permission中的一个或两个方法。

下面分别举例说明各方法的实际作用:

首先是has_permission,这里对列入黑名单的IP进行全局权限检查,如果IP已被列入黑名单,则拒绝该请求。

接着是has_object_permission,它的作用就是允许对象的所有者对其进行编辑,而对于其它用户只允许进行只读操作,比如对于GET、HEAD、OPTIONS,即只读操作,返回 True。

而对于POST、PUT、PATCH、DELETE,则需要验证请求的用户是否是对象的所有者,如果对象的 owner 属性与请求的用户相匹配,则返回 True,表示用户有权限执行操作,否则返回 False,表示用户无权限执行操作。

但正如Django Rest Framework官方所述,has_permission方法可以提供一个基本的权限检查,用于验证用户是否具有访问整个API视图的权限。而has_object_permission方法可以在has_permission验证通过后,进一步验证用户是否具有访问特定对象的权限,所以为了确保安全性,最优的方式就是在自定义权限类中同时实现这两个方法。

回到漏洞代码,不难发现IsSessionAssignee只实现了has_object_permission。

搜索该类的使用情况:

只有SessionViewSet使用,这是用来处理与Session相关的 API 请求的视图集,相关接口可以通过JumpServer提供的API文档进行查阅。而此次漏洞泄露的信息为session列表,获取的信息如下:

至此,第一个API未授权访问导致session信息泄露已经分析结束,接下来就是利用目录权限绕过下载录像文件。

我们可以先通过JumpServer提供的API文档,尝试未授权下载录像文件:

发现该接口做了鉴权:

那就只能去安全版本查看更新日志,发现这一条涉及到了静态录像文件路径:

查看对应的http_server.conf后可得,录像文件存放于/media/replay/下:

进入docker内查看完整目录结构,即/media/replay/{time}/{id}.cast.gz(Linux)或/media/replay/{time}/{id}.replay.gz(Windows):

按照这个格式构造请求后发现被禁止访问了:

这里先看下静态文件是如何管理的:

不难发现是使用了第三方模块django-private-storage。这个模块就是将敏感的文件存储在受保护的位置,并通过授权的方式提供对这些文件的访问。

而我们需要关注的,是它用于验证对私有文件访问权限的配置选项PRIVATE_STORAGE_AUTH_FUNCTION。

全局搜索后发现,该配置选项指定了一个自定义函数allow_access:

跟进分析可知,这个函数先获取了request和request_path,接着将 request_path 根据 / 进行分割,得到path_list,并提取path_list中的第二个元素作为path_base,再去从 path_perms_map 中通过 path_base 获取对应的 path_perm值。如果path_list长度不大于 1,则将 path_base 设置为 None。接着就是通过path_perm值进行权限验证了:

(1)如果 path_perm 为空,返回 False,禁止访问文件;
(2)如果 path_perm 等于 '*',说明该路径对应的文件允许任何用户访问,或者用户拥有指定的权限;
(3)如果 path_perm 等于 'default',说明只允许已认证用户访问;
(4)如果以上条件都不满足,则说明用户必须拥有指定的权限才能访问文件,直接返回False。

所以我们最需要关注的就是,能够将path_perm 值等于 '*'的字符串,这里提供了两个:’xpack’和’settings’。那么攻击者就可以通过/xpack/../或/settings/../绕过权限校验,最终实现目录权限绕过下载录像文件。当然这里的自定义函数校验的是静态文件,而静态文件显然不止录像文件。也就是说,攻击者可以通过这种方式获取全站静态文件。

参考demo如下:

漏洞复现

首先获取seesion信息:

接着下载相应录像文件:

最后通过官方播放器还原操作记录即可:

修复方案

JumpServer已发布修复版本,https://github.com/jumpserver/jumpserver/releases/tag/v3.6.4

修复细节如下:

https://github.githistory.xyz/jumpserver/jumpserver/blob/dev/apps/terminal/permissions.py中,已新增has_permission验证:

https://github.githistory.xyz/jumpserver/jumpserver/blob/dev/apps/jumpserver/rewriting/storage/permissions.py中,验证了请求路径中是否存在跨目录行为:

# 数据泄露 # web安全 # 漏洞分析 # 网络安全技术
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录