页面上只有三个链接的站点,扫八个路径,
/debug/exec 和 /.env 都回 200——页面上从没提过它们。
还有一种后门不占路径:guest / letmein 这个账号在用户表里根本不存在,却能登录。
后门最难的是发现,不是清除。
前面十几节都是「从外面打进来」。后门是「已经进来的人留下的门」,所以它属于事后,不属于攻防。
一、两种形态
路径型:多出来的接口、多出来的文件。
/debug/exec 无鉴权就能执行命令,/.env 里直接写着数据库口令,/backup.zip 是整个源码。
逻辑型:代码里写死的那一句 if pass == 'letmein': pass。
它不占路径、不占账号、不占端口,页面上一点痕迹都没有。
Demo 扫的八个路径里,带后门时有五个回 200,清掉后只剩三个——差出来的 ← 标出的两条就是后门:
/debug/exec 和 /.env。
逻辑型的实测更直白:guest / letmein 登录回 200,而这个账号在用户表里根本查不到。
二、为什么万能口令最难查
路径型的还能靠扫目录、比对文件清单发现——多出来的东西总会露头。 逻辑型藏在正常代码里,长得跟一段业务判断一模一样。 它也不触发任何告警:登录请求合法、密码对得上、权限正常。 从日志上看,它就是一次成功登录——日志恰恰是它最容易骗过的东西。 唯一可靠的发现方式是读代码加比对版本。 所以「谁能提交代码」这件事本身就是一条安全边界,比任何扫描工具都硬。 这也是为什么教材把它放在最后:前面十几节讲「怎么打」,这一节讲「打完之后」。 真实入侵里,门往往不是被撬开的,是有人配了一把钥匙。
三、三条防线
部署前比对文件哈希:产物清单之外的任何文件都是嫌疑。 这一条能挡住「多出来的文件」,成本只是流水线里多一步。 定期扫常见路径:Demo 就是这个做法——八个路径扫一遍,把「回 200 的」减去「页面上有链接的」, 剩下的就是嫌疑。 最根本的一条:不让任何人能随手往生产环境塞代码。 代码评审、发布走流水线、生产机上不给交互式 shell。 最后补一句:发现后门之后,光删掉不够。 要问「他是怎么进来的」——否则同一个口子还在,下一个人照样能再放一个。
四、动手 Demo:八个路径,两条回 200
造一个只有三个页面的小站点,先不加后门扫一遍这八个路径,再加两个「页面上没链接的接口」重扫一遍。 最后试一次万能口令。
PATHS = (u'/', u'/about', u'/login', u'/admin',
u'/debug/exec', u'/.env', u'/backup.zip', u'/robots.txt')
for p in PATHS:
st, hd, bd = H.recv_response(conn(), b'GET ' + p.encode()
+ b' HTTP/1.1\r\nHost: x\r\n')
print(u'%-14s %s' % (p, st))
实跑输出:
--------------------------------------------------------------------
后门程序:藏在路由表里的那一条
--------------------------------------------------------------------
假设你接手一个站点,页面上只有三个链接。先用一份路径清单扫一遍:
【带后门】
/ 200 首页
/about 200 关于
/login 200 登录
/admin 404 404
/debug/exec 200 命令执行接口(无鉴权) ←
/.env 200 数据库口令 ←
/backup.zip 404 404
/robots.txt 404 404
【清掉后门】
/ 200 首页
/about 200 关于
/login 200 登录
/admin 404 404
/debug/exec 404 404
/.env 404 404
/backup.zip 404 404
/robots.txt 404 404
第一段里 `←` 标出的两条:`/debug/exec` 和 `/.env` 页面上从没提过,
但它们回 200——这就是后门。`/.env` 里通常直接写着数据库口令。
后门还有另一种形式,不体现在路径上:
用 guest / letmein 登录 200 万能口令登录成功
而这个账号在用户表里 根本不存在
这叫「万能口令」:代码里写死了一句 `if pass == 'letmein': pass`。
它不占路径、不占账号,只看代码才能发现——所以后门最难的是**发现**,不是清除。
防御上能做三件事:部署前比对文件哈希(多出来的文件就是嫌疑)、
定期扫常见路径、以及最根本的一条——不让任何人能随手往生产环境塞代码。
第一段八个路径里五个回 200,第二段只剩三个。
差出来的两条正是 ← 标出的:/debug/exec(命令执行接口,无鉴权)和 /.env(数据库口令)。
判断哪条是后门不靠猜:回 200 的减去页面上有链接的,剩下的就是嫌疑。
这个减法比任何「可疑路径清单」都可靠,因为它不依赖你知道对方用了什么框架。
/.env 那一条特别典型:里面通常直接写着数据库地址和口令,拿到它就等于拿到数据,
根本不用再找注入点。
万能口令那两行:guest / letmein 回 200,账号表里没有这个人。
这一条只能靠读代码发现——日志上看,它就是一次普通登录。
Demo 没做的两件事我也说清楚:比对文件修改时间、比对部署产物的哈希清单。
这两件事在这台机器上做了也说明不了什么,所以我不编数字。
30 秒实验
- 拿一份常见路径清单扫你自己负责的站点(先确认你有授权)。
- 想一想:为什么「删掉后门」不等于「修好漏洞」?
- 在项目里搜一搜
if password ==,看有没有类似写法。
常见误区
- 「页面上没链接就访问不到」——11.3.1 已经证过,按路径请求照样通。
- 「删掉后门文件就没事了」——没弄清进来的路,口子还在。
- 「内网不用管后门」——横向移动靠的正是这些门。
自测三问(点开对答案)
1. 后门有哪两种形态? —— 路径型(多出来的接口或文件)和逻辑型(写死在代码里的判断)。 2. 怎么快速筛出路径型后门? —— 扫路径,把「回 200 的」减去「页面上有链接的」。 3. 为什么万能口令难发现? —— 不占路径、不占账号,日志上看就是一次成功登录。这一章的十七节手法讲完了,它们其实是同一个问题的不同面孔:程序相信了不该相信的输入, 或者少问了一句该问的话。防御也是同一句话——校验输入、转义输出、管好会话、别信「没人知道」。
- ☐ (全书完)