sql_security.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package utils
  2. import (
  3. "regexp"
  4. "strings"
  5. )
  6. // SQLSecurityUtils SQL安全工具类
  7. type SQLSecurityUtils struct{}
  8. // 危险的SQL关键字
  9. var dangerousKeywords = []string{
  10. "select", "insert", "update", "delete", "drop", "create", "alter", "exec", "execute",
  11. "union", "script", "javascript", "vbscript", "onload", "onerror", "onclick",
  12. "--", "/*", "*/", ";", "'", "\"", "xp_", "sp_", "master", "truncate", "shutdown",
  13. }
  14. // 允许的排序字段字符(字母、数字、下划线、点号、反引号、空格、逗号、DESC、ASC)
  15. var orderByPattern = regexp.MustCompile(`^[a-zA-Z0-9_.,\x60\s]+(\s+(ASC|DESC))?(\s*,\s*[a-zA-Z0-9_.,\x60\s]+(\s+(ASC|DESC))?)*$`)
  16. // 允许的列名字符(字母、数字、下划线)
  17. var columnNamePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_]*$`)
  18. // 允许的表名字符(字母、数字、下划线)
  19. var tableNamePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_]*$`)
  20. // ValidateColumnName 验证列名是否安全
  21. func (s *SQLSecurityUtils) ValidateColumnName(columnName string) bool {
  22. if columnName == "" {
  23. return false
  24. }
  25. // 检查长度
  26. if len(columnName) > 64 {
  27. return false
  28. }
  29. // 检查是否匹配安全的列名模式
  30. return columnNamePattern.MatchString(columnName)
  31. }
  32. // ValidateTableName 验证表名是否安全
  33. func (s *SQLSecurityUtils) ValidateTableName(tableName string) bool {
  34. if tableName == "" {
  35. return false
  36. }
  37. // 检查长度
  38. if len(tableName) > 64 {
  39. return false
  40. }
  41. // 检查是否匹配安全的表名模式
  42. return tableNamePattern.MatchString(tableName)
  43. }
  44. // ValidateOrderBy 验证ORDER BY子句是否安全
  45. func (s *SQLSecurityUtils) ValidateOrderBy(orderBy string) bool {
  46. if orderBy == "" {
  47. return true // 空的ORDER BY是安全的
  48. }
  49. // 检查长度
  50. if len(orderBy) > 200 {
  51. return false
  52. }
  53. // 转换为大写进行检查
  54. upperOrderBy := strings.ToUpper(orderBy)
  55. // 检查是否包含危险关键字
  56. for _, keyword := range dangerousKeywords {
  57. if strings.Contains(upperOrderBy, strings.ToUpper(keyword)) {
  58. // 允许ASC和DESC关键字
  59. if keyword != "desc" && keyword != "asc" {
  60. return false
  61. }
  62. }
  63. }
  64. // 检查是否匹配安全的ORDER BY模式
  65. return orderByPattern.MatchString(orderBy)
  66. }
  67. // SanitizeString 清理字符串,移除潜在的SQL注入字符
  68. func (s *SQLSecurityUtils) SanitizeString(input string) string {
  69. if input == "" {
  70. return input
  71. }
  72. // 移除或转义危险字符
  73. input = strings.ReplaceAll(input, "'", "''") // 转义单引号
  74. input = strings.ReplaceAll(input, "\"", "\\\"") // 转义双引号
  75. input = strings.ReplaceAll(input, "\\", "\\\\") // 转义反斜杠
  76. input = strings.ReplaceAll(input, "\x00", "") // 移除NULL字符
  77. input = strings.ReplaceAll(input, "\n", " ") // 替换换行符
  78. input = strings.ReplaceAll(input, "\r", " ") // 替换回车符
  79. input = strings.ReplaceAll(input, "\t", " ") // 替换制表符
  80. return strings.TrimSpace(input)
  81. }
  82. // ValidateOperator 验证操作符是否在允许的列表中
  83. func (s *SQLSecurityUtils) ValidateOperator(operator string) bool {
  84. allowedOps := []string{"=", ">", "<", ">=", "<=", "like", "between", "in", "not in"}
  85. operator = strings.ToLower(strings.TrimSpace(operator))
  86. for _, allowedOp := range allowedOps {
  87. if operator == allowedOp {
  88. return true
  89. }
  90. }
  91. return false
  92. }
  93. // ValidateLimit 验证LIMIT值是否安全
  94. func (s *SQLSecurityUtils) ValidateLimit(limit int) bool {
  95. return limit > 0 && limit <= 10000 // 限制最大查询数量
  96. }
  97. // ValidateOffset 验证OFFSET值是否安全
  98. func (s *SQLSecurityUtils) ValidateOffset(offset int) bool {
  99. return offset >= 0 && offset <= 1000000 // 限制最大偏移量
  100. }
  101. // ContainsDangerousKeywords 检查输入是否包含危险的SQL关键字
  102. func (s *SQLSecurityUtils) ContainsDangerousKeywords(input string) bool {
  103. upperInput := strings.ToUpper(input)
  104. for _, keyword := range dangerousKeywords {
  105. if strings.Contains(upperInput, strings.ToUpper(keyword)) {
  106. return true
  107. }
  108. }
  109. return false
  110. }
  111. // 创建全局实例
  112. var SQLSecurity = &SQLSecurityUtils{}