前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从 0 到 RCE:Cockpit CMS

从 0 到 RCE:Cockpit CMS

原创
作者头像
Khan安全团队
发布2022-01-04 10:51:00
2.7K0
发布2022-01-04 10:51:00
举报
文章被收录于专栏:Khan安全团队

开源内容管理系统 Cockpit 的源代码中搜索错误。以下是其官方网站上对 Cockpit 的描述:

Cockpit 是一个无头 CMS,采用 API 优先方法,将内容放在首位。它旨在通过将内容管理与客户端的内容消费分离来简化发布过程。 Cockpit 只专注于管理内容的后端工作。与其担心通过页面传递内容,它的目标是通过简单的 API 跨不同渠道提供结构化内容。

在调查 Cockpit 源代码时,我们发现了许多漏洞。攻击者可以利用它们来控制任何用户帐户并执行远程代码执行。

在本文中,我将讨论技术细节并演示如何利用这些漏洞。

提取用户帐户名称

在源代码中,我们发现了两种易受 NoSQL 注入攻击的方法,可用于提取应用程序用户名。这些方法都不需要身份验证。

NoSQL 注入/auth/check(CVE-2020-35846)

让我们考虑负责对应用程序用户进行身份验证checkAuth控制器的方法:

验证::检查方法

以及模块的authenticate功能:

验证功能

如您所见,该代码不检查用户参数的类型,这允许在查询中嵌入具有任意 MongoDB 运算符的对象。

这是盲注,因此要成功利用,您需要找到返回条件结果的方法。

在分析了方法源代码之后,我们开发了一种技术。本质上,我们在密码参数中传递了一个数组(而不是字符串)。这会导致password_verify函数显示一个关于无效值类型的警告:

验证功能

现在我将演示更多利用 NoSQL 盲注入的方法:

1. 使用$eq运算符

$eq操作符匹配字段的值等于指定值的文档。

例如,您可以使用它通过字典对名称进行暴力破解。

满足条件:已找到名为admin的用户

不满足条件:未找到名为admini 的用户

2. 使用$regex运算符

为查询中的模式匹配字符串提供正则表达式功能

您可以使用它来暴力破解所有应用程序用户的名称。

满足条件:已找到名称以字符ad开头的用户

不满足条件:未找到名称以字符ada开头的用户

我们可以通过$nin在查询中添加运算符来加速暴力破解,这将排除任何已经找到的用户:

$nin 选择字段值不在指定数组中的文档

条件满足:已找到名字以字符j开头的用户

不满足条件:未找到名称以字符a开头的用户(具有此名称的唯一用户是admin,但该用户已从搜索中排除)

我们可以通过向正则表达式添加一个固定量词来调整它,以查找或限制字符串的长度:

满足条件:已找到名称以字符a开头并包含4个字符的用户

满足条件:已找到名称以字符ad开头且包含3个字符的用户

条件不满足:未找到名称以字符a开头并包含12个字符的用户

3.使用MongoLite库的$func操作符(默认使用)

这个非标准运算符允许调用标准函数$b(任何带有单个参数的 PHP 函数),它接受一个等于字段的参数$a(在本例中为用户字段):

通过传递 PHP 函数var_dumpvar_export作为参数,我们将盲注入变成经典的带内注入。通过一次查询,我们可以获得所有应用程序用户的姓名:

NoSQL 注入 /auth/requestreset

requestreset负责创建密码重置令牌的Auth控制器的方法:

Auth::requestreset 方法

与前一种情况一样,没有对用户参数进行类型检查。利用是类似的,但没有任何困难,例如密码或 CSRF 令牌验证:

提取密码重置令牌

与许多其他 Web 应用程序一样,Cockpit 允许重置帐户密码。 我们发现了两种容易受到 NoSQL 注入攻击并允许为任何用户获取密码重置令牌的方法。

NoSQL 注入/auth/resetpassword(CVE-2020-35847)

resetpasswordAuth控制器的方法,它负责使用重置令牌更改用户密码:

Auth::resetpassword 方法

令牌参数没有类型检查,因此您可以使用以下查询提取现有令牌:

NoSQL 注入/auth/newpassword(CVE-2020-35848)

newpasswordAuth控制器的方法,负责显示用户密码重置表单:

认证::新密码方法

同样,没有对令牌参数进行类型检查。该查询与上一个类似:

用户帐户泄露

现在,能够获得密码重置令牌,我们可以破坏我们感兴趣的任何用户帐户。这只需几个步骤:

1.访问/auth/requestreset生成用于重置所选用户密码的令牌:

2. 使用刚才描述的方法之一(/auth/resetpassword/auth/newpassword)提取令牌:

3. 使用/auth/newpassword上一步获取的方法和密码重置令牌提取用户帐户数据(用户名、密码哈希、API 密钥、密码重置令牌):

提取用户帐户管理员

提取用户帐户loopa

有了这些数据,我们就可以:

  1. 使用带有 API 密钥的应用程序。
  2. 从哈希中暴力破解帐户密码。
  3. 使用以下/auth/resetpassword方法更改帐户密码:

远程代码执行

简单的RCE

在入侵了管理员帐户后,我们可以使用 Cockpit 的标准Finder组件上传一个 web shell ,以实现远程代码执行:

上传 web shell _shell.php 到 Cockpit 根目录

使用 web shell 在服务器上执行命令

UtilArrayQuery::buildConditionMongoLite库的方法中的PHP注入

让我们考虑方法registerCriteriaFunction的的Database类,它创建文档的指定条件(过滤器)的条件函数:

Database::registerCriteriaFunction 方法

和相关功能buildCondition的的UtilArrayQuery类:

UtilArrayQuery::buildCondition 函数

记下$key包含字段名称的变量。它的内容按原样插入到未来的字符串文字中,而不会被转义。 因此,通过控制$key变量的内容,我们可以使用单引号从字符串文字中转义(打破它)以注入任意 PHP 代码。 为了演示该漏洞,我们将使用该/accounts/find方法(需要身份验证)。此方法支持自定义条件(过滤器),这意味着它允许我们将任意内容放入$key

结论

在本文中,我展示了几种利用 NoSQL 盲注入的方法,一种未经身份验证的用户接管任何帐户的方法,以及 MongoLite 库中的远程代码执行。

每个人都应该立即更新到最新版本 (>= 0.12.0)。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 提取用户帐户名称
    • NoSQL 注入/auth/check(CVE-2020-35846)
      • 1. 使用$eq运算符
      • 2. 使用$regex运算符
    • 3.使用MongoLite库的$func操作符(默认使用)
      • NoSQL 注入 /auth/requestreset
      • 提取密码重置令牌
        • NoSQL 注入/auth/resetpassword(CVE-2020-35847)
          • NoSQL 注入/auth/newpassword(CVE-2020-35848)
          • 用户帐户泄露
          • 远程代码执行
            • 简单的RCE
              • UtilArrayQuery::buildConditionMongoLite库的方法中的PHP注入
              • 结论
              相关产品与服务
              数据库
              云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档