Cybersecurity-Projects/PROJECTS/beginner/dns-lookup/learn/04-CHALLENGES.md

719 lines
18 KiB
Markdown

# Challenges and Extensions
## Beginner Challenges
### Challenge 1: Add DNSSEC Validation
**Goal:** Verify DNSSEC signatures on DNS responses.
**Current State:** The tool retrieves records but doesn't validate signatures. Line `resolver.py:200-201` just fetches data without cryptographic verification.
**Implementation Tasks:**
1. Enable DNSSEC in resolver (`resolver.py:91-107`)
```python
resolver = dns.asyncresolver.Resolver()
resolver.use_edns(0, dns.flags.DO, 4096) # Request DNSSEC records
```
2. Check RRSIG records in responses
3. Validate signatures against DNSKEY records
4. Walk chain of trust from root to target domain
**Resources:**
- RFC 4033, 4034, 4035 (DNSSEC specs)
- dnspython DNSSEC validation examples
- Test with `dnssec-tools.org` (signed domain)
**Security Impact:** Prevents accepting forged DNS responses. Critical for high-security environments.
### Challenge 2: Implement DNS Query Logging
**Goal:** Log all queries to a file for analysis.
**What to Log:**
- Timestamp
- Domain queried
- Record types requested
- DNS server used
- Response time
- Number of records returned
**Implementation:**
1. Create logger in `resolver.py:213-250`
2. Log before query: `logging.info(f"Querying {domain} for {record_types}")`
3. Log after query: `logging.info(f"Got {len(result.records)} records in {result.query_time_ms}ms")`
4. Add CLI flag: `--log-file queries.log`
**Analysis Ideas:**
- Which domains take longest to resolve?
- Which record types fail most often?
- Time series analysis of response times
**Security Application:** Detect reconnaissance by analyzing query patterns.
### Challenge 3: Add CSV Output Format
**Goal:** Export results to CSV for spreadsheet analysis.
**Current State:** JSON output exists (`output.py:379-410`), but CSV would be more useful for some workflows.
**Implementation:**
1. Add `results_to_csv()` function in `output.py`
2. Flatten nested structure:
```
domain,record_type,value,ttl,priority,query_time_ms
example.com,A,93.184.216.34,86400,,45.2
example.com,MX,mail.example.com,3600,10,45.2
```
3. Handle multiple records per domain
4. Add `--csv` flag to commands
**Use Case:** Import into Excel/Google Sheets for analysis, sorting, filtering.
## Intermediate Challenges
### Challenge 4: Subdomain Enumeration
**Goal:** Discover subdomains through various techniques.
**Techniques to Implement:**
**1. Brute Force** (`cli.py:266-350` as starting point)
```python
common_subdomains = ['www', 'mail', 'ftp', 'admin', 'test', 'dev', 'staging']
for sub in common_subdomains:
fqdn = f"{sub}.{domain}"
result = await lookup(fqdn, [RecordType.A])
if result.records:
print(f"Found: {fqdn}")
```
**2. Certificate Transparency Logs**
Query crt.sh API for domains in SSL certificates:
```python
import requests
response = requests.get(f"https://crt.sh/?q=%.{domain}&output=json")
```
**3. DNS Zone Transfer** (AXFR)
```python
try:
zone = dns.zone.from_xfr(dns.query.xfr(nameserver, domain))
for name in zone:
print(f"{name}.{domain}")
except:
print("Zone transfer refused")
```
**Security Note:** Zone transfers are often blocked. Only test on domains you own.
**Real World:** Subdomain enumeration is first step in reconnaissance (MITRE T1590.002).
### Challenge 5: DNS Monitoring and Alerting
**Goal:** Continuously monitor domains and alert on changes.
**Architecture:**
```
Periodic Queries (every 5 min)
Compare to Previous State
Detect Changes
Send Alerts (email/Slack/webhook)
```
**What to Monitor:**
- A/AAAA record changes (infrastructure moved)
- MX record changes (email routing modified)
- NS record changes (DNS provider changed)
- New/removed records
**Implementation:**
1. Store previous state in SQLite database
2. Query on schedule (use `schedule` library or cron)
3. Compare current vs previous
4. Trigger alerts on differences
**Security Application:** Detect DNS hijacking attempts. If NS records suddenly change, someone might have compromised the registrar account.
**Real Incident:** MyEtherWallet (2018) - BGP hijack changed DNS to point to phishing site. Monitoring would have detected this.
### Challenge 6: DNS Performance Analysis
**Goal:** Measure and visualize DNS resolver performance.
**Metrics to Track:**
- Query latency percentiles (p50, p95, p99)
- Success rate by record type
- Timeout frequency
- Resolver comparison (8.8.8.8 vs 1.1.1.1 vs ISP)
**Implementation:**
1. Extend `DNSResult` with more metrics
2. Query same domains from multiple resolvers
3. Store results in time-series database (InfluxDB)
4. Visualize with Grafana
**Add to `resolver.py`:**
```python
@dataclass
class DNSResult:
# ... existing fields ...
resolver_ip: str | None = None
tcp_fallback: bool = False
truncated: bool = False
```
**Analysis Questions:**
- Which resolver is fastest for your location?
- Does performance vary by time of day?
- Which domains have the longest resolution times?
## Advanced Challenges
### Challenge 7: DNS Tunnel Detection
**Goal:** Identify DNS tunneling for data exfiltration.
**DNS Tunneling Characteristics:**
- High volume of queries to a single domain
- Large TXT record queries/responses
- Unusual subdomain lengths
- Base64/hex-encoded subdomains
- Regular query intervals
**Implementation:**
**1. Entropy Analysis**
```python
import math
from collections import Counter
def calculate_entropy(subdomain: str) -> float:
"""High entropy suggests encoded data"""
counter = Counter(subdomain)
length = len(subdomain)
return -sum((count/length) * math.log2(count/length)
for count in counter.values())
# Legitimate: www.example.com (low entropy)
# Tunneling: aGVsbG8=.attacker.com (high entropy)
```
**2. Query Volume Detection**
```python
# Track queries per domain
query_counts = defaultdict(int)
for domain in queries:
query_counts[domain] += 1
if query_counts[domain] > threshold:
alert(f"Possible tunneling: {domain}")
```
**3. Subdomain Length Analysis**
```python
if len(subdomain) > 63: # DNS label limit
alert("Suspicious long subdomain")
```
**Real Malware:** Houdini worm, Feederbot, DNScat2 all use DNS tunneling.
**References:**
- CWE-406: Insufficient Control of Network Message Volume
- MITRE T1071.004: Application Layer Protocol: DNS
### Challenge 8: Passive DNS Database
**Goal:** Build a historical database of DNS resolutions.
**Architecture:**
```
DNS Queries (from monitoring/batch)
Store in Database
Query Historical Data
```
**Schema:**
```sql
CREATE TABLE dns_records (
id INTEGER PRIMARY KEY,
domain TEXT,
record_type TEXT,
value TEXT,
ttl INTEGER,
first_seen TIMESTAMP,
last_seen TIMESTAMP,
seen_count INTEGER
);
CREATE INDEX idx_domain ON dns_records(domain);
CREATE INDEX idx_value ON dns_records(value);
```
**Queries to Support:**
- When did example.com first resolve to 1.2.3.4?
- What domains have resolved to this IP?
- How often does this domain change IPs?
**Security Application:** Track malware C2 infrastructure. Malicious domains often change IPs frequently.
**Commercial Examples:** VirusTotal, PassiveTotal, Farsight DNSDB.
### Challenge 9: Real-time DNS Query Stream Analysis
**Goal:** Analyze live DNS query streams (from router/firewall logs).
**Input Sources:**
- pcap files from network captures
- Syslog from DNS servers
- Netflow/IPFIX data
- Cloud DNS query logs (AWS Route53, Google Cloud DNS)
**Detection Patterns:**
**1. DGA (Domain Generation Algorithm)**
```python
def is_dga(domain: str) -> bool:
"""DGA domains are often random-looking"""
labels = domain.split('.')
if len(labels) < 2:
return False
sld = labels[-2] # second-level domain
# High consonant ratio
consonants = sum(1 for c in sld if c in 'bcdfghjklmnpqrstvwxyz')
if consonants / len(sld) > 0.7:
return True
# No dictionary words
# Low vowel ratio
# High entropy
return False
```
**2. Fast Flux Detection**
Many IPs for one domain, changing frequently:
```python
# Track A records over time
if len(unique_ips_for_domain) > 10 and avg_ttl < 300:
alert("Possible fast flux")
```
**3. C2 Beaconing**
Regular periodic queries:
```python
# Calculate query intervals
intervals = [queries[i+1].time - queries[i].time
for i in range(len(queries)-1)]
# If intervals are suspiciously regular
if std_dev(intervals) < threshold:
alert("Possible C2 beaconing")
```
**Tools to Study:** Zeek (formerly Bro), Suricata DNS analysis modules.
### Challenge 10: DNS Firewall / Sinkhole
**Goal:** Block malicious domains by serving fake responses.
**Architecture:**
```
Client Query
Your DNS Server
Check Blocklist
If Blocked: Return 0.0.0.0
If Allowed: Forward to Upstream Resolver
```
**Implementation:**
**1. Basic DNS Server** (use `dnslib` library)
```python
from dnslib import DNSRecord, RR, QTYPE, A
from dnslib.server import DNSServer
class BlocklistResolver:
def __init__(self, blocklist):
self.blocklist = set(blocklist)
def resolve(self, request, handler):
qname = str(request.q.qname)
if qname.rstrip('.') in self.blocklist:
# Return sinkhole IP
reply = request.reply()
reply.add_answer(RR(qname, QTYPE.A, rdata=A("0.0.0.0")))
return reply
else:
# Forward to real resolver
return proxy_request(request)
```
**2. Blocklist Sources**
- Malware domain lists (abuse.ch)
- Phishing feeds (PhishTank)
- Ad/tracker lists (EasyList)
- Threat intel feeds
**3. Logging and Analytics**
- Track blocked query attempts
- Identify infected machines
- Measure effectiveness
**Real Products:** Pi-hole, AdGuard Home, Cisco Umbrella.
## Expert Challenges
### Challenge 11: DNS Amplification Attack Detection
**Goal:** Detect when your DNS server is being used for amplification attacks.
**Attack Pattern:**
1. Attacker sends queries with spoofed source IP (victim's address)
2. Your server sends large responses to victim
3. Victim gets flooded
**Detection Signals:**
```python
# 1. High volume from single IP
queries_per_ip = defaultdict(int)
# 2. Queries for large record types
if record_type in [RecordType.TXT, RecordType.ANY]:
suspicious_count += 1
# 3. Responses much larger than queries
if response_size / query_size > 50:
alert("High amplification factor")
# 4. No follow-up queries (victim doesn't actually want data)
if client_ip in one_shot_queries:
alert("Possible spoofed source")
```
**Mitigation:**
- Rate limit queries per IP
- Disable ANY queries (RFC 8482)
- Response rate limiting (RRL)
- BCP38 filtering (prevent spoofed source IPs)
### Challenge 12: Custom DNS Record Types
**Goal:** Add support for newer/specialized record types.
**Record Types to Add:**
**CAA (Certification Authority Authorization)**
```python
# In resolver.py:24-33
class RecordType(StrEnum):
# ... existing types ...
CAA = "CAA" # RFC 8659
```
Specifies which CAs can issue certificates for domain. Security-critical.
**SSHFP (SSH Fingerprint)**
```python
SSHFP = "SSHFP" # RFC 4255
```
Publishes SSH server key fingerprints in DNS for verification.
**TLSA (DANE/TLSA)**
```python
TLSA = "TLSA" # RFC 6698
```
DNS-based Authentication of Named Entities. Publishes TLS certificate hashes.
**DNSKEY, DS, RRSIG** (DNSSEC records)
For challenge 1 (DNSSEC validation).
### Challenge 13: Geographic DNS Analysis
**Goal:** Determine where DNS servers are located and analyze geographic distribution.
**Implementation:**
**1. GeoIP Lookup**
```python
import geoip2.database
reader = geoip2.database.Reader('GeoLite2-City.mmdb')
for nameserver_ip in result.nameserver_ips:
response = reader.city(nameserver_ip)
print(f"{nameserver_ip}: {response.city.name}, {response.country.name}")
```
**2. Latency-based Geolocation**
Ping from multiple vantage points, use speed-of-light calculations to estimate location.
**3. Anycast Detection**
If same IP resolves to different locations, it's anycast (like root servers, Google DNS, Cloudflare DNS).
**Security Analysis:**
- Is DNS infrastructure geographically diverse? (resilience)
- Are responses coming from unexpected countries? (hijacking)
- Latency analysis for optimal resolver selection
### Challenge 14: DNS Covert Channel Communication
**Goal:** Implement bidirectional communication over DNS (for research/education only).
**How It Works:**
**Client → Server (via queries)**
```
Encode message in subdomain:
aGVsbG8=.tunnel.attacker.com
```
**Server → Client (via responses)**
```
Encode response in TXT record:
"d29ybGQ="
```
**Implementation:**
```python
def encode_query(data: bytes, domain: str) -> str:
"""Encode data in subdomain"""
encoded = base64.b64encode(data).decode()
# Split into DNS labels (63 char max)
labels = [encoded[i:i+63] for i in range(0, len(encoded), 63)]
return '.'.join(labels) + '.' + domain
def decode_response(txt_record: str) -> bytes:
"""Decode data from TXT record"""
return base64.b64decode(txt_record)
```
**Challenges:**
- DNS has size limits (512 bytes UDP, 4096 TCP)
- Must handle fragmentation
- Packet loss requires retransmission
- High latency (1-2s per request)
**Countermeasures to Study:**
- Entropy analysis (challenge 7)
- Query volume limits
- Subdomain length restrictions
- TXT record size monitoring
**Ethical Note:** Only test on infrastructure you own. DNS tunneling without authorization is illegal.
### Challenge 15: Build a Recursive DNS Resolver
**Goal:** Implement a full recursive resolver from scratch (like BIND, Unbound).
**What It Does:**
1. Accept queries from clients
2. Iterate through DNS hierarchy (like trace command)
3. Cache results
4. Return answers
**Core Components:**
**1. Cache**
```python
from functools import lru_cache
import time
class DNSCache:
def __init__(self):
self.cache = {}
def get(self, key):
if key in self.cache:
value, expiry = self.cache[key]
if time.time() < expiry:
return value
return None
def set(self, key, value, ttl):
self.cache[key] = (value, time.time() + ttl)
```
**2. Recursive Resolution** (extend `trace_dns()` from `resolver.py:293-426`)
**3. Server Loop**
```python
from dnslib.server import DNSServer
class RecursiveResolver:
def resolve(self, request, handler):
qname = str(request.q.qname)
# Check cache
cached = self.cache.get(qname)
if cached:
return cached
# Perform recursive resolution
result = trace_and_resolve(qname)
# Cache result
self.cache.set(qname, result, ttl=300)
return result
resolver = RecursiveResolver()
server = DNSServer(resolver, port=5353)
server.start_thread()
```
**Challenges:**
- Handle CNAME chains
- Implement negative caching (NXDOMAIN)
- Deal with timeouts and retries
- DNSSEC validation
- Handle TCP fallback for large responses
**Testing:**
```bash
dig @localhost -p 5353 example.com
```
## Research Challenges
### Challenge 16: Machine Learning for Malicious Domain Detection
**Goal:** Train ML model to classify domains as malicious or benign.
**Features to Extract:**
- Domain length
- Character entropy
- N-gram frequencies
- Vowel/consonant ratio
- TLD (.com vs .xyz vs .tk)
- Registration age (from WHOIS)
- Subdomain count
- Historical IP changes
- ASN reputation
**Training Data:**
- Benign: Alexa/Majestic top sites
- Malicious: abuse.ch, PhishTank, malware feeds
**Models to Try:**
- Random Forest
- XGBoost
- Neural networks for sequence data
**Evaluation:**
- Precision/recall on test set
- False positive rate (critical for blocklists)
- Performance on DGA domains
**Challenge:** Low false positives while catching novel threats.
### Challenge 17: DNS Privacy Analysis
**Goal:** Measure information leakage from DNS queries.
**What Leaks:**
- Browsing history from query logs
- Location from resolver choice
- Device type from query patterns
- App usage from CDN queries
**Experiments:**
**1. Reconstruct Browsing Session**
Collect DNS queries for 1 hour. Can you infer:
- Which websites visited?
- Which apps used?
- User's interests/demographics?
**2. DNS Fingerprinting**
Different devices make different queries:
- Android queries android.googleapis.com
- iOS queries apple.com services
- Windows queries microsoft.com
**3. Correlation Attacks**
Even with DoH, timing analysis can reveal sites:
```python
# Time between query and HTTP request
# Query pattern (images, scripts, API calls)
# Size of responses
```
**References:**
- "The Effect of DNS on Tor's Anonymity" (research paper)
- CWE-201: Information Exposure Through Sent Data
### Challenge 18: Develop DNS Benchmarking Suite
**Goal:** Create comprehensive DNS performance testing toolkit.
**Benchmarks:**
**1. Latency**
- Measure p50, p95, p99 query latency
- Test from multiple geographic locations
- Compare resolvers (Google, Cloudflare, Quad9)
**2. Throughput**
- Queries per second capacity
- Concurrent query handling
**3. Reliability**
- Success rate over 24 hours
- NXDOMAIN handling
- Timeout frequency
**4. Privacy**
- Query minimization support (RFC 7816)
- DNSSEC validation
- DoH/DoT support
**5. Censorship Resistance**
- Are queries filtered?
- Are results manipulated?
**Tools to Build:**
- Automated test runner
- Result aggregation and visualization
- Historical tracking
- Alerting on degradation
**Public Service:** Publish results like [DNSPerf.com](https://www.dnsperf.com/)
## Wrap-Up
Each challenge builds specific skills:
- **Challenges 1-3**: Tool development, output formats
- **Challenges 4-6**: Security monitoring, performance analysis
- **Challenges 7-10**: Threat detection, defensive tools
- **Challenges 11-15**: Advanced DNS concepts, covert channels
- **Challenges 16-18**: Research, ML, measurement studies
**Next Steps:**
1. Pick challenges matching your skill level
2. Start with beginner challenges to learn codebase
3. Progress to security-focused intermediate challenges
4. Tackle advanced challenges for deep expertise
**Resources:**
- DNS RFCs (1034, 1035, and extensions)
- OWASP Testing Guide (DNS sections)
- MITRE ATT&CK Framework (T1590, T1071.004, T1584.002)
- DNSViz for visualizing DNSSEC
- Wireshark for packet analysis
Happy hacking! Remember: only test on systems you own or have explicit permission to test.