Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This resolves the issue where the allow-legit-browsers rule was incor… #27

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion caddywaf.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,15 @@ func (m *Middleware) handleMetricsRequest(w http.ResponseWriter, r *http.Request
m.logger.Debug("Handling metrics request", zap.String("path", r.URL.Path))
w.Header().Set("Content-Type", "application/json")

// Collect rule hits using getRuleHitStats
ruleHits := m.getRuleHitStats()

// Collect all metrics
metrics := map[string]interface{}{
"total_requests": m.totalRequests,
"blocked_requests": m.blockedRequests,
"allowed_requests": m.allowedRequests,
"rule_hits": m.getRuleHitStats(),
"rule_hits": ruleHits,
"rule_hits_by_phase": m.ruleHitsByPhase,
"geoip_stats": m.geoIPStats,
}
Expand Down
54 changes: 18 additions & 36 deletions rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,13 @@ import (
"os"
"regexp"
"strings"
"time"

"github.com/google/uuid"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// processRuleMatch handles the logic when a rule is matched.
func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, rule *Rule, value string, state *WAFState) {
// Default action to "block" if empty
if rule.Action == "" {
rule.Action = "block"
m.logger.Debug("Rule action is empty, defaulting to 'block'", zap.String("rule_id", rule.ID))
}

// Extract log ID from request context
logID, _ := r.Context().Value("logID").(string)
Expand All @@ -41,9 +34,18 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru

// Increment rule hit counter
if count, ok := m.ruleHits.Load(rule.ID); ok {
m.ruleHits.Store(rule.ID, count.(int)+1)
newCount := count.(int) + 1
m.ruleHits.Store(rule.ID, newCount)
m.logger.Debug("Incremented rule hit count",
zap.String("rule_id", rule.ID),
zap.Int("new_count", newCount),
)
} else {
m.ruleHits.Store(rule.ID, 1)
m.logger.Debug("Initialized rule hit count",
zap.String("rule_id", rule.ID),
zap.Int("new_count", 1),
)
}

// Increase the total anomaly score
Expand All @@ -58,29 +60,6 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru
zap.Int("anomaly_threshold", m.AnomalyThreshold),
)

// Capture detailed request and rule information for comprehensive logging
requestInfo := []zap.Field{
zap.String("log_id", logID),
zap.String("rule_id", rule.ID),
zap.String("target", strings.Join(rule.Targets, ",")),
zap.String("value", value), // Be cautious with logging sensitive data
zap.String("description", rule.Description),
zap.Int("score", rule.Score),
zap.Int("total_score", state.TotalScore),
zap.Int("anomaly_threshold", m.AnomalyThreshold),
zap.String("mode", rule.Action),
zap.String("severity", rule.Severity),
zap.String("source_ip", r.RemoteAddr),
zap.String("user_agent", r.UserAgent()),
zap.String("request_method", r.Method),
zap.String("request_path", r.URL.Path),
zap.String("query_params", r.URL.RawQuery),
zap.Time("timestamp", time.Now()),
}

// Log the rule match in detail with Info level
m.logRequest(zapcore.InfoLevel, "Detailed rule match information", requestInfo...)

// Determine if a blocking action should be taken
shouldBlock := false
blockReason := ""
Expand All @@ -92,14 +71,17 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru
} else if rule.Action == "block" {
shouldBlock = true
blockReason = "Rule action is 'block'"
} else if rule.Action != "log" {
shouldBlock = true
blockReason = "Unknown rule action"
}
} else {
m.logger.Debug("Blocking actions skipped, response already written", zap.String("log_id", logID), zap.String("rule_id", rule.ID))
}

// Log the decision-making process
m.logger.Debug("Processing rule action",
zap.String("rule_id", rule.ID),
zap.String("action", rule.Action),
zap.Bool("should_block", shouldBlock),
zap.String("block_reason", blockReason),
)

// Perform blocking action if needed and response not already written
if shouldBlock && !state.ResponseWritten {
state.Blocked = true
Expand Down
136 changes: 100 additions & 36 deletions rules.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,104 @@
[
{
"id": "allow-legit-browsers",
"phase": 1,
"pattern": "(?i)(Mozilla|Chrome|Safari|Edge|Firefox|Opera|AppleWebKit|Gecko|Trident|MSIE|Googlebot|Bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Sogou|Exabot|facebot|facebookexternalhit)",
"targets": ["HEADERS:User-Agent"],
"severity": "LOW",
"action": "log",
"score": 0,
"description": "Allow and log traffic from legitimate browsers and search engine crawlers."
},
{
"id": "log-legit-tools",
"phase": 1,
"pattern": "(?i)(wget|curl|libwww-perl|python-requests|Go-http-client|Java|HttpClient|axios|PostmanRuntime|Paw|Insomnia|Fiddler|Charles)",
"targets": ["HEADERS:User-Agent"],
"severity": "MEDIUM",
"action": "log",
"score": 2,
"description": "Log traffic from legitimate tools like wget, curl, and API testing tools."
},
{
"id": "block-scanners",
"phase": 1,
"pattern": "(?i)(nikto|sqlmap|nmap|acunetix|nessus|openvas|wpscan|dirbuster|burpsuite|owasp zap|netsparker|appscan|arachni|skipfish|gobuster|wfuzz|hydra|metasploit|nessus|openvas|qualys|zap|w3af|openwebspider|netsparker|appspider|rapid7|nessus|qualys)",
"targets": ["HEADERS:User-Agent"],
"severity": "CRITICAL",
"action": "block",
"score": 10,
"description": "Block traffic from known vulnerability scanners and penetration testing tools."
},
{
"id": "block-bad-bots",
"phase": 1,
"pattern": "(?i)(ahrefsbot|semrushbot|mj12bot|dotbot|petalbot|blexbot|rogerbot|exabot|megaindex|linkdexbot|spbot|sistrix|xoviobot|yandeximages|baiduspider|yandexbot|sogou|exabot|facebot|facebookexternalhit|python-requests|Go-http-client|Java|HttpClient|axios|PostmanRuntime|masscan|zgrab|ja3|ja3s|badbot|evilbot|maliciousbot|spammerbot|scrapy|phantomjs|headlesschrome|headlessfirefox)",
"targets": ["HEADERS:User-Agent"],
"severity": "HIGH",
"action": "block",
"score": 8,
"description": "Block traffic from known bad bots and automated scripts."
},
{
"id": "block-suspicious-user-agents",
"phase": 1,
"pattern": "(?i)(bot|crawl|spider|scan|hack|exploit|inject|sql|xss|bypass|brute|force|attack|malware|phishing|spyware|adware|ransomware|trojan|virus|worm|keylogger|backdoor|rootkit|shellcode|payload|exploit|vulnerability|scanner|harvest|scrape|collect|grab|fetch|extract|parse|analyze|monitor|track|log|record|report|submit|send|receive|execute|run|launch|start|stop|kill|terminate|restart|reboot|shutdown|suspend|resume|pause|wait|sleep|delay|timeout|retry|repeat|loop|cycle|iterate|recur|recurse|recurring|recurrent|recursive|recursion)",
"targets": ["HEADERS:User-Agent"],
"severity": "HIGH",
"action": "block",
"score": 8,
"description": "Block traffic with suspicious or malicious User-Agent strings."
},
{
"id": "block-no-user-agent",
"phase": 1,
"pattern": "^$",
"targets": ["HEADERS:User-Agent"],
"severity": "HIGH",
"action": "block",
"score": 8,
"description": "Block traffic with missing or empty User-Agent headers."
},
{
"id": "block-headless-browsers",
"phase": 1,
"pattern": "(?i)(headlesschrome|headlessfirefox|phantomjs|puppeteer|selenium|playwright|electron|chrome-lighthouse)",
"targets": ["HEADERS:User-Agent"],
"severity": "HIGH",
"action": "block",
"score": 8,
"description": "Block traffic from headless browsers and automation frameworks."
},
{
"id": "block-suspicious-tools",
"phase": 1,
"pattern": "(?i)(sqlmap|hydra|metasploit|nmap|nikto|wpscan|dirbuster|burpsuite|owasp zap|netsparker|appscan|arachni|skipfish|gobuster|wfuzz|masscan|zgrab|ja3|ja3s)",
"targets": ["HEADERS:User-Agent"],
"severity": "CRITICAL",
"action": "block",
"score": 10,
"description": "Block traffic from suspicious tools commonly used for attacks."
},
{
"id": "block-unknown-bots",
"phase": 1,
"pattern": "(?i)(bot|crawler|spider|scanner|harvester|fetcher|grabber|collector|extractor|parser|analyzer|monitor|tracker|logger|recorder|reporter|submitter|sender|receiver|executor|runner|launcher|starter|stopper|killer|terminator|restarter|rebooter|shutdown|suspender|resumer|pauser|waiter|sleeper|delayer|timeouter|retrier|repeater|looper|cycler|iterator|recurrer|recurser|recurring|recurrent|recursive|recursion)",
"targets": ["HEADERS:User-Agent"],
"severity": "HIGH",
"action": "block",
"score": 8,
"description": "Block traffic from unknown or generic bots with suspicious behavior."
},
{
"id": "block-evasion-attempts",
"phase": 1,
"pattern": "(?i)(obfuscate|encode|decode|encrypt|decrypt|base64|hex|urlencode|urldecode|rot13|xor|aes|des|rc4|md5|sha1|sha256|sha512|hmac|jwt|token|bearer|oauth|api_key|secret|password|credential|auth|authentication|session|cookie|csrf|xss|sql|inject|payload|exploit|vulnerability|bypass|brute|force|attack|malware|phishing|spyware|adware|ransomware|trojan|virus|worm|keylogger|backdoor|rootkit|shellcode|payload|exploit|vulnerability|scanner|harvest|scrape|collect|grab|fetch|extract|parse|analyze|monitor|track|log|record|report|submit|send|receive|execute|run|launch|start|stop|kill|terminate|restart|reboot|shutdown|suspend|resume|pause|wait|sleep|delay|timeout|retry|repeat|loop|cycle|iterate|recur|recurse|recurring|recurrent|recursive|recursion)",
"targets": ["HEADERS:User-Agent"],
"severity": "CRITICAL",
"action": "block",
"score": 10,
"description": "Block traffic with User-Agent strings indicating evasion or attack attempts."
},
{
"id": "932130",
"phase": 2,
Expand Down Expand Up @@ -38,30 +138,6 @@
"score": 1,
"description": "No description provided."
},
{
"id": "malicious-referer-test",
"phase": 2,
"pattern": "(?i)malicious-referer",
"targets": [
"HEADERS"
],
"severity": "HIGH",
"action": "block",
"score": 5,
"description": "Block requests with malicious Referer headers (Target: HEADERS)"
},
{
"id": "scanner-detection",
"phase": 1,
"pattern": "(?i)(?:sqlmap|acunetix|nikto|nessus|netsparker|nmap|dirbuster|w3af|openvas|burpsuite|webinspect|qualys|commix|zap|arachni|gobuster|hydra|metasploit|zgrab|masscan|wfuzz|crackmapexec|nuclei|shodan|censys|dirsearch|ffuf|vega|skipfish|wpscan|whatweb|dirmap)",
"targets": [
"HEADERS"
],
"severity": "CRITICAL",
"action": "block",
"score": 9,
"description": "Block requests from known security scanners based on User-Agent (Target: HEADERS)"
},
{
"id": "sql-injection",
"phase": 2,
Expand Down Expand Up @@ -180,18 +256,6 @@
"score": 7,
"description": "Block requests to unusual or suspicious paths (Target: URI)."
},
{
"id": "block-bad-bots",
"phase": 1,
"pattern": "(?i)(?:sqlmap|acunetix|nikto|nessus|netsparker|dirbuster|burpsuite|wpscan|nuclei|qualys|arachni|openvas|zap|vega|skipfish|w3af|gobuster|owasp zap|webinspect|appscan|detectify|nessuscloud|retire\\.js|fortify|checkmarx|veracode|snyk|rapid7|nexpose|insightvm|hydra|medusa|ncrack|john the ripper|hashcat|patator|masscan|shodan|censys|whatweb|dirmap|nmap|amap|zmap|theharvester|recon-ng|fierce|metasploit|commix|crackmapexec|cobalt strike|empire|powersploit|httrack|wget|scrapy|beautifulsoup|phantomjs|headlesschrome|puppeteer|grabber|node-fetch|axios|bugcrowd|hackerone|intruder|selenium|openscap|ffuf|webscarab|sublist3r|dirsearch|sql ninja|eyewitness|gau|waybackurls|assetfinder|ahrefsbot|mj12bot|semrushbot|dotbot|rogerbot|exabot|yandexbot|baiduspider|googlebot-image|bingbot|go-http-client|python-requests|okhttp|lwp-request|libwww-perl|kube-hunter|cloudmapper|pacu|dirb|uniscan|vega|arachni|xsser|davtest|jexboss|joomscan|droopescan|cmsmap|xsstrike|thesprawl|cloudgoat|sqlmapapi|wpscanapi|impacket|responder|bloodhound|mimikatz|pupy|veil-framework|evilginx|mitmproxy|bettercap|playwright|nightmare|zombie\\.js|splash)",
"targets": [
"HEADERS"
],
"severity": "CRITICAL",
"action": "block",
"score": 9,
"description": "Block requests from known security scanners and bad bots (Target: HEADERS)."
},
{
"id": "mass-assignment-indicators",
"phase": 2,
Expand Down
Loading