php代码审计

代码审计

  • 基础配置
    • 常量定义
    • 安全配置选项
  • sql注入
    • 宽字节
    • 二次urldecode注入
    • 漏洞防御
  • xss
    • 防御
  • csrf
    • 防御
  • 文件操作漏洞
    • 文件包含漏洞
      • 文件包含截断
      • 防御
    • 文件上传漏洞
    • windows FindFirstFile利用
    • 文件操作漏洞防范
  • 代码执行漏洞
    • 防御
  • 命令执行漏洞
    • 漏洞防御
  • 变量覆盖漏洞
    • 漏洞防御
  • 逻辑处理漏洞

基础配置

常量定义

1.PHP_INI_USER                  PHP脚本,windows注册表中设置
2.PHP_INI_PERDIR php.ini        htaccess,httpd.conf中设置
3.PHP_INI_SYSTEMphp.ini         httpd.conf中设置
4.PHP_INI_ALL                   任何地方中设置
5.php.ini only                   php.ini中设置

安全配置选项

1.allow_url_include(是否允许包含远程文件) 
  allow_url_fopen(是否打开远程文件)
  配置范围:PHP_INI_ALL
2. magic_quotes_gpc(魔术引号自动过滤)
  会在 ‘,“,\,NULL前加 \
  配置范围:PHP_INI_ALL
  magic_quotes_runtime(魔术引号自动过滤)
  只对数据库或文件中获取的数据过滤
  php版本<5.4 
  配置范围:PHP_INI_ALL
3.safe_mode(安全模式)
  文件操作函数受到限制
  poen(),system,exec()执行命令会提示错误
4.open_basedir(PHP 可访问目录)
  限制php只能访问那些目录
   配置范围:php版本>5.2.3 PHP_INI_ALL , php版本<5.2.3 PHP_INI_SYSTEM   
5.disable_functions(禁用函数)
   禁用敏感函数 
   配置范围:php.ini only
6.display_errors,error_reporting(错误显示)
	display_errors开启关闭错误回显,error_reporting回显错误等级
   配置范围:PHP_INI_ALL 
7.expose_php(隐藏版本信息)
8.file_uploads(任意文件上传)

sql注入

SQL注入详解

宽字节

php连接mysql 设置 setcharacter_set_clinet=gbkcharacter_set_clinet=gbk
SET NAME ‘gbk’

由于gbk编码,输入%81–%ff(除%7f)和\组成一个gbk字符以达到绕过目的

挖掘关键字:
SET NAEMS
character_set_client=gbk
mysql_set_charset('gbk')

二次urldecode注入

当过滤了单引号但使用
urldecode(),rawurldecode()函数
提交?id=1%2527时,第一次解码为?id=1%27无单引号,第二次函数解码为?id=1'
搜索相关函数

漏洞防御

1.魔术引号:magic_quotes_gpc(get,post,cookie)/runtime(数据库,文件数据)  php<5.4
		对 ‘'," ,\ ,null  字符前加\
2.过滤函数和类(union,select等)
3.addslashes()与gpc一致(参数必须为string)
4.mysql_[real_]escape_string() 过滤 \x00,\n,\r,\,',",\xla等
  php版本>4.0..3  
5. intval等字符转换:将变量转换成int类型 主要防御数字型注入
6. PDO prepare 预编译

xss

寻找带有变量的函数
print,print_r,echo,printf,sprintf,die,var_dump,var_export

防御

1.在输出和二次调用时过滤特殊字符 ',",<,>,\,;,&,#
2.标签事件黑白名单
3.htmlentites()和htmlspecialcahrs()函数将输入转换为HTML实体

csrf

用于越权操作,管理员后台,会员中心,论坛帖子,
交易管理等地方 ,在核心文件中找有无验证token和referer相关代码

防御

1.token
2.referer,自定义HTTP头
3.验证码 ,二次验证等

文件操作漏洞

文件包含漏洞

本地文件包含:远程包含文件漏洞(allow_url_include=on)
远程文件包:只能包含本机文件(输出参数进行路径拼接)

查找相关函数:
include() , include_once()报错程序继续执行
require(),require_once()报错推出程序

文件包含截断

程序代码include($mode.'php')
1.%00截断(受限与gpc,addslashes)
2.利用多个点(.),反斜杠(\)截断 php <5.3
3.远程文件包含时用?截断,问号后当请求参数

防御

1.严格限制包含中的参数,取消那些不可控的参数。
2.开启open_basedir()函数,将其设置为指定目录,则只有该目录的文件允许被访问。
3.关闭allow_url_include。
4.白名单,对包含文件进行限制

文件上传漏洞

上传函数:move_uploaded_file()
过滤机制:
1.未过滤直接cpoy到新文件
2.黑名单
3.文件头,content-type验证 getimagesszie()函数,文件头加GIF89a

文件上传漏洞详解

windows FindFirstFile利用

当不知上传的webshell的文件路径时,只需知道文件所在目录。利用windows特性findfristfile 的winapi函数。将文件名未知部分用‘<’或‘>’代替。
测试:在同一目录下创建123456.txt内容


include($_GET['file']);
?>

成功的包含了123456.txt文件
php代码审计_第1张图片
其他一些相关函数:

  • include(),包含文件
  • include_once(),包含文件
  • require(),包含文件
  • require()_once,包含文件
  • fopen() ,打开文件
  • copy 复制文件
  • readfile() 读取文件

文件操作漏洞防范

1.对权限管理合理
2.隐藏文件名,利用更安全的方法代替以文件名为参数下的操作,把文件名,文件路径,文件id,文件上传人,上传至数据库,对比文件id和当前用户判断。
3.避免目录跳转问题(禁止 .,/ 字符传参等)open_basedir

代码执行漏洞

相关函数 :
eval(),assert(),preg_replace(),call_user_func(),call_user_func_array(),array_map()
call_user_func(),call_user_func_array()函数功能:调用函数多用在框架动态调用函数
array_map():调用函数并且除第一个参数以外其他参数为数组
preg_replace():对字符进行正则处理

preg_replace():


php代码审计_第2张图片
php代码审计_第3张图片
call_user_func(),array_map()传入参数可控:


php代码审计_第4张图片
php代码审计_第5张图片
同类函数:
php代码审计_第6张图片
php代码审计_第7张图片
动态函数执行:php函数可由字符拼接


php代码审计_第8张图片

防御

结合正则进行白名单

命令执行漏洞

命令执行漏洞

相关函数:
system()
exec():只返回最后一行
shell_exec()
passthru()
pcntl_exec()
proc_open()
popen():返回一个文件指针不返回执行结果。
反引号`

漏洞防御

命令防注入:
escapeshellarg():过滤参数将参数包裹在双引号里,确保参数为字符串
escapeshellcmd() 过滤整条命令
参数白名单

变量覆盖漏洞

原理:用户自定义的参数值替换源程序原有的变量值。如:文件上传的白
名单列表在配置文件的变量中,若存在变量覆盖漏洞,就可以覆盖一个
php的拓展名。
  • 相关函数
    • extract()
    • parse_str()
    • import_request_variables()

在没有开启全局变量注册时,调用这些函数相当于开启全局变量注册(< php 5.4)

extract()函数

  • extract(array,extract_rules,prefix)
  • array: 必需。规定要使用的数组。
  • extract_rules:可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定(EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。EXTR_IF_EXISTS - 仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。)
  • prefix:该参数规定了前缀。前缀和数组键名之间会自动加上一个下划线。
  • 测试:

$a=5;
$b=array('a'=>'1');
extract($b);
print_r($a);
?>

变量a被覆盖
php代码审计_第9张图片
parse_str()函数

  • parse_str(string,array) 函数把查询字符串解析到变量中。如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。
  • string :必需。规定要解析的字符串。
  • array:可选。规定存储变量的数组名称。该参数指示变量存储到数组中。
  • 测试:

$a=5;
parse_str('a=2');
print($a);
?>

变量被覆盖为2
php代码审计_第10张图片
import_request_variables函数

  • bool import_request_variables ( string $types [, string $prefix ] ) 函数将 GET/POST/Cookie 变量导入到全局作用域中。
  • $types:指定需要导入的变量,可以用字母 G、P 和 C 分别表示 GET、POST 和 Cookie。
  • $prefix: 变量名的前缀,置于所有被导入到全局作用域的变量之前。
  • 测试

$a=5;
import_request_variables('GP')
print($a);
?>

get提交变量,被覆盖为3
php代码审计_第11张图片

漏洞防御

  • 使用原始变量,不进行变量注册
  • 验证变量存在,先进行变量存在的验证,在进行注册

逻辑处理漏洞

等于与存在判断相关函数:

  • in_array()函数,判断一个值是否在数组列表里。在比较之前会做类型转换。
    测试:

if (in_array('1abc', array(1,2,3,4)))
{
     
	print('aaa');
}
?>

php代码审计_第12张图片

  • is_numeric()函数判断一个变量是否为数字。当输入字符a的16进制0x61时仍返回true。

if (is_numeric($_GET['test']))
{
     
	print('aaa');
}
?>

php代码审计_第13张图片

  • 双等于== 与in_array()函数一致,在比较前会进行类型转换

if (in_array('1abc', array(1,2,3,4)))
{
     
	print('aaa');
}
?>

在这里插入图片描述

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