206 lines
4.5 KiB
Python
206 lines
4.5 KiB
Python
"""
|
||
XSS (跨站脚本) 漏洞知识
|
||
"""
|
||
|
||
from ..base import KnowledgeDocument, KnowledgeCategory
|
||
|
||
|
||
XSS_REFLECTED = KnowledgeDocument(
|
||
id="vuln_xss_reflected",
|
||
title="Reflected XSS",
|
||
category=KnowledgeCategory.VULNERABILITY,
|
||
tags=["xss", "reflected", "javascript", "html", "injection"],
|
||
severity="high",
|
||
cwe_ids=["CWE-79"],
|
||
owasp_ids=["A03:2021"],
|
||
content="""
|
||
反射型XSS:恶意脚本来自当前HTTP请求,服务器将用户输入直接反射到响应中。
|
||
|
||
## 危险模式
|
||
|
||
### Python/Flask
|
||
```python
|
||
# 危险 - 直接返回用户输入
|
||
@app.route('/search')
|
||
def search():
|
||
query = request.args.get('q')
|
||
return f"<h1>搜索结果: {query}</h1>"
|
||
|
||
# 危险 - 禁用自动转义
|
||
return render_template_string(user_input)
|
||
return Markup(user_input)
|
||
```
|
||
|
||
### JavaScript/Express
|
||
```javascript
|
||
// 危险
|
||
res.send(`<h1>Hello ${req.query.name}</h1>`);
|
||
res.write(req.body.content);
|
||
```
|
||
|
||
### PHP
|
||
```php
|
||
// 危险
|
||
echo "Hello " . $_GET['name'];
|
||
print($_POST['content']);
|
||
```
|
||
|
||
## 攻击载荷
|
||
```html
|
||
<script>alert('XSS')</script>
|
||
<img src=x onerror=alert('XSS')>
|
||
<svg onload=alert('XSS')>
|
||
javascript:alert('XSS')
|
||
<body onload=alert('XSS')>
|
||
```
|
||
|
||
## 安全实践
|
||
1. 输出编码/HTML转义
|
||
2. 使用模板引擎的自动转义
|
||
3. Content-Type设置正确
|
||
4. 使用CSP头
|
||
|
||
## 修复示例
|
||
```python
|
||
# 安全 - 使用escape
|
||
from markupsafe import escape
|
||
return f"<h1>搜索结果: {escape(query)}</h1>"
|
||
|
||
# 安全 - 使用模板(自动转义)
|
||
return render_template('search.html', query=query)
|
||
```
|
||
""",
|
||
)
|
||
|
||
|
||
XSS_STORED = KnowledgeDocument(
|
||
id="vuln_xss_stored",
|
||
title="Stored XSS",
|
||
category=KnowledgeCategory.VULNERABILITY,
|
||
tags=["xss", "stored", "persistent", "javascript", "database"],
|
||
severity="high",
|
||
cwe_ids=["CWE-79"],
|
||
owasp_ids=["A03:2021"],
|
||
content="""
|
||
存储型XSS:恶意脚本被存储在服务器(数据库、文件等),当其他用户访问时执行。
|
||
|
||
## 危险场景
|
||
- 用户评论/留言板
|
||
- 用户个人资料
|
||
- 论坛帖子
|
||
- 文件名/描述
|
||
- 日志查看器
|
||
|
||
## 危险模式
|
||
```python
|
||
# 危险 - 存储未过滤的用户输入
|
||
comment = request.form['comment']
|
||
db.save_comment(comment) # 存储
|
||
|
||
# 危险 - 显示未转义的内容
|
||
comments = db.get_comments()
|
||
return render_template_string(f"<div>{comments}</div>")
|
||
```
|
||
|
||
## 检测要点
|
||
1. 追踪用户输入到数据库的流程
|
||
2. 检查从数据库读取后的输出处理
|
||
3. 关注富文本编辑器的处理
|
||
4. 检查管理后台的数据展示
|
||
|
||
## 安全实践
|
||
1. 输入时过滤/存储时转义
|
||
2. 输出时始终转义
|
||
3. 使用白名单HTML标签(如需富文本)
|
||
4. 使用DOMPurify等库清理HTML
|
||
|
||
## 修复示例
|
||
```python
|
||
# 安全 - 使用bleach清理HTML
|
||
import bleach
|
||
clean_comment = bleach.clean(comment, tags=['p', 'b', 'i'])
|
||
db.save_comment(clean_comment)
|
||
```
|
||
""",
|
||
)
|
||
|
||
|
||
XSS_DOM = KnowledgeDocument(
|
||
id="vuln_xss_dom",
|
||
title="DOM-based XSS",
|
||
category=KnowledgeCategory.VULNERABILITY,
|
||
tags=["xss", "dom", "javascript", "client-side"],
|
||
severity="high",
|
||
cwe_ids=["CWE-79"],
|
||
owasp_ids=["A03:2021"],
|
||
content="""
|
||
DOM型XSS:漏洞存在于客户端JavaScript代码,通过修改DOM环境执行恶意脚本。
|
||
|
||
## 危险源 (Sources)
|
||
```javascript
|
||
// URL相关
|
||
location.href
|
||
location.search
|
||
location.hash
|
||
document.URL
|
||
document.referrer
|
||
|
||
// 存储相关
|
||
localStorage.getItem()
|
||
sessionStorage.getItem()
|
||
|
||
// 消息相关
|
||
window.postMessage
|
||
```
|
||
|
||
## 危险汇 (Sinks)
|
||
```javascript
|
||
// 危险 - HTML注入
|
||
element.innerHTML = userInput;
|
||
element.outerHTML = userInput;
|
||
document.write(userInput);
|
||
document.writeln(userInput);
|
||
|
||
// 危险 - JavaScript执行
|
||
eval(userInput);
|
||
setTimeout(userInput, 1000);
|
||
setInterval(userInput, 1000);
|
||
new Function(userInput);
|
||
|
||
// 危险 - URL跳转
|
||
location.href = userInput;
|
||
location.assign(userInput);
|
||
window.open(userInput);
|
||
```
|
||
|
||
## 危险模式
|
||
```javascript
|
||
// 危险 - 从URL获取并直接使用
|
||
const name = new URLSearchParams(location.search).get('name');
|
||
document.getElementById('greeting').innerHTML = 'Hello ' + name;
|
||
|
||
// 危险 - hash注入
|
||
const hash = location.hash.substring(1);
|
||
document.getElementById('content').innerHTML = decodeURIComponent(hash);
|
||
```
|
||
|
||
## 安全实践
|
||
1. 使用textContent代替innerHTML
|
||
2. 使用安全的DOM API
|
||
3. 对URL参数进行验证
|
||
4. 使用DOMPurify清理HTML
|
||
|
||
## 修复示例
|
||
```javascript
|
||
// 安全 - 使用textContent
|
||
element.textContent = userInput;
|
||
|
||
// 安全 - 使用DOMPurify
|
||
element.innerHTML = DOMPurify.sanitize(userInput);
|
||
|
||
// 安全 - 创建文本节点
|
||
element.appendChild(document.createTextNode(userInput));
|
||
```
|
||
""",
|
||
)
|