1、XSS 攻击
| 类型 | 攻击特征 | 典型案例 |
|---|---|---|
| 反射型 XSS | 恶意脚本通过 URL 参数注入,受害者点击链接触发(如钓鱼邮件中的“官方链接”) | 攻击者伪造 https://example.com?q=<script>stealCookie()</script> 诱导点击,窃取会话 Cookie |
| 存储型 XSS | 恶意脚本存入数据库(如评论、私信),所有访问页面的用户自动执行脚本 | 某论坛评论区注入 <script>sendDataToAttacker()</script>,用户浏览时隐私数据被窃取 |
| DOM型 XSS | 前端 JavaScript 动态操作 DOM 时未过滤输入,无需服务端参与 | 单页应用(SPA)解析 location.hash 时直接插入页面:eval(decodeURIComponent(location.hash.slice(1))) |
反射型 XSS
- 用户点击伪造链接访问被攻击的网站,并且伪造链接的恶意脚本会被被攻击网站获取并且执行。
- 例如访问:
http://localhost:3000?q=alert(document.cookie)。 - 在代码中执行
eval(location.search.slice(3))。
存储型 XSS
- 攻击者在博客中写入脚本并存入数据库。
- 被攻击者访问博客时在本地执行攻击脚本导致个人信息泄露或者数据被篡改。
DOM型 XSS
- 用户点击伪造链接访问被攻击的网站,并且伪造链接的恶意脚本会被被攻击网站获取并且执行。
- 例如访问:
http://localhost:3000?q=<img src="/" onerror="alert('hello world!')" />。 - 在代码中执行
dom.innerHTML = decodeURI(location.search.slice(3))。
防范方式
- 输入校验
- 输出转码
- Cookie保护 设置
HttpOnly属性阻止JS读取 - 启用
Content-Security-Policy: script-src 'self'限制脚本源 - 审计 UGC 内容与安全策略
2、CSRF 攻击
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种利用用户已登录状态伪造请求的Web攻击手段,攻击者诱导用户访问恶意页面或点击链接,以受害者身份执行非授权操作。 CSRF本质是滥用浏览器的自动凭证发送机制,防御需结合服务端Token验证、Cookie策略及操作流程设计,形成多层次防护。 其核心原理、流程及防御如下:
攻击流程
- 利用用户已登录的身份凭证
- 伪造请求
- 诱导触发
- 服务器响应
防御措施
- CSRF Token验证
- SameSite Cookie属性
- Referer校验
- 敏感操作二次验证
- 避免GET敏感操作
与xss的区别
csrf是依赖服务端对客户端的信任,通过伪造请求去篡改数据,无法直接获取用户信息,防护重心在于服务端验证; xss是依赖用户对网站的信任,通过注入脚本的方式获取用户的信息,防护重心在于输入输出的验证
知识巩固
浏览器的自动凭证发送机制
- 服务器通过
Set-Cookie响应头下发凭证(如会话ID、Token),浏览器按域名、路径等属性存储该凭证 - 浏览器发起同源请求时,自动匹配并附加存储的凭证至
Cookie请求头,无需用户手动干预 - 安全特性《HttpOnly》,禁止JavaScript访问Cookie,防XSS窃取会
- 安全特性《Secure》,仅通过HTTPS传输凭证,防中间人劫持
- 安全特性《同源策略》仅同域名请求自动携带凭证(部分浏览器限制跨域)
3、中间人攻击
中间人攻击(Man-in-the-Middle Attack,简称 MITM 攻击)是一种网络攻击方式,攻击者通过技术手段将自己插入通信双方之间,在受害者毫无察觉的情况下拦截、窃取或篡改传输数据,进而实施信息窃取、身份冒充或欺诈行为。以下是其核心要点:
攻击方式
- ARP欺骗:篡改局域网内设备的MAC地址映射,将流量导向攻击者设备
- DNS欺骗:伪造DNS响应,将用户访问的域名解析到恶意IP地址
- SSL剥离:强制将HTTPS连接降级为HTTP,使加密数据变为明文传输
- 伪造Wi-Fi热点:在公共场所架设名称相似的恶意热点,诱骗用户连接以监控流量
- Browser in the Browser(新型钓鱼) :利用浏览器全屏API(如Fullscreen API)伪造全屏登录弹窗(如模仿Steam邮箱登录界面),隐藏真实网址栏,诱导用户输入账号密码
防御措施
- 网站启用HTTPS(HSTS防止SSL剥离),应用程序使用TLS/SSL协议加密传输
- 关键账户开启双因素认证(2FA)
- 部署公钥基础设施(PKI) ,验证数字证书合法性
- 避免连接公共Wi-Fi,使用VPN加密流量
- 定期清除ARP缓存,启用动态ARP检测(DAI)
知识巩固
什么是ARP?
ARP 是 TCP/IP 协议栈中网络层与数据链路层之间的桥梁,负责将目标设备的 IP 地址解析为 MAC 地址,实现数据链路层的物理寻址,数据帧传输需依赖 MAC 地址,但网络层仅知 IP 地址,ARP 解决了两者之间的映射问题。
工作原理如下
1. 主机A检查本地ARP缓存表 → 若无B的IP-MAC映射
2. 主机A广播ARP请求(目标MAC=FF:FF:FF:FF:FF:FF)
3. 主机B单播响应自身MAC地址
4. 主机A更新ARP缓存表,后续通信直接封装目标MAC
4、点击劫持
点击劫持是一种视觉欺骗的攻击手段。攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击。
防御措施
1、X-FRAME-OPTIONS
- DENY,表示页面不允许通过 iframe 的方式展示
- SAMEORIGIN,表示页面可以在相同域名下通过 iframe 的方式展示
- ALLOW-FROM,表示页面可以在指定来源的 iframe 中展示
2、JavaScript 防御
<style id="click-jack"> html { display: none !important; } </style>
<script>
if (self == top) {
var style = document.getElementById('click-jack')
document.body.removeChild(style)
} else {
top.location = self.location
}
</script>
5、URL跳转漏洞
借助未验证的URL跳转,将应用程序引导到不安全的第三方区域,从而导致的安全问题。
http://gate.baidu.com/index?act=go&url=http://t.cn/RVTatrd
http://qt.qq.com/safecheck.html?flag=1&url=http://t.cn/RVTatrd
http://tieba.baidu.com/f/user/passport?jumpUrl=http://t.cn/RVTatrd
攻击方式
伪造自动跳转链接,将用户跳转到攻击网站,然后在攻击网站内部伪造登录页面去窃取用户信息。
常见触发点
- 用户登录/注销后的跳转逻辑
- 跨站点认证授权回调(如OAuth)
- 内容分享、收藏后的跳转链接
- 注册/密码修改完成页的自动跳转
防御措施
- 白名单机制 严格限制自动跳转链接的域名
- 签名验证 对跳转的链接增加验证机制
- 前端提示 离开本站给用户提醒
- 禁用用户可控跳转 禁止跳转到完整的链接地址,只允许相对地址站内跳转
- 纵深防御 后端日志记录所有跳转请求,便于溯源攻击行为
6、SQL注入
攻击流程
- 获取用户请求参数
- 拼接到代码当中
- SQL语句按照我们构造参数的语义执行成功
// 预期用户输入 admin password 进行查询
SELECT * FROM user WHERE username='admin' AND psw='password'
// 如果用户输入 `admin' --`,则导致拼接的查询语句为如下,由于--表示注释,所以在没有进行验证的情况下就能查询所有数据导致数据泄漏,这就是SQL注入
SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'
预防措施
- 严格校验用户输入
- 避免拼接sql语句
- 降低用户查询sql语句的权限
7、OS命令注入攻击
OS命令注入和SQL注入差不多,只不过SQL注入是针对数据库的,而OS命令注入是针对操作系统的。OS命令注入攻击指通过Web应用,执行非法的操作系统命令达到攻击的目的。只要在能调用Shell函数的地方就有存在被攻击的风险。倘若调用Shell时存在疏漏,就可以执行插入的非法命令。
攻击流程
命令注入攻击可以向Shell发送命令,让Windows或Linux操作系统的命令行启动程序。也就是说,通过命令注入攻击可执行操作系统上安装着的各种程序。
我们通过一个例子来说明其原理,假如需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去返回一个结果给用户
// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* 用户输入的参数 */};
exec(`git clone ${params.repo} /some/path`);
如果 params.repo 传入的是 https://github.com/admin/admin.github.io.git 确实能从指定的 git repo 上下载到想要的代码。 但是如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf /* && 恰好你的服务是用 root 权限起的就糟糕了。
预防措施
- 用户输入校验
- 用户数据转码,用转译处理工具:shell-escape
- 避免拼接系统命令