本文目录导读:

PHP 运行时防护是一个系统工程,主要针对代码安全、执行环境和恶意攻击三个层面,以下是 PHP 运行时防护的完整策略:
核心安全配置(php.ini)
危险函数禁用
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,phpinfo
关键参数设置
; 关闭错误显示(生产环境) display_errors = Off display_startup_errors = Off log_errors = On error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT ; 内存和超时限制 memory_limit = 256M max_execution_time = 30 max_input_time = 30 ; 上传安全 file_uploads = On upload_max_filesize = 10M max_file_uploads = 20 post_max_size = 10M upload_tmp_dir = /tmp/php_uploads ; 关闭危险特性 allow_url_fopen = Off allow_url_include = Off expose_php = Off
代码层面防护
输入验证与过滤
<?php
// 使用 filter_var 进行严格过滤
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
$int = filter_var($_GET['id'], FILTER_VALIDATE_INT);
// 使用 htmlspecialchars 防止 XSS
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// 使用参数化查询防止 SQL 注入
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$_GET['id']]);
?>
CSRF 防护
<?php
// 生成 CSRF Token
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// 验证 CSRF Token
function validateCsrfToken($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
?>
文件上传安全
<?php
function validateUpload($file) {
// 验证 MIME 类型
$allowed = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($file['type'], $allowed)) {
return false;
}
// 检查文件内容(不仅仅是扩展名)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
// 重新生成文件名
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$newName = md5(uniqid(rand(), true)) . '.' . $extension;
return $newName;
}
?>
Web服务器层防护
Nginx 配置示例
server {
# 禁止执行敏感目录
location ~* ^/uploads/.*\.(php|php5)$ {
deny all;
}
# 设置安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'" always;
# 限制请求大小
client_max_body_size 10M;
# 防恶意爬虫(可选)
if ($http_user_agent ~* (sqlmap|nikto|scanner|hacker)) {
return 403;
}
}
Apache 配置(.htaccess)
# 禁止危险操作
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) [NC]
RewriteRule ^.*$ - [F]
# 防止目录遍历
RewriteCond %{REQUEST_URI} (\.\./|\.\.\\|%2e%2e|%252e) [NC]
RewriteRule ^.*$ - [F]
# 禁止文件上传目录执行PHP
<FilesMatch "\.(php|php5)$">
Deny from all
</FilesMatch>
应用安全框架
使用安全头中间件
<?php
class SecurityMiddleware {
public static function addHeaders() {
if (!headers_sent()) {
header('X-Frame-Options: SAMEORIGIN');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");
}
}
public static function checkHttps() {
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit();
}
}
}
?>
Session 安全
<?php
// session 安全配置
ini_set('session.use_strict_mode', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_samesite', 'Strict');
session_start();
// 定期更换 session ID
if (!isset($_SESSION['created'])) {
session_regenerate_id(true);
$_SESSION['created'] = time();
} elseif (time() - $_SESSION['created'] > 3600) {
session_regenerate_id(true);
$_SESSION['created'] = time();
}
?>
运行时检测与防御
请求频率限制
<?php
class RateLimiter {
private $redis;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function check($key, $limit = 10, $window = 60) {
$current = $this->redis->get($key);
if ($current >= $limit) {
throw new Exception("请求过于频繁,请稍后再试");
}
$this->redis->incr($key);
$this->redis->expire($key, $window);
}
}
// 使用示例
$limiter = new RateLimiter();
try {
$limiter->check($_SERVER['REMOTE_ADDR'], 100, 60); // 每分钟100次
} catch (Exception $e) {
http_response_code(429);
die($e->getMessage());
}
?>
WAF 规则实现
<?php
class WAF {
public static function detectAttack() {
$patterns = [
'SQL注入' => '/(\bSELECT\b.*\bFROM\b)|(\bUNION\b.*\bSELECT\b)|(\bDROP\b.*\bTABLE\b)|(\bINSERT\b)/i',
'XSS' => '/<script\b[^>]*>/i',
'命令注入' => '/\b(cat|ls|pwd|rm|whoami|nc|wget)\b/i',
'路径遍历' => '/(\.\.\/|\.\.\\\\)/i'
];
foreach ($_GET as $key => $value) {
foreach ($patterns as $type => $pattern) {
if (preg_match($pattern, $value)) {
self::blockRequest("检测到{$type}攻击");
}
}
}
}
private static function blockRequest($reason) {
error_log("WAF Blocked: {$reason}, IP: " . $_SERVER['REMOTE_ADDR']);
header('HTTP/1.1 403 Forbidden');
die('Access Forbidden');
}
}
WAF::detectAttack();
?>
第三方防护工具推荐
开源工具
- Suhosin: PHP 增强安全模块
- mod_security: Web 应用防火墙
- Snuffleupagus: 深层次的 PHP 防护
商业防护
- Sucuri
- Cloudflare WAF
- 阿里云 Web 应用防火墙
PHP 安全扩展
# 安装安全扩展 pecl install apcu # 缓存 pecl install mongodb # 数据库 pecl install redis # 缓存 apt-get install php-dev # 开发工具
日志与监控
安全日志
<?php
// 记录安全事件
function logSecurityEvent($event, $level = 'warning') {
$logData = [
'time' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'],
'uri' => $_SERVER['REQUEST_URI'],
'event' => $event,
'level' => $level,
'user_agent' => $_SERVER['HTTP_USER_AGENT']
];
$logFile = '/var/log/php_security.log';
file_put_contents($logFile, json_encode($logData) . PHP_EOL, FILE_APPEND | LOCK_EX);
}
?>
实时监控
<?php
// 异常检测
class SecurityMonitor {
public static function checkAnomalies() {
// 检查访问频率
$ip = $_SERVER['REMOTE_ADDR'];
$cache = new Redis();
$key = "visits:{$ip}:" . date('H');
$count = $cache->get($key);
if ($count > 100) { // 异常的高访问量
logSecurityEvent("异常访问频率", "critical");
}
// 检查输入异常
if (strpos($_SERVER['REQUEST_URI'], 'eval') !== false) {
logSecurityEvent("检测到代码执行尝试", "critical");
}
}
}
SecurityMonitor::checkAnomalies();
?>
最佳实践建议
部署清单
- 定期更新 PHP 版本和扩展
- 使用最新版本的框架
- 定期备份数据库和文件
- 使用 HTTPS 加密传输
- 启用 OPcache 和缓存
安全测试
# 常规安全检查命令 php -m # 查看已加载模块 php -i | grep disable_functions # 检查禁用函数 php -v # 检查 PHP 版本 find / -name "*.php" -perm -000 -o -perm -002 2>/dev/null # 寻找危险权限文件
应急响应
<?php
// 紧急关闭网站
function emergencyShutdown() {
file_put_contents('/tmp/shutdown_flag', time());
header('HTTP/1.1 503 Service Unavailable');
echo '站点暂时关闭,请稍后访问';
exit();
}
// 检查是否需要关闭
if (file_exists('/tmp/shutdown_flag')) {
emergencyShutdown();
}
?>
核心原则:
- 纵深防御:多层防护,不要依赖单一手段
- 最小权限:给予系统和应用最小必要权限
- 持续监控:及时发现和响应攻击行为
- 及时更新:保持 PHP 和依赖库最新版本
- 安全编码:从源头消除漏洞,安全开发规范
如果需要更具体的防护方案,请告诉我你的具体使用场景(如 API、电商或 CMS 等),我可以给出针对性建议。