13 KiB
13 KiB
安全性检查
本文档详细说明如何使用 AI 分析代码安全问题。
📋 概述
安全性检查是智能代码审查的关键维度,通过识别常见的安全漏洞和风险,帮助开发者提升代码安全性,防止潜在的安全攻击。
🎯 检查维度
1. SQL 注入(SQL Injection)
风险等级: 🔴 HIGH
描述: 攻击者通过恶意构造的输入篡改数据库查询逻辑。
检测模式:
- 字符串拼接 SQL 语句
- 直接使用用户输入构造查询
- 未使用参数化查询
示例:
// ❌ 存在 SQL 注入风险
query := "SELECT * FROM users WHERE username = '" + username + "'"
db.Query(query)
// ✅ 安全的参数化查询
query := "SELECT * FROM users WHERE username = ?"
db.Query(query, username)
修复建议:
- 使用参数化查询或 ORM
- 对用户输入进行验证和转义
- 使用最小权限的数据库账户
2. XSS 跨站脚本(Cross-Site Scripting)
风险等级: 🔴 HIGH
描述: 攻击者在网页中注入恶意脚本,窃取用户信息或进行攻击。
检测模式:
- 直接输出用户输入到 HTML
- 未对用户输入进行 HTML 转义
- 使用
innerHTML直接插入用户内容
示例:
// ❌ 存在 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, "'");
}
修复建议:
- 对用户输入进行 HTML 转义
- 使用
textContent而非innerHTML - 使用 CSP(Content Security Policy)
- 对输出进行白名单验证
3. 敏感信息泄露(Sensitive Data Exposure)
风险等级: 🔴 HIGH
描述: 代码中包含硬编码的密钥、密码、Token 等敏感信息。
检测模式:
- 硬编码的密码、密钥、Token
- 代码中包含 API 密钥
- 敏感配置信息
示例:
// ❌ 硬编码敏感信息
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")
修复建议:
- 使用环境变量存储敏感信息
- 使用配置管理工具(如 Vault)
- 不要在代码中硬编码密钥
- 使用
.env文件并加入.gitignore
4. 认证和授权问题(Authentication & Authorization)
风险等级: 🔴 HIGH
描述: 认证或授权机制存在缺陷,导致未授权访问。
检测模式:
- 缺少认证检查
- 权限验证不充分
- 会话管理不当
示例:
// ❌ 缺少权限检查
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)
}
修复建议:
- 每个敏感操作都要进行权限检查
- 使用最小权限原则
- 实施适当的会话管理
- 定期轮换密钥和证书
5. 输入验证(Input Validation)
风险等级: ⚠️ MEDIUM
描述: 对用户输入缺少充分的验证,可能导致各种安全问题。
检测模式:
- 缺少输入长度检查
- 缺少输入格式验证
- 缺少类型检查
示例:
// ❌ 缺少输入验证
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 });
}
修复建议:
- 验证输入长度、格式、类型
- 使用白名单而非黑名单
- 在客户端和服务端都进行验证
- 对不同来源的输入都要验证
6. 资源泄漏(Resource Leak)
风险等级: ⚠️ MEDIUM
描述: 资源(文件、连接、内存)未正确释放,可能导致 DoS。
检测模式:
- 文件打开后未关闭
- 数据库连接未关闭
- 网络连接未关闭
示例:
// ❌ 资源未关闭
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
}
修复建议:
- 使用
defer确保资源释放 - 使用
try-with-resources(Java) - 使用连接池管理数据库连接
- 定期检查和清理资源
7. 不安全的随机数(Insecure Randomness)
风险等级: ⚠️ MEDIUM
描述: 使用可预测的随机数生成器,可能被攻击者预测。
检测模式:
- 使用
Math.random()生成安全相关随机数 - 使用时间戳作为随机种子
- 使用线性同余生成器
示例:
// ❌ 不安全的随机数
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');
修复建议:
- 使用加密安全的随机数生成器
- 不要使用时间戳作为随机种子
- 对于密钥、Token 等安全相关数据,使用 CSPRNG
8. 不安全的反序列化(Insecure Deserialization)
风险等级: 🔴 HIGH
描述: 反序列化不受信任的数据可能导致远程代码执行。
检测模式:
- 反序列化用户输入
- 使用不安全的序列化格式
- 缺少完整性验证
示例:
// ❌ 不安全的反序列化
Object obj = deserializeObject(userInput);
// ✅ 安全的反序列化
// 1. 使用白名单限制可反序列化的类型
// 2. 验证数据的完整性
// 3. 使用安全的序列化格式(如 JSON)
修复建议:
- 避免反序列化不受信任的数据
- 使用白名单限制可反序列化的类型
- 使用安全的序列化格式(如 JSON)
- 验证数据的完整性和来源
🔧 分析流程
开始安全性分析
↓
1. 解析代码结构
├─ 识别数据库操作
├─ 识别用户输入处理
└─ 识别敏感信息
↓
2. 检测安全漏洞
├─ SQL 注入
├─ XSS 跨站脚本
├─ 敏感信息泄露
├─ 认证授权问题
├─ 输入验证
├─ 资源泄漏
├─ 不安全的随机数
└─ 不安全的反序列化
↓
3. 评估风险等级
├─ 根据漏洞类型评估
├─ 根据上下文评估
└─ 根据影响范围评估
↓
4. 生成安全报告
├─ 漏洞列表
├─ 风险等级
└─ 修复建议
↓
完成
📊 输出格式
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 格式
## 安全性分析: 70/100 ⚠️
### 🔴 高危漏洞(2)
#### 1. SQL 注入漏洞
- **文件**: `src/auth/login.go:45`
- **风险等级**: 🔴 HIGH
- **类别**: sql_injection
- **代码**:
```go
query := "SELECT * FROM users WHERE username = '" + username + "'"
- 描述: 直接拼接用户输入到 SQL 语句,存在 SQL 注入风险
- 影响: 攻击者可以通过构造恶意输入访问或篡改数据库
- 修复建议: 使用参数化查询或 ORM
- 参考:
2. 敏感信息泄露
- 文件:
config/database.go:10 - 风险等级: 🔴 HIGH
- 类别: sensitive_data
- 代码:
const DB_PASSWORD = "admin123" - 描述: 代码中硬编码数据库密码
- 影响: 敏感信息可能被泄露,导致数据库被攻击
- 修复建议: 使用环境变量或配置管理工具存储敏感信息
⚠️ 中危漏洞(3)
1. 输入验证缺失
- 文件:
src/api/user.go:78 - 风险等级: ⚠️ MEDIUM
- 修复建议: 添加用户名和密码的格式验证
📊 漏洞统计
- 总计: 5 个漏洞
- 🔴 高危: 2 个
- ⚠️ 中危: 3 个
- ℹ️ 低危: 0 个
📝 安全建议
- 立即修复:修复所有高危漏洞,特别是 SQL 注入和敏感信息泄露
- 加强验证:对所有用户输入进行严格的格式和长度验证
- 使用工具:集成静态安全分析工具(如 SonarQube、Snyk)
- 定期审计:定期进行安全代码审查
📚 参考资源
## 💡 最佳实践
### 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 攻击
// ✅ 使用 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. 保护敏感信息
// ✅ 使用环境变量
dbPassword := os.Getenv("DB_PASSWORD")
// ✅ 使用配置文件(加密)
config := loadConfig("config.enc")
// ✅ 使用密钥管理服务
secret := vault.GetSecret("database_password")
🔍 常见问题
Q: 如何确定漏洞的风险等级?
A: 综合考虑以下因素:
- 利用难度: 容易利用的漏洞风险更高
- 影响范围: 影响范围大的漏洞风险更高
- 数据敏感性: 涉及敏感数据的漏洞风险更高
- 业务影响: 对业务影响大的漏洞风险更高
Q: 如何处理误报?
A:
- 审查代码上下文,确认是否真的存在安全风险
- 如果是误报,添加注释说明为什么是安全的
- 可以配置白名单忽略特定规则
- 提供反馈改进安全检查规则
Q: 安全审查如何与 CI/CD 集成?
A:
- 在 CI 流程中添加安全扫描步骤
- 设置安全门禁(如不允许高危漏洞合并)
- 定期生成安全报告
- 集成 SAST 工具(如 SonarQube、Snyk)
📚 相关文档
- OWASP Top 10 - Web 应用安全风险
- 代码质量检查 - 代码质量分析
- 性能检查 - 性能分析
最后更新: 2026-06-12