forked from Gitlink/gitlink-cli
521 lines
13 KiB
Markdown
521 lines
13 KiB
Markdown
# 安全性检查
|
||
|
||
本文档详细说明如何使用 AI 分析代码安全问题。
|
||
|
||
## 📋 概述
|
||
|
||
安全性检查是智能代码审查的关键维度,通过识别常见的安全漏洞和风险,帮助开发者提升代码安全性,防止潜在的安全攻击。
|
||
|
||
## 🎯 检查维度
|
||
|
||
### 1. SQL 注入(SQL Injection)
|
||
|
||
**风险等级**: 🔴 HIGH
|
||
|
||
**描述**: 攻击者通过恶意构造的输入篡改数据库查询逻辑。
|
||
|
||
**检测模式**:
|
||
- 字符串拼接 SQL 语句
|
||
- 直接使用用户输入构造查询
|
||
- 未使用参数化查询
|
||
|
||
**示例**:
|
||
```go
|
||
// ❌ 存在 SQL 注入风险
|
||
query := "SELECT * FROM users WHERE username = '" + username + "'"
|
||
db.Query(query)
|
||
|
||
// ✅ 安全的参数化查询
|
||
query := "SELECT * FROM users WHERE username = ?"
|
||
db.Query(query, username)
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 使用参数化查询或 ORM
|
||
2. 对用户输入进行验证和转义
|
||
3. 使用最小权限的数据库账户
|
||
|
||
### 2. XSS 跨站脚本(Cross-Site Scripting)
|
||
|
||
**风险等级**: 🔴 HIGH
|
||
|
||
**描述**: 攻击者在网页中注入恶意脚本,窃取用户信息或进行攻击。
|
||
|
||
**检测模式**:
|
||
- 直接输出用户输入到 HTML
|
||
- 未对用户输入进行 HTML 转义
|
||
- 使用 `innerHTML` 直接插入用户内容
|
||
|
||
**示例**:
|
||
```javascript
|
||
// ❌ 存在 XSS 风险
|
||
div.innerHTML = userComment;
|
||
document.write(userName);
|
||
|
||
// ✅ 安全的 HTML 转义
|
||
div.textContent = userComment;
|
||
div.innerHTML = escapeHtml(userComment);
|
||
|
||
function escapeHtml(text) {
|
||
return text
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """)
|
||
.replace(/'/g, "'");
|
||
}
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 对用户输入进行 HTML 转义
|
||
2. 使用 `textContent` 而非 `innerHTML`
|
||
3. 使用 CSP(Content Security Policy)
|
||
4. 对输出进行白名单验证
|
||
|
||
### 3. 敏感信息泄露(Sensitive Data Exposure)
|
||
|
||
**风险等级**: 🔴 HIGH
|
||
|
||
**描述**: 代码中包含硬编码的密钥、密码、Token 等敏感信息。
|
||
|
||
**检测模式**:
|
||
- 硬编码的密码、密钥、Token
|
||
- 代码中包含 API 密钥
|
||
- 敏感配置信息
|
||
|
||
**示例**:
|
||
```go
|
||
// ❌ 硬编码敏感信息
|
||
const (
|
||
DB_PASSWORD = "admin123"
|
||
API_KEY = "sk-1234567890abcdef"
|
||
SECRET_KEY = "my-secret-key"
|
||
)
|
||
|
||
// ✅ 使用环境变量
|
||
dbPassword := os.Getenv("DB_PASSWORD")
|
||
apiKey := os.Getenv("API_KEY")
|
||
secretKey := os.Getenv("SECRET_KEY")
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 使用环境变量存储敏感信息
|
||
2. 使用配置管理工具(如 Vault)
|
||
3. 不要在代码中硬编码密钥
|
||
4. 使用 `.env` 文件并加入 `.gitignore`
|
||
|
||
### 4. 认证和授权问题(Authentication & Authorization)
|
||
|
||
**风险等级**: 🔴 HIGH
|
||
|
||
**描述**: 认证或授权机制存在缺陷,导致未授权访问。
|
||
|
||
**检测模式**:
|
||
- 缺少认证检查
|
||
- 权限验证不充分
|
||
- 会话管理不当
|
||
|
||
**示例**:
|
||
```go
|
||
// ❌ 缺少权限检查
|
||
func getUserProfile(userID int) (*User, error) {
|
||
return db.GetUser(userID)
|
||
}
|
||
|
||
// ✅ 添加权限检查
|
||
func getUserProfile(userID int, currentUser *User) (*User, error) {
|
||
// 检查是否有权限访问该用户信息
|
||
if currentUser.ID != userID && !currentUser.IsAdmin {
|
||
return nil, ErrPermissionDenied
|
||
}
|
||
return db.GetUser(userID)
|
||
}
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 每个敏感操作都要进行权限检查
|
||
2. 使用最小权限原则
|
||
3. 实施适当的会话管理
|
||
4. 定期轮换密钥和证书
|
||
|
||
### 5. 输入验证(Input Validation)
|
||
|
||
**风险等级**: ⚠️ MEDIUM
|
||
|
||
**描述**: 对用户输入缺少充分的验证,可能导致各种安全问题。
|
||
|
||
**检测模式**:
|
||
- 缺少输入长度检查
|
||
- 缺少输入格式验证
|
||
- 缺少类型检查
|
||
|
||
**示例**:
|
||
```javascript
|
||
// ❌ 缺少输入验证
|
||
function createUser(username, password) {
|
||
db.insert({ username, password });
|
||
}
|
||
|
||
// ✅ 添加输入验证
|
||
function createUser(username, password) {
|
||
if (!username || username.length < 3 || username.length > 20) {
|
||
throw new Error('用户名长度必须在 3-20 个字符之间');
|
||
}
|
||
|
||
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
|
||
throw new Error('用户名只能包含字母、数字和下划线');
|
||
}
|
||
|
||
if (!password || password.length < 8) {
|
||
throw new Error('密码长度至少为 8 个字符');
|
||
}
|
||
|
||
db.insert({ username, password });
|
||
}
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 验证输入长度、格式、类型
|
||
2. 使用白名单而非黑名单
|
||
3. 在客户端和服务端都进行验证
|
||
4. 对不同来源的输入都要验证
|
||
|
||
### 6. 资源泄漏(Resource Leak)
|
||
|
||
**风险等级**: ⚠️ MEDIUM
|
||
|
||
**描述**: 资源(文件、连接、内存)未正确释放,可能导致 DoS。
|
||
|
||
**检测模式**:
|
||
- 文件打开后未关闭
|
||
- 数据库连接未关闭
|
||
- 网络连接未关闭
|
||
|
||
**示例**:
|
||
```go
|
||
// ❌ 资源未关闭
|
||
func processData(filename string) error {
|
||
file, _ := os.Open(filename)
|
||
// 处理文件
|
||
// 忘记关闭文件
|
||
|
||
db, _ := sql.Open("mysql", dsn)
|
||
// 处理数据库
|
||
// 忘记关闭连接
|
||
}
|
||
|
||
// ✅ 使用 defer 确保资源关闭
|
||
func processData(filename string) error {
|
||
file, err := os.Open(filename)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer file.Close()
|
||
|
||
db, err := sql.Open("mysql", dsn)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer db.Close()
|
||
|
||
// 处理文件和数据库
|
||
return nil
|
||
}
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 使用 `defer` 确保资源释放
|
||
2. 使用 `try-with-resources`(Java)
|
||
3. 使用连接池管理数据库连接
|
||
4. 定期检查和清理资源
|
||
|
||
### 7. 不安全的随机数(Insecure Randomness)
|
||
|
||
**风险等级**: ⚠️ MEDIUM
|
||
|
||
**描述**: 使用可预测的随机数生成器,可能被攻击者预测。
|
||
|
||
**检测模式**:
|
||
- 使用 `Math.random()` 生成安全相关随机数
|
||
- 使用时间戳作为随机种子
|
||
- 使用线性同余生成器
|
||
|
||
**示例**:
|
||
```javascript
|
||
// ❌ 不安全的随机数
|
||
const token = Math.random().toString(36);
|
||
const seed = Date.now();
|
||
const random = srand(seed);
|
||
|
||
// ✅ 安全的随机数
|
||
const crypto = require('crypto');
|
||
const token = crypto.randomBytes(16).toString('hex');
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 使用加密安全的随机数生成器
|
||
2. 不要使用时间戳作为随机种子
|
||
3. 对于密钥、Token 等安全相关数据,使用 CSPRNG
|
||
|
||
### 8. 不安全的反序列化(Insecure Deserialization)
|
||
|
||
**风险等级**: 🔴 HIGH
|
||
|
||
**描述**: 反序列化不受信任的数据可能导致远程代码执行。
|
||
|
||
**检测模式**:
|
||
- 反序列化用户输入
|
||
- 使用不安全的序列化格式
|
||
- 缺少完整性验证
|
||
|
||
**示例**:
|
||
```java
|
||
// ❌ 不安全的反序列化
|
||
Object obj = deserializeObject(userInput);
|
||
|
||
// ✅ 安全的反序列化
|
||
// 1. 使用白名单限制可反序列化的类型
|
||
// 2. 验证数据的完整性
|
||
// 3. 使用安全的序列化格式(如 JSON)
|
||
```
|
||
|
||
**修复建议**:
|
||
1. 避免反序列化不受信任的数据
|
||
2. 使用白名单限制可反序列化的类型
|
||
3. 使用安全的序列化格式(如 JSON)
|
||
4. 验证数据的完整性和来源
|
||
|
||
## 🔧 分析流程
|
||
|
||
```
|
||
开始安全性分析
|
||
↓
|
||
1. 解析代码结构
|
||
├─ 识别数据库操作
|
||
├─ 识别用户输入处理
|
||
└─ 识别敏感信息
|
||
↓
|
||
2. 检测安全漏洞
|
||
├─ SQL 注入
|
||
├─ XSS 跨站脚本
|
||
├─ 敏感信息泄露
|
||
├─ 认证授权问题
|
||
├─ 输入验证
|
||
├─ 资源泄漏
|
||
├─ 不安全的随机数
|
||
└─ 不安全的反序列化
|
||
↓
|
||
3. 评估风险等级
|
||
├─ 根据漏洞类型评估
|
||
├─ 根据上下文评估
|
||
└─ 根据影响范围评估
|
||
↓
|
||
4. 生成安全报告
|
||
├─ 漏洞列表
|
||
├─ 风险等级
|
||
└─ 修复建议
|
||
↓
|
||
完成
|
||
```
|
||
|
||
## 📊 输出格式
|
||
|
||
### JSON 格式
|
||
|
||
```json
|
||
{
|
||
"security_analysis": {
|
||
"overall_score": 70,
|
||
"status": "NEEDS_REVIEW",
|
||
"vulnerabilities": [
|
||
{
|
||
"id": 1,
|
||
"severity": "HIGH",
|
||
"category": "sql_injection",
|
||
"title": "SQL 注入漏洞",
|
||
"file": "src/auth/login.go",
|
||
"line": 45,
|
||
"code_snippet": "query := \"SELECT * FROM users WHERE username = '\" + username + \"'\"",
|
||
"description": "直接拼接用户输入到 SQL 语句,存在 SQL 注入风险",
|
||
"impact": "攻击者可以通过构造恶意输入访问或篡改数据库",
|
||
"recommendation": "使用参数化查询或 ORM",
|
||
"references": [
|
||
"https://owasp.org/www-community/attacks/SQL_Injection",
|
||
"https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
|
||
]
|
||
},
|
||
{
|
||
"id": 2,
|
||
"severity": "HIGH",
|
||
"category": "sensitive_data",
|
||
"title": "敏感信息泄露",
|
||
"file": "config/database.go",
|
||
"line": 10,
|
||
"code_snippet": "const DB_PASSWORD = \"admin123\"",
|
||
"description": "代码中硬编码数据库密码",
|
||
"impact": "敏感信息可能被泄露,导致数据库被攻击",
|
||
"recommendation": "使用环境变量或配置管理工具存储敏感信息",
|
||
"references": [
|
||
"https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html"
|
||
]
|
||
}
|
||
],
|
||
"summary": {
|
||
"total": 5,
|
||
"critical": 0,
|
||
"high": 2,
|
||
"medium": 3,
|
||
"low": 0
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Markdown 格式
|
||
|
||
```markdown
|
||
## 安全性分析: 70/100 ⚠️
|
||
|
||
### 🔴 高危漏洞(2)
|
||
|
||
#### 1. SQL 注入漏洞
|
||
- **文件**: `src/auth/login.go:45`
|
||
- **风险等级**: 🔴 HIGH
|
||
- **类别**: sql_injection
|
||
- **代码**:
|
||
```go
|
||
query := "SELECT * FROM users WHERE username = '" + username + "'"
|
||
```
|
||
- **描述**: 直接拼接用户输入到 SQL 语句,存在 SQL 注入风险
|
||
- **影响**: 攻击者可以通过构造恶意输入访问或篡改数据库
|
||
- **修复建议**: 使用参数化查询或 ORM
|
||
- **参考**:
|
||
- [OWASP SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
|
||
- [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)
|
||
|
||
#### 2. 敏感信息泄露
|
||
- **文件**: `config/database.go:10`
|
||
- **风险等级**: 🔴 HIGH
|
||
- **类别**: sensitive_data
|
||
- **代码**:
|
||
```go
|
||
const DB_PASSWORD = "admin123"
|
||
```
|
||
- **描述**: 代码中硬编码数据库密码
|
||
- **影响**: 敏感信息可能被泄露,导致数据库被攻击
|
||
- **修复建议**: 使用环境变量或配置管理工具存储敏感信息
|
||
|
||
### ⚠️ 中危漏洞(3)
|
||
|
||
#### 1. 输入验证缺失
|
||
- **文件**: `src/api/user.go:78`
|
||
- **风险等级**: ⚠️ MEDIUM
|
||
- **修复建议**: 添加用户名和密码的格式验证
|
||
|
||
### 📊 漏洞统计
|
||
|
||
- 总计: 5 个漏洞
|
||
- 🔴 高危: 2 个
|
||
- ⚠️ 中危: 3 个
|
||
- ℹ️ 低危: 0 个
|
||
|
||
### 📝 安全建议
|
||
|
||
1. **立即修复**:修复所有高危漏洞,特别是 SQL 注入和敏感信息泄露
|
||
2. **加强验证**:对所有用户输入进行严格的格式和长度验证
|
||
3. **使用工具**:集成静态安全分析工具(如 SonarQube、Snyk)
|
||
4. **定期审计**:定期进行安全代码审查
|
||
|
||
### 📚 参考资源
|
||
|
||
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
|
||
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
|
||
- [CWE Top 25](https://cwe.mitre.org/top25/)
|
||
```
|
||
|
||
## 💡 最佳实践
|
||
|
||
### 1. 防御 SQL 注入
|
||
|
||
```go
|
||
// ✅ 使用参数化查询
|
||
stmt, err := db.Prepare("SELECT * FROM users WHERE username = ?")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer stmt.Close()
|
||
|
||
rows, err := stmt.Query(username)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer rows.Close()
|
||
|
||
// ✅ 使用 ORM
|
||
var user User
|
||
result := db.Where("username = ?", username).First(&user)
|
||
```
|
||
|
||
### 2. 防御 XSS 攻击
|
||
|
||
```javascript
|
||
// ✅ 使用 DOMPurify 库
|
||
import DOMPurify from 'dompurify';
|
||
|
||
const clean = DOMPurify.sanitize(userInput);
|
||
div.innerHTML = clean;
|
||
|
||
// ✅ 使用 CSP
|
||
// 在 HTML 头中添加 CSP
|
||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||
```
|
||
|
||
### 3. 保护敏感信息
|
||
|
||
```go
|
||
// ✅ 使用环境变量
|
||
dbPassword := os.Getenv("DB_PASSWORD")
|
||
|
||
// ✅ 使用配置文件(加密)
|
||
config := loadConfig("config.enc")
|
||
|
||
// ✅ 使用密钥管理服务
|
||
secret := vault.GetSecret("database_password")
|
||
```
|
||
|
||
## 🔍 常见问题
|
||
|
||
### Q: 如何确定漏洞的风险等级?
|
||
|
||
**A**: 综合考虑以下因素:
|
||
- **利用难度**: 容易利用的漏洞风险更高
|
||
- **影响范围**: 影响范围大的漏洞风险更高
|
||
- **数据敏感性**: 涉及敏感数据的漏洞风险更高
|
||
- **业务影响**: 对业务影响大的漏洞风险更高
|
||
|
||
### Q: 如何处理误报?
|
||
|
||
**A**:
|
||
1. 审查代码上下文,确认是否真的存在安全风险
|
||
2. 如果是误报,添加注释说明为什么是安全的
|
||
3. 可以配置白名单忽略特定规则
|
||
4. 提供反馈改进安全检查规则
|
||
|
||
### Q: 安全审查如何与 CI/CD 集成?
|
||
|
||
**A**:
|
||
1. 在 CI 流程中添加安全扫描步骤
|
||
2. 设置安全门禁(如不允许高危漏洞合并)
|
||
3. 定期生成安全报告
|
||
4. 集成 SAST 工具(如 SonarQube、Snyk)
|
||
|
||
## 📚 相关文档
|
||
|
||
- [OWASP Top 10](https://owasp.org/www-project-top-ten/) - Web 应用安全风险
|
||
- [代码质量检查](code-review-quality.md) - 代码质量分析
|
||
- [性能检查](code-review-performance.md) - 性能分析
|
||
|
||
---
|
||
|
||
*最后更新: 2026-06-12*
|