WEB-PHP核心配置

— 从零开始的笔记 —
—PHP5核心配置及测试—

前言

最近在学习《代码审计》这本书,按照书上大致理一遍重要的PHP配置,并做了测试。
还提及了allow_url_include及allow_url_fopen的相应延伸知识。

wamp/lamp

解释两个名词:

  • wamp:Windows下的Apache(web服务器软件)+Mysql/MariaDB(数据库系统)+Perl/PHP/Python(编程语言)
  • lamp:Linux下的Apache(web服务器软件)+Mysql/MariaDB(数据库系统)+Perl/PHP/Python(编程语言)

另外还有以Nginx代替Apache作为web服务器软件,即形成wnmp/lnmp

PHP指令设定的范围

模式 含义
PHP_INI_USER 可在用户脚本(例如 ini_set())或 Windows 注册表(自 PHP 5.3 起)以及 .user.ini 中设定
PHP_INI_PERDIR 可在 php.ini(php中),.htaccess(网站目录) 或 httpd.conf(Apache) 中设定
PHP_INI_SYSTEM 可在 php.ini 或 httpd.conf 中设定
PHP_INI_ALL 可在任何地方设定(包括ini_set())

PHP 指令配置修改

php.ini修改 打开文件修改。
Windows注册表和httpd.conf修改官方说明
具体说 .htaccess 和 ini_set

.htaccess修改

.htaccess是apache在网站目录下的的配置文件,作用域有限,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表等功能。
其他具体功能不细说,有兴趣点这里=w=QAQ
此处说明如何在.htaccess中修改php配置

  • 配置httpd.conf中的AllowOverride,使.htaccess能用
  • 创建.htaccess文件(windows需要在命令行下创建)
  • 写入配置内容

配置内容格式php_value 配置名称 值

1
php_value register_globals On

ini_set()修改

ini_set — 为一个配置选项设置值
string ini_set ( string $varname , string $newvalue )
设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。
成功时返回旧的值,失败时返回 FALSE。

1
2
3
4
5
6
7
<?php
echo ini_get('display_errors');
echo '<br>';
if(ini_set('display_errors','1')!=FALSE) echo 'success';
echo '<br>';
echo ini_get('display_errors');
?>


9.png

register_globals(全局变量注册开关)

在 PHP <= 4.2.3 时是 PHP_INI_ALL。之后版本是 PHP_INI_PERDIR
在 php < 5.3.0 时是 默认为On
在 php >= 5.3.0 时是 默认为Off
在 php 5.4.0 版本移除该选项,即永久为Off
作用:设置为On时,会直接把用户GET、POST等方式提交上来的参数注册成全局变量并初始化只为参数对应的值,使得提交参数可以直接在脚本中使用

测试

以下测试是在php5.2中完成(PHP_INI_PERDIR,默认为On)

1
2
3
4
5
6
7
8
<?php
if($user=='admin'){
echo 'admin';
}
else{
echo 'user';
}
?>

1.png
当代码中已经初始化则无效:

1
2
3
4
5
6
7
8
9
<?php
$user='user';
if($user=='admin'){
echo 'admin';
}
else{
echo 'user';
}
?>


2.png

allow_url_include(是否允许包含远程文件)

具体范围的版本 在书中与官网不全一致。以下为官网的说明
在 PHP 5 时是 PHP_INI_SYSTEM,默认为Off,从 PHP 5.2.0 起可用。
现在为 PHP_INI_ALL

但是测试时发现一个BUG:
allow_url_include 的可配置范围为PHP_INI_ALL,也就是可以用ini_set()来设置
但是事实确实设置不了,从PHP5.2到PHP7都不行。
所以结论是:allow_url_include 与 allow_url_fopen 一样都是 PHP_IN_SYSTEM

作用:设置为On时,可以直接包含远程文件(http:// 与ftp:// ),比如include包含。include($var) 当$var可控时,可以执行PHP代码
allow_url_include的同时就会提到allow_url_fopen。因为在官方文档中使用allow_url_include的前提是allow_url_fopen为On

allow_url_fopen(是否允许打开远程文件)

在 PHP <= 4.3.4 时是 PHP_INI_ALL。之后版本是 PHP_INI_SYSTEM,默认为On
作用:设置为On时,允许打开远程文件,比如fopen打开。

测试

其实这两个选项形成的就是远程文件包含漏洞RFI
查看另一篇博客吧戳这里

magic_quotes_gpc(魔术引号自动过滤)

在 PHP <= 4.2.3 时是 PHP_INI_ALL,之后是 PHP_INI_PERDIR, 默认为On。
从 PHP 5.3.0 起不推荐使用。 在 PHP 5.4.0 中移除该选项。(避免了magic_quotes_gpc未设置,用户依赖这个设置而带来了安全隐患)
作用:为 GPC (Get/Post/Cookie) 操作设置 magic_quotes 状态。当 magic_quotes 为 on,自动在单引号(‘)、双引号(“)、反斜杠()及空字符(NULL)前面加上反斜杠()。不会过滤$_SERVER变量,可以利用client-ip、referer一类的漏洞。
如果 magic_quotes_sybase 也是 ON,它会完全覆盖 magic_quotes_gpc

测试

以下测试是在php5.2中完成。
magic_quotes_gpc 为 On

1
2
3
<?php
print_r($_GET);
?>


10.png

magic_quotes_runtime(魔术引号自动过滤)

范围是 PHP_INI_ALL,默认为 Off
本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。
作用:对于从数据库或者文件中获取的数据自动在单引号(‘)、双引号(“)、反斜杠()及空字符(NULL)前面加上反斜杠() (测试后貌似对空字符无效)
如果 magic_quotes_sybase 也是 ON,它会完全覆盖 magic_quotes_runtime
覆盖函数列表:

get_meta_tags()
file_get_contents()
file()
fgets()
fwrite()
fread()
fputcsv()
stream_socket_recvfrom()
exec()
system()
passthru()
stream_get_contents()
bzread()
gzfile()
gzgets()
gzwrite()
gzread()
exif_read_data()
dba_insert()
dba_replace()
dba_fetch()
ibase_fetch_row()
ibase_fetch_assoc()
ibase_fetch_object()
mssql_fetch_row()
mssql_fetch_object()
mssql_fetch_array()
mssql_fetch_assoc()
mysqli_fetch_row()
mysqli_fetch_array()
mysqli_fetch_assoc()
mysqli_fetch_object()
pg_fetch_row()
pg_fetch_assoc()
pg_fetch_array()
pg_fetch_object()
pg_fetch_all()
pg_select()
sybase_fetch_object()
sybase_fetch_array()
sybase_fetch_assoc()
SplFileObject::fgets()
SplFileObject::fgetcsv()
SplFileObject::fwrite()

测试

以下测试是在php5.2中完成。
magic_quotes_runtime 为 On

1
2
3
4
<?php
//1.txt '"\
echo file_get_contents("1.txt");
?>


11.png

magic_quptes_sybase(魔术引号自动过滤)

范围是 PHP_INI_ALL 。默认为Off
在 PHP 5.4.0 中移除该选项。
作用:当设置为On时,会覆盖掉magic_quotes_gpc=On。仅仅 转义空字符 以及 单引号(‘)前再加一个单引号(‘)。会覆盖掉magic_quotes_runtime=On,仅仅把单引号(‘)前再加一个单引号(‘)

测试

以下测试是在php5.2中完成。
magic_quotes_gpc 为 On
magic_quotes_runtime 为 On
magic_quotes_sybase 为 On

1
2
3
4
5
6
<?php
//1.txt 1'2"3\
print_r($_GET);
echo '<br>';
echo file_get_contents("1.txt");
?>


12.png

safe_mode(安全模式)

范围是 PHP_INI_SYSTEM ,默认为 Off。
在 PHP 5.4.0 中移除该选项。
官方文档
作用
1.PHP 所有文件操作函数 会受到限制。会检查当前脚本的拥有者是否和将被操作的文件的拥有者相匹配,即你不能操作不属于你的文件。如果需要用 include等函数 加载一些放在非WEB服务启动用户所有的目录下的脚本文件,使用safe_mode_include_dir指令来配置可以包含的路径。
2.PHP 函数执行命令或程序会提示错误。当使用外部脚本时,集中在一个目录下,使用safe_mode_exec_dir指令指向目录。
当safe_mode为On时,下面选项开启
下列选项范围都为PHP_INI_SYSTEM

  • safe_mode_gid:默认”0”。安全模式在打开文件时会做 UID 比较检查。如果想将其放宽到 GID 比较,则打开 safe_mode_gid。
  • safe_mode_include_dir:默认为NULL。当从此目录及其子目录(目录必须在 include_path 中 或者 用完整路径来包含)包含文件时越过 UID/GID 检查。

从 PHP 4.2.0 开始,本指令可以接受和 include_path 指令类似的风格用冒号(Windows 中是分号)隔开的路径,而不只是一个目录。 指定的限制实际上是一个前缀,而非一个目录名,目录名需要以/结尾。
“safe_mode_include_dir = /dir/incl” 将允许访问 “/dir/include”和“/dir/incls”等文件
“safe_mode_include_dir = /dir/incl/” 将允许访问 “/dir/incl/”目录下的文件
如果本指令的值为空,在 PHP 4.2.3 中以及 PHP 4.3.3 起具有不同 UID/GID 的文件将不能被包含。在较早版本中,所有文件都能被包含。

include_path :范围是 PHP_INI_ALL。 默认”.;/path/to/php/pear”
作用:指定一个目录列表,让require、include、fopen()、file()、readfile()和file_get_contents()函数从中查找文件。该格式类似于系统的PATH环境变量:在Unix中使用冒号(:)分隔的目录列表或在Windows中使用分号(;)。
修改: set_include_path()

  • safe_mode_exec_dir:默认””。如果 PHP 使用了安全模式,system() 和其它程序执行函数(见文末)将拒绝启动不在此目录中的程序。必须使用 / 作为目录分隔符,包括 Windows 中。
  • safe_mode_allowed_env_vars:默认为”PHP_”。设置某些环境变量可能是潜在的安全缺口。本指令包含有一个逗号分隔的前缀列表。在安全模式下,用户只能改变那些名字具有在这里提供的前缀的环境变量。默认情况下,用户只能设置以 PHP_ 开头的环境变量(例如 PHP_FOO = BAR)。

如果本指令为空,PHP 将使用户可以修改任何环境变量!

  • safe_mode_protected_env_vars:默认为”LD_LIBRARY_PATH”。本指令包含有一个逗号分隔的环境变量的列表,最终用户不能用 putenv() 来改变这些环境变量。甚至在 safe_mode_allowed_env_vars 中设置了允许修改时也不能改变这些变量。

putenv() — 设置环境变量的值
添加 setting 到服务器环境变量。 环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。
如:putenv(“UNIQID=$uniqid”);
getenv() — 得到环境变量的值
putenv/getenv、$_ENV、phpinfo(INFO_ENVIRONMENT) 三者变量完全隔离不会互相影响

影响函数

以下函数只做大致了解,知道其大致作用。
文件操作函数

apache_request_headers — 获取当前请求的所有请求头信息 
fopen — 打开文件或者 URL
header — 发送原生 HTTP 头
dl — 运行时载入一个 PHP 扩展
link — 建立一个硬连接
file — 把整个文件读入一个数组中
chdir — 改变目录,将 PHP 的当前目录改为 directory。 
chgrp — 改变文件所属的组
chmod — 改变文件模式
chown — 改变文件的所有者
copy — 拷贝文件
rename — 重命名一个文件或目录
popen — 打开进程文件指针
mkdir — 创建目录
rmdir — 删除目录
touch — 设定文件的访问和修改时间
dbase_open — 打开一个数据库
dba_open — 打开一个数据库
filepro等 — 有关映射文件函数
putenv — 设置环境变量的值
......过多不列举

程序执行函数:

escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数
escapeshellcmd — shell 元字符转义
exec — 执行一个外部程序
passthru — 执行外部程序并且显示原始输出
proc_close — 关闭由 proc_open 打开的进程并且返回进程退出码
proc_get_status — 获取由 proc_open 函数打开的进程的信息
proc_nice — 修改当前进程的优先级
proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。
proc_terminate — 杀除由 proc_open 打开的进程
shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
system — 执行外部程序,并且显示输出

open_basedir PHP可访问目录

范围是 PHP_INI_ALL 。 默认是 NULL 是允许打开所有文件
在 PHP < 5.3.0 时是 PHP_INI_SYSTEM
作用:open_basedir 将能打开的文件限制在指定的目录树下。本指令不受安全模式打开或者关闭的影响。

  • 特殊值. 指定脚本的工作目录被作为基准目录。但是可以通过chdir来改变工作目录
  • 指定的限制实际上是一个前缀,而非一个目录名,目录名需要以/结尾,与safe_mode_include_dir相同。
  • 可以在httpd.conf中修改来关闭
  • 在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录

display_errors 和 error_reporting

官网详情
两者范围都是 PHP_INI_ALL
display_errors 默认为 On 。 error_reporting 默认为 NULL
display_errors作用:该选项设置是否将错误信息作为输出的一部分显示到屏幕,或者对用户隐藏而不显示。
还可以设置 “display=stderr” 表示发送到 stderr 而不是 stdout。(只影响CGI/CLI的二进制文件)
“stderr”从 PHP 5.2.4 开始可用。在以前的版本中,该配置值的类型为 boolean.


13.png

当 display_errors=On 时,可以设置error_reporting

error_reporting

error_reporting的作用: 设置错误报告的级别。
该参数可以是一个任意的表示二进制位字段的整数,或者内置常量配置。
在PHP 4和PHP 5之中,其默认值为 E_ALL & ~E_NOTICE。 该设置表示除了 E_NOTICE 其他都显示的错误级别。

其他安全常用指令

指令 范围 说明
expose_php php.ini only 是否在服务器返回信息HTTP头显示PHP版本
max_execution_time PHP_INI_ALL 每个脚本做多执行秒数
memory_limit PHP_INI_ALL 每个脚本能够使用的最大内存数量
log_errors PHP_INI_ALL 将错误输入到日志文件
log_errors_max_len PHP_INI_ALL 设定log_errors的最大长度
variables_order PHP_INI_PERDIR 描述PHP注册GET、POST、Cookie、环境、内置变量的顺序,注册从左往右,新值会覆盖旧值
post_max_size PHP_INI_PERDIR PHP可以接受的最大POST数据大小
auto_prepend_file PHP_INI_PERDIR 在任何PHP文档之前自动包含的文件
auto_append_file PHP_INI_PERDIR 在任何PHP文档之后自动包含的文件
extension_dir PHP_INI_SYSTEM 可加载的扩展(模块)的目录位置
file_uploads PHP_INI_SYSTEM 是否允许HTTP文件上传
upload_tmp_dir PHP_INI_SYSTEM 对于HTTP上传文件的临时文件目录
upload_max_filesize PHP_INI_SYSTEM 允许上传的最大文件大小