PHP代码审计


PHP代码审计

SQL注入

经常出现在登录页面/获取HTTP头/订单处理等地方。

防范

  1. addslashes函数

过滤的值范围和_gpc时一样的

  1. mysql_[real_]escape_string函数

在PHP 4.0.3以上,\x00 \n \r \ ‘ “ \xla受影响

  1. intval等字符转化

上面提到的过滤方式,对int类型注入效果并不好。

  1. PDO prepare预编译

XSS漏洞

输出函数:print/print_r/echo/var_dump/printf/sprintf/die/var_export

经常出现在文章发表/评论回复/留言以及资料设置等地方。特别是在发表文章的时候,因为这里大多都是富文本,有各种图片引用/文字格式设置等,所以经常出现对标签事件过滤不严格导致的xss。

CSRF漏洞

CSRF主要用于越权操作,所以漏洞自然在有权限控制的地方,像管理后台/会员中心/论坛帖子以及交易管理等。

黑盒挖掘经验:打开几个有非静态操作的页面,抓包看看有没有token,如果没有的话,再直接请求(不带referer)这个页面,如果返回的数据还是一样的话,那说明很有可能有CSTF漏洞了。

白盒挖掘经验:通读代码看看几个核心文件里面有没有验证token和referer相关的代码。核心文件指被大量文件引用的文件。

文件包含漏洞

include/include_once/require/require_once

文件包含漏洞大多出现在模块加载/模板加载以及cache调用的地方,比如传入的模块名参数,实际上是直接把这个拼接到了包含文件的路径中。

文件包含截断:

  1. %00;受限于gpc和addslashes,php5.3之后被修复。

  2. ././….;不受限gpc,同样在PHP5.3之后被修复。windows下240个.或者./能够截断,linux2038个./组合才能截断

文件上传漏洞

move_uploaded_file

  1. 未过滤或本地过滤

  2. 黑名单拓展名过滤

  3. 文件头/content-type验证绕过

代码执行漏洞

eval/assert/preg_replace/call_user_func/call_user_func_array/array_map等,还有PHP东陶函数a(a(b)

preg_replace:读字符串进行正则处理,当pattern部分带/e修饰符时,replacement的值会被当成php代码执行。

call_user_func和array_map等数十个函数…

命令执行漏洞

system/exec/shell_exec/passthru/pcntl_exec/popen/proc_open/另外``实际上时调用shell_exec函数

system/exec/shell_exec/passthru会执行命令并直接回显结果

pcntl_exec:pcntl是PHP的多进程处理拓展,在处理大量任务的情况下会使用到

popen/prc_open不会直接回显结果,而是返回一个文件指针:popen(‘whoami >> D:2.txt’,’r’)

变量覆盖漏洞

extract/parse_str,import_request_variables则是用在没有开启全局变量注册的时候,调用这个函数则相当于开启了全部变量这侧,PHP5.4以后被取消。

$$extract需要一定条件,没有第二个参数或者第二个参数extract_type为EXTR_OVERWRITE/EXTR_IF_EXISTS时,可覆盖。

parse_str直接覆盖

import_request_variables把GET/POST/COOKIE的参数注册成变量,用在register_globals被禁止时,需要php4.1~5.4。

业务逻辑漏洞

逻辑漏洞很大,这里单说业务逻辑上面的漏洞。

支付/找回密码/程序安装等。

挖掘经验:通读代码,理解业务流程。

值得关注的点:程序是否可重复安装/修改密码处是否可越权修改其他用户密码/找回密码验证码是否可暴力破解以及修改其他用户密码/cookie是否可预测/cookie验证是否可绕过等

危险的函数

可控参数

变量 说明
$_GET 数组,存放着所有通过URL参数传递的数据
$_POST 数组,当HTTP POST请求的Content-Type是application/x-www-form-urlencoded或multipart/form-data的部分解析成关联数组
$_FILES 数据,存放着HTTP POST上传的文件信息
$_COOKIE 数组,存放着HTTP头里面cookie段内容
$_REQUEST 数组,默认情况下包含了$_GET, $_POST, $_COOKIE的数据
$_SERVER 数组,包含了HTTP头,服务器环境等信息
$_SESSION 数组,存放当前会话可用的session变量

执行任意代码函数

把传入的字符串直接当成php代码直接执行,如:

函数 函数说明 例子 运行结果
1 assert 判断一个断言是否为false assert(‘print(123)’) 输出123
2 eval 把一个字符串当做php代码执行 eval(‘echo 123’) 输出123
3 create_function 用给的一个字符串创建匿名函数 create_function(‘$a’,’print($a);’)(123) 输出123

文件形式执行代码

通过引入文件的形式执行php代码,如:(利用:查看这些引入文件参数是否外部可控)

函数 函数说明 例子 结果
1 include 包含并运行指定文件 include ‘1.php’ 包含文件1.php,并执行里面的代码
2 include_once 包含并运行指定文件 include_once ‘1.php’ 包含文件1.php,并执行里面的打码
3 require 包含并运行指定文件 require ‘1.php’ 包含文件1.php,并执行里面的代码
4 require_once 包含并运行指定文件 require_once ‘1.php’ 包含文件1.php,并执行里面的代码

数据处理函数

函数 函数说明 例子 结果
1 preg_replace 使用正则替换内容,php7之前的正则表达式参数可以开启\e的模式,执行任意代码 preg_replce(“/(.)/e”,’print(\1),’123’); php5下输出123
2 array_map 为数组的每个元素应用回调函数 $b=array_map(‘assert’,[‘print(123)’]); php5下输出123
3 array_filter 用回调函数过滤数组中的单元 array_filter([‘print(123)’],’assert’); php5下输出123
4 array_walk 使用用户自定义函数对数组中的每个元素做回调处理 $a=[‘print(123)’];array_walk($a,’assert’) php5下输出123
5 call_user_func 把第一个参数作为回调函数调用 call_user_func(‘assert’,’print(123)’); 输出123

能够读取网络资源的函数

能够读取网络资源的函数(配置 allow_url_include=1 才可以使用)

函数 函数说明 例子 结果
1 curl系列 发起网络请求
2 file_get_contents 原本功能是读取文件,但是支持封装协议,所以可以读取网络上的资源 file_get_contents(‘https://url.com') 请求url.com
3 file 原本功能是读取文件,但是支持封装协议,所以可以读取网络上的资源 file(‘https://url.com') 请求url.com
4 fopen 原本功能是读取文件,但是支持封装协议,所以可以读取网络上的资源 fopen(‘https://url.com') 请求url.com
5 copy 原本功能是复制文件,但是支持封装协议,所以可以读取网络上的资源 copy(‘https://url.com') 请求url.com,并保存txt文档

能够执行系统命令或者调用外部程序的函数

函数 函数说明 例子 结果
exec 执行一个外部程序 exec(‘touch 1.txt’) 在当前目录下生成1.txt
shell_exec 通过shell执行命令,并且将完整的输出以字符串的方式返回 shell_exec(‘touch 1.txt’) 在当前目录下生成1.txt
system 执行外部程序,并显示输出 system(‘touch 1.txt’) 在当前目录下生成1.txt
passthru 执行外部程序,并显示输出 passthru(‘touch 1.txt’) 在当前目录下生成1.txt
popen 打开进程文件指针 popen(‘touch 1.txt’,’r’) 在当前目录下生成1.txt
proc_open 执行一个命令,并打开用来输入/输出的文件指针 proc_open(‘touch 1.txt’,[],$a) 在当前目录下生成1.txt
两个反引号 反引号包含的内容会当成系统命令执行 touch 1.txt 在当前目录下生成1.txt

能够修改运行时候的上下文环境

函数 函数说明 例子 结果
extract 从数组中将变量导入到当前的符号表,审计时候需要判别传输数组是否外部可控 $a=’1’;extract([‘a’=>’2’]);echo $a 输出2
parse_str 将字符串解析成多个变量 $a=’1’;parse_str(‘a=2’);echo $a 输出2
ini_set 修改运行时php配置 ini_set(‘memory_limit’,’2048M’) 设置运行时最大占用额内存为2048M

声明

本文为转载,原链接目前没有找到


文章作者: Carrot2
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Carrot2 !
评论
  目录