query.string的一些思考


这周强基计划有一道rctf的题目。感觉很有意思然后正好也通过这个题目扩展了一写东西。题目是rctf的verysafe。原理这里就不做过多的描述了,这里和大家分享一下关于pearcmd的一些利用技巧。

pecl是PHP中用于管理扩展而使用的命令行工具,而pear是pecl依赖的类库。在7.3及以前,pecl/pear是默认安装的;在7.4及以后,需要我们在编译PHP的时候指定--with-pear才会安装。

不过,在Docker任意版本镜像中,pcel/pear都会被默认安装,安装的路径在/usr/local/lib/php

原本pear/pcel是一个命令行工具,并不在Web目录下,即使存在一些安全隐患也无需担心。但我们遇到的场景比较特殊,是一个文件包含的场景,那么我们就可以包含到pear中的文件,进而利用其中的特性来搞事。

这里我在验证过程中是使用的MAMP,他的安装目录为/Applications/MAMP/bin/php/php7.4.21/lib/php/pearcmd.php .pearcmd的利用思路就是当php开启register_argc_argv这个配置,用户的输入将会被赋予给$argc$argv$_SERVER['argv']几个变量。

这里PHP读取命令行参数的逻辑可以在Getopt.php->readPHPArgv()中看到:

    /**
     * Safely read the $argv PHP array across different PHP configurations.
     * Will take care on register_globals and register_argc_argv ini directives
     *
     * @return mixed the $argv PHP array or PEAR error if not registered
     */
    public static function readPHPArgv()
    {
        global $argv;
        if (!is_array($argv)) {
            if (!@is_array($_SERVER['argv'])) {
                if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
                    $msg = "Could not read cmd args (register_argc_argv=Off?)";
                    return PEAR::raiseError("Console_Getopt: " . $msg);
                }
                return $GLOBALS['HTTP_SERVER_VARS']['argv'];
            }
            return $_SERVER['argv'];
        }
        return $argv;
    }

}

这里PHP会依此验证argv,$_SERVER[‘argv’]是否有值。后者可通过query-string控制。也就是说,可以通过Web访问了pear命令行的功能,且能够控制命令行的参数。

这里可以先看看pearcmd可以使用的命令有哪些:

image-20220814194917281

这里重点可以利用的有config-create,install和download。这里关于这三个命令的具体利用方式,这里不做过多赘述。接来下是一些其他关于query.string的利用。看了p神的这文章以后,我比较感兴趣的还有p神的另外两篇文章分别是:《PHP-CGI远程代码执行漏洞(CVE-2012-1823)分析》和《[Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写》。通过这两篇文章,我大概学到的一些东西有:php-fpm,fast-cgi和php-cgi等一些基础的知识。

首先,php-fpm就是一个fastcgi的解释器,web中间件将用户请求按照fastcgi规则打包以后就会发送给fpm,然后fpm会按照fastcgi的规则将TCP流解析成真正的数据。完整的fastcgi的参数如下:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

举个例子,用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对:

{
    'GATEWAY_INTERFACE': 'FastCGI/1.0',
    'REQUEST_METHOD': 'GET',
    'SCRIPT_FILENAME': '/var/www/html/index.php',
    'SCRIPT_NAME': '/index.php',
    'QUERY_STRING': '?a=1&b=2',
    'REQUEST_URI': '/index.php?a=1&b=2',
    'DOCUMENT_ROOT': '/var/www/html',
    'SERVER_SOFTWARE': 'php/fcgiclient',
    'REMOTE_ADDR': '127.0.0.1',
    'REMOTE_PORT': '12345',
    'SERVER_ADDR': '127.0.0.1',
    'SERVER_PORT': '80',
    'SERVER_NAME': "localhost",
    'SERVER_PROTOCOL': 'HTTP/1.1'
}

这里引起我兴趣的是p神提到的CVE-2012-1823,因为这里利用到的也是通过qurey.string来传入命令行参数。还有一个是p神提到的关于fpm和fastcgi的任意代码执行漏洞。这里漏洞的利用方式主要是设置auto_prepend_file = php://inputallow_url_include = On,然后将需要执行的代码放在Body中,即可执行任意代码。当然,这个漏洞的利用条件还比较苛刻。目前正在复现中。

参考文章:

Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

Docker PHP裸文件本地包含综述

PHP-CGI远程代码执行漏洞(CVE-2012-1823)分析

关于pearcmd利用总结


文章作者: kento
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kento !
评论
  目录