首页 / 帮助文档 / debian服务器LAMP环境漏洞防护加固

debian服务器LAMP环境漏洞防护加固

Debian 12 默认的 LAMP 环境安装脚本跑完后,系统其实处于一个相当脆弱的状态。PHP 的默认配置允许执行远程文件、Apache 暴露了详细的版本信息、MySQL 的 root 用户默认使用 auth_socket 插件导致运维人员为了方便直接改成弱密码——这些都不是危言耸听,而是每次渗透测试中高频出现的问题。我们直接动手,从操作系统内核参数到应用层配置,逐层加固。

内核级 TCP 协议栈加固

应用层防护做得再好,如果 SYN Flood 攻击直接把服务器半连接队列打满,服务照样不可用。编辑 /etc/sysctl.conf 或创建 /etc/sysctl.d/99-security.conf,加入以下参数:

# 开启 SYN Cookie,防止 SYN Flood
net.ipv4.tcp_syncookies = 1

# 忽略所有 ICMP 回显请求(禁止 ping)
net.ipv4.icmp_echo_ignore_all = 1

# 忽略广播 ICMP
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 记录有伪造源地址的数据包
net.ipv4.conf.all.log_martians = 1

# 禁止源路由
net.ipv4.conf.all.accept_source_route = 0

# 启用反向路径过滤,防止 IP 欺骗
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# 减少 TIME_WAIT 连接的最大数量,缓解 DDoS
net.ipv4.tcp_max_tw_buckets = 5000

# 加快 TCP 连接回收
net.ipv4.tcp_tw_reuse = 1

保存后执行 sysctl -p 使其生效。这些参数能有效缓解基于 TCP 协议的常见拒绝服务攻击,同时减少 IP 欺骗的风险。特别注意 rp_filter 参数,在多网卡服务器上如果做了非对称路由可能需要根据实际情况调整,但对于典型的单网卡 LAMP 服务器,开启反向路径过滤是最佳实践。

Apache 信息泄露防护与访问控制

默认安装的 Apache 会向客户端发送详细的服务器版本信息和操作系统类型,这为攻击者提供了精准的漏洞利用信息。编辑 Apache 主配置文件 /etc/apache2/conf-available/security.conf,修改或添加以下指令:

ServerTokens Prod
ServerSignature Off
TraceEnable Off

ServerTokens Prod 让 Apache 仅返回 "Apache",不暴露版本号和操作系统。ServerSignature Off 关闭错误页面底部的服务器签名。TraceEnable Off 禁用 HTTP TRACE 方法,防止跨站追踪攻击。启用这些模块和配置:

a2enmod headers
a2enmod rewrite
systemctl restart apache2

接下来配置安全头。在虚拟主机配置或 .htaccess 中添加:

Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"

这些 HTTP 响应头分别防止 MIME 类型嗅探、点击劫持、反射型 XSS、Referer 泄露和不必要的浏览器功能调用。对于生产环境,还应该配置 Content-Security-Policy,但 CSP 策略需要根据实际加载的资源定制,错误的 CSP 规则会导致页面功能异常,建议先在测试环境调试。

PHP 运行时安全加固

PHP 是 LAMP 栈中最容易出问题的环节。编辑 /etc/php/8.2/apache2/php.ini(路径根据 PHP 版本调整),逐项检查并修改以下关键参数:

# 禁止远程文件包含
allow_url_fopen = Off
allow_url_include = Off

# 隐藏 PHP 版本信息
expose_php = Off

# 禁用危险的函数
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

# 限制文件上传大小,防止资源耗尽
upload_max_filesize = 10M
post_max_size = 12M
max_execution_time = 30
max_input_time = 60

# 严格限制可访问目录
open_basedir = "/var/www/html:/tmp"

# 会话安全
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Strict"
session.use_strict_mode = 1

disable_functions 列表需要谨慎处理。如果网站程序依赖 ImageMagick 或某些需要 exec 功能的插件,盲目禁用会导致业务中断。建议先在 staging 环境测试,或使用白名单方式逐步收紧。open_basedir 是防止 PHP 跨目录访问的有效手段,但如果有多个虚拟主机,需要把各自的目录都加进去,用冒号分隔。session.cookie_secure 要求网站必须启用 HTTPS,如果还没有配置 SSL 证书,这个选项会导致会话 Cookie 无法传输,务必先完成 HTTPS 部署。

MySQL 权限最小化与审计

很多人安装完 MySQL 后直接用 root 账户连接应用程序,这是极其危险的做法。先运行 mysql_secure_installation 脚本,它会引导你设置 root 密码、删除匿名用户、禁止 root 远程登录、删除测试数据库。然后为每个应用创建独立的数据库用户,并严格限制权限:

CREATE USER 'appuser'@'localhost' IDENTIFIED BY '强密码';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

除非应用程序确实需要 ALTER、DROP、CREATE 等 DDL 权限,否则只授予基本的 CRUD 权限。对于需要执行备份的脚本,单独创建一个只读用户:

CREATE USER 'backup'@'localhost' IDENTIFIED BY '另一组强密码';
GRANT SELECT, LOCK TABLES ON appdb.* TO 'backup'@'localhost';

MySQL 8.0 引入了密码过期策略和密码复杂度验证组件,建议启用:

INSTALL COMPONENT 'file://component_validate_password';
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 14;

这要求密码至少 14 位,包含大小写字母、数字和特殊字符。对于已有的弱密码账户,用 ALTER USER 语句强制更新。

文件系统权限与 SUID/SGID 审计

Web 目录的权限设置直接决定了攻击者拿到 Webshell 后能造成多大破坏。核心原则:Web 服务器进程(www-data)只对需要写入的目录拥有写权限,其他目录全部只读。典型的权限设置:

# 设置所有文件所有者为部署用户,组为 www-data
chown -R deploy:www-data /var/www/html
# 目录权限 755,文件权限 644
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# 仅对需要上传的目录授予写权限
chmod 770 /var/www/html/uploads

全系统范围内查找并清理不必要的 SUID 和 SGID 文件:

find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null

常见的可移除 SUID 位文件包括 /usr/bin/chage、/usr/bin/gpasswd、/usr/bin/wall 等,如果系统不需要普通用户修改密码,可以考虑去除这些文件的 SUID 位。但 /bin/su、/usr/bin/sudo 等核心工具不能动,否则会导致系统管理功能异常。

ModSecurity WAF 部署与 OWASP 规则

应用层防火墙是拦截 SQL 注入、XSS、文件包含等攻击的最后一道防线。在 Debian 上安装 ModSecurity:

apt install libapache2-mod-security2
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

编辑 /etc/modsecurity/modsecurity.conf,将 SecRuleEngine 从 DetectionOnly 改为 On:

SecRuleEngine On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

下载 OWASP 核心规则集:

apt install modsecurity-crs

规则集安装在 /usr/share/modsecurity-crs/ 目录下。需要手动创建包含文件,在 /etc/apache2/mods-enabled/security2.conf 中添加:

Include /usr/share/modsecurity-crs/crs-setup.conf
Include /usr/share/modsecurity-crs/rules/*.conf

CRS 默认是偏严格的,部署后一定会产生误报。关键是要花时间根据业务日志调整规则排除项,而不是直接关掉整个模块。可以通过调整规则阈值(Paranoia Level)来平衡安全性和可用性,生产环境建议从 PL 1 开始,逐步提升。

Fail2Ban 暴力破解防御

SSH、MySQL、Apache 认证页面都是暴力破解的目标。安装 Fail2Ban 并配置监控规则:

apt install fail2ban

创建 /etc/fail2ban/jail.local,不要直接修改 jail.conf,因为后者会在包更新时被覆盖:

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
mode = aggressive

[apache-auth]
enabled = true

[apache-badbots]
enabled = true

[mysqld-auth]
enabled = true
port = 3306
logpath = /var/log/mysql/error.log

重启 Fail2Ban 后,任何在 10 分钟内失败 5 次的 IP 将被封禁 1 小时。对于 SSH,建议改用密钥认证并禁用密码登录,这样 Fail2Ban 的 SSH 规则就变成了辅助手段而非主要防线。修改 /etc/ssh/sshd_config:

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
日志监控与入侵检测

加固完成后的工作不是结束,而是持续监控的开始。配置 logrotate 确保日志不会撑满磁盘,同时部署 AIDE 进行文件完整性校验:

apt install aide
aideinit
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

创建定时任务每天检查文件变更:

0 3 * * * /usr/bin/aide --check | mail -s "AIDE Report" admin@example.com

对于 MySQL,启用慢查询日志和错误日志,并定期分析:

SET GLOBAL slow_query_log = 1;
SET GLOBAL log_queries_not_using_indexes = 1;

Apache 的访问日志中重点关注 404 和 500 错误激增的时段,这通常是扫描器在探测漏洞。可以使用简单的 awk 命令统计每分钟请求量,异常波动直接触发告警。

自动更新策略与测试流程

Debian 的 unattended-upgrades 可以自动安装安全更新,但直接在生产环境启用有风险——更新后服务可能启动失败。推荐的做法是启用安全更新的自动下载和通知,但手动执行安装:

apt install unattended-upgrades apt-listchanges
dpkg-reconfigure unattended-upgrades

在配置中选择仅自动安装安全更新,并配置邮件通知。对于 PHP 和 MySQL 的小版本升级,通常向后兼容性很好,可以放心自动更新。但大版本升级(如 PHP 8.2 到 8.3)必须在测试环境完整回归后再操作。

整个加固过程不是一次性工作。每次部署新代码、安装新插件、调整架构后,都需要重新审视安全配置是否依然有效。建议把这些加固步骤写成 Ansible Playbook 或 Shell 脚本,纳入服务器的初始化流程,确保每一台新上线的 LAMP 服务器都达到相同的安全基线。安全是一个持续的过程,今天的加固方案可能在明天的新漏洞面前就不够用了,保持对安全公告的关注和快速响应能力,才是长期运维的核心竞争力。