PHP代码审计之基础篇

最近在学PHP代码审计,那就将学习的笔记都整理一遍吧~


前期准备:

当然,最基本的前提是至少大致学过PHP的语法。

1、安装相关软件,如Sublime text、 Notepad++、editplus、 Seay源代码审计系统等

2、获得源码,可以到网上下载各种网站源码

3、安装网站


审计方法:

通读全文法:麻烦但全面

敏感函数参数回溯法:高效常用,Seay源代码审计系统

定向功能分析法:主要根据程序的业务逻辑来审计,首先是用浏览器逐个访问,看看程序有哪些功能,根据相关功能推测可能存在的漏洞


审计的基本流程:

1、整体了解

2、根据定向功能法针对每一项功能进行审计

3、敏感函数参数回溯法


整体了解:

1、网站结构:

浏览源码文件夹,了解程序的大致目录。

admin:后台管理目录

install:网站的安装目录,其中的install.sql为数据库的结构信息

sys:这个目录里面一般存放着配置信息文件和公共函数库,分别为config.php和lib.php

user:这里面记录着用户的一些操作,如用户注册等

index.php:一般为网页的首页文件,也是审计的突破口

2、入口文件:

index.php、admin.php文件一般都是整个程序的入口,通过index文件可以知道程序的架构、运行流程、包含哪些配置文件、哪些过滤文件以及安全过滤文件,了解程序的业务逻辑。

3、配置文件:

一般类似config.php等文件,保存一些数据库相关信息、程序的一些信息。先看看数据库编码,若是gbk则可能存在宽字节注入;若变量的值用双引号,则可能存在双引号解析代码执行的问题。

4、过滤功能:

通过公共函数文件、安全过滤文件可看出用户输入的数据哪些被过滤和哪些无过滤,在哪、如何过滤,能否绕过过滤的数据,过滤的方式是替换还是正则,有无GPC和使用addslasher()处理等。


常见的功能漏洞:

程序初始安装漏洞

站点信息泄露

文件上传管理

登录认证、权限管理漏洞

数据库备份漏洞

验证码漏洞等


漏洞形成的条件:

1、可控的变量(一切输入都是有害的)

2、变量到达有利用价值的函数(危险的函数)

代码审计的本质:找漏洞其实相当于找对应变量和函数。

变量跟踪的过程:

正向跟踪——通过变量找函数

逆向跟踪——通过函数找变量


常见的INI配置:

1、php INI文件:

PHP 的配置文件一般是 php.ini 文件

php.ini 文件必须命名为'php.ini'并放置在httpd.conf中的PHPIniDir指令指定的目录中,使用phpinfo()函数可以查看。

一般情况下需要对其进行配置,使环境更加安全

2、配置文件:

php.ini:在启动PHP时被读取。对于服务器模块版本的PHP,仅在Web服务器启动时读取一次;对于CGI和CLI版本,每次调用都会读取。在php.ini中可以使用环境变量。Apache Web服务器在启动时,会把目录转到根目录,这将导致PHP尝试在根目录下读取php.ini,若存在的话。还可以在httpd.conf中覆盖php.ini的值以进行更灵活的配置:php_value name value。PHP常量仅能在php.ini中使用,在httpd.conf中必须使用相应的掩码值。


.user.ini文件:自PHP5.3.0起,PHP支持基于每个目录的.htaccess风格的INI文件,此类文件仅被CGI/FastCGI SAPI处理;此功能使得PECL的htscanner扩展作废;若使用Apache,则用.htaccess文件有同样的效果。在.user.ini风格的INI文件中只有具有PHP_INI_PERDIR和PHP_INI_USER模式的INI设置可被识别。当使用PHP作为Apache模块时,也可以用Apache的配置文件和.htaccess文件中的指令来修改PHP的配置设定;需要有“AllowOverride Options”或“AllowOverride All”权限。


语法:设置指令的格式:directive = value 大小写敏感

Value可以使:用引号界定的字符串("foo”)、数组、PHP常量(E_ALL、M_PI)、INI常量(On、Off、none)、表达式

INI文件中表达式仅使用:!、()、|位或、&位与、~位非、

一个空字符串可以用在等号后不写任何东西表示,或者用 none 关键字:

foo =     ; 将foo设为空字符串

foo = none  ; 将foo设为空字符串

foo = "none" ; 将foo设为字符串''none''


启用全局变量:register_globals=off

作用是关闭自动注册的全局变量。

设置为On,php会将$_POST,$_GET,$_COOKIE,$_ENV,$_SESSION数组中的$key=>$value直接注册为变量,但有三个问题:不知道变量来源;变量之间相互覆盖;安全问题。因而要设置为Off。


短标签:short_open_tag=off

作用是决定是否允许使用PHP代码开始标志的缩写形式()。若禁用,就必须使用PHP代码开始标志的完整形式()。


安全模式:safe_mode=off

控制一些PHP函数如system(),同时对文件操作函数进行权限限制,但默认php.ini没有打开安全模式。自PHP5.4.0起废除。


安全模式下执行程序主目录:safe_mode_exec_dir=/var/www/html

使用安全模式后,system()和其他程序执行函数将值可以在此目录下执行程序。


禁用类/函数:disable_classes= ,disable_functions=opendir,readdir,scandir,fopen

接受逗号分隔的函数名。


设置上传及最大上传文件大小:file_uploads=on  upload_max_filesize=8M


文件上传临时目录:upload_tmp_dir =

(系统临时目录/tmp、C:\Windows\Temp)


用户访问目录限制:open_basedir = .:/tmp/

一般可以设置只能访问网站目录,表示允许访问当前目录和/tmp/目录。


错误信息控制:display_error=On

调试时On;站点发布后应关闭,以免暴露信息。


设置错误报告级别:error_reporting=E_ALL

作用是将错误级别设置为最高,可以显示所有的问题,方便查错。

日志级别是常量,在php.ini中有,推荐使用E_ALL|E_STRICT


错误日志:

error_log= 错误日志的位置,若不定义则默认写入Web服务器的错误日志中去。

log_errors = on 建议将错误日志输出到文件而不是直接输出到前端。

log_errors_max_length = 1024 错误日志关联信息的最大长度,设为0为无限长度。


魔术引号:自PHP 5.3.0起弃用

magic_quotes_gpc=On

magic_quotes_runtime=Off

功能是自动转义,和 addslashes() 作用完全相同


是否允许打开远程文件:allow_url_fopen=on

使得可以访问URL对象例如文件


是否允许包含远程文件:allow_url_include=off

允许include、include_once、require、require_once等函数使用URL形式的fopen封装协议。


常见的危险函数及特殊函数:

1、PHP代码执行函数:

eval(),将字符串作为PHP代码执行

PHP代码审计之基础篇_第1张图片


assert(),检测一个断言是否为FALSE;因为eval列入了黑名单,所以用assert替代其


preg_replace(),作用是执行正则表达式,这个函数的原型为:mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit]),如果在构造正则表达式的时候,使用了/e修正符,这时,preg_replace() 就会将 replacement 参数当作 PHP代码执行。

第一种模式:

phpinfo()';
preg_replace("/

(.*?)$re", '\\1', $var); ?>

PHP代码审计之基础篇_第2张图片

第二种模式:

PHP代码审计之基础篇_第3张图片

第三种模式:


PHP代码审计之基础篇_第4张图片


create_function(),创建一个匿名函数

call_user_func()、call_user_func_array(),回调函数


2、包含函数:

require()、include()、require_once()、include _once()

分本地文件包含和远程文件包含,可以读取任意文件内容。


3、命令执行函数:

exec():执行一个外部程序

";
echo exec($cmd);
echo "
"; ?>

PHP代码审计之基础篇_第5张图片


passthru():执行外部程序并且显示原始输出

";
passthru($cmd);
echo "
"; ?>


proc_open():执行一个命令,并且打开用来输入的文件指针


shell_exec():通过shell环境执行命令,并且将完整的输出以字符串方式返回

";
echo shell_exec($cmd);
echo "
"; ?>


system():执行外部程序,并且显示输出

";
system($cmd);
echo "
"; ?>

PHP代码审计之基础篇_第6张图片


popen():popen()的参数传递一条命令,并对并对 popen() 所打开的文件进行执行。

";
echo popen($cmd,'r');
echo "
"; ?>

PHP代码审计之基础篇_第7张图片


`` 反引号:

";
echo `$cmd`;
echo "
"; ?>

4、文件操作函数:

copy():拷贝文件

file_get_contents():将整个文件读入为一个字符串

file_put_contents():将一个字符串写入文件

file():把整个文件读入一个数组中

fopen():打开文件或者 URL

move_uploaded_file():将上传的文件移动到新位置

readfile():输出文件

rename():重命名一个文件或目录

rmdir():删除目录

unlink() & delete():删除文件


5、特殊函数:

信息泄露:phpinfo()

软连接,读取文件内容:symlink()、readlink()

环境变量:getenv()、putenv()

加载扩展:dl(),载入指定参数library的PHP扩展

配置相关:ini_get()、ini_set()、ini_alter()、ini_restore()

数字判断:is_numeric(),仅用该函数判断而不用intval()转换可能会导致SQL二次注入,因为可能会插入16进制的字符串。

数组相关:in_array(),检查数组中是否存在某个值

变量覆盖:parse_str(),将字符串解析为变量并设置到当前作用域,另外还有extract()、mb_parse_str()、import_request_variables()

列目录:glob(),使用规则筛选所有与pattern匹配的文件路径

无参数获取信息:get_defined_vars()返回一个包含所有已定义变量列表的多维数组、get_defined_constants()返回当前所有已定义的常量名和值、get_defined_functions()返回一个包含所有已定义函数列表的多维数组、get_included_files()返回所有被包含的文件名


审计的常用调试函数与注释符:

echo()、print():两者输出一样,前者为PHP语句,后者为函数

print_r():输出数组

var_dump():会额外输出数据类型

debug_zval_dump():跟上一个类似,区别是增加了refcount记录变量被引用的次数

exit():退出当前程序执行

单行注释://

多行注释:/**/


单引号与双引号的区别:

双引号解析变量、而单引号不解析变量

$str = "hello";
echo "$str";//双引号解析变量
echo '$str';//单引号不解析

PHP代码审计之基础篇_第8张图片


超全局变量:

在 php 中可由用户操作的全局变量列表如下:

$GLOBALS:引用全局作用域中可用的全部变量

	echo $test="test2";
	echo $GLOBALS['test'];
}
$test = "test1";
test();
?>

PHP代码审计之基础篇_第9张图片


$_SERVER:服务器和执行环境信息

PHP代码审计之基础篇_第10张图片


$_GET:HTTP GET 变量

PHP代码审计之基础篇_第11张图片


$_POST:HTTP POST 变量

PHP代码审计之基础篇_第12张图片


$_FILES:HTTP 文件上传变量

表单:


PHP代码审计之基础篇_第13张图片


$_REQUEST:HTTP Request 变量

GET: 

PHP代码审计之基础篇_第14张图片

POST: 

PHP代码审计之基础篇_第15张图片


$_SESSION:Session 变量

PHP代码审计之基础篇_第16张图片


$_ENV:环境变量

这里输出为空数组:

PHP代码审计之基础篇_第17张图片

接着修改php.ini文件,添加E:


PHP代码审计之基础篇_第18张图片


$_COOKIE:HTTP Cookies

PHP代码审计之基础篇_第19张图片

PHP代码审计之基础篇_第20张图片


你可能感兴趣的:(代码审计,Web安全)