WEB-PHP核心配置
前言
最近在学习《代码审计》这本书,按照书上大致理一遍重要的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
echo ini_get('display_errors');
echo '<br>';
if(ini_set('display_errors','1')!=FALSE) echo 'success';
echo '<br>';
echo ini_get('display_errors');
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
if($user=='admin'){
echo 'admin';
}
else{
echo 'user';
}
当代码中已经初始化则无效:1
2
3
4
5
6
7
8
9
$user='user';
if($user=='admin'){
echo 'admin';
}
else{
echo 'user';
}
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 为 On1
2
3
print_r($_GET);
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 为 On1
2
3
4
//1.txt '"\
echo file_get_contents("1.txt");
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 为 On1
2
3
4
5
6
//1.txt 1'2"3\
print_r($_GET);
echo '<br>';
echo file_get_contents("1.txt");
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.
当 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 | 允许上传的最大文件大小 |