☰
FastAdmin后台Getshell链路与四层收敛防护
2026/10/2 4:57:21 网站建设 项目流程

一个做企业站的朋友凌晨给我打电话,说网站首页被人换成了黑页,服务器上多出来一个他不认识的 PHP 文件。我远程连过去看了十分钟,框架是 FastAdmin,后台登录页就挂在公网上,账号还是三年前建站时那套admin/ 弱口令组合。整件事从头到尾没有用到任何 0day,攻击者做的每一步,都是后台本来就"允许"的操作。这也是我后来反复跟人强调 FastAdmin 后台 Getshell 这件事的原因:大多数时候,问题不在于框架被攻破,而在于后台被设计成了一把万能钥匙,而我们却把它插在了公网的门锁上。

这篇内容我会把这条链路拆开讲透,包括 FastAdmin 后台里哪些功能天生具备"落地文件"的能力、攻击者面对一个后台账号时会怎么选路、防守方应该从哪几层去收敛,以及真出事之后一套能直接跑起来的排查顺序。适合正在用 FastAdmin 或类似 ThinkPHP 系后台框架做站的开发、运维,也适合做安全巡检和应急的同学。文中涉及攻击链的部分只讲到"理解原理"的层面,目的是让防守方能对上号,不会给出可直接使用的工具或载荷。

1. 后台入口本身就是最大的风险面

1.1 FastAdmin 在中小项目里为什么这么普及

FastAdmin 是基于 ThinkPHP 的一套后台快速开发框架,把权限管理、菜单、CRUD 生成、插件市场、附件管理这些后台标配全部打包好了。对中小团队和外包建站来说,它的价值很直接:一个下午能搭出一套带权限体系的管理后台,插件市场里还能直接下到 CMS、商城、问答、API 之类的现成模块。我接触过的中小站点里,用 FastAdmin 做底座的占比相当高,尤其是那种"预算有限、上线要快"的项目。

问题恰恰出在这个"快"上。框架帮你省掉的每一分工作量,背后都对应着一个已经开放的、可被调用的功能。写代码的人不需要理解文件系统权限、不需要理解模板引擎的执行上下文、不需要理解数据库导出目录放在哪,因为这些框架都替你做了。你只需要点几下鼠标,功能就跑起来了。

1.2 功能齐全和攻击面大,是同一枚硬币

我习惯把后台功能按"是否触及文件系统和数据库"分成三类看,这个分类对判断风险很有用:

功能类别典型功能触及对象风险权重
纯数据操作文章管理、用户列表、订单查询数据库表低
配置类站点设置、参数配置、邮箱配置数据库 + 缓存文件中
文件与代码类插件安装、模板编辑、数据库备份恢复、附件上传磁盘文件 + 可能的执行高

第三类功能是后台的"必需品",因为一个后台如果不能让管理员上传 Logo、不能装插件、不能改模板,那它的实用性会大打折扣。但这些功能一旦被非授权的人拿到,性质就变了——它们本质上都是"在服务器上写文件"的合法接口。攻击者不需要自己造一个上传漏洞,他只需要登录进去,用你以为给管理员准备的功能,做他需要的事。

1.3 入口挂在公网上,链路就已经开始了

我见过的站点里,后台地址直接是域名/后台入口文件的占了大多数,有的甚至连默认入口名都没改。这意味着什么?意味着攻击者不需要做任何信息收集,扫一遍域名就能定位到登录页,接着就是自动化工具跑弱口令、跑历史上泄露过的账号密码组合。更麻烦的是,很多站点是外包做的,交付时给了一套账号,客户自己又加了两三个运营账号,等到出问题的时候,连"一共有几个能登后台的账号"都说不清楚。

后台入口暴露在公网这件事,本身不构成漏洞,但它把整条链路的难度从"需要挖洞"降到了"需要撞库"。这两件事的成本差了一个数量级。

2. 拆一拆 FastAdmin 后台里那些"碰文件"的功能点

2.1 插件与模块的安装通道

FastAdmin 的插件机制是它的核心卖点之一,也是风险最集中的地方。插件安装的典型流程是:上传一个压缩包或者从市场拉取,服务端解压到指定目录,然后框架读取插件里的配置文件完成注册。这个流程里有三个环节值得盯:

  • 解压:压缩包解压是文件落地的第一跳,如果解压目标目录可写且可以被 Web 访问,文件就已经在服务器上了;
  • 注册:插件配置里通常包含入口、菜单、权限节点等信息,这部分是写进数据库或者配置文件的;
  • 加载:插件目录下的 PHP 文件会被框架按规则加载执行。

这里的关键认知是:插件安装本质上是一次受信任的代码部署操作。设计它的前提是"操作者已经是管理员,管理员不会害自己"。当这个前提被打破,整个机制就变成了一个合法的代码上传通道。我之前做过一次内部复盘,把后台里所有会往磁盘写文件的功能列出来,光是插件相关的入口就有六七个,这还是没算上各个插件自己带的子功能。

2.2 模板与静态资源的在线编辑

后台的模板管理功能通常提供在线编辑能力,方便管理员改改文案、调调样式。这类功能的实现方式有几种,风险等级完全不同:

  • 只允许编辑白名单后缀(如.html、.css),且编辑后的文件不经过模板引擎编译,风险最低;
  • 允许编辑模板文件本身,模板引擎在渲染时会编译成 PHP 缓存文件,风险中等偏高;
  • 允许自由编辑任意路径下的文本文件,风险最高。

第二种情况在很多 ThinkPHP 系项目里都存在。模板引擎的工作方式是:读取模板文件,编译成 PHP 文件放进运行时缓存目录,然后 include 执行。所以哪怕你只写了一个看起来"不像代码"的模板文件,最终也会变成一段被执行的 PHP。这是理解"为什么改个模板就能拿 shell"的核心——危险的不是模板语法,而是模板最终会变成 PHP 被执行。

2.3 数据库与备份恢复相关功能

数据库备份功能通常会把导出结果存成一个文件放在服务器上,常见格式是 SQL 或者压缩包,路径一般是在application或者runtime之类的目录下。恢复功能则是读取一个文件并执行里面的 SQL。

这条链路的危险点有两个:一是备份文件如果落在 Web 可访问目录且后缀可被解析,它就是一个"能写内容到磁盘"的跳板;二是恢复功能如果允许指定任意路径,读取的范围就不受控了。我遇到过最离谱的一次,是某个项目的备份目录权限是 777,而且目录下堆了几十个历史备份文件,里面有完整的用户表,包括密码哈希。

2.4 附件上传与那些"看起来无害"的配置项

附件上传是每个后台都有的功能,它的安全边界取决于三件事:后缀校验、存储位置、解析配置。这三件事里,只有第一件是应用层能完全控制的,后两件取决于服务器配置。很多站点上线时用的是集成环境或者别人给的配置文件,上传目录的解析规则根本没人看过。

除了上传,还有一些容易被忽略的配置项:站点设置里的"允许上传的文件类型"、伪静态规则、CDN 回源配置、附件域名。这些配置本身不是漏洞,但它们会改变其他功能的风险等级。举个例子,如果附件目录被单独绑定了一个域名,而这个域名指向的还是同一份代码目录,那么上传目录的访问权限没有任何变化,只是多了一个入口而已。

3. 从后台账号到代码落地:一次链路的决策复盘

3.1 第一步永远是入口发现与账号获取

这一步没什么技术含量,但它是整条链路的前提。常见的获取方式按成本从低到高排:

  1. 默认口令或弱口令直接登录,比如admin/admin123、admin/123456;
  2. 撞库,用其他地方泄露的邮箱密码组合批量尝试;
  3. 从项目交付文档、代码仓库、聊天记录里翻到的明文账号;
  4. 后台账号被盗(钓鱼、键盘记录、浏览器保存的密码被读取)。

我在帮人做应急时统计过一个粗略比例,超过六成的后台入侵事件,第一步都是"密码太简单"或者"离职员工账号没删"。这不是技术问题,是流程问题,但它决定了后面所有事情会不会发生。

3.2 第二步是找一个"能落文件"的功能

拿到后台之后,攻击者不会立刻乱点,他会先看菜单,判断这个后台有哪些能力。判断的优先级大致是:有没有插件管理、有没有模板编辑、有没有数据库管理、有没有文件上传、有没有系统设置里的路径类配置。原因很简单,这些功能直接对应"能不能写文件"。

这里有个细节值得注意:权限粒度决定了攻击者能碰哪些功能。如果拿到的是超级管理员,基本畅通无阻;如果拿到的是运营账号,可能只有内容管理权限,那他能做的事情就受限很多。所以后台的权限划分不只是管理方便的问题,它直接影响入侵之后的影响半径。

3.3 第三步是让文件真的被执行

文件写到磁盘上,和文件被执行,是两件不同的事。这一步骤需要满足几个条件之一:

  • 文件被写在了可以被 Web 服务器解析为脚本的位置,且后缀在解析规则之内;
  • 文件被框架的自动加载机制读取,比如插件配置、路由配置、语言包;
  • 文件被其他业务逻辑主动 include。

这也是为什么"上传点 + 解析配置不当"是经典组合:上传点负责把文件放上去,解析配置负责让它跑起来。反过来,如果上传目录被明确配置成不解析脚本,那第一步写得再多也没用。

3.4 第四步是维持与痕迹处理

这一步是防守方最需要关注的,因为痕迹处理往往比攻击本身更有迹可循。常见的手法包括:新增一个不知名的管理员账号、修改已有账号的密码、写入定时任务、在正常文件里插入一小段代码、删除或篡改日志。从防守方角度看,这些动作有几个共同特征:时间集中、路径集中、来源 IP 相同。只要你把日志留住了,这些特征很难完全抹掉。

4. 为什么这类问题反复出现

4.1 "后台即可信"这个假设从一开始就不成立

几乎所有后台框架的设计哲学都是:登录之后的操作都视为可信操作。这个假设在内部系统里勉强成立,但在公网暴露的后台上完全不成立。攻击者一旦拿到账号,他在系统眼里就是一个合法的管理员,所有的权限校验、所有的日志记录都会把他当成"自己人"。

我经常用一个类比:这就像你把家门钥匙和保险柜钥匙串在一起挂着,门锁再结实,只要钥匙被拿到,里面就全开了。后台的账号安全等级,必须和它背后的功能危险等级匹配。一个能装插件、能改模板的后台账号,其敏感程度应该等同于服务器的登录凭据。

4.2 默认配置面向的是易用性,不是安全性

FastAdmin 这类框架在安装时会尽量降低门槛:数据库连接、目录权限、上传大小,全部按"能跑起来"的标准配。这本身无可厚非,问题是很多项目上线之后就没再改过。

我列过一张"上线前必须改掉"的清单,每次做安全巡检都能用上:

  • 默认后台入口文件名;
  • 示例数据、示例账号;
  • 安装目录(如果安装脚本留在服务器上);
  • 调试模式开关;
  • 错误信息详细程度;
  • 运行目录和缓存目录的可访问性。

这几项里,调试模式和错误信息详细程度被忽略得最多。开着调试模式的站点,报错页面会吐出文件路径、SQL 语句、甚至配置项,这些信息对攻击者来说等于一份地图。

4.3 一个后台管理员到底该有多大权力

权限设计上有个常见误区:为了省事,给所有后台账号都开超级管理员。结果就是运营、客服、美工全都能装插件、改模板、备份数据库。这套权限体系形同虚设。

正确的做法是按最小权限原则拆:内容编辑只给内容权限,运营只给订单和用户权限,只有运维和开发负责人保留插件、模板、数据库这几类功能的访问权。多花半小时配权限,能省掉后面一堆麻烦。

5. 四层收敛:把后台拉回可控面

5.1 入口层:让后台不那么容易被定位

第一件事是把后台入口从默认名称改掉,改成不容易被猜到的字符串,并且做好记录。第二件事是加访问控制:

  • 如果团队有固定出口 IP,直接做 IP 白名单,这一招性价比最高;
  • 没有固定 IP 的,加一层反向代理的路径级认证,或者接入统一的身份认证网关;
  • 至少也要加登录频率限制和验证码,把自动化爆破的成本抬上去。

我个人的偏好是:能白名单就白名单,不能白名单就改成非常规路径名 + 强口令 + 双因素三件套,别只做其中一件。

5.2 账号层:把密码和会话管住

口令策略要说人话:长度优先于复杂度,禁止使用和站点相关的词汇,禁止复用。给所有后台账号启用双因素认证,这是目前投入产出比最高的措施之一。另外两件事容易被忽略:

  • 离职和转岗账号要及时禁用,不是改密码,是禁用;
  • 会话要有失效机制,改完密码要主动让旧会话失效,别指望密码改了别人就登不上。

5.3 功能层:关掉不需要的,限制必须的

这一层的原则是"用不到就别开"。具体可以这么做:

功能建议处理
插件在线安装生产环境关闭,改为本地测试后手动部署
模板在线编辑关闭,或者只允许编辑非模板类静态文件
数据库备份保留但限制目录权限,备份文件不落在 Web 目录
附件上传限制后缀白名单,独立存储目录
调试与日志输出全部关闭,只记录到服务器本地

5.4 运行层:让落地的东西跑不起来

这是最后一道防线,也是最有效的一道。核心思路是:即使文件被写进去了,也让它不能被执行。

  • 上传目录、附件目录、缓存目录配置为禁止执行脚本;
  • 用open_basedir限制 PHP 能访问的目录范围;
  • 关闭不必要的危险函数,尤其是命令执行类和文件操作类;
  • Web 进程用户权限降到最低,不要用 root 跑;
  • 给代码目录做定期文件完整性比对。

这五条里,我觉得最容易被低估的是"Web 进程权限"。很多站点用一个高权限用户跑 Web 服务,一旦被落地代码,攻击者直接就是服务器级别权限,前面所有的加固全都白做。

6. 事后排查:确认有没有被植入

6.1 先把时间线拉出来

排查的第一步不是找文件,是定范围。你要先知道"可能是什么时候被入侵的"。信息来源包括:首页被改的时间、监控告警的时间、用户反馈的时间、日志里异常访问的时间。拿到一个大致区间,后面的搜索才有意义。

6.2 找新增和可疑的文件

按修改时间找是最直接的办法:

# 查找最近 7 天内被修改过的 PHP 文件 find /www/wwwroot/你的项目 -type f -name "*.php" -mtime -7 -ls # 按时间排序,看最近被动过的文件 find /www/wwwroot/你的项目 -type f -printf '%T+ %p\n' | sort -r | head -50

除了时间,还要看几个特征:

  • 文件大小异常:一个几千字节的"图片"或者"日志"里可能是可执行内容;
  • 目录位置异常:上传目录、缓存目录、日志目录里出现 PHP 文件,基本可以直接判定异常;
  • 内容特征:搜索常见的高危函数名,注意要结合业务确认,避免误报。
# 在可疑目录里搜索常见危险函数调用 grep -rn --include="*.php" -E "(eval|assert|system|exec|shell_exec|passthru|popen)" /www/wwwroot/你的项目/uploads

6.3 看日志,把访问路径串起来

日志排查的顺序我一般是这样:先看 Web 访问日志里后台登录相关的记录,找出异常来源 IP 和登录成功的时间点;再看这个 IP 在登录之后访问了哪些路径,尤其是功能类接口;最后对照文件修改时间,看两者能不能对上。

# 统计访问量最高的 IP awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20 # 查看某个 IP 的完整访问记录 grep "可疑IP" access.log | awk '{print $4, $7}' | head -100

如果日志被清过或者被截断,这本身就是一个强信号。建议把日志同步到独立的日志服务,本地被删了还有一份。

6.4 看外连、看任务、看账号

文件层面查完之后,还要查三个地方:进程与网络连接、计划任务、账号列表。这三个地方是权限维持的常见落脚点。

  • 网络连接:看有没有异常的外连,尤其是固定周期性的连接;
  • 计划任务:crontab -l,以及/etc/cron.d/、/etc/cron.daily/等目录;
  • 账号:系统账号列表、后台管理员列表,对比一下有没有多出来的。

排查的时候一定要留证据。文件先复制一份再删,日志先导出再清理,不然后面复盘和安全加固都没有依据。

7. 几个只有真做过才记得住的细节

7.1 备份文件和缓存目录最容易被漏掉

我做过几次应急,最后翻出来的东西都不是在代码目录,而是在runtime缓存目录和备份目录里。缓存目录平时没人看,文件又多又杂,扔一个文件进去完全不显眼。备份目录更麻烦,里面的 SQL 文件本身就带着完整的表结构和数据。

所以排查范围一定要覆盖:上传目录、缓存目录、日志目录、备份目录、插件目录、模板编译目录。这几个地方单独列一遍,别只扫主代码目录。

7.2 改了密码不等于踢掉了登录态

这是我在一次应急里踩过的坑。当时发现异常账号后立刻改了密码,以为事情结束了。结果第二天又被登进来——原因是框架的会话是存在服务端或者 Cookie 里的,改密码不会让已有会话失效。正确的顺序是:先禁用账号或者清空会话存储,再改密码。有些框架的会话存在文件里,直接清空会话目录就能把所有人踢下线。

7.3 "上传目录禁止执行"不是每个环境都生效

这个配置在不同环境下的落地方式完全不一样。Nginx 用 location 匹配加deny,Apache 用.htaccess,还有一些环境是靠 PHP 层的open_basedir和函数禁用。最坑的情况是:.htaccess文件在 Nginx 环境下根本不生效,配置的人以为已经做好了,实际上一点作用都没有。

我的做法是配完之后一定要实测:往目标目录传一个测试用的脚本文件,然后从浏览器访问,看返回的是文件内容还是被拒绝。配置这件事,没验证过就等于没做。

7.4 插件升级会覆盖你的配置文件

FastAdmin 的插件升级机制会覆盖插件目录下的文件,如果你在那个目录里做过安全相关的修改(比如加了访问限制文件),升级之后可能就没了。所以安全配置尽量不要放在会被覆盖的目录里,要么放在 Web 服务器层面,要么放在框架的全局配置里。

还有一个相关的小细节:卸载插件的时候要注意,有些插件卸载不彻底,会留下目录和数据库表。这些残留的东西没人维护,反而成了隐患。

7.5 定期做一次"假设已被入侵"的演练

这是我最近两年养成的习惯,每季度抽半天时间,假设后台已经被拿下,然后按第 6 章的流程走一遍:拉时间线、扫异常文件、看日志、看外连。做下来你会发现两件事,一是能提前发现很多平时看不见的问题(比如某个目录权限莫名其妙是 777),二是真出事的时候不至于手忙脚乱。

我个人在实际操作中的体会是,后台安全这件事,八成的工作量都在"日常"里:账号有没有及时清理、权限有没有最小化、危险功能有没有关掉、目录权限有没有定期看。剩下两成的工作量在应急上。这两件事都不难,难的是有人真的去做,并且隔一段时间就回头看一眼。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询