安全加固

上线前 10 件必做的事、密钥与权限的正确姿势、注入/XSS/CSRF 的边界,以及被挂马或被 SEO 劫持后怎么查。

约 13 分钟 进阶 代码块右上角可一键复制
本页目录(13 分钟读完)

这一章只做一件事:让站点不被人端掉。

文本
99% 的被挂马不是框架漏洞。
是弱密码、目录权限过宽、插件来路不明、备份没做。

伪静态在 建站第一小时。 本章只讲安全规则,不掺伪静态。

上线前必做这 10 件#

作用:堵住最常见的入口。

步骤:逐条做完。

顺序做什么怎么做
1删掉 install/ 目录mv install /root/backup
2确认 install.lock 存在看 runtime/install.lock
3后台密码改强密码16 位以上,别和邮箱同密码
4开登录验证码系统设置 → 安全设置
5后台绑定 IP有固定 IP 才填
6数据库最小权限别用 root 连站
7data/ 禁止 Web 访问见下面「安全规则」
8备份 secret.key见下面「怎么管密钥」
9全站 HTTPS证书配好 + 开 HSTS
10配好备份并验证能恢复才算数

打不开? → 看 排错手册

怎么配安全规则#

作用:禁止直接访问核心目录。和伪静态无关,单独加。

步骤:

  1. 打开 Nginx 站点配置(宝塔:网站 → 设置 → 配置文件)
  2. 在 server { } 里加上下面这些行
  3. 保存,重载 Nginx
Nginx
# 安全规则:禁止直接访问核心目录
location ^~ /app/    { deny all; }
location ^~ /core/   { deny all; }
location ^~ /config/ { deny all; }
location ^~ /data/   { deny all; }
location ^~ /docs/   { deny all; }
location ^~ /lang/   { deny all; }
location ^~ /tests/  { deny all; }

也可以直接用随包自带的完整规则:.workbuddy/deploy/00-security.conf。 整个文件放进宝塔的「网站 → 设置 → 配置文件」里。

效果:

访问结果
/data/secret.key403
/config/app.php403
/core/Bootstrap.php403

验证:

Shell
curl -s -o /dev/null -w "%{http_code}\n" https://你的域名/data/secret.key
# 期望 403 或 404,绝不能是 200
文本
这些规则只管「谁能直接访问文件」。
伪静态是另一回事,在建站第一小时里配。
不要把两者混在一起写。

打不开? → 看 排错手册

怎么改后台路径#

作用:让别人猜不到你的后台地址。

步骤:

  1. 打开 config/app.php
  2. 找到 admin_path
  3. 改成猜不到的名字
PHP
'admin_path' => 'my-console-9f2',
  1. 重建缓存
Shell
php aucms cache:rebuild
  1. 检查 Nginx 里有没有硬编码 /admin
  2. 确认没有插件把 /admin 写死

效果:/admin 打不开,要用新路径进后台。

打不开? → 看 排错手册

怎么管密钥#

作用:data/secret.key 决定全站加密安全。

事实说明
唯一来源data/secret.key,安装时生成
配置里必须为 null不要写死值
读不到就失败不会降级成不加密
不能进版本库也不该在发布包里

备份步骤:

  1. 复制到安全地方
Shell
cp data/secret.key ~/aucms-secret-backup-$(date +%F).key
  1. 放进密码管理器或离线备份
  2. 不要放在网站目录里

丢了会怎样:

影响说明
加密配置解不开如第三方支付 secret
签名链接全部失效下载、激活、找回密码
已登录用户被踢下线—
文本
丢了没有「找回」。
只能换新密钥 + 重新配三方凭证。
所以备份它比备份数据库还优先。

打不开? → 看 排错手册

怎么配权限#

作用:控制谁能进后台、谁能点什么。

三层防线:

层管什么
会话层能不能进后台(登录 + 指纹 + IP + 超时)
操作层敏感操作只有超管能做
数据层普通管理员能看哪些模块

给普通管理员授权:

  1. 后台 → 插件 → 会员管理 → 角色与权限
  2. 建角色,勾权限点
  3. 会员详情里把人放进角色
文本
没声明过的模块,默认只有超管能进。
这是「默认拒绝」,不是 bug。
新增插件后台页时记得注册权限点。

写敏感操作时注意:

PHP
$deny = $this->requireSuperAdmin();
if ($deny !== true) {
    return $deny;      // 返回的是 403 响应,不是 false
}
文本
requireSuperAdmin() 返回 true 或 Response,不是 true/false。
写成 if (!$this->requireSuperAdmin()) 会把 Response 当 false,
表现为「点了没反应」。

打不开? → 看 排错手册

怎么防 SQL 注入#

作用:别让攻击者拼 SQL。

规则只有一条:所有用户输入都通过 QueryBuilder 传参。

正确写法:

PHP
$db->table('content')->where('id', $id)->where('status', 1)->first();

$db->table('content')
   ->where('title', 'like', '%' . $kw . '%')
   ->get();

危险写法:

PHP
$db->query("select * from content where id = " . $_GET['id']);
文本
whereRaw() / select() 里的字符串不经过参数绑定,必须自己保证安全。
config/security.php 里 allow_raw_sql 默认 false —— 保持默认。

怎么防 XSS#

作用:别让攻击者注入脚本。

场景做法
标题、昵称、摘要模板默认转义,什么都不用做
富文本正文入库前 Security::purify(),输出 |raw
用户提交的富文本先 purify() 再存,绝不能直接 |raw

系统已内置(了解即可):

PHP
$row['content'] = \Aucms\Security::purify($input['content']);
$row['title']   = \Aucms\Security::strip($input['title'], 255);
文本
purify() 会去掉 <script>、<iframe>、on* 属性、javascript: 链接。
正文要嵌视频得改 xss 白名单 —— 改之前想清楚风险。

怎么防 CSRF#

作用:别让别的网站伪造你的表单提交。

两个令牌,都要有:

令牌字段名防什么有效期
CSRF Token_token跨站伪造会话级
表单 Token_form_token重复提交一次性

表单里这么写:

HTML
<form method="post" action="/admin/xxx/save">
  <input type="hidden" name="_token" value="{$csrf}">
  <input type="hidden" name="_form_token" value="{$form_token}">
  ...
</form>

少了会怎样:

少了什么提示
_token419 跨站请求被拒
_form_token419 表单已过期
两个都少419,信息可能不一样

打不开? → 看 排错手册

上传安全:系统已挡的三件事#

挡了什么怎么挡的
伪装后缀文件名重命名,按真实类型定扩展名
上传目录执行脚本Nginx 规则禁止(要用 00-security.conf)
危险扩展名php/phtml/phar/svg/html 强制剔除

验证上传目录不能执行:

Shell
curl -s -o /dev/null -w "%{http_code}\n" https://你的域名/runtime/upload/test.php
# 期望 403

被挂马了怎么查#

作用:发现异常时按顺序排查。

五个症状:

症状可能是
从搜索点进来跳赌博站SEO 劫持
页面底部多出隐藏链接黑链
网站变慢、CPU 跑满挖矿脚本
后台多出陌生账号被种后门
手机跳转、电脑正常UA 判断型木马

排查顺序:

顺序查什么命令
1入口文件有没有被动md5sum index.php 对比官方包
2最近改过的 PHPfind . -name "*.php" -mtime -7
3上传目录有没有可执行文件find runtime/upload -name "*.php"
4可疑函数grep -rn "eval|base64_decode" --include="*.php"
5异常计划任务crontab -l
6隐藏文件find . -name ".*.php"

SEO 劫持专项:

用蜘蛛 UA 访问,和正常 UA 对比:

Shell
curl -s -A "Mozilla/5.0 (compatible; Baiduspider/2.0)" https://你的域名/ | tail -40
curl -s https://你的域名/ | tail -40

两边 HTML 不一样,就是有 UA 判断。常见藏身处:

藏身处怎么查
index.php 顶部对比官方包
.user.ini 的 auto_prepend_file看文件内容
nginx 的 sub_filter看配置
主题 footer.html看有没有插 JS
来路不明的插件逐个停用试

清理步骤:

  1. 备份现场(整个目录 + 数据库),别急着删
  2. 用官方包覆盖被改的文件
  3. 改所有密码:后台、数据库、FTP、SSH、宝塔
  4. 检查有没有新增管理员、新增计划任务
  5. 检查 nginx 有没有被加 sub_filter
  6. 升级到最新版本
  7. 观察 3 天日志
文本
只删木马不改密码 = 没修。
二次入侵大多从旧密码和留着的后门账号进来。

打不开? → 看 排错手册

怎么看日志追责#

日志在哪看什么
应用日志runtime/log/Y-m-d.log异常堆栈
后台操作日志后台 → 操作日志谁删了什么
登录日志会员详情页异常 IP
Web 访问日志Nginx 站点日志高频 404、可疑 UA

找出可疑 IP:

Shell
# 访问量异常高的
awk '{print $1}' /www/wwwlogs/站点.log | sort | uniq -c | sort -rn | head -10

# 扫描器(大量 404)
grep " 404 " /www/wwwlogs/站点.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

主机层:最后一道门#

检查项命令期望
只开该开的端口ufw status verbose没有多余端口
数据库不监听公网grep bind-address /etc/mysql/my.cnf127.0.0.1
MySQL 没有 % 账号mysql -e "select user,host from mysql.user where host='%';"空
文本
宝塔、SSH、FTP 全部改非默认端口 + IP 白名单。
这三样是服务器被拿下的主入口,比 CMS 本身风险大得多。

改完代码先跑这三条#

Shell
php .workbuddy/tools/lint_classes.php
php .workbuddy/tools/lint_methods.php
php .workbuddy/tools/lint_redirects.php

出事了怎么走#

看到什么先做什么
打不开看 runtime/log + server_debug.php
被跳转用蜘蛛 UA 对比 HTML
变慢了看 CPU/带宽,查挖矿脚本
数据被改看后台操作日志定位账号

然后:

  1. 备份现场(目录 + 数据库 + 日志)
  2. 断源(改密码 / 关站点 / 关插件)
  3. 用官方包覆盖未知文件
  4. 复现验证 + 观察日志
  5. 写复盘:入口、时间、影响、怎么防

还没解决?→ 看 排错手册

接下看哪一章#

我想…去看
站点打不开了排错手册
上线前逐条勾上线检查清单
部署、HTTPS部署上线
没找到答案? 在后台「缓存与维护 → 系统体检」里看环境是否正常;仍无解就打开 server_debug.php 复现一次,页面会直接告诉你异常文件与行号。