| name | security |
| description | 自动检查常见安全漏洞和安全最佳实践 |
| allowed-tools | ["fs_read","bash_run"] |
| triggers | [{"type":"keyword","keywords":["安全","security","漏洞","vulnerability","攻击","认证","授权"]},{"type":"context","condition":"during /review"},{"type":"context","condition":"during /analyze"}] |
安全检查知识库
本技能提供常见安全漏洞的检测和防护建议,涵盖 OWASP Top 10 和其他常见安全问题。
OWASP Top 10 安全风险
1. 注入攻击 (Injection)
SQL 注入
最常见和危险的攻击方式之一。
query := "SELECT * FROM users WHERE username = '" + username + "'"
db.Query(query)
query := "SELECT * FROM users WHERE username = ?"
db.Query(query, username)
db.Where("username = ?", username).Find(&user)
命令注入
cmd := exec.Command("sh", "-c", "ls "+userInput)
cmd := exec.Command("ls", userInput)
if !isValidFilename(userInput) {
return errors.New("invalid filename")
}
cmd := exec.Command("ls", userInput)
NoSQL 注入
db.collection.find({ username: req.body.username })
if (typeof req.body.username !== 'string') {
return res.status(400).send('Invalid input')
}
db.collection.find({ username: req.body.username })
2. 失效的身份认证 (Broken Authentication)
密码安全
user.Password = password
hashedPassword := md5.Sum([]byte(password))
hashedPassword, err := bcrypt.GenerateFromPassword(
[]byte(password),
bcrypt.DefaultCost,
)
err := bcrypt.CompareHashAndPassword(
[]byte(user.HashedPassword),
[]byte(password),
)
会话管理
sessionID := fmt.Sprintf("%d", time.Now().Unix())
sessionID, err := generateSecureToken(32)
func generateSecureToken(length int) (string, error) {
bytes := make([]byte, length)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(bytes), nil
}
多因素认证
func Login(username, password, totpCode string) error {
user, err := authenticateUser(username, password)
if err != nil {
return err
}
if user.MFAEnabled {
if !verifyTOTP(user.MFASecret, totpCode) {
return errors.New("invalid MFA code")
}
}
return createSession(user)
}
3. 敏感数据泄露 (Sensitive Data Exposure)
加密存储
user.CreditCard = creditCardNumber
encryptedData, err := encrypt(creditCardNumber, encryptionKey)
user.EncryptedCreditCard = encryptedData
HTTPS/TLS
http.ListenAndServe(":8080", handler)
http.ListenAndServeTLS(":443", "cert.pem", "key.pem", handler)
func redirectToHTTPS(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://"+r.Host+r.URL.String(),
http.StatusMovedPermanently)
}
日志脱敏
log.Printf("User login: %s, password: %s", username, password)
log.Printf("User login: %s", username)
func maskCreditCard(cc string) string {
if len(cc) < 4 {
return "****"
}
return "************" + cc[len(cc)-4:]
}
4. XML 外部实体 (XXE)
decoder := xml.NewDecoder(input)
decoder.Decode(&data)
decoder := xml.NewDecoder(input)
decoder.Entity = xml.HTMLEntity
decoder.Strict = false
5. 失效的访问控制 (Broken Access Control)
权限检查
func DeleteUser(w http.ResponseWriter, r *http.Request) {
userID := r.URL.Query().Get("id")
db.Delete(&User{}, userID)
}
func DeleteUser(w http.ResponseWriter, r *http.Request) {
currentUser := getCurrentUser(r)
userID := r.URL.Query().Get("id")
if !currentUser.IsAdmin && currentUser.ID != userID {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
db.Delete(&User{}, userID)
}
对象级访问控制
func GetDocument(w http.ResponseWriter, r *http.Request) {
currentUser := getCurrentUser(r)
docID := r.URL.Query().Get("id")
var doc Document
if err := db.First(&doc, docID).Error; err != nil {
http.Error(w, "Not found", http.StatusNotFound)
return
}
if doc.OwnerID != currentUser.ID && !currentUser.IsAdmin {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
json.NewEncoder(w).Encode(doc)
}
6. 安全配置错误 (Security Misconfiguration)
环境变量
const APIKey = "sk-1234567890abcdef"
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("API_KEY not set")
}
错误信息
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
if err != nil {
log.Printf("Internal error: %v", err)
http.Error(w, "Internal server error",
http.StatusInternalServerError)
}
默认凭证
if password == "" {
password = "admin123"
}
if password == "" {
return errors.New("password required")
}
if !isStrongPassword(password) {
return errors.New("password too weak")
}
7. 跨站脚本 (XSS)
输出编码
fmt.Fprintf(w, "<div>%s</div>", userInput)
import "html"
fmt.Fprintf(w, "<div>%s</div>", html.EscapeString(userInput))
tmpl.Execute(w, data)
Content Security Policy
w.Header().Set("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'")
8. 不安全的反序列化 (Insecure Deserialization)
var data MyStruct
json.Unmarshal(untrustedInput, &data)
processData(data)
var data MyStruct
if err := json.Unmarshal(untrustedInput, &data); err != nil {
return fmt.Errorf("invalid input: %w", err)
}
if err := validateData(&data); err != nil {
return fmt.Errorf("validation failed: %w", err)
}
processData(data)
9. 使用已知漏洞的组件 (Using Components with Known Vulnerabilities)
依赖管理
go get -u ./...
go list -json -m all | nancy sleuth
最小化依赖
10. 不足的日志和监控 (Insufficient Logging & Monitoring)
安全事件日志
func Login(username, password string) error {
user, err := db.FindUser(username)
if err != nil {
securityLog.Warn("Login attempt for non-existent user",
"username", username,
"ip", getClientIP())
return err
}
if !verifyPassword(user, password) {
securityLog.Warn("Failed login attempt",
"username", username,
"user_id", user.ID,
"ip", getClientIP())
return errors.New("invalid credentials")
}
securityLog.Info("Successful login",
"username", username,
"user_id", user.ID,
"ip", getClientIP())
return nil
}
审计日志
func DeleteUser(userID string, operatorID string) error {
auditLog.Info("User deletion",
"user_id", userID,
"operator_id", operatorID,
"timestamp", time.Now(),
"action", "DELETE_USER")
return db.Delete(&User{}, userID)
}
其他常见安全问题
CSRF (跨站请求伪造)
func HandleForm(w http.ResponseWriter, r *http.Request) {
if !validateCSRFToken(r) {
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
return
}
}
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: sessionID,
SameSite: http.SameSiteStrictMode,
Secure: true,
HttpOnly: true,
})
目录遍历
filepath := "/var/www/" + userInput
filepath := filepath.Clean("/var/www/" + userInput)
if !strings.HasPrefix(filepath, "/var/www/") {
return errors.New("invalid path")
}
速率限制
limiter := rate.NewLimiter(rate.Limit(10), 100)
func HandleRequest(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Too many requests",
http.StatusTooManyRequests)
return
}
}
安全检查清单
输入验证
认证和授权
数据保护
注入防护
配置安全
监控和响应
安全问题报告模板
### 安全问题: [漏洞类型]
**严重程度**: 🔴 严重 / 🟡 重要 / 🟢 一般
**位置**: [文件名:行号]
**漏洞描述**: [详细说明安全问题]
**攻击场景**: [说明如何利用这个漏洞]
**影响**: [说明可能的后果]
**修复建议**:
[提供安全的代码示例]
**参考**: [OWASP 或其他安全标准链接]