本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
一、代码审计前的准备
把握大局:
网站结构: 浏览源码文件夹,了解该程序的大致目录 入口文件: index.php,admin.php文件一般时整个程序的入口,详细读一下index文件可以知道程序的架构,运行流程,包含那些配置文件,包含哪些过滤文件以及包含那些安全过滤文件,了解程序的业务逻辑
配置文件:一般类似config.php等文件,保存一些数据库相关信息,程序的一些信息,先看看数据库编码,如果是gbk则可能存在宽字节注入,如果变量的值用双引号,咋可能存在双引号解析代码执行的问题, 过滤功能: 通过详读公共函数文件和安全过滤文件等文件,清晰掌握用户输入的数据,哪些被过滤,哪些无过滤,在哪里被过滤了,如何过滤的,能否绕过过滤的数据,过滤的方式是替换还是正则?有没有GPC?有没有使用addslasher()处理?
审计方法:
1,通读全文法
2,敏感函数参数回溯法(shell_exec)
3,定向功能分析法(安装问题)
二、常见的INI配置
PHP的配置文件:
php.ini
在PHP启动时被读取,对于服务器模块版本的PHP,仅在web服务器启动时读取一次,对于CGI和CLI版本,每次调用都会读取
*Apache web服务器在启动时会把目录转到根目录,这将导致PHP尝试在根目录下读取php.ini,如果存在的话,在PHP.ini中可以使用环境变量
.user.ini
自PHP5.3.0起,PHP支持基于每个目录的 .htaccess风格的INI文件,此类文件仅被CGI/FastCGI SAPI处理。此功能使得PECL的htscanner扩展作废,如果使用Apache,则用 .htaccess文件有同样效果。
常见重要配置-变量相关
启用全局变量:
register_globals = off
有些程序例如OSC需要启用全局变量,这个设置的作用时关闭自动注册的全局变量,
在设置为On时,php会将 _GET, _ENV , key => _POST['username']就会被注册为 _POST来的还是 $_SESSION来的呢?非常不方便别人阅读代码,
2,变量之间相互覆盖,引起不必要的麻烦,
3,安全问题,所以要设置为Off
短标签: short_open_tag = On 这个设置决定是否允许使用PHP代码开始标志的缩写形式( ) 如果禁用了,必须使用PHP代码开始标志的完整形式() 本指令也会影响到缩写形式 <?=,它和<? echo等价,使用此所写需要 short_open_tag的值为On.从PHP 5.4.0起,<? = 总是可用的。 安全模式: safe_mode = off php的安全模式是一个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,但是默认的php.ini是没有打开安全模式的 本特性已自PHP 5.3.0 起废弃并将自 PHP5.4.0起移除 禁用类/函数 disable_classes = ,disable_functions =,disable_functions = opendir,readdir,scandir,fopen,unlink禁用某些类,禁止某些函数。接受逗号分割的函数名列表作为参数。只能设置在php.ini中 安全模式下执行程序主目录: safe_mode_exec_dir = /var/www/html 设置上传及最大上传文件大小: file_uploads = on upload_max_filesize = 8M 文件上传临时目录 upload_tmp_dir = 用户访问目录限制 open_basedir = .:/tmp/ 错误信息控制 display_error = on 设置错误报告级别 error_reporting = E_ALL(可显示所有问题,方便差错) 错误日志 error_log = log_error = on log_errors_max_length = 1024(错误日志关联信息的最大长度,0表示无限长度) 魔术引号: magic_quotes_gpc = on GPC(Get/Post/Cookie) magic_quotes_runtime = off 是否允许打开远程文件 allow_url_fopen = on 是否允许包含远程文件 allow_url_include = off
三、常见危险函数及特殊函数
PHP代码执行函数: **mixed eval( string code 作为PHP代码执行 很多常见的webshell都是用eval来执行具体操作的
eval一般出现的场景是
<?php
$string = ‘杯子';
$name = '咖啡';
$str = '这个 $string 中装有 $name.<br>';
echo $str;
eval("$str = "$str";");
echo $str;
?>
bool assert (mixed description ]) 检查一个断言是否为FALSE,(吧字符串 $assertion作为PHP代码执行) 因为大多数杀软把eval例入黑名单了,所以用assert来替代eval来执行具体操作
mixed preg_replace( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count]])
/e修正符使preg_replace()将replacement 参数作为php代码 preg_replace("/test/e",$_GET["V"],"jutst test"); 如果我们提交 ?h=phpinfo(),phpinfo()将会被执行
string create_function ( string code ) 创建一个匿名函数 , 并返回独一无二的函数名 v','return system(newfunc('whoami');就相当于system('whoami')
php命令执行函数: exec() --执行一个外部程序 passthru() --执行外部程序并且显示原始输出 proc_open() --执行一个程序,并且打开用来输入\输出的文件指针 shell_exec() & ' ' --通过shell环境执行命令,并且将完整的输出以字符串的方式返回。 system() --执行外部程序,并且显示输出 popen() --通过popen() 的参数传递一条命令,并对popen() 所打开的文件进行执行
文件操作函数: copy --拷贝文件 file_get_contents --将整个文件读入为一个字符串 file_put_contents --将一个字符串写入文件 file --把整个文件读入一个数组中 fopen --打开文件或者URL move _uploaded_file --将上传的文件移动到新位置 readfile --输出文件 rename --重命名一个文件或目录 rmdir --删除目录 unlink & delete --删除文件
特殊函数: 信息泄露 bool phpinfo ([ int $what = INFO_ALL])\
软连接-读取文件内容 bool symlink( string link ) symlink() 对于已有的target建立一个名为link的符号连接 string readlink (string $path) readlink()和同名的C函数做同样的是,返回符号连接的内容
环境变量 string getenv( string setting )
配置相关 string ini_get( string varname , string varname , string varname ) 恢复指定的配置选项到他的原始值。
数字判断 bool is_numeric ( mixed $var ) 如果var是数字和数字字符串则返回true,否则返回FALSE 仅用is_numeric判断而不用intval转换就有可能插入16进制的字符串到数据库,进而可能导致sql二次注入
数组相关 bool in_array ( mixed haystack [,bool $strict = FALSE] ) 在haystack中搜索needle,
四、XDebug的配置与使用
日志: xdebug.trace_output_dir 追踪日志输出目录 xdebug,trace_options 记录添加到文件中方式:1=追加(如果存在该文件).0(default) = 覆盖(如果存在该文件) 显示数据 xdebug.collect_params 非零值 = 控制function的参数显示选项 0 = 不显示 1 = 参数类型,值(例如:array(9)) 2 = 同上1,只是在CLI模式下略微有区别 3 = 所有变量内容 4 = 所有变量内容和变量名(例如:array(0 => 9)) xdebug.collect_return 1 = 显示function返回值,Default 0 不显示 xdebug.collect_vars 1 = 显示当前作用域使用了哪里变量,显示变量名,该选项不会记录变量的值 xdebug.collect_assignments 1 = 添加一行显示变量赋值(若为1,形如 $a = 1;这类Assignment Expression会在trace文件里显示) 格式 xdebug.trace_format -日志追踪输出目录 0 = 人可读 行为 xdebug.auto_trace 1 = 打开自动追踪 xdebug.trace_enable_trigger 该特性是在2.2+版本才能设置 1 =触发方式追踪
四、命令注入
PHP脚本中,我们可以对输入进行注入攻击,注入即是通过利用无验证变量构造特殊语句对服务器进行渗透 注入的种类有很多,而不仅仅只是SQL injection 呢么PHP中有哪些注入呢
命令注入
Eval注入
客户端脚本攻击
跨网站脚本攻击
SQL注入攻击
动态函数注入攻击
序列化注入&对象注入
命令注入:
PHP中可以使用下列5个函数来执行外部的应用程序或函数(当然,能实现这样功能的手段不止是这5个函数)
SQL注入问题的审计
SQL攻击,简称注入攻击,是发生于应用程序之数据库层的安全漏洞
简而言之
是在输入的字符串中注入SQL指令,在设计不良的程序当中忽略了检查,呢么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏。
而数字型注入一般就不用考虑到引号的问题了
任意文件读取
任意文件读取是属于文件操作漏洞的一种
一般任意文件读取漏洞可以读取的配置信息甚至系统重要文件
严重的话,就可能导致SSRF,进而漫游内网
五、二次注入
SQL攻击,简称注入攻击,是发生于应用程序之数据库层的安全漏洞
简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,呢么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏
因为字符型注入一般都带有单引号('),构造注入攻击需要闭合单引号
或者双条件查询的情况下转义一个单引号,这个时候就要考虑到截断了