专业汉语词典知识平台,分享汉字词语知识、历史文学知识解答!

励北网
励北网

phpinfo用法,phpinfo使用教程

来源:小易整编  作者:小易  发布时间:2023-03-06 04:50
摘要:phpinfo用法,phpinfo使用教程在PHP中,我们往往通过phpinfo()函数(及可选选项)来检查配置设置和预定义变量,返回结果输出关于PHP的配置信息,其中包含了PHP编译选项、启用的扩展、PHP版本、服务器信息和环境变量(如果...

phpinfo用法,phpinfo使用教程

在PHP中,我们往往通过phpinfo()函数(及可选选项)来检查配置设置和预定义变量,返回结果输出关于PHP的配置信息,其中包含了 PHP 编译选项、启用的扩展、PHP 版本、服务器信息和环境变量(如果编译为一个模块的话)、PHP环境变量、操作系统版本信息、path 变量、配置选项的本地值和主值、HTTP 头和PHP授权信息(License)。根据phpinfo()的可选选项,重点分析部分选项信息。

选项名称选项描述
INFO_GENERAL1配置的命令行、 php.ini 的文件位置、建立的时间、Web 服务器、系统及更多其他信息
INFO_CREDITS2PHP 贡献者名单
INFO_CONFIGURATION4当前PHP指令的本地值和主值
INFO_MODULES8已加载的模块和模块相应的设置
INFO_ENVIRONMENT16环境变量信息
INFO_VARIABLES32显示所有来自 EGPCS (Environment, GET, POST, Cookie, Server) 的 预定义变量
INFO_LICENSE64PHP的LICENSE信息
INFO_ALL-1显示以上所有信息,默认

一般信息(INFO_GENERAL)

版本

首先很明显就是PHP的版本了。截至写下这篇文章,PHP已经发布到PHP 8.0.3,但目前应用最广泛的仍然还是5和7版本了。PHP各个版本之间有很多特定的安全利用的trick,以下列举PHP 5到8版本之间与安全性的部分改动信息。

PHP5.2及以前

  • __autoload自动加载类,但只能一次调用;spl_autoload_register加载类,__autoload的实现

PHP5.3

  • 修复空字符截断
  • 新增全局变量__DIR__
  • phar://流包装,绕过后缀限制、文件操作触发反序列化
  • glob://绕过open_dir列目录

PHP5.4

  • 删除注册全局变量、魔术引号、和安全模式
  • 新增session.upload_progress.enabled,默认为1,可用来文件包含

PHP5.5

  • 废除pg_replace中可代码执行的\e修饰符
  • 容易引发变量覆盖的函数import_request_variables()不可用

PHP5.6

  • 运算符...实现函数中支持可变数量的参数列表

PHP7.0

  • 移除script标签<script language="php"></script>、asp标签<% ... %>、<%= ... %>
  • 含十六进制字符串不再被认为是数字
  • assert()成为一种语言构造,而不是一个函数,意味着很多assert一句话都会失效
  • 移除pg_replace中可代码执行的\e修饰符

PHP7.1

  • 废除mb_ereg_replace()和mb_eregi_replace()的e模式修饰符

PHP7.2

  • 禁用assert以字符串作为第一个参数
  • 废除可以动态执行字符串的create_function
  • 废除容易导致变量覆盖的parse_str()无设置参数的行为

PHP8.0

  • 字符串数字弱类型比较优化
  • assert()不再支持执行代码
  • 移除mb_ereg_replace()的e模式
  • 移除create_function
  • 移除php://filter中的string.strip_tags

这里仅仅列举各版本之间部分的改动信息,更多内容可在官方文档中进行查看。

操作系统版本和SAPI

操作系统版本信息可用于后续提权

SAPI可以明显地判断PHP的连接方式

Apache 2.0 Handler是通过Apache服务器的mod_php模块部署PHP服务的运行方式

FPM(FastCGI流程管理器)则是PHP FastCGI的一种替代实现。FPM有一个设计缺陷,由于两个进程间的通信没有进行安全性验证,可以伪造Nginx发送给FastCGI封装的数据给PHP-FPM去进行解析

配置文件路径和加载路径

Configuration File (php.ini) Path指的是PHP默认的配置文件路径,Loaded Configuration File是实际加载的配置文件。这个php.ini文件可有或可无真实的文件(比如docker),其加载的配置文件会表示为"none"。

有无加载php.ini之间,其默认配置会有一些区别。phith0n师傅在小密圈通过Discuz 7.x/6.x的全局变量防御绕过导致代码执行这个例子,提出了这样一个差异,request_order项在apt安装(有php.ini)和docker(无php.ini)下的默认值分别为GP和CGP。

由于这里显示的是apt安装自己设定好的情况,查看安装的模块配置文件是放在Scan this dir for additional .ini files目录,显示加载到的模块详情在Additional .ini files parsed查看,源码安装其值则为none。当源码安装PHP或安装扩展时候,使用设置--with-config-file-path或--with-config-file-scan-dir选项来完成,那么在运行时,PHP将扫描加载所有以.ini为后缀的文件,并在显示在Additional .ini files parsed项。假设以上路径可控,即可读可写,那么可控制覆盖PHP配置进行提权等操作。

协议/包装器(Registered PHP Streams)

php://是php特有的协议,用于访问PHP的输入输出流、标准输入输出和错误描述符等功能

  • php://input可访问请求的原始数据的只读流,即POST请求的情况下,php://input可以获取到POST数据,但使用enctype="multipart/form-data"的时候,php://input是无效的
  • php://output只写的数据流,允许允许以print和echo一样的方式写入到输出缓冲区
  • php://filter常用到的伪协议,设计用于数据流打开时的筛选过滤应用(即Registered Stream Filters),读文件、读源码等有明显效果

file://访问本地文件系统(绝对路径)guan,比如浏览器打开file:///d:/www/example.html、读取本地文件readfile('file:///etc/passwd');

glob://查找匹配的文件路径模式,查找的文件路径也需要限定在open_basedir范围内

data://可分为三部分,比如data://text/plain;base64,cGhwaW5mbw==

  • 第一部分就是data协议头,标识了这个内容为一个data URI资源
  • 第二部分为MIME类型,表示这个内容以怎样的方式去展现,比如text/plain即以文本类型展示
  • 第三部分为编码设置,默认编码是 charset=US-ASCII,以上示例即为base64

http、https、ftp和ftps这些再熟悉不过了,略...

zipPHP的读写zip文件的压缩流,zip文件压缩包可以压缩存放一个webshell,利用文件读取或者包含漏洞,比如file=zip:///var/www/html/upload/abc.zip#shell.php可执行利用。除此之外,类似的压缩流协议还有compss.bzip2://和compss.zlib://等。

pharPHP的读写归档,在不经过解压的情况下能够被php所访问并且执行。phar配合文件操作直接拓展了PHP反序列化攻击的利用面,并且还能绕过一大部分文件上传检测。

流过滤器(Registered Stream Filters)

PHP在Registered Stream Filters项默认提供了可用过滤器列表,以用于在调用php://filter打开数据流进行读写时,应用相应的流过滤器对数据筛选。

可用过滤器列表如下

  • 压缩过滤器zlib和bzip2,与协议相比,压缩过滤器更加通用,能在任何时候压缩任何数据流。例如解压zlib.deflate的数据readfile('php://filter/zlib.inflate/resource=test.deflated');还有zlib.inflate流压缩数据突破libxml解析器限制的实体长度php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd
  • 字符串过滤器string.*,字符串转换,string.rot13对字符串rot13编码,string.toupper转换为大写, string.tolower转换为小写,string.strip_tags去除标签
  • 转换过滤器convert.*,CTF中最常用的就是convert.base64-encode读源码读文件php://filter/read=convert.base64-encode/recource=flag.php

核心配置(Core)

allow_url_fopen选项激活了URL形式的fopen封装协议使得可以访问URL对象例如文件。默认的封装协议提供用ftp和http协议来访问远程文件,一些扩展库例如zlib可能会注册更多的封装协议。

allow_url_include允许将具有URL意识的fopen包装器与文件包含函数(include,include_once, require,require_once)一起使用。当该选项与allow_url_fopen同时开启,将实现远程文件包含。

注意这里的两项配置项

  • auto_ppend_file在目前页面执行之前,先require指定文件
  • auto_append_file在执行完目标页面之后,再require指定文件

disable_functions禁用某些内部函数。特别是webshell无法命令执行时,其中一种原因是php.ini使用此指令禁用了能执行系统命令的函数,比如以上的system、exec、shell_exec、passthru、popen等函数。列举几种绕过disable_functions的方法。

  • 尝试被遗漏未禁用的函数,比如pcntl_exec、proc_popen、dl等
  • 利用有漏洞的组件,比如ImageMagick()、bash shellshock(CVE-2014-6271)等
  • 利用环境变量LD_pLOAD,mail、sendmail、putenv等

此外,AntSword针对该指令开了一个Bypass Disable Functions专题,并提供了相应的插件

open_basedir将PHP可访问的活动范围限定在指定的目录,比如open_basedir=/var/www/app1/:/tmp/,那么通过app1访问服务器的用户除了/var/www/html/app1/和/tmp/以外,不可访问其他目录及其文件。但需要注意的是,open_basedir指定的限定实际上是目录名,而不是前缀,例如open_basedir=/var/www/app,那么/var/www/app1和/var/www/app2都是可以访问的,容易造成跨站问题。

cgi-fcgi

cgi是服务器后端编程语言(如php、java)与web服务器(如nginx)之间数据交换的通信协议

fastcgi就是升级版的cgi,本质上跟cgi也是协议。nginx根据fastcgi协议拓展了一个模块,也叫fastcgi,虽然同名但两者有本质区别

php-cgi就是php实现的自带fastcgi的管理器,它本身只能解析请求返回结果,但不会进程管理

php-fpm则是fastcgi协议解析器,用来管理php解释器php-cgi的。php-fpm通过生成新的子进程可以实现php.ini修改后的平滑重启

我们可以这样理解,nginx本不支持对PHP程序的直接调用或者解析,必须间接通过fastcgi调用,假设请求一个php程序,nginx会将请求信息按照fastcgi协议封装成数据包转发给php-fpm,php-fpm拿到以后调度管理php-cgi解析php程序代码

这里是一个Nginx服务器通过php-fpm运行的phpinfo,可以看到的该状态是active

看到cgi.fix_pathinfo=On,你应该会联想到Nginx解析漏洞,但它与php、nginx的版本都无关,属于用户配置不当造成的解析漏洞。PHP获取当前URL请求http://127.0.0.1/index.php/index/index/test的路径信息一般是通过环境变量$_SERVER['PATH_INFO']来获取的,key名PATH_INFO是一个cgi 1.1的标准,cgi.fix_pathinfo选项则与这个value值的获取相关。然而,php先前是将设置PATH_TRANSLATED为SCRIPT_FILENAME,而不是现在的PATH_INFO。

默认情况下,cgi.fix_pathinfo是打开的,设置为Off或者为0会导致像以前一样运行。举个例子,以国内最流行的thinkphp框架为例,框架使用PATH_INFO来作为路由载体,该请求是的实际执行脚本SCRIPT_FILENAME是index.php,PATH_INFO为/index/index/test,即访问index模块的index控制器的test方法;当关闭cgi.fix_pathinfo时,访问的则是web根目录下的index.php/index/index/test文件

回到漏洞本身,比如如下的nginx.conf

location ~ \.php($|/) {     fastcgi_pass   127.0.0.1:9000;     fastcgi_index  index.php;     set $script    $uri;     set $path_info "";     if ($uri ~ "^(.+\.php)(/.*)") {          set  $script     $1;          set  $path_info  $2;     }     include       fastcgi_params;     fastcgi_param SCRIPT_FILENAME   $document_root$script;     fastcgi_param SCRIPT_NAME       $script;     fastcgi_param PATH_INFO         $path_info; }

php.ini设置(默认开启)

cgi.fix_pathinfo=1

URL请求http://127.0.0.1/evil.jpg/xxx.php将触发以下逻辑

if (script_path_translated &&    (script_path_translated_len = strlen(script_path_translated)) > 0 &&    (script_path_translated[script_path_translated_len-1] == '/' ||    (real_path = tsrm_realpath(script_path_translated, NULL)) == NULL)   ) {......//略}

以上xxx.php结尾的请求通过了nginx的正则匹配,然后丢给php-fpm,php.ini开启了cgi.fix_pathinfo,将/xxx.php作为PATH_INFO的值,那么evil.jpg就是SCRIPT_FILENAME,php把evil.jpg当作php文件来执行

php从5.3.9开始,php-fpm配置(php-fpm.d/www.conf)新增了一个选项security.limit_extensions来限制值fpm允许解析的脚本扩展名,以预防web服务器配置的错误使用其他扩展名运行php代码

; Limits the extensions of the main script FPM will allow to parse. This can ; pvent configuration mistakes on the web server side. You should only limit ; FPM to .php extensions to pvent malicious users to use other extensions to ; exectute php code. ; Note: set an empty value to allow all extensions. ; Default Value: .php ;security.limit_extensions = .php .php3 .php4 .php5 .php7

会话(session)

php内置了很多中处理器用于存取$_SESSION数据时,会对数据进行序列化和反序列化,Registered serializer handlers配置项可以设置序列化及反序列化时使用的处理器,常用的有以下的三种,对应不同的处理格式

处理器对应的存储格式
php键名 + 竖线 | + 经过serialize()函数序列化处理的值
php_binary键名的长度对应的ASCII字符 + 键名 + 经过serialize()函数序列化处理的值
php_serialize(php>=5.5.4)经过serialize()函数序列化处理的数组

一般地,默认使用php处理器

引发的安全问题:PHP bug 71101

如果php在反序列存储的$_SESSION数据时使用的处理器和序列化时使用的处理器不同,会导致数据无法正确反序列化,通过特殊的构造,可以伪造任意数据

举个例子,当存储时php_serialize处理,然后调用时php去处理。假设这个时候注入的数据是这样的

<?php session_start(['serialize_handler' => 'php_serialize',]); class test{} $_SESSION['a'] = '|O:4:"test":0:{}'; session_write_close();

那么session中的内容就是a:1:{s:1:"a";s:16:"|O:4:"test":0:{}";},根据反序列化解释,其中a:1:{s:1:"a";s:16:"在经过php解析后被看成了键名,则后面就是构造了一个实例化的test对象注入

php.ini默认关闭session.auto_start,开启与关闭的区别在于时候需要调用函数session_start()开启会话,当值等于On时,执行session_start()将产生新的session_id

session.upload_progress.enabled这个参数是默认开启的,在设置为On的时候,就会在上传的过程中生成上传进度文件,它的存储路径为session.save_path,即基本表现为/var/lib/php/session/sess_{PHPSESSID}

session.upload_progress.cleanup开启时,在清除所有的POST数据后,清除上传进度信息。也就是说,文件上传完毕,这个session会自动被清除

上面提及session.auto_start默认是关闭的,当session.upload_progress.enabled开启,在处理一个POST上传,php会执行$_POST[ini_get("session.upload_progress.name")],成功则启用会话,记录上传进度

session.use_strict_mode可防止会话模块使用未初始化的session ID,即会话模块仅接受由它自己创建的有效的会话 ID, 而拒绝由用户自己提供的会话 ID。php默认是未启用session.use_strict_mode的,这就相当于session文件名可控

session与文件包含

不妨回顾一下HITCON CTF 2018的一道题目One Line PHP Challenge

<?php ($_=@$_GET['orange'] && @substr(file($_)[0],0,6)) ==='@<?php' ? include($_) : highlight_file(__FILE__);

curl http://127.0.0.1/session_upload.php -H 'Cookie: PHPSESSID=test' -F 'PHP_SESSION_UPLOAD_PROGRESS=hhh' -F 'file=@/etc/passwd' ls -a /var/lib/php/session/ # 输出结果sess_test

因为默认开启session.upload_progress.cleanup,在清除session内容之前,其内容大致为session.upload_progress.pfix + hhh(PHP_SESSION_UPLOAD_PROGRESS=hhh) + | + session序列,hhh即为可控的写入内容。因此需要条件竞争,在文件清除之前包含利用

phpinfo用法,phpinfo使用教程

当然,回到题目中,还需要结合利用php://filter和base64容错fuzz,以满足包含条件

文件包含phpinfo获取session.save_path的Local Value 先来看看一个登录功能的代码段

if (isset($_POST['username']) && isset($_POST['password'])) {    $query = $mysqli->ppare('select name, password, uuid from user where name = ? and password = sha1(?)');    $query->bind_param('ss', $_POST['username'], $_POST['password']);    $query->execute();    $query->bind_result($name, $password, $uuid);    if ($query->fetch()) {        $_SESSION['user'] = $name;        $_SESSION['uuid'] = $uuid;    }

当session记录了用户信息,意味着session内容可控,可通过注册一个包含恶意代码的username传入到session中,然后尝试包含。问题在于,session的文件保存路径未必为默认值,假如同时存在一个phpinfo.php页面,使用当前会话包含该phpinfo页面可获取到session.save_path的Local Value

包含session文件

环境变量

此处主要关注两个变量PHP_ADMIN_VALUE和PHP_VALUE,

PHP_ADMIN_VALUE可以设定指定的配置项的值,php_value可以设定指定的值,但只能用于PHP_INI_ALL或PHP_INI_PERDIR类型的配置项,这两个变量经常出现在攻击php-fpm的场景中,这里的phpinfo环境变量信息是通过PHP-FPM未授权访问漏洞远程代码执行打印出来的

在核心配置(Core)一节中提到auto_ppend_file,在执行目标文件之前先包含指定文件。该漏洞实现代码执行的部分就利用到前面提到SAPI中FPM/FastCGI的安全缺陷,伪造一个fastcgi协议的数据包,这个数据包其中传入的环境变量如下

{    'GATEWAY_INTERFACE': 'FastCGI/1.0',    'REQUEST_METHOD': 'GET',    'SCRIPT_FILENAME': '/var/www/html/index.php',    'SCRIPT_NAME': '/index.php',    'QUERY_STRING': '?a=1&b=2',    'REQUEST_URI': '/index.php?a=1&b=2',    'DOCUMENT_ROOT': '/var/www/html',    'SERVER_SOFTWARE': 'php/fcgiclient',    'REMOTE_ADDR': '127.0.0.1',    'REMOTE_PORT': '12345',    'SERVER_ADDR': '127.0.0.1',    'SERVER_PORT': '80',    'SERVER_NAME': "localhost",    'SERVER_PROTOCOL': 'HTTP/1.1'    'PHP_VALUE': 'auto_ppend_file = php://input',    'PHP_ADMIN_VALUE': 'allow_url_include = On' }

即通过PHP_VALUE和PHP_ADMIN_VALUE作为FPM的环境变量“覆盖”了配置信息,auto_ppend_file则设置了在执行目标文件之前,先包含request.body内容,最后将包丢给FPM去执行body中的代码

本地文件包含与phpinfo问题

核心配置(Core)中有一个配置项file_uploads默认是开启的,php允许用户向服务器上任意php文件以form-data方式提交请求上传数据

文件被上传后,首先默认地会被储存到服务端的默认临时目录中,可以修改php.ini中的upload_tmp_dir设置为其它的路径。服务端的默认临时目录也可以通过更改PHP运行环境的环境变量TMPDIR来重新设置。一般地,临时目录是/tmp,可以通过函数sys_get_temp_dir()进行查询

然而,即使得知临时目录,也不知道临时文件名。假如同时存在一个phpinfo页面,往phpinfo页面上传文件,通过_FILES变量来获取上传的文件信息,然后在这个临时文件在极短时间被删除的时候,竞争时间包含这个临时文件

phpinfo用法,phpinfo使用教程

<!doctype html> <html> <body> <form action="http://192.168.175.140/info.php" method="post" enctype="multipart/form-data">    <h3>LFI with phpinfo</h3>    <label for="file">filename</label>    <input type="file" name="file">    <input type="submit" name="submit" value="submit"/> </body> </html>

在被php删除临时文件之前,竞争时间包含执行这个tmp_name文件


本文地址:百科问答频道 https://www.neebe.cn/wenda/916649.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


百科问答
小编:小易整编
相关文章相关阅读
  • 手机蓝牙的作用和用法(手机蓝牙有什么用途)

    手机蓝牙的作用和用法(手机蓝牙有什么用途)

    每部手机上都有一个蓝牙功能,大家以前都会用它来传输文件,不过随着移动网络和WiFi的普及,这个功能也渐渐被大家忽略了。今天,我们就来科普一些手机蓝牙不为人知的功能,让大家可以更好的使用这一功能。1、传输文件传输文件,这一功能应该是大家最熟悉...

  • 磁盘阵列raid5的用法

    磁盘阵列raid5的用法

    操作方法01在日常应用中,大多是把服务器上所有的硬盘创建RAID5,并且只划分了一个“逻辑磁盘”,这样从理论上来讲没有任何问题,在实际中也可以可以使用的,但是这种方法并不可取。RAID5是一种存储性...

  • C语言while语句的用法

    C语言while语句的用法

    while语句的一般形式为:while(表达式)语句其中表达式是循环条件,语句为循环体。#includeintmain(void){inti,sum=0;i=1;while(i...

  • 详解Linux中hdparm命令查看硬盘信息的用法

    详解Linux中hdparm命令查看硬盘信息的用法

    功能说明:显示与设定硬盘的参数。语  法:hdparm[-CfghiIqtTvyYZ][-a][-A][-c][-d][-k][-K][-m][-n...

  • 机动都市阿尔法枪盾好用吗 枪盾用法大全

    机动都市阿尔法枪盾好用吗 枪盾用法大全

    机动都市阿尔法中各式各样的武器,每个都有自己的特点,枪盾也是深受玩家青睐,那么机动都市阿尔法枪盾好用吗,下面就和小编一起来了解一下吧。一、武器简介:枪盾从外观即可看出组成,一面盾牌,一把散弹枪,可以看出这是攻守兼备的一个武器,尤其是在近战中...

  • 口袋超萌高级精灵球怎么用 高级精灵球用法攻略

    口袋超萌高级精灵球怎么用 高级精灵球用法攻略

    各位玩家们大家好,对于新手玩家在游戏中获得的高级球,高级球是十分珍贵的道具。那么口袋超萌高级精灵球怎么用才能有效的捕捉到精灵,小编总结出以下内容,希望可以帮助到大家。首先在口袋超萌的游戏中,玩家们也许都想拥有一只属于自己的强力神宠。那么究竟...

  • 霓虹深渊无限能量转换器怎么使用 能量转换器的用法介绍

    霓虹深渊无限能量转换器怎么使用 能量转换器的用法介绍

    本次要为大家介绍一款像素动作游戏——霓虹深渊无限,这里会有很多玩法以及很多有趣的道具,其中有一种叫做能量转换器,很多人好奇霓虹深渊无限能量转换器怎么使用,那么接下来小编就为大家介绍下这个道具的玩法,感兴趣的快跟小编一起来看看吧。霓虹深渊无限...

  • 原神温蒂用法攻略 全服最强打法

    原神温蒂用法攻略 全服最强打法

    温蒂在三测时号称全服最强角色,很多PC版玩家攒着原石不抽就是在等这期的温蒂,今天给大家带来原神温蒂用法攻略,全服最强打法。多功能性第1最先从多功能性上来说一说温蒂。她是1个拿弓的人物,这预示着许多射气球有关的谜题,都能用温蒂出场处理,而这...

  • 周排行
  • 月排行
  • 年排行

精彩推荐