Update Penggunaan Gorm
This commit is contained in:
172
internal/utils/validation/sanitizer.go
Normal file
172
internal/utils/validation/sanitizer.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"html"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// InputSanitizer provides comprehensive input sanitization
|
||||
type InputSanitizer struct {
|
||||
maxLength int
|
||||
}
|
||||
|
||||
// NewInputSanitizer creates a new input sanitizer
|
||||
func NewInputSanitizer(maxLength int) *InputSanitizer {
|
||||
return &InputSanitizer{maxLength: maxLength}
|
||||
}
|
||||
|
||||
// SanitizeString performs comprehensive sanitization on a string
|
||||
func (s *InputSanitizer) SanitizeString(input string) string {
|
||||
if input == "" {
|
||||
return input
|
||||
}
|
||||
|
||||
// Check length limit
|
||||
if utf8.RuneCountInString(input) > s.maxLength {
|
||||
input = string([]rune(input)[:s.maxLength])
|
||||
}
|
||||
|
||||
// Remove null bytes and control characters
|
||||
input = strings.Map(func(r rune) rune {
|
||||
if r < 32 && r != 9 && r != 10 && r != 13 { // Allow tab, LF, CR
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}, input)
|
||||
|
||||
// HTML escape to prevent XSS
|
||||
input = html.EscapeString(input)
|
||||
|
||||
// Remove potentially dangerous patterns
|
||||
dangerousPatterns := []string{
|
||||
`<script[^>]*>.*?</script>`,
|
||||
`<iframe[^>]*>.*?</iframe>`,
|
||||
`<object[^>]*>.*?</object>`,
|
||||
`<embed[^>]*>.*?</embed>`,
|
||||
`javascript:`,
|
||||
`vbscript:`,
|
||||
`data:`,
|
||||
`on\w+\s*=`,
|
||||
}
|
||||
|
||||
for _, pattern := range dangerousPatterns {
|
||||
re := regexp.MustCompile(`(?i)` + pattern)
|
||||
input = re.ReplaceAllString(input, "")
|
||||
}
|
||||
|
||||
// Trim whitespace
|
||||
return strings.TrimSpace(input)
|
||||
}
|
||||
|
||||
// SanitizeSQLInput sanitizes input specifically for SQL queries
|
||||
func (s *InputSanitizer) SanitizeSQLInput(input string) string {
|
||||
input = s.SanitizeString(input)
|
||||
|
||||
// Additional SQL-specific sanitization
|
||||
sqlPatterns := []string{
|
||||
`;`, `--`, `/*`, `*/`, `@@`, `@`,
|
||||
`xp_`, `sp_`, `exec`, `execute`,
|
||||
`information_schema`, `sysobjects`,
|
||||
`syscolumns`, `sysdatabases`,
|
||||
}
|
||||
|
||||
for _, pattern := range sqlPatterns {
|
||||
input = strings.ReplaceAll(input, pattern, "")
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
// ValidateSQLSafe checks if input is safe for SQL queries
|
||||
func (s *InputSanitizer) ValidateSQLSafe(input string) bool {
|
||||
if input == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for SQL injection patterns
|
||||
suspiciousPatterns := []string{
|
||||
"union select", "union all select",
|
||||
"select.*from", "insert.*into", "update.*set", "delete.*from",
|
||||
"drop table", "drop database", "alter table", "create table",
|
||||
"information_schema", "sysobjects", "syscolumns", "sysdatabases",
|
||||
"mysql.", "pg_", "sqlite_",
|
||||
";--", "/*", "*/", "@@",
|
||||
"script>", "<script",
|
||||
"javascript:", "vbscript:",
|
||||
"onload=", "onerror=", "eval(", "alert(",
|
||||
}
|
||||
|
||||
lowerInput := strings.ToLower(input)
|
||||
for _, pattern := range suspiciousPatterns {
|
||||
if strings.Contains(lowerInput, pattern) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// SanitizeJSON sanitizes JSON input
|
||||
func (s *InputSanitizer) SanitizeJSON(input string) string {
|
||||
input = s.SanitizeString(input)
|
||||
|
||||
// Remove JSON-specific dangerous patterns
|
||||
jsonPatterns := []string{
|
||||
`{"\w+":\s*"[^"]*javascript:[^"]*"}`,
|
||||
`{"\w+":\s*"[^"]*vbscript:[^"]*"}`,
|
||||
`{"\w+":\s*"[^"]*data:[^"]*"}`,
|
||||
}
|
||||
|
||||
for _, pattern := range jsonPatterns {
|
||||
re := regexp.MustCompile(`(?i)` + pattern)
|
||||
input = re.ReplaceAllString(input, "")
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
// SanitizeFilename sanitizes filename inputs
|
||||
func (s *InputSanitizer) SanitizeFilename(filename string) string {
|
||||
filename = s.SanitizeString(filename)
|
||||
|
||||
// Remove path traversal attempts
|
||||
filename = strings.ReplaceAll(filename, "../", "")
|
||||
filename = strings.ReplaceAll(filename, "..\\", "")
|
||||
|
||||
// Remove dangerous characters for filenames
|
||||
dangerousChars := []string{"/", "\\", ":", "*", "?", "\"", "<", ">", "|"}
|
||||
for _, char := range dangerousChars {
|
||||
filename = strings.ReplaceAll(filename, char, "")
|
||||
}
|
||||
|
||||
return filename
|
||||
}
|
||||
|
||||
// BatchSanitize sanitizes multiple inputs at once
|
||||
func (s *InputSanitizer) BatchSanitize(inputs map[string]string) map[string]string {
|
||||
sanitized := make(map[string]string)
|
||||
for key, value := range inputs {
|
||||
sanitized[key] = s.SanitizeString(value)
|
||||
}
|
||||
return sanitized
|
||||
}
|
||||
|
||||
// IsValidInputLength checks if input length is within acceptable limits
|
||||
func (s *InputSanitizer) IsValidInputLength(input string, minLen, maxLen int) bool {
|
||||
length := utf8.RuneCountInString(input)
|
||||
return length >= minLen && length <= maxLen
|
||||
}
|
||||
|
||||
// ContainsHTML checks if input contains HTML tags
|
||||
func (s *InputSanitizer) ContainsHTML(input string) bool {
|
||||
htmlRegex := regexp.MustCompile(`<[^>]+>`)
|
||||
return htmlRegex.MatchString(input)
|
||||
}
|
||||
|
||||
// StripHTML removes HTML tags from input
|
||||
func (s *InputSanitizer) StripHTML(input string) string {
|
||||
htmlRegex := regexp.MustCompile(`<[^>]+>`)
|
||||
return htmlRegex.ReplaceAllString(input, "")
|
||||
}
|
||||
Reference in New Issue
Block a user