2021-07-09 06:08:43
PHP函数安全需通过输入验证、禁用高危函数、限制内存、使用安全函数及CSP策略等综合措施防范常见漏洞,并结合代码审查与实战案例提升防护能力。以下是具体内容:
常见PHP函数安全漏洞及原理参数注入漏洞
原理:未验证用户输入时,攻击者可构造恶意参数执行任意代码。例如calculateAge($birthdate)函数中,若$birthdate未过滤,攻击者可输入"; system('id'); //,导致strtotime()执行恶意命令。
风险:直接拼接用户输入到SQL查询、文件操作或系统命令中,可能引发代码注入、命令注入或文件包含漏洞。
函数重写漏洞
原理:攻击者通过rename_function()或自定义同名函数覆盖内置函数(如重写file_get_contents()返回恶意内容)。
风险:破坏程序逻辑,例如篡改文件读取结果或拦截敏感操作。
缓冲区溢出漏洞
原理:函数分配的内存缓冲区不足,用户输入超限时导致程序崩溃或数据泄露。例如readInput($length)中,若input.txt内容过长且未严格限制,可能触发溢出。
风险: denial of service(拒绝服务攻击)或敏感信息泄露。
输入验证与过滤
方法:使用filter_var($_GET['param'], FILTER_SANITIZE_STRING)过滤字符串,或preg_match('/^[a-zA-Z0-9]+$/', $input)限制输入格式。
场景:用户注册、表单提交、API参数接收等需严格校验数据合法性的场景。
禁用高危函数
配置:在php.ini中设置disable_functions = exec,passthru,shell_exec,system,禁止执行系统命令的函数。
注意:需权衡功能需求,例如共享主机环境通常默认禁用此类函数。
限制内存与资源
配置:通过memory_limit = 128M限制脚本内存使用,防止恶意输入耗尽服务器资源。
补充:结合max_execution_time控制脚本运行时间,避免长时间阻塞。
使用安全替代函数
输出编码:htmlspecialchars($output, ENT_QUOTES)防止XSS攻击。
数据库操作:使用PDO预处理语句(prepare()->execute())替代直接拼接SQL。
密码存储:password_hash($password, PASSWORD_DEFAULT)生成加密哈希,避免明文存储。
内容安全策略(CSP)
配置:HTTP头添加Content-Security-Policy: default-src 'self',限制脚本仅从当前域名加载。
效果:阻止攻击者注入外部恶意脚本,即使存在XSS漏洞也能降低风险。
案例1:参数注入漏洞
漏洞代码:$input = $_GET['name'];echo "你的名字是: $input"; // 直接拼接未过滤输入
攻击方式:访问?name=<script>alert(1)</script>触发XSS,或?name=; system('rm -rf /');执行命令(若服务器未禁用system())。
修复代码:$input = filter_var($_GET['name'], FILTER_SANITIZE_STRING);echo "你的名字是: " . htmlspecialchars($input, ENT_QUOTES);
案例2:函数重写漏洞
漏洞代码:function file_get_contents($filename) { return "恶意内容"; // 覆盖内置函数}echo file_get_contents("test.txt"); // 始终返回恶意内容
防御措施:
避免在代码中定义与内置函数同名的函数。
使用function_exists('file_get_contents')检查函数是否被篡改。
在php.ini中启用suhosin.executor.disable_eval=On(若使用Suhosin扩展)限制动态函数执行。
案例3:缓冲区溢出漏洞
漏洞代码:function readInput($length) { $input = file_get_contents('input.txt'); if (strlen($input) > $length) { throw new Exception("Input too long"); } return $input; // 未提前截断,仍可能处理超长内容}
修复方案:function readInput($length) { $input = file_get_contents('input.txt'); $input = substr($input, 0, $length); // 强制截断 return $input;}