按「打谁」分两类:主动攻击直接打服务器,攻击者能亲眼看到结果; 被动攻击把陷阱布在页面上,等别人的浏览器去执行。 XSS 属于后者,所以它的受害者是用户,不是服务器。
上一节说客户端不可信,这一节把攻击手法分成两类——分清楚这两类,才知道一个漏洞该由谁来修。
一、主动攻击:直接对服务器下手
攻击者自己构造请求,发给服务器,然后看返回什么。 整个过程他能看到结果,可以反复调整——就像在调试一个自己写的程序。 SQL 注入、OS 命令注入、目录遍历、DoS、暴力破解,全是这一类。 共同点是攻击者和目标之间是直接对话。 这类攻击有个明显的特征:服务器日志里会留下大量异常请求。 因为它必须一次又一次地试,才能从返回里读到自己想要的信息。
二、被动攻击:让别人的浏览器去执行
被动攻击里,攻击者不直接碰服务器。
他先把一段恶意内容留在服务器上(比如一条带脚本的评论),然后等别人打开那个页面。
脚本在那个人的浏览器里跑起来,用的是那个人的身份、那个人的 cookie。
攻击者要的是这个人的数据,不是服务器的。
XSS、CSRF、点击劫持都属于这一类。共同点是受害者是用户,服务器只是被当成了投递渠道。
Demo 里测了这一类最关键的一步:把 <script>alert(1)</script> 作为搜索词发过去,服务端原样回显,
整段 payload 完整地进了 HTML 正文。
三、两类攻击,两种修法
主动攻击的修法在服务端:参数化查询、路径校验、命令不用 shell 拼、限流限并发。
核心是不信任输入。
被动攻击的修法在「输出」那一头:转义、CSP、HttpOnly、X-Frame-Options、SameSite。
核心是不让用户输入变成代码。
搞混这两件事会修错地方。比如 XSS 有人去过滤输入(拦 <script>),那是治标——攻击者有的是别的写法。
正确的做法是在输出时按上下文转义,因为「这段数据要放在 HTML 的哪个位置」只有输出那一刻才知道。
四、动手 Demo:分类表加一次被动攻击的实测
先列一张「主动/被动 × 打谁」的表,再做一个最小的搜索引擎:把搜索词原样回显到页面上, 看 payload 是不是完整地进去了。
word = q.get(u'q', [u''])[0]
page = u'<html><body><p>你搜的是:%s</p></body></html>' % word
return 200, page # 原样回显,就是 XSS 的土壤
实跑输出:
--------------------------------------------------------------------
主动攻击与被动攻击:各打谁
--------------------------------------------------------------------
类型 打的是谁 典型手法
主动攻击 服务器 SQL 注入、OS 命令注入、DoS
主动攻击 服务器里的数据 目录遍历、越权读取
被动攻击 用户的浏览器 XSS、点击劫持、开放重定向
被动攻击 用户与站点之间的流量 窃听、篡改
主动攻击是攻击者直接对服务器发请求,他能看到结果。
被动攻击是攻击者先把陷阱布在页面上,等**别人**的浏览器去执行——他自己不用碰服务器。
搜索词 <script>alert(1)</script>
服务端回显的整段 73 字节
回显里含 <script> 有
回显的正文是:<html><body><p>你搜的是:<script>alert(1)</script></p></body></html>
本机没有浏览器,所以「脚本会不会执行」我测不到,也不编。
但**能测的是这一条**:payload 原封不动地进入了 HTML 正文。浏览器拿到这样一段 HTML,`<script>` 就是会执行——这是 HTML 的规矩,不是猜测。
分类表里主动攻击 2 行、被动攻击 2 行。
注意被动攻击那两行里,「打的是谁」写的是用户的浏览器和用户与站点之间的流量——不是服务器。
实测那一行:搜索词 <script>alert(1)</script>,服务端回显的整段 73 字节,
里面确实含 <script>。
本机没有浏览器,所以「脚本会不会执行」我测不到,也不编。
能测的是 payload 原封不动进了 HTML 正文——而浏览器遇到 <script> 就会执行,这是 HTML 的规矩。
所以被动攻击的关键一步是「让恶意数据变成页面上的标记」。下一节专门讲怎么在输出时拦住它。
30 秒实验
- 想一想:一条带脚本的评论,危害的是发评论的人,还是看评论的人?
- 把 payload 换成一个只改页面样式的(比如
<style>body{display:none}),想想能干什么。 - 判断一下:CSRF 属于主动还是被动?为什么?
常见误区
- 「XSS 是服务器被黑了」——服务器没事,受害的是访问页面的用户。
- 「过滤输入就能防住 XSS」——输入可能从数据库、从接口、从文件来,只有输出那一刻才知道它要去哪。
- 「主动攻击和被动攻击只是叫法不同」——受害者不同,修的地方也不同。
自测三问(点开对答案)
1. 主动攻击和被动攻击的核心区别是什么? —— 主动攻击者直接对服务器发请求并能看到结果;被动攻击靠别人的浏览器执行。 2. XSS 属于哪一类?受害者是谁? —— 被动攻击,受害者是访问页面的用户。 3. 为什么 XSS 应该在输出时转义,而不是在输入时过滤? —— 只有输出那一刻才知道这段数据要放进 HTML 的哪个位置,要转的字符不一样。数量最多的一类漏洞,就是「输出没转义」。第一个是 XSS。
- ☐ (本节完,下一节 11.2.1 跨站脚本攻击)