5.6 KiB
5.6 KiB
Network/Web Security Rules
Network and web security vulnerabilities can lead to data leakage and unauthorized access.
Rules:
- Redirects MUST be validated against an allowlist of domains.
- HTTP servers MUST configure
ReadTimeout,WriteTimeout, andIdleTimeout. - Pprof endpoints MUST NEVER be exposed publicly.
- XML parsers MUST disable XXE — reject
<!DOCTYPEand<!ENTITYdeclarations.
Open Redirect Vulnerability — Medium
Redirects to unvalidated URLs can be used for phishing.
Bad:
target := r.URL.Query().Get("url")
http.Redirect(w, r, target, http.StatusFound) // DON'T
Good:
target := r.URL.Query().Get("url")
u, _ := url.Parse(target)
// Only allow http/https
if u.Scheme != "http" && u.Scheme != "https" {
return errors.New("invalid scheme")
}
// Block javascript/data schemes
if strings.HasPrefix(target, "javascript:") || strings.HasPrefix(target, "data:") {
return errors.New("blocked scheme")
}
// Check against whitelist
if !isAllowedDomain(u.Host) {
return errors.New("invalid domain")
}
http.Redirect(w, r, target, http.StatusFound)
Bind to All Interfaces — Medium
Binding to 0.0.0.0 exposes services to all network interfaces.
Bad:
listener, _ := net.Listen("tcp", "0.0.0.0:8080") // DON'T: Exposes all interfaces
Good:
// Bind only to localhost
listener, _ := net.Listen("tcp", "127.0.0.1:8080")
// Or specific internal IP
listener, _ := net.Listen("tcp", "10.0.1.5:8080")
Slowloris Attack Vulnerability — Medium
Slowloris attacks exhaust connection pools.
Bad:
server := &http.Server{
Addr: ":8080",
// Missing ReadTimeout, WriteTimeout, IdleTimeout
}
Good:
server := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20, // Limit header size to 1MB
}
Insecure HTTP Server Configuration — Medium
Running HTTP servers without proper security settings.
Bad:
http.ListenAndServe(":8080", handler) // DON'T: No security hardening
Good:
server := &http.Server{
Addr: ":443",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20,
}
server.ListenAndServeTLS("cert.pem", "key.pem")
Observable Timing (Timing Attacks) — Medium
Timing differences can leak sensitive information.
Bad:
func checkPassword(input, secret string) bool {
return input == secret // DON'T: Short-circuit leaks length
}
Good:
import "crypto/subtle"
// For comparing fixed-length tokens or hashes:
func checkToken(input, expected string) bool {
// ConstantTimeCompare already handles unequal lengths without leaking timing
return subtle.ConstantTimeCompare([]byte(input), []byte(expected)) == 1
}
// For passwords, use Argon2id (preferred) or bcrypt — they handle hashing
// and constant-time comparison internally:
// argon2: hash := argon2.IDKey([]byte(password), salt, 3, 64*1024, 4, 32)
// bcrypt: err := bcrypt.CompareHashAndPassword([]byte(storedHash), []byte(password))
// For HMAC verification:
import "crypto/hmac"
func verifyHMAC(message, messageMAC, key []byte) bool {
mac := hmac.New(sha256.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
return hmac.Equal(messageMAC, expectedMAC) // Constant-time
}
Exposed pprof Profiling Endpoints — High
Debug pprof endpoints expose sensitive runtime information.
Bad:
import _ "net/http/pprof" // DON'T: Automatically registers /debug/pprof
http.ListenAndServe(":8080", handler)
Good:
// Option 1: Use build tags to exclude pprof from production builds
// File: debug_pprof.go
//go:build !production
package main
import _ "net/http/pprof"
// Option 2: Serve pprof on a separate internal-only listener
func startDebugServer() {
debugMux := http.NewServeMux()
debugMux.HandleFunc("/debug/pprof/", pprof.Index)
debugMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
debugMux.HandleFunc("/debug/pprof/profile", pprof.Profile)
debugMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
debugMux.HandleFunc("/debug/pprof/trace", pprof.Trace)
go http.ListenAndServe("127.0.0.1:6060", debugMux) // localhost only
}
XXE Vulnerability — High
XML parsers that process external entity references.
Bad:
decoder := xml.NewDecoder(bytes.NewReader(xmlData))
decoder.Decode(&person) // DON'T: May process external entities
Good:
decoder := xml.NewDecoder(bytes.NewReader(xmlData))
decoder.Strict = true
// Block DTD declarations
xmlStr := string(xmlData)
if strings.Contains(xmlStr, "<!DOCTYPE") || strings.Contains(xmlStr, "<!ENTITY") {
return errors.New("XML contains DTD - potential XXE")
}
decoder.Decode(&person)
Permissive Regex Validation — Low
Weak regex validation can allow malicious input.
Bad:
matched, _ := regexp.MatchString(`.+@.+\..+`, email) // DON'T: Too permissive
Good:
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
if !emailRegex.MatchString(email) {
return errors.New("invalid email")
}
// Also block injection patterns
CWE References
- CWE-601: Open Redirect
- CWE-208: Observable Timing Discrepancy
- CWE-611: Improper Restriction of XML External Entity Reference
- CWE-770: Allocation of Resources Without Limits
- CWE-20: Improper Input Validation
- CWE-200: Exposure of Sensitive Information