PHP代码审计
SQL注入
经常出现在登录页面/获取HTTP头/订单处理等地方。
防范
- addslashes函数
过滤的值范围和_gpc时一样的
- mysql_[real_]escape_string函数
在PHP 4.0.3以上,\x00 \n \r \ ‘ “ \xla受影响
- intval等字符转化
上面提到的过滤方式,对int类型注入效果并不好。
- 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调用的地方,比如传入的模块名参数,实际上是直接把这个拼接到了包含文件的路径中。
文件包含截断:
%00;受限于gpc和addslashes,php5.3之后被修复。
././….;不受限gpc,同样在PHP5.3之后被修复。windows下240个.或者./能够截断,linux2038个./组合才能截断
文件上传漏洞
move_uploaded_file
未过滤或本地过滤
黑名单拓展名过滤
文件头/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 |
声明
本文为转载,原链接目前没有找到