一文带你了解PHP代码审计⼊⻔指南
序⾔
PHP代码审计
PHP代码审计是指对PHP程序源代码进⾏系统性的检查,它的⽬的是为了发现PHP程序存在的⼀些漏洞或
者逻辑问题,避免程序缺陷被⾮法利⽤从⽽带来不必要的安全⻛险.
作者的话
你在这篇指南中将要学习到的不⽌是php审计!
本⽂除了审计代码点,另外还讲述了漏洞产⽣原理和防护⽅法. 在了解漏洞产⽣原理后你会对漏洞利⽤有更
加深刻的理解和掌握. WEB代码审计不同语⾔之间其实有很多相通的东⻄呢,你会发现在学习php审计后学
习其他代码审计速度会更快.相信你在学习完这本指南之后会让你对WEB安全有更加深刻的认识.
⼯具准备
Visual Studio Code 是⼀个开源免费的代码编辑器 本指南中使⽤该编辑器作为示例
安装
前往微软官⽹下载安装
https://code.visualstudio.com/
VS CODE 扩展商店拥有⼤量实⽤的扩展插件. 本⽂使⽤PHP Intelephense扩展⽤于辅助审计
插件
VS CODE 扩展商店拥有⼤量实⽤的扩展插件. 本⽂使⽤PHP Intelephense扩展⽤于辅助审计
点击左侧⼯具条扩展按钮安装图示进⾏安装
VS CODE 常⽤快捷键
使⽤快捷键可以⼤幅度地提升审计效率
关闭当前窗⼝: Ctrl+W
⽂件之间切换: Ctrl+T_a_b
移动到⾏⾸: Home
移动到⾏尾: End
移动到⽂件开头: Ctrl+Home
移动到⽂件结尾: Ctrl+End
查找/转到定义: F12
查找/转到引⽤: Shift+F12
代码格式化: Shift+Alt+F
查找: Ctrl+F
F9 打断点
F5 开始调试
在项⽬⽂件中搜索: Ctrl+Shift+F
插件辅助功能
前⽂中安装的插件提供了⼀些强⼤的功能 本书主要使⽤该插件的函数跳转追踪功能
该插件可以帮助你快速查找代码引⽤的函数/类/变量/常量 以及被引⽤的代码位置
将⿏标指针指向要查找的内容可以预览定义
按住ctrl 点击被引⽤对象可以快速跳转定义位置(或把光标放在查找位置 点击F12)
按住ctrl 点击定义可以快速查找项⽬中所有的引⽤位置(或把光标放在查找位置 点击Shift+F12)
这个功能在有复杂的⽂件包含时(如CMS框架)可以快速在众多⽂件中找到定义位置
PHP代码审计思路
这⾥列出⼏个审计思路 除了PHP外其他的⼤部分web开发语⾔
也可按照这个思路审计
PHP代码审计思路
敏感函数⽅法回溯(反向审计)
查找项⽬中的敏感函数⽅法 回溯传⼊的参数 判断⽤户是否可控 是否得到有效的过滤
缺点:很难发现越权等逻辑漏洞
⽤户可控参数追踪(正向审计)
查找项⽬中的⽤户输⼊ 追踪⽤户输⼊ 判断是否得到有效的过滤/调⽤敏感函数/存在逻辑问题
关键业务功能分析(功能审计)
专⻔审计易出现漏洞的关键功能点
如 头像上传 系统登陆 ⽂件下载 等功能
优点:可以快速完成审计 减少审计⾯ 可发现越权等逻辑漏洞
缺点:审计不完全
完全审计源代码
优点:完全覆盖源代码 可发现⼀些特殊条件的漏洞
缺点:耗时⻓ 容易遗漏
PHP⽤户可控输⼊速查表
来⾃⽤户可控的输⼊ --永远不要相信⽤户的输⼊
PHP敏感函数速查表
PHP⼀些容易出现安全问题的函数⽅法
命令执⾏
⼀些常⻅的可以执⾏系统命令的函数/语法
函数/语法 描述 例⼦
system 执⾏命令并输出结果 system('id');
exec 执⾏命令 只可获取最后⼀⾏结
果
exec('id',$a); print_r($a);
passthru 同 system passthru('id');
shell_exec ` (反引号) 执⾏命令并返回结果 $a=shell_exec('id');print_r($a);
$a=`id`;print_r($a);
popen 执⾏命令并建⽴管道 返回⼀个
指针 使⽤fread等函数操作指针
进⾏读写
$a=popen("id", "r"); echo
fread($a, 2096);
proc_open 同 popen (进程控制功能更强
⼤)
⻅PHP⼿册
pcntl_exec 执⾏命令 只返回是否发⽣错误 pcntl_exec('id');
代码注⼊/⽂件包含
函数/语法结构 描述 例⼦
eval 将传⼊的参数内容作为PHP代
码执⾏ eval 不是函数 是⼀种语
法结构 不能当做函数动态调⽤
eval('phpinfo();');
assert 将传⼊的参数内容作为PHP代
码执⾏ 版本在PHP7以下是函
数 PHP7及以上为语法结构
assert('phpinfo();');
preg_replace 当preg_replace使⽤/e修饰符
且原字符串可控时时 有可能执
⾏php代码
echo preg_replace("/e","
{${PHPINFO()}}","123");
call_user_func 把第⼀个参数作为回调函数调
⽤ 需要两个参数都完全可控才
可利⽤ 只能传⼊⼀个参数调⽤
call_user_func('assert',
'phpinfo();');
call_user_func_array 同call_user_func 可传⼊⼀个
数组带⼊多个参数调⽤函数
call_user_func_array
('file_put_contents',
['1.txt','6666']);
create_function 根据传递的参数创建匿名函
数,并为其返回唯⼀名称 利⽤
需要第⼆个参数可控 且创建的
函数被执⾏
$f =
create_function('','system($_
GET[123]);'); $f();
include 包含并运⾏指定⽂件 执⾏出错
会抛出错误
include 'vars.php'; (括号可有可
⽆)
require 同include 执⾏出错会抛出警告 require('somefile.php'); (括号
可有可⽆)
require_once 同require 但会检查之前是否已
经包含该⽂件 确保不重复包含
include_once 同include 但会检查之前是否已
经包含该⽂件 确保不重复包含
SQL/LDAP注⼊
函数/⽅法 备注
mysql_query
odbc_exec
mysqli_query
mysql_db_query
mysql_unbuffered_query
mysqli::query
⽤法
$mysqli = new mysqli("localhost", "my_user",
"my_password", "world");
$mysqli->query();
pg_query
pg_query_params
pg_send_query
pg_send_query_params
sqlsrv_query
pdo::query
$pdo=new
PDO("mysql:host=localhost;dbname=phpdem
o","root","1234"); $pdo->query($sql);;
PDO
SQLite3::query
SQLite3::exec
$db = new SQLite3('mysqlitedb.db'); $db-
>query('SELECT bar FROM foo'); $db-
>exec('CREATE TABLE bar (bar STRING)');
$mongo = new mongoclient(); $data = $coll-
>find($data);
https://wooyun.js.org/drops/Mongodb%E6%
B3%A8%E5%85%A5%E6%94%BB%E5%87
%BB.html
$ld = ldap_connect("localhost");…. $lb =
@ldap_bind($ld, "cn=test,dc=test,dc=com",
https://www.cnblogs.com/0nc3/p/12063436.
html
19
⽂件读取/SSRF
"test");
Db::query Thinkphp
Db::execute Thinkphp
⽂件上传/写⼊/其他
PHP原⽣过滤⽅法
过滤函数
escapeshellarg 传⼊参数添加单引号并转义原有单引号 ⽤于防⽌命令注⼊
例 传⼊ ' id # 处理后 '\' id #' 处理后的字符串可安全的添加到命令执⾏参数
escapeshellcmd 转义字符串中的特殊符号 ⽤于防⽌命令注⼊
反斜线(\)会在以下字符之前插⼊: &#;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 ' 和 " 仅在不配对⼉的时候被
转义
来⾃ <https://www.php.net/manual/zh/function.escapeshellcmd.php>
__
addslashes 在单引号(')、双引号(")、反斜线(\)与 NUL前加上反斜线 可⽤于防⽌SQL注⼊
mysqli::real_escape_string mysqli::escape_string mysqli_real_escape_string
mysql_real_escape_string SQLite3::escapeString
以上函数会在\x00(NULL), \n, \r, , ', " 和 \x1a (CTRL-Z) 前加上反斜线 并考虑了当前数据库连接字符
集进⾏处理
注意: 经过以上函数处理后的字符串不可直接⽤于sql查询拼接 需要使⽤引号包裹后拼接到sql语句中 否
则仍可导致sql注⼊
PDO::quote 转义特殊字符 并添加引号
PDO::prepare 预处理SQL语句 有效防⽌SQL注⼊ (推荐)
htmlspecialchars 和 htmlentities 将特殊字符转义成html实体 可⽤于防⽌XSS
intval($input) floatval() floatval() floor() (int)$input num+0 将输⼊强制转换为整数/浮点 常⻅于防⽌
SQL注⼊
todo
防护配置项
- 点赞
- 收藏
- 关注作者
评论(0)