princemaxp commited on
Commit
292c399
·
verified ·
1 Parent(s): a235ecf

Update header_analyzer.py

Browse files
Files changed (1) hide show
  1. header_analyzer.py +29 -16
header_analyzer.py CHANGED
@@ -3,40 +3,53 @@ import re
3
  def analyze_headers(headers):
4
  findings = []
5
  score = 0
 
6
 
7
- # --- 1. SPF / DKIM / DMARC checks ---
8
- auth_results = headers.get("Authentication-Results", "")
9
- if "dkim=fail" in auth_results.lower() or "dkim=permerror" in auth_results.lower():
10
  findings.append("Header: DKIM check failed")
11
  score += 25
12
- if "spf=fail" in auth_results.lower():
13
  findings.append("Header: SPF check failed")
14
  score += 25
15
- if "dmarc=fail" in auth_results.lower():
16
  findings.append("Header: DMARC check failed")
17
  score += 25
18
 
19
- # --- 2. From / Reply-To mismatch ---
20
- from_addr = headers.get("From", "")
21
- reply_to = headers.get("Reply-To", "")
22
- if reply_to and reply_to not in from_addr:
23
- findings.append(f"Header: Reply-To mismatch (From: {from_addr}, Reply-To: {reply_to})")
24
- score += 20
 
25
 
26
- # --- 3. Suspicious sender domain ---
27
- sender = headers.get("From", "")
 
 
 
 
 
 
 
 
 
 
28
  match = re.search(r'@([a-zA-Z0-9.-]+)', sender)
29
  if match:
30
  domain = match.group(1).lower()
 
31
  if any(free in domain for free in ["gmail.com", "yahoo.com", "outlook.com"]):
32
  findings.append(f"Header: Free email provider used ({domain})")
33
  score += 10
34
- if len(domain.split(".")) > 3 or any(char.isdigit() for char in domain.split(".")[0]):
35
  findings.append(f"Header: Suspicious-looking domain ({domain})")
36
  score += 15
37
 
38
- # --- 4. BCC usage ---
39
- if "bcc" in headers:
40
  findings.append("Header: Email sent with BCC (common in mass phishing)")
41
  score += 15
42
 
 
3
  def analyze_headers(headers):
4
  findings = []
5
  score = 0
6
+ headers = headers or {}
7
 
8
+ # 1) SPF / DKIM / DMARC
9
+ auth_results = (headers.get("Authentication-Results") or "").lower()
10
+ if "dkim=fail" in auth_results or "dkim=permerror" in auth_results:
11
  findings.append("Header: DKIM check failed")
12
  score += 25
13
+ if "spf=fail" in auth_results:
14
  findings.append("Header: SPF check failed")
15
  score += 25
16
+ if "dmarc=fail" in auth_results:
17
  findings.append("Header: DMARC check failed")
18
  score += 25
19
 
20
+ # softer signals
21
+ if any(x in auth_results for x in ["spf=softfail", "spf=neutral", "spf=none"]):
22
+ findings.append("Header: SPF not properly aligned")
23
+ score += 10
24
+ if any(x in auth_results for x in ["dmarc=temperror", "dkim=temperror"]):
25
+ findings.append("Header: Temporary auth errors (DKIM/DMARC)")
26
+ score += 5
27
 
28
+ # 2) From / Reply-To mismatch (domain-level)
29
+ from_addr = headers.get("From", "") or ""
30
+ reply_to = headers.get("Reply-To", "") or ""
31
+ from_domain = re.search(r'@([a-zA-Z0-9.-]+)', from_addr)
32
+ reply_domain = re.search(r'@([a-zA-Z0-9.-]+)', reply_to)
33
+ if from_domain and reply_domain:
34
+ if from_domain.group(1).lower() != reply_domain.group(1).lower():
35
+ findings.append(f"Header: Reply-To domain mismatch (From: {from_domain.group(1)}, Reply-To: {reply_domain.group(1)})")
36
+ score += 20
37
+
38
+ # 3) Suspicious sender domain
39
+ sender = headers.get("From", "") or ""
40
  match = re.search(r'@([a-zA-Z0-9.-]+)', sender)
41
  if match:
42
  domain = match.group(1).lower()
43
+ parts = domain.split(".")
44
  if any(free in domain for free in ["gmail.com", "yahoo.com", "outlook.com"]):
45
  findings.append(f"Header: Free email provider used ({domain})")
46
  score += 10
47
+ if len(parts) > 4 or (parts and any(char.isdigit() for char in parts[0])):
48
  findings.append(f"Header: Suspicious-looking domain ({domain})")
49
  score += 15
50
 
51
+ # 4) BCC usage (note: often stripped)
52
+ if headers.get("Bcc"):
53
  findings.append("Header: Email sent with BCC (common in mass phishing)")
54
  score += 15
55