§ 8.3 · Section

Web 攻击:四板斧

SQL Injection · XSS · CSRF · SSRF

前两节把路修得固若金汤:数据装进了信封(加密),对面的身份也有了钢印(证书)。可如果你盯着战报看,会发现一件泄气的事——绝大多数成功的攻击,压根没碰这两道防线。加密和证书防的是"路上的贼",而本节的四板斧(SQL 注入、XSS、CSRF、SSRF)全都不在路上动手:它们钻的是网站自己代码的空子、浏览器合法机制的空子、甚至是你自己的手的空子这一节的中心思想只有一句:攻击的最高境界不是破墙,而是让系统自己开门——用合法的通道、拿着合法的证件、干非法的事。看懂这四板斧,你对"网络安全"的理解会从"防黑客"升级成"防自己家的规则被人玩坏"。

生活场景
📞 「我是官方客服,把验证码报给我」

你接过这种电话吧:对方一口报出你的姓名和订单尾号,说"我是平台官方的,系统检测到异常,请您把刚收到的六位验证码念一下"。每个环节都是"官方"的:电话能打通、短信是真的、验证码确实是你收到的——骗子没有攻破银行任何一堵墙,他只是把你变成了那堵墙上的门。

网络攻击的绝大多数,走的就是这条路:不撬锁、不翻墙、不破密码,而是利用系统里本来就合法的通道——输入框、评论区、自动登录的会员卡、服务器替你跑腿的功能——把恶意指令混进合法流程里。

本节四板斧,板板都是这个套路:SQL 注入混进"点菜单",XSS 混进"留言墙",CSRF 借用"你的会员卡",SSRF 指使"店里的跑腿员"。下面一个一个拆。

先把这一节的术语翻译成人话

照例,先上术语对照表。这四个攻击名全是英文缩写,听着唬人,其实每种都对应一个你天天见的生活机制。老规矩:读完正文回来再扫一遍,收获翻倍。

术语换成大白话生活里对应的东西
SQL 注入说白了就是"在点菜单的空白处夹带暗语,让后厨执行"点菜纸条上写「宫保鸡丁,顺便把收银机打开」
XSS(跨站脚本)说白了就是"往别人家的留言墙上贴会自己动手的小偷贴纸"商场留言墙里藏了张会偷你会员卡的贴纸
CSRF(跨站请求伪造)说白了就是"冒不出你本人,就借你自动出示的会员卡替你下单"熟客的会员卡被别人抢去刷了一单
SSRF(服务端请求伪造)说白了就是"骗店里的跑腿员,让他替你去敲后厨仓库的门"让快递代收员去撬隔壁办公室的门
注入(Injection)说白了就是"该当数据的东西被当成了指令来执行"——上头几种的总纲把"备注栏的文字"当成了"店员的操作指令"
Cookie / 会话说白了就是"网站发给你、浏览器替你自动出示的会员卡"健身房手环,进门自动刷
同源策略说白了就是"浏览器画的隔离带:A 店的页面不许翻 B 店的柜台"各家柜台之间的一米线
转义(Escape)说白了就是"把顾客递来的纸条裱进相框再挂墙——只许看,不许动"展柜里的留言:封塑处理,贴不上去
参数化查询说白了就是"后厨只认印刷的菜单模板,顾客的字只能填进空格"官方点菜单:菜名是印好的,你只能勾选
CSRF Token说白了就是"每张回执单上的一次性暗号,光有会员卡报不出暗号"取件必须同时出示短信取件码
CSP(内容安全策略)说白了就是"本店声明:只上自家厨房的菜,外卖一律不收"食堂只收本食堂饭卡
WAF(Web 应用防火墙)说白了就是"门口站了个安检员,进店的每句话先过他一遍"商场入口的安检门

一句话串起整节:四板斧同宗同源——全都在钻"数据与指令不分家"的空子;防法也同宗同源——把数据永远关在"只许被看、不许被执行"的笼子里。下面先搭舞台,再一板一板拆。

先认清舞台:浏览器是个过分听话的执行器

要看懂四板斧,得先接受一个设定:你打开的每一个网页,本质上是一段服务器发来的、让浏览器执行的程序。HTML 是骨架、CSS 是妆容、JavaScript 是动作——浏览器拿到这三样,忠实照办,一秒都不犹豫。这个"过分听话"是 Web 的立身之本(不然哪来的各种网页应用),但也意味着:谁能往网页里塞内容,谁就能在你的浏览器里执行代码。

浏览器自己也知道这个设定危险,所以出厂自带一条最重要的隔离带——同源策略:A 网站的页面,不许读 B 网站的数据、不许操作 B 网站的页面。好比商场里各家柜台之间的一米线:你可以站在任何柜台前,但不能伸手翻别人家的钱箱。这条线画在"域名"上——本节的主角 XSS,干的就是"绕过或滥用这条线"的种种戏法。

舞台的另一侧是服务器。网站后端每天最重要的工作之一,是把用户交上来的东西(注册的用户名、评论、搜索词、头像链接)存进数据库、再取出来贴回网页。注意这个循环:用户的输入,兜一圈后会变成"发给所有访客看的内容"。这个循环是整个 Web 的活力所在,也是四板斧里三板(注入、XSS、CSRF)的命门所在。记住这个循环,本节后面所有的攻击你都能一眼看穿:它们全是在这个循环的某个环节,把"应该被当成文字的东西"偷偷变成了"会被执行的指令"。

第一板斧 · SQL 注入:点菜单里夹暗语

先看历史最悠久、也最好懂的一板。网站的登录框,后端处理时其实是在数据库里查一句话,大意是:"找出用户名为『张三』、密码为『123456』的那一行。"很多新手程序的写法,是把用户敲进输入框的文字直接拼进这句话里——你输入什么,这句话里就嵌进什么。

机会来了。攻击者在用户名框里不填"张三",而是填一段精心设计的文字,比如 admin' --。拼进查询语句后,整句话的意思被硬生生扭成了:"找出用户名为 admin 的那一行——后面的密码检查,统统注释掉。"后厨照单执行,门开了。这还只是最入门的玩法:真正放飞起来,攻击者能通过输入框让数据库把整张用户表吐出来、把别的网站的订单拖走、甚至给自己开一个管理员账号。好比你在餐厅的点菜单"口味备注"栏写:「微辣,另外请把收银机打开让这位客人看看」——服务员如果一字不差地念给后厨听,后厨一听是店里的指令,照办了。备注是"数据",却被当成了"指令",这就是SQL 注入

有个流传很广的真事,可以感受这板斧的威力:某安全研究员给一家公司发"被攻击通知",故意在自己的姓氏一栏写了一段注入代码,公司员工照常把他的姓氏录入数据库、再在后台系统里显示出来——代码就在员工的屏幕上执行了,他借此证明"你们家的墙确实漏"。姓氏、地址、快递备注、搜索框——任何一处"会被拼进指令的文字",都是一扇可能被夹带暗语的窗。

SQL 注入的防法:菜单可以填空,不许作文

防注入的思路一句话讲透:让"指令"和"数据"永远不碰面。具体做法叫参数化查询:程序先给数据库递一张印好的菜单模板——「找出用户名为 ___、密码为 ___ 的行」,两个空格是专门的填空位;用户输入什么,一律塞进空格里,当纯文字对待。你填 admin' --?没关系,它就是一串六个字符的"用户名",数据库会老老实实去找有没有人叫这个名字——找不到,登录失败,天衣无缝。好比官方印刷的点菜单:菜名是印死的,你只能在"辣度""份量"的空格里填字;你写"打开收银机",服务员只会觉得这位客人的口味真奇怪。

配套的还有几条常识级的军规:给数据库账号最小权限(日常营业的账号根本不需要"删库"的权限——收银员不该有金库钥匙);错误信息别外泄(把数据库的报错原文显示给访客,等于把后厨平面图递给了踩点的人);重要的入口再加一道 WAF 安检门。注入是老攻击了,现代框架下默认写法就是安全的——但全世界跑着二十年前代码的老系统,仍是这板斧的粮仓。注入的病根和药方,其实是同一句话:数据就是数据,指令就是指令,谁也别冒充谁。

第二板斧 · XSS:留言墙上的小偷贴纸

第二板斧攻击的不是服务器,而是每一个访问这个网页的人,包括你。原理接着上一节的舞台设定讲:网页内容由服务器发来、浏览器忠实执行——那么,如果攻击者能让一段恶意代码混进某个正规网站的页面,这段代码就会在所有访客的浏览器里执行,还顶着这个正规网站的名分。这就是 XSS,跨站脚本。

混进去的通道常常就是评论区。假如网站的评论功能偷懒:用户提交什么,就原封不动地存库、再原封不动地贴到网页上。攻击者提交的"评论"就不是文字,而是一段脚本,比如「<script>把你的会员卡拍照发给我</script>」。下一位访客打开这篇帖子,浏览器收到这段内容,照例忠实执行——在受害者毫不知情的情况下,代码已经在他自己的浏览器里跑起来了:可以偷走他保存在浏览器里的登录凭证(Cookie),可以伪造他看到的页面(把收款账号偷偷改掉),可以记下他接下来的每次击键。好比商场的一面公共留言墙:有人递来一张"贴纸",管理员没检查就给贴上墙了——而这张贴纸会自己伸手,摸走每个驻足观看的顾客口袋里的会员卡。墙是商场的墙(正规网站),手是贴纸的手(攻击者的代码),丢卡的顾客只会怪商场。

XSS 的三种形态认个脸熟就够:存储型——恶意代码存进了数据库,每个来看的人都中招(留言墙贴纸,危害最大);反射型——代码藏在一条特制链接里,谁点谁中招(把贴纸直接塞到某个人手里,常配合钓鱼邮件);DOM 型——页面自己的脚本不规范,从网址参数里取内容直接上墙。名字不用背,共同点只有一条:恶意内容混进了页面,浏览器分不清"这是网站想让我执行的代码,还是某个用户递来的文字"。

XSS 的防法:裱起来,只许看

防 XSS 的主思路和防注入一脉相承——分不清,就别让它有被执行的机会。第一招:输出转义。网站把用户内容贴回页面前,先把其中所有"可能被当成代码的符号"统统翻译成"无害的纯文字":<script> 里的尖括号,会被换成另外两个普通字符,浏览器再看到它时,只会老老实实把它显示成一行字,而不是执行成一段代码。好比留言墙的规矩:所有递来的纸条一律封塑裱框再上墙——纸条上的字随便你写,但它从此只是"被观看的字",永远变不成"会动的手"。现代 Web 框架默认对所有输出做转义,开发者要专门费劲才能关掉它——默认安全的方向,才是好框架。

第二招:CSP 内容安全策略。网站郑重声明:"本页面的脚本,只许来自本站,别处的一律不许执行。"就算 XSS 漏了、恶意代码上了墙,浏览器一看它不是自家厨房出的菜,也拒绝上桌——好比食堂门口贴的告示"只收本食堂饭卡",外头的贴纸再花哨也刷不开闸门。第三招:重要 Cookie 加上 HttpOnly 标记——告诉浏览器"这张会员卡只许随请求自动出示,不许页面上的任何脚本读取"。就算脚本真在页面里跑起来了,也摸不到那张卡。三招各守一道,还是那四个字:纵深防御。XSS 防到最后,防的其实是"内容"和"代码"的边界——转义守住边界,CSP 兜底,HttpOnly 护住最后的会员卡。

第三板斧 · CSRF:借你的手刷你的卡

第三板斧最"优雅":攻击者写的代码一个字节都不进你的浏览器,也不进网站的页面——他只是让你自己的浏览器,替他发了一个请求。要理解它,得先感谢(或者说警惕)浏览器的一个贴心设计:每次你向某网站发请求,浏览器都会自动附上你在这个网站的身份凭证(Cookie)。这是"登录一次、处处通行"的来源——会员卡存在浏览器里,每次进店自动出示,你才不用每点一个页面都重新输密码。

但"自动出示"不挑场合。设想这个时间线:上午你登录了网银,会员卡留在了浏览器里;中午你点开一个陌生链接,那个页面上藏着一个看不见的表单,页面加载的瞬间自动向网银的转账接口提交了一次请求。你的浏览器发这个请求时,照例自动附上了你的会员卡——网银收到的请求手续齐全:本人卡片、本人地址,于是照办了。攻击者从头到尾没碰你的卡,是你自己的浏览器替他把卡刷了。这就是 CSRF,跨站请求伪造。好比你在健身房办了张"进门自动刷"的手环,某天有人举着你的手环照片在门口晃了一下闸机——闸机只认手环不认人,门开了。手环没丢、没复制、没破解,丢的是"刷卡"这个动作和"本人意愿"之间的绑定。

注意 CSRF 和 XSS 的分工差别:XSS 是"在别人家店里安插自己的人手",CSRF 是"不出人手,借对方本人的手";前者要找页面漏洞,后者只要你还登录着、又点了不该点的链接。所以 CSRF 的受害者画像特别日常:开着一堆标签页、随手点链接的每一个我们。

CSRF 的防法:卡之外,再加一道当次暗号

防 CSRF 的思路:既然"自动出示的卡"不可靠,那就让每个关键动作都额外要求一样"卡上没有、只有本人才拿得到"的东西。主流做法是 CSRF Token:网站发给你页面时,在表单里嵌一个一次性的随机暗号;提交转账这类关键请求时,光有 Cookie 不够,必须同时报出这个暗号。攻击者那个藏在你浏览器里的假表单,能借到你的卡,却拿不到"只有从正规页面里才发得出"的暗号——请求被拒。好比快递柜取件:光出示手机尾号不够,必须同时报出短信里的取件码——尾号人人可查,取件码只发本人。

第二道防线是 SameSite Cookie:给会员卡加一条使用规则——"这张卡,只许在从本站页面跳转过去的请求里出示"。你在网银页面里点的请求,卡正常附上;从陌生网站里发出的跨站请求,浏览器干脆不带卡——闸机前根本不刷你的手环,门自然开不了。如今主流浏览器已把这个属性默认打开,CSRF 的生存空间被压掉了一大半。CSRF 防的是"卡在、人不在":token 验的是暗号,SameSite 锁的是出示卡的场合——两道锁,锁的都是"这个请求真是你本人发起的吗"。

第四板斧 · SSRF:指使店里的跑腿员

第四板斧相对年轻,攻击对象也换了——不再是你的浏览器,而是服务器自己"替人跑腿"的功能。很多网站都有这类功能:"导入一个网址的图片""检测一个链接能不能访问""网页截图服务"。这些功能的本意,是服务器替用户去访问一个用户指定的地址。问题来了:服务器住在机房的内网里,它能看到的世界跟你的浏览器完全不同——你给的地址如果填的是"内网门牌"(那些只对内网开放、从外面根本访问不到的地址),服务器就会忠实地替你去敲内网的门,再把敲门的结果原样带回给你。

这就是 SSRF,服务端请求伪造:攻击者够不着内网,就骗一台住在内网里的服务器当自己的眼睛和手。最经典的猎物是云服务器上那个特殊的本机地址(云厂商用它提供内部配置信息,里面常藏着临时的密钥)——外网防火墙把守森严,可服务器自己访问它畅通无阻,攻击者借"帮我取个网址"的功能,让服务器把自家的钥匙串取出来递到了墙外。好比写字楼里"前台可代客收发快递"的服务:外面的人进不了办公区,但可以递一张单子给前台——单子上写的收件地址是「本公司档案室,取出客户名单寄到××地址」。前台是内部的人,各道门禁对他敞开;他只是照单办事,没意识到自己成了外人伸进楼里的那只手。

防 SSRF 的思路也就顺理成章:跑腿员出发前,先检查目的地。凡是用户指定的地址,一律先解析、再校验:内网地址段、本机地址、云内部地址——名单上的门,一个都不许替外人敲;跑腿回来的"战利品",也别原样递给用户(那可能正是内网的机密)。再加上前面提过的最小权限:跑腿用的账号本身就没有档案室的权限,单子写得再花哨也白搭。SSRF 的教训是条通用军规:凡是"服务器替用户去访问某地址"的功能,都要把用户当成最不怀好意的甲方来对待。

四板斧的总纲:数据冒充了指令

四板斧拆完,把它们放回一张桌上,你会发现攻击的"总纲"其实只有一句:在某个环节,本该被当成"数据"处理的东西,被系统当成"指令"执行了。SQL 注入是用户输入冒充了数据库指令;XSS 是用户内容冒充了页面脚本;CSRF 稍有不同——它冒充的是"你本人的意愿";SSRF 是用户填的地址冒充了"内网合法访客"。四板斧的四副药,其实也是一张方子:把数据的生命活动限制在"被存储、被展示、被比对"里,永远不给它"被执行"的机会。

板斧混入的通道冒充了什么核心防法生活原型
SQL 注入输入框、搜索框数据库指令参数化查询(填空不作文)点菜单夹暗语
XSS评论区、个人资料页面脚本输出转义 + CSP + HttpOnly留言墙小偷贴纸
CSRF陌生页面里的隐藏表单你本人的意愿CSRF Token + SameSite借你的手环刷闸机
SSRF"帮我取个网址"类功能内网合法访客目的地白名单 + 最小权限指使前台进档案室

把这张表裱起来:每一行你都能在生活中演一遍,每一个防法你都能说出"它挡的是哪一环"——这比背下四个英文缩写有用一百倍。

载入史册的四战:四板斧都真实干过票大的

四板斧不是教科书上的理论兵器,每一种都有写进安全史册的实战案例。四个案例一人认领一板,看完你会对本节的"总纲"有更冷的敬意。

四个战例放在一起看规律更清楚:攻击者用的全是"合法通道",破的全是"默认设置"——所以现代安全的每次升级,几乎都是把某个"默认相信"改成"默认验证"。

一次完整的围剿:现代网站的三道防线

讲完四板斧的"个防",再看现代网站怎么把它们挡在门外——注意,成熟的做法从来不是指望某一道神墙,而是层层设防、层层兜底,行话叫纵深防御:

三道防线的哲学:不赌任何一堵墙永远不倒,而是让"攻破所有墙"的成本,远远高于墙里东西的价值。

作为普通用户,你能做的三件事

四板斧的防守主力当然是网站自己,但站在用户位上,有三件事真实有效——它们恰好对应四板斧里的三个"借刀"套路:

三件事的共同点:都不需要你懂技术,只需要你承认一个事实——系统防的是"技术上的贼",而很多贼是踩着用户的配合进门的。

常见误区:三条最容易念歪的经

Analogy · 一家餐厅的攻防日:把本节所有概念装进一个画面

如果你只记住这一节的一个画面,请记住这家餐厅的一天:一家新开业的网红店,装修气派、门口还请了保安(HTTPS 加密 + 证书)——保安确实尽责,所有进门的人都验过证件。可这一天的四起案件,没有一起发生在门外。

① 上午,点菜单被夹了暗语(SQL 注入)。一位客人把"口味备注"栏写得极长,末尾缀了一句「另外请把会员数据库打印一份给我」。新来的服务员一字不差念给了后厨——后厨以为这是店长的指令,照办了。整改:全部换成印刷的官方菜单(参数化查询),备注只能在指定空格里填字,服务员不再"念单"而是"递单"。

② 中午,留言墙被贴了小偷贴纸(XSS)。有人递来一张"感谢信",管理员直接贴上了墙——贴纸上藏着一双小手,悄悄摸走了每个驻足观看的顾客口袋里的会员卡(Cookie),还顺手偷记了几位顾客接下来聊的银行卡号。整改:所有递来的纸条一律封塑裱框(输出转义)——只许被看,永远不能动;墙上加挂"本墙贴纸只收本店印刷品"的告示(CSP);会员卡换成"仅限本人柜台出示、贴纸摸不到"的新卡(HttpOnly)。

③ 下午,熟客的手环被借去刷了闸机(CSRF)。一位阿姨在店里办过"进门自动刷"的手环,回家路上接了张传单,传单背面的小字是张代客下单的单子——店里的闸机只认手环不认人,阿姨的手环被传单"代刷"了一单大额外卖。整改:贵重菜品一律"手环 + 短信取件码"双验(CSRF Token),并给手环加了新规矩:只在本人到店的场合才生效(SameSite)。

④ 傍晚,前台被指使进了档案室(SSRF)。店外的人进不来后厨,但前台提供"代客取件"服务——有人递来一张取件单,地址写的却是「本店档案室:客户名单一份,寄往墙外」。前台有内部门禁,畅通无阻地把档案取出来递了出去。整改:代客取件的目的地加了白名单(档案室之类的内部门牌一概不送),跑腿权限也降到"只能取快递不能进档案"。

⑤ 打烊复盘:老板明白了两件事——保安拦不住店里自己人被当枪使;真正的安全是"菜单不许作文、纸条必须裱框、刷卡认人不认卡、跑腿不进内门"这四条家规的层层叠加。注入是夹带暗语的备注、XSS 是裱不进框的贴纸、CSRF 是被借刷的手环、SSRF 是被指使的前台——四起案件一个病根:把"别人的字"当成了"自己的指令"。

一句话送给你:本节的三个心法

收束全节,带走三句话。第一,攻击走的是正门:四板斧没有一板在撬锁——它们混进输入框、藏进链接、借你的卡、指使你的服务器,全程手续合法。第二,病根只有一个:数据冒充指令。所以防法也只有一张方子:转义、参数化、白名单、最小权限——全是"把数据关进笼子"的不同说法。第三,纵深防御是唯一的信仰:框架默认、门面安检、失守止损,三道防线谁也不指望谁,谁也兜得住谁。带着这三句话往下走:下一节换一种完全不同的攻击——不偷不骗不夹带,就是喊一帮人把你家门口堵死。DDoS,纯力气的暴力。

Recap · 收束

一句话总结:Web 四板斧不破墙、不撬锁,专钻"数据与指令不分家"的空子——注入混进点菜单、XSS 贴上留言墙、CSRF 借你的手刷你的卡、SSRF 指使服务器跑腿进内网;四板斧一张药方:数据永远只许被看、被存、被比对,永远不许被执行。

机制上记住五件事
· SQL 注入:输入被拼进查询语句——防法是参数化查询:菜单印死,顾客只能填空。
· XSS:恶意脚本混进正规页面、在访客浏览器执行——防法是输出转义(裱框只许看)+ CSP(只上自家菜)+ HttpOnly(卡摸不走)。
· CSRF:浏览器自动带 Cookie 的特性被借用,"卡在、人不在"——防法是一次性 CSRF Token(卡+取件码)与 SameSite(只在本人场合出示)。
· SSRF:服务器"替用户访问网址"的功能被骗去敲内网的门——防法是目的地白名单与最小权限。
· 纵深防御:框架默认抬地板、WAF 拦大网、失守后靠最小权限止损——不赌单点,层层兜底。

下一步:四板斧讲的是"巧劲",下一节讲"蛮力"——不偷密码、不夹暗语,就是组织百万台肉鸡同时朝你发请求,把你家门口彻底堵死,再好的锁也架不住门被堵死。§ 8.4 DDoS 与防护,看一场"人海战术"的攻防。

☰ 主页
Xue Hai Wu Ya · Network · § 8.3 · Web 攻击四板斧