php代码审计学习之函数缺陷
字数 1353 2025-08-20 18:18:05
PHP代码审计之函数缺陷全面解析
一、in_array函数缺陷
1. 基础缺陷分析
class Challenge {
const UPLOAD_DIRECTORY = './solutions/';
private $file;
private $whitelist;
public function __construct($file) {
$this->file = $file;
$this->whitelist = range(1, 24);
}
public function __destruct() {
if (in_array($this->file['name'], $this->whitelist)) {
move_uploaded_file(
$this->file['tmp_name'],
self::UPLOAD_DIRECTORY . $this->file['name']
);
}
}
}
漏洞原理:
in_array()函数在未设置第三个参数为true时使用松散比较- PHP弱类型比较时,
"6php"会被转换为6 - 6在1-24范围内,导致可以上传非预期文件
防御方法:
// 严格模式检查
if (in_array($this->file['name'], $this->whitelist, true)) {
// 安全代码
}
2. 实际案例:Piwigo 2.7.1
// include/functions_rate.inc.php
if (!in_array($rate, $conf['rate_items'])) {
// 过滤逻辑
}
// 攻击者可构造
$rate = array(0,1,2,3,4,5); // 绕过检查
二、filter_var函数缺陷
1. URL验证问题
class Template {
public function getNexSlideUrl() {
$nextSlide = $_GET['nextSlide'];
return filter_var($nextSlide, FILTER_VALIDATE_URL);
}
}
绕过方法:
javascript://comment%250aalert(1)
2. 实际案例:Anchor CMS
// system/uri.php
if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {
// 处理逻辑
}
攻击载荷:
http://example.com/%3Cscript%3Ealert(1)%3C/script%3E
三、escapeshellarg与escapeshellcmd组合问题
1. 漏洞原理
$param = "127.0.0.1' -v -d a=1";
$a = escapeshellcmd($param); // 127.0.0.1\' -v -d a=1
$b = escapeshellarg($a); // '127.0.0.1\\'\'' -v -d a=1\'
$cmd = "curl ".$b; // 最终命令可注入
2. 实际案例:Postcard应用
class Mailer {
private function sanitize($email) {
return escapeshellarg($email);
}
public function send($data) {
mail($data['to'], $data['subject'], $data['message'], '', "-f".$data['from']);
}
}
绕过方法:
- 利用FILTER_VALIDATE_EMAIL缺陷:
"aaa'aaa"@example.com - 组合使用导致命令注入
四、preg_replace函数/e模式漏洞
1. 代码执行漏洞
function complexStrtolower($regex, $value) {
return preg_replace(
'/(' . $regex . ')/ei',
'strtolower("\\1")',
$value
);
}
// 攻击载荷
\S*=${phpinfo()}
修复方案:
- 禁用/e修饰符
- 使用
preg_replace_callback()替代
2. 实际案例:CmsEasy 5.5
// lib/tool/form.php
if (preg_match('/\{(.*)\}/', $form[$name]['default'], $matches)) {
eval("\$form[$name]['default'] = {$matches[1]};");
}
五、str_replace过滤缺陷
1. 目录穿越漏洞
class LanguageManager {
private function sanitizeLanguage($language) {
return str_replace('../', '', $language);
}
}
绕过方法:
....// 或 ..././
2. 实际案例:Metinfo 6.0.0
// app/system/include/module/old_thumb.class.php
$dir = strstr($dir, 'http') ? $dir : '';
攻击载荷:
http://target/include/thumb.php?dir=http/../../config.php
六、parse_str变量覆盖
1. 漏洞原理
extract($_POST); // 危险函数
if (!isset($pi) || !is_numeric($pi)) {
goAway();
}
// 攻击者可覆盖$pi变量
安全做法:
$allowed = ['pi' => ''];
$options = array_intersect_key($_POST, $allowed);
extract($options);
2. 实际案例:DuomiCMS 3.0
// duomiphp/common.php
foreach(Array('_GET','_POST','_COOKIE') as $_request) {
foreach(
$$
_request as $_k => $_v) {
${$_k} = _RunMagicQuotes($_v);
}
}
攻击方法:
覆盖$_SESSION变量实现权限提升
七、unserialize反序列化漏洞
1. 基础漏洞
class Template {
public function loadData($data) {
if (!preg_match('/O:\d:/', $data)) {
return unserialize($data);
}
return [];
}
}
绕过方法:
- 使用数组包装:
a:1:{i:0;O:+8:"Class"...} - 利用
+绕过数字检测
2. 实际案例:Typecho 1.1
// install.php
$config = unserialize(base64_decode($_COOKIE['__typecho_config']));
利用链:
- 触发
__toString() - 调用
__get() - 通过
call_user_func执行代码
八、addslashes绕过技巧
1. 字符截断绕过
class LoginManager {
public function sanitizeInput($input, $length = 20) {
$input = addslashes($input);
if (strlen($input) > $length) {
$input = substr($input, 0, $length);
}
return $input;
}
}
攻击载荷:
user=1234567890123456789'&passwd=or 1=1#
2. 实际案例:苹果CMS 8.0
// inc/common/function.php
$res = $magicq ? $_REQUEST[$key] : @addslashes($_REQUEST[$key]);
双重编码绕过:
wd=))||if((select%0b(select(m_name)from(mac_manager))regexp(0x5e61)),(`sleep`(3)),0)#%25%35%63
九、MD5哈希注入
1. RAW输出问题
class RealSecureLoginManager {
public function isValid() {
$pass = md5($this->password, true);
$query = "password = '$pass' AND user = '$user'";
}
}
特殊值:
ffifdyop→ 二进制包含'or'语句129581926211651571912466741651878684928
十、其他重要函数缺陷
1. htmlentities过滤不全
$query = htmlentities($query, ENT_COMPAT); // 不转义单引号
安全用法:
htmlentities($query, ENT_QUOTES); // 转义单引号和双引号
2. $_SERVER['PHP_SELF']问题
$parts = explode('/', $_SERVER['PHP_SELF']);
$baseFile = end($parts);
XSS载荷:
/index.php/http:%252f%252fevil.com/script.js
3. $_REQUEST数组特性
$_GET = array_map('intval', $_GET);
$_POST = array_map('intval', $_POST);
// 但$_REQUEST仍可能包含未过滤数据
防御建议总结
- 严格类型检查:始终使用
===和!==进行比较 - 安全函数使用:
htmlspecialchars($var, ENT_QUOTES)filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)
- 禁用危险特性:
- 禁用
preg_replace的/e修饰符 - 禁用
register_globals
- 禁用
- 输入验证:
- 白名单验证优于黑名单
- 对文件路径使用
realpath()检查
- 安全配置:
open_basedir限制文件访问disable_functions禁用危险函数
通过深入理解这些PHP函数缺陷和安全编码实践,可以有效提升Web应用的安全性,防止常见的安全漏洞被利用。