To gitea and beyond, let's go(-yco)

This commit is contained in:
2025-11-10 19:12:09 +01:00
parent 8f6133392d
commit 71a031342b
245 changed files with 83994 additions and 0 deletions

View File

@@ -0,0 +1,237 @@
package middleware
import (
"log"
"net/http"
"os"
"strings"
"time"
)
type SecurityLogger struct {
logger *log.Logger
}
func NewSecurityLogger() *SecurityLogger {
return &SecurityLogger{
logger: log.New(os.Stdout, "[SECURITY] ", log.LstdFlags|log.Lshortfile),
}
}
type SecurityEvent struct {
Type string
IP string
UserAgent string
Path string
Method string
UserID uint
Details string
Timestamp time.Time
Severity string
}
func (sl *SecurityLogger) LogSecurityEvent(event SecurityEvent) {
sl.logger.Printf("[%s] %s - %s %s %s - UserID: %d - %s - %s",
event.Severity,
event.IP,
event.Method,
event.Path,
event.UserAgent,
event.UserID,
event.Type,
event.Details,
)
}
func SecurityLoggingMiddleware(logger *SecurityLogger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
rw := &securityResponseWriter{ResponseWriter: w, statusCode: http.StatusOK}
next.ServeHTTP(rw, r)
userID := GetUserIDFromContext(r.Context())
ip := getClientIP(r)
event := SecurityEvent{
IP: ip,
UserAgent: r.UserAgent(),
Path: r.URL.Path,
Method: r.Method,
UserID: userID,
Timestamp: start,
}
switch {
case rw.statusCode >= 400 && rw.statusCode < 500:
event.Type = "Client Error"
event.Severity = "WARN"
event.Details = "Client error response"
case rw.statusCode >= 500:
event.Type = "Server Error"
event.Severity = "ERROR"
event.Details = "Server error response"
case strings.HasPrefix(r.URL.Path, "/api/auth/"):
event.Type = "Authentication"
event.Severity = "INFO"
event.Details = "Authentication endpoint accessed"
case strings.HasPrefix(r.URL.Path, "/api/posts/") && r.Method == "POST":
event.Type = "Post Creation"
event.Severity = "INFO"
event.Details = "Post creation attempt"
case strings.HasPrefix(r.URL.Path, "/api/posts/") && (r.Method == "PUT" || r.Method == "DELETE"):
event.Type = "Post Modification"
event.Severity = "INFO"
event.Details = "Post modification attempt"
default:
event.Type = "API Access"
event.Severity = "INFO"
event.Details = "API endpoint accessed"
}
logger.LogSecurityEvent(event)
})
}
}
func SuspiciousActivityMiddleware(logger *SecurityLogger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip := getClientIP(r)
userAgent := r.UserAgent()
suspicious := false
details := ""
if containsSQLInjection(r.URL.RawQuery) || containsSQLInjection(r.URL.Path) {
suspicious = true
details = "Potential SQL injection attempt"
}
if containsXSS(r.URL.RawQuery) || containsXSS(r.URL.Path) {
suspicious = true
details = "Potential XSS attempt"
}
if isSuspiciousUserAgent(userAgent) {
suspicious = true
details = "Suspicious user agent"
}
if isRapidRequest(ip) {
suspicious = true
details = "Rapid request pattern"
}
if suspicious {
event := SecurityEvent{
Type: "Suspicious Activity",
IP: ip,
UserAgent: userAgent,
Path: r.URL.Path,
Method: r.Method,
Details: details,
Timestamp: time.Now(),
Severity: "WARN",
}
logger.LogSecurityEvent(event)
}
next.ServeHTTP(w, r)
})
}
}
type securityResponseWriter struct {
http.ResponseWriter
statusCode int
}
func (rw *securityResponseWriter) WriteHeader(code int) {
rw.statusCode = code
rw.ResponseWriter.WriteHeader(code)
}
func getClientIP(r *http.Request) string {
return GetSecureClientIP(r)
}
func containsSQLInjection(input string) bool {
sqlPatterns := []string{
"' OR '1'='1",
"'; DROP TABLE",
"UNION SELECT",
"INSERT INTO",
"DELETE FROM",
"UPDATE SET",
}
input = strings.ToUpper(input)
for _, pattern := range sqlPatterns {
if strings.Contains(input, strings.ToUpper(pattern)) {
return true
}
}
return false
}
func containsXSS(input string) bool {
xssPatterns := []string{
"<script>",
"javascript:",
"onload=",
"onerror=",
"onclick=",
"<iframe>",
"<img src=",
}
input = strings.ToLower(input)
for _, pattern := range xssPatterns {
if strings.Contains(input, pattern) {
return true
}
}
return false
}
func isSuspiciousUserAgent(userAgent string) bool {
suspiciousPatterns := []string{
"sqlmap",
"nikto",
"nmap",
"masscan",
"zap",
"burp",
"w3af",
"havij",
"acunetix",
"nessus",
}
userAgent = strings.ToLower(userAgent)
for _, pattern := range suspiciousPatterns {
if strings.Contains(userAgent, pattern) {
return true
}
}
return false
}
var requestCounts = make(map[string]int)
var lastReset = time.Now()
func isRapidRequest(ip string) bool {
now := time.Now()
if now.Sub(lastReset) > time.Minute {
requestCounts = make(map[string]int)
lastReset = now
}
requestCounts[ip]++
return requestCounts[ip] > 100
}