Grav 是一个快速、简单、灵活的基于文件的 Web 平台。需要零安装。只需解压缩 ZIP 存档,您就已经启动并运行了。
当然,这又是一次给我们0day打猎的机会。您将阅读我们在研究过程中遇到的步骤。
绕过管理员页面保护
我知道我们不会找到任何唾手可得的果实。我不能透露我们客户的名字,但我可以坦率地说,他们拥有一支非常有才华、年轻且积极进取的安全团队。
当我们确定 GravCMS 时,我知道他们已经采取了一些预防措施来减少攻击向量。我意识到我们无法访问 /admin 端点,立即验证了我的假设。进一步的分析表明,保护是通过负载平衡器进行的。
我过去做过很多框架。每当我在负载均衡器上看到基于 URI 的黑/白名单保护时,我总是记得框架的路由组件。在这种情况下,我们的目标也是使用 GravCMS 的 langswitcher 插件。只需访问以下网址,您就可以轻松地在不同语言之间切换。
http://www.x.com/en/
http://www.y.com/tr/
但问题是,它怎么知道请求的是哪种语言?它是否执行 URI 解析?如果是,它如何决定将执行哪个控制器和相应的方法?
花一点时间阅读源代码已经回答了我心中的所有问题。
http://www.x.com/en/some-page-on-the-site
例如,每当 GravCMS 接收到上述 URI 时, langswitcher 就会 启动并通过解析“ /en/” 部分来决定语言包。框架的其余部分继续使用 URI 的剩余部分,即 /some-page-on-the-site 。
这意味着我们可以访问 /admin 路径,这给了我们一个巨大的攻击面,只需访问以下 URL。
http://www.x.com/en/admin
负载均衡器将看到 /en/admin 而不是 /admin(LB 不会对 URI 执行“包含”操作)。当框架收到 /en/admin 路径时,我们将在管理员控制器中执行方法!
GravCMS 方法调用和针对未受保护的方法
正如我之前所说,我过去曾研究过很多框架。阅读源代码和学习开发人员的代码设计和架构总是很有趣。以下代码片段取自 AdminBaseController.php 文件。
正如您在上面看到的$method,将动态调用的变量由$this->task变量填充。我不想分享框架如何执行该分配的完整函数调用,但该$this->task变量由用户通过 POST 参数控制。
这意味着用户可以执行任何以“task”开头的函数名。让我们看看 AdminController 类中有多少方法,从“task”开始。
身份验证和权限检查
我已经写了关于这些验证的正确方法的想法。如果您愿意,请随时花时间阅读���
https://pentest.blog/why-secure-design-matters-secure-approach-to-session-validation-on-modern-frameworks-django-solution/
让我们看一下 AdminController 方法之一。可以执行以下方法,因为它被放置在 AdminController 类中并以“task”开头。
所以它做的第一件事就是验证许可。如果您继续检查剩余的方法,您将$this->authorizeTask首先看到函数调用。但问题是,如果开发人员忘记调用它会发生什么?
未经身份验证的任意 YAML 写入
感谢 IDE——我喜欢 PhpStorm 尤其喜欢审查 PHP 项目——我们可以快速浏览我在上一节中确定的所有功能。
出于显而易见的原因,以下功能引起了我的注意。取决于变量的命名约定,它会以某种方式重新加载配置文件。另外,它不执行权限检查,并且函数名称以“task”开头!
了解该特定方法的目的至关重要。所以我们要了解getDataType()和getConfigurationData()方法。
简洁明了的代码。它从 URI 中返回一个值。我们可以控制它,它将用作其余执行的数据类型。
getConfigurationData()有 107 行代码。出于这个原因,我不想在这里复制完整的代码。我只取了它的重要部分来帮助你理解它的作用。
请看 31-34 之间的线。如果$type与“config/”匹配,则获取 POST 数据,然后找到相应的 YAML 文件并更新其内容!它对 users/、plugins/ 或 media-manager/ 文件夹下的其他 YAML 文件执行相同的操作。
这意味着我们可以将任何我们想要的内容写入 YAML 文件。那些在config文件夹下负责系统配置!
我们有未经身份验证的任意 YAML 文件写入/更新漏洞!
漏洞复现
为了证明我们可以更新 YAML 文件,我想向您展示如何更改网站标题���
1 – 转到 http://target/admin URL。
2 – 获取 cookie 并从登录表单中提取 admin-nonce 值。
3-执行以下 POST 请求。
即使我们看到一个登录页面,我们也有更新操作的结果消息。继续检查 GravCMS 的主页。标题正在更改为我们给定的字符串。
#1 远程执行代码的方法——调度器
我们几乎可以更改项目中的每一个 YAML 文件。然而,我们需要找到一种实现 RCE 的方法。
GravCMS 具有内置的调度程序功能,使您能够定义操作系统命令和执行周期。当然,调度器信息也存储在相应的 YAML 文件中。
跟随 HTTP 请求正在定义每分钟执行一次的新命令。
这里没有什么花哨的。这是一个特点!我们执行带有 1337 参数的 echo 命令,输出将写入 /tmp/1.txt 文件。
#2 远程代码执行方式——Redis 作为缓存服务
GravCMS 的默认配置是自动选择缓存方法。但是我们可以在系统 YAML 文件中定义 Redis 连接字符串。这将告诉 GravCMS 使用给定的 Redis 服务来存储缓存和会话信息!
通过利用同样的漏洞,我们可以告诉 GravCMS 使用 Redis���我们只需要如下:
1 – 启动 EC2 实例。
2 – 安装 Redis 服务。
3 – 更改 Redis 的配置,使其可以从 Internet 访问。
4 – 向您的目标发送以下 HTTP 请求。
5 – 运行“redis-cli monitor”命令查看传入数据。
6 – 找出管理员会话密钥
7 – 成为管理员!
8 – 转到 /admin/tools/direct-install 并上传您自己的自定义 GravCMS 插件,其中包含您的有效负载。
Metasploit 模块
对于那些喜欢自动化的人^^