Learning Objectives
By the end of this week, you will be able to:
- Use lists, dictionaries, sets, and tuples for security data organization
- Implement control flow (if/for/while) for automated security tasks
- Parse and analyze security logs programmatically
- Build a multi-target vulnerability scanner with result tracking
- Create password validation tools with complex rule enforcement
1) Strings: The Language of Security Data
In cybersecurity, almost everything is a string: log entries, HTTP responses, exploit payloads, configuration files, and network traffic. Mastering string manipulation is essential.
String Operations for Security
# Log entry from a web server
log_entry = '192.168.1.100 - - [18/Jan/2024:10:15:23] "GET /admin HTTP/1.1" 403 512'
# Extracting information
if "403" in log_entry or "404" in log_entry:
print("⚠️ Client error detected")
# Splitting on delimiters
parts = log_entry.split('" "')
request = parts[0].split(']')[1].strip() # "GET /admin HTTP/1.1"
status_code = parts[1].split()[0] # "403"
# Finding substrings
ip_start = 0
ip_end = log_entry.find(" - -")
ip_address = log_entry[ip_start:ip_end] # "192.168.1.100"
print(f"IP: {ip_address}, Request: {request}, Status: {status_code}")
Common String Methods
# Case manipulation (important for comparison)
username = "Admin"
if username.lower() == "admin": # Case-insensitive comparison
print("Admin user detected")
# Whitespace handling
dirty_input = " user@example.com \n"
clean_input = dirty_input.strip() # "user@example.com"
# Replacement (payload generation, sanitization)
unsafe_query = "SELECT * FROM users WHERE name=''"
payload = unsafe_query.replace("", "admin' OR '1'='1")
# Checking prefix/suffix (file type validation)
filename = "malware.exe"
if filename.endswith((".exe", ".dll", ".bat")):
print("⚠️ Executable file detected")
# Splitting and joining
ports = "80,443,8080,8443"
port_list = ports.split(",") # ['80', '443', '8080', '8443']
formatted = " | ".join(port_list) # "80 | 443 | 8080 | 8443"
F-Strings for Payload Construction
# Modern Python 3.6+ f-strings (preferred method)
target = "10.0.0.5"
port = 445
protocol = "SMB"
# Clean and readable
message = f"Scanning {target}:{port} ({protocol})"
# Expression evaluation inside f-strings
cvss_score = 7.5
severity = f"CVSS {cvss_score} - {'CRITICAL' if cvss_score >= 9 else 'HIGH' if cvss_score >= 7 else 'MEDIUM'}"
# SQL injection payload generation
username = "admin"
sqli_payloads = [
f"' OR '1'='1",
f"' OR 1=1--",
f"admin'--",
f"' UNION SELECT NULL,NULL,NULL--"
]
Raw Strings for Regex and Paths
# Regular string - backslashes are escape characters
path = "C:\\Users\\Admin\\Documents" # Need to escape \
# Raw string - backslashes are literal
path = r"C:\Users\Admin\Documents" # Much cleaner
# Essential for regex patterns (we'll cover regex in Week 4)
ip_pattern = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
2) Lists: Sequential Security Data
Lists store ordered collections—perfect for targets, scan results, wordlists, and vulnerability findings.
Creating and Manipulating Lists
# Common security uses
targets = ["192.168.1.1", "192.168.1.5", "192.168.1.10"]
common_ports = [21, 22, 23, 25, 80, 443, 3389, 8080]
vulnerabilities = [] # Start empty, populate during scan
# Adding items
vulnerabilities.append({"type": "SQL Injection", "cvss": 9.0})
vulnerabilities.append({"type": "XSS", "cvss": 6.5})
# Extending lists
more_targets = ["10.0.0.1", "10.0.0.2"]
targets.extend(more_targets) # Adds all items
# Inserting at specific position
common_ports.insert(0, 20) # FTP data port at beginning
# Removing items
common_ports.remove(20) # Remove by value
last_port = common_ports.pop() # Remove and return last item
del common_ports[0] # Remove by index
List Indexing and Slicing
hosts = ["192.168.1.1", "192.168.1.5", "192.168.1.10", "192.168.1.20", "192.168.1.50"]
# Indexing (zero-based)
first_host = hosts[0] # "192.168.1.1"
last_host = hosts[-1] # "192.168.1.50" (negative counts from end)
# Slicing [start:end:step]
first_three = hosts[0:3] # ["192.168.1.1", "192.168.1.5", "192.168.1.10"]
last_two = hosts[-2:] # ["192.168.1.20", "192.168.1.50"]
every_other = hosts[::2] # ["192.168.1.1", "192.168.1.10", "192.168.1.50"]
# Reversing
reversed_hosts = hosts[::-1]
List Comprehensions (Powerful Filtering)
# Traditional loop
open_ports = []
for port in range(1, 1001):
if scan_port(host, port):
open_ports.append(port)
# List comprehension (more Pythonic)
open_ports = [port for port in range(1, 1001) if scan_port(host, port)]
# Filtering with conditions
high_severity = [v for v in vulnerabilities if v["cvss"] >= 7.0]
# Transforming data
ip_list = ["192.168.1.1", "192.168.1.2", "192.168.1.3"]
with_ports = [f"{ip}:80" for ip in ip_list]
# ['192.168.1.1:80', '192.168.1.2:80', '192.168.1.3:80']
# Nested comprehensions (advanced)
subnet_scan = [f"192.168.{subnet}.{host}"
for subnet in range(1, 4)
for host in range(1, 11)]
Sorting and Searching
# Sorting lists
ports = [443, 80, 22, 3389, 8080]
ports.sort() # Sorts in-place: [22, 80, 443, 3389, 8080]
ports.sort(reverse=True) # Descending
# Sorting with custom key
vulns = [
{"name": "XSS", "cvss": 6.5},
{"name": "SQLi", "cvss": 9.0},
{"name": "CSRF", "cvss": 5.0}
]
sorted_vulns = sorted(vulns, key=lambda v: v["cvss"], reverse=True)
# Highest CVSS first
# Searching
if 80 in ports:
print("HTTP port is in list")
index = ports.index(443) # Find position of 443
# Counting occurrences
protocols = ["TCP", "UDP", "TCP", "TCP", "ICMP"]
tcp_count = protocols.count("TCP") # 3
3) Dictionaries: Key-Value Security Mappings
Dictionaries are Python's hash tables—perfect for scan results, configuration, API responses, and vulnerability databases.
Creating and Using Dictionaries
# Scan result for a single host
scan_result = {
"target": "192.168.1.100",
"timestamp": "2024-01-18 10:30:00",
"open_ports": [80, 443, 3306],
"services": {
80: "Apache 2.4.41",
443: "nginx 1.18.0",
3306: "MySQL 5.7.33"
},
"vulnerabilities": [
{"cve": "CVE-2023-1234", "cvss": 7.5},
{"cve": "CVE-2023-5678", "cvss": 9.0}
],
"risk_level": "HIGH"
}
# Accessing values
target_ip = scan_result["target"]
http_service = scan_result["services"][80]
# Safe access (won't crash if key missing)
ssh_service = scan_result.get("services", {}).get(22, "Not found")
# Adding/modifying
scan_result["scanned_by"] = "lab2_scanner.py"
scan_result["open_ports"].append(8080)
# Checking for keys
if "vulnerabilities" in scan_result:
vuln_count = len(scan_result["vulnerabilities"])
Dictionary Methods
services = {22: "SSH", 80: "HTTP", 443: "HTTPS"}
# Get all keys, values, or items
ports = list(services.keys()) # [22, 80, 443]
names = list(services.values()) # ['SSH', 'HTTP', 'HTTPS']
pairs = list(services.items()) # [(22, 'SSH'), (80, 'HTTP'), (443, 'HTTPS')]
# Iterating
for port, service in services.items():
print(f"Port {port}: {service}")
# Merging dictionaries (Python 3.9+)
default_config = {"timeout": 2, "retries": 3}
user_config = {"timeout": 5}
merged_config = default_config | user_config # {timeout: 5, retries: 3}
# Dictionary comprehensions
port_status = {port: "OPEN" if check_port(host, port) else "CLOSED"
for port in [21, 22, 23, 80, 443]}
Nested Dictionaries (Complex Security Data)
# Multi-host scan results
network_scan = {
"192.168.1.1": {
"hostname": "router.local",
"ports": {80: "HTTP", 443: "HTTPS"},
"os": "Linux 5.4"
},
"192.168.1.5": {
"hostname": "webserver.local",
"ports": {22: "SSH", 80: "HTTP", 3306: "MySQL"},
"os": "Ubuntu 20.04",
"vulnerabilities": ["CVE-2023-1234"]
}
}
# Accessing nested data
webserver_os = network_scan["192.168.1.5"]["os"]
webserver_vulns = network_scan["192.168.1.5"].get("vulnerabilities", [])
# Safe nested access
router_vulns = network_scan.get("192.168.1.1", {}).get("vulnerabilities", [])
4) Sets and Tuples: Specialized Collections
Sets: Unique Collections
Sets store unique items—perfect for deduplication and set operations.
# Deduplicate IPs from logs
log_ips = ["10.0.0.1", "10.0.0.2", "10.0.0.1", "10.0.0.3", "10.0.0.2"]
unique_ips = set(log_ips) # {'10.0.0.1', '10.0.0.2', '10.0.0.3'}
# Set operations (comparing scan results)
scan1_ports = {21, 22, 80, 443}
scan2_ports = {22, 80, 443, 3389, 8080}
# Intersection (in both scans)
common = scan1_ports & scan2_ports # {22, 80, 443}
# Union (in either scan)
all_ports = scan1_ports | scan2_ports # {21, 22, 80, 443, 3389, 8080}
# Difference (in scan1 but not scan2)
scan1_only = scan1_ports - scan2_ports # {21}
# Fast membership testing
if 3389 in scan2_ports:
print("RDP port found")
Tuples: Immutable Sequences
Tuples are like lists but cannot be modified—useful for constants and dictionary keys.
# Common port definitions (won't change)
WELL_KNOWN_PORTS = (
(20, "FTP Data"),
(21, "FTP Control"),
(22, "SSH"),
(23, "Telnet"),
(25, "SMTP"),
(80, "HTTP"),
(443, "HTTPS")
)
# Tuple unpacking
for port, service in WELL_KNOWN_PORTS:
print(f"{service}: {port}")
# Using tuples as dictionary keys (lists can't be keys)
scan_results = {
("192.168.1.1", 80): "OPEN",
("192.168.1.1", 443): "OPEN",
("192.168.1.5", 22): "CLOSED"
}
# Named tuples (more readable)
from collections import namedtuple
ScanResult = namedtuple("ScanResult", ["ip", "port", "status", "service"])
result = ScanResult("192.168.1.1", 80, "OPEN", "HTTP")
print(f"{result.ip}:{result.port} is {result.status} ({result.service})")
5) Control Flow: Automating Security Decisions
If Statements: Risk-Based Decision Making
# CVSS-based severity classification
cvss_score = 8.5
if cvss_score >= 9.0:
severity = "CRITICAL"
action = "Patch immediately"
color = "\033[91m" # Red
elif cvss_score >= 7.0:
severity = "HIGH"
action = "Patch within 7 days"
color = "\033[93m" # Yellow
elif cvss_score >= 4.0:
severity = "MEDIUM"
action = "Patch within 30 days"
color = "\033[94m" # Blue
else:
severity = "LOW"
action = "Patch at next maintenance window"
color = "\033[92m" # Green
print(f"{color}[{severity}] CVSS {cvss_score}: {action}\033[0m")
# Compound conditions (authentication checks)
username = "admin"
password = "P@ssw0rd123!"
is_from_trusted_ip = True
failed_attempts = 0
if username == "admin" and password == "admin":
print("❌ Default credentials - BLOCK")
elif failed_attempts >= 5:
print("❌ Account locked - too many failures")
elif not is_from_trusted_ip:
print("⚠️ Login from untrusted IP - require MFA")
else:
print("✅ Authentication successful")
For Loops: Iterating Over Security Data
# Scanning multiple targets
targets = ["192.168.1.1", "192.168.1.5", "192.168.1.10"]
ports = [22, 80, 443]
print("Starting network scan...")
for target in targets:
print(f"\nScanning {target}...")
for port in ports:
result = scan_port(target, port)
status = "OPEN" if result else "CLOSED"
print(f" Port {port}: {status}")
# Using enumerate (when you need index)
vulns = ["SQLi", "XSS", "CSRF", "SSRF"]
for index, vuln in enumerate(vulns, start=1):
print(f"{index}. {vuln}")
# Range for numeric sequences
print("Scanning ports 1-1024...")
for port in range(1, 1025):
if scan_port(target, port):
print(f"[+] Port {port} is OPEN")
# Dictionary iteration
scan_results = {
"10.0.0.1": {"ports": [80, 443], "os": "Linux"},
"10.0.0.2": {"ports": [22, 3389], "os": "Windows"}
}
for ip, details in scan_results.items():
open_count = len(details["ports"])
print(f"{ip} ({details['os']}): {open_count} open ports")
While Loops: Retry Logic and Persistence
# Connection retry with exponential backoff
import time
def connect_with_retry(host, port, max_attempts=3):
attempts = 0
backoff = 1 # Start with 1 second
while attempts < max_attempts:
try:
print(f"Attempt {attempts + 1}/{max_attempts}: Connecting to {host}:{port}...")
sock = socket.socket()
sock.settimeout(2)
sock.connect((host, port))
sock.close()
print("✅ Connection successful")
return True
except:
attempts += 1
if attempts < max_attempts:
print(f"⚠️ Failed. Waiting {backoff}s before retry...")
time.sleep(backoff)
backoff *= 2 # Exponential backoff: 1, 2, 4 seconds
print("❌ All connection attempts failed")
return False
# Interactive menu (continues until user quits)
while True:
print("\n[1] Scan host")
print("[2] View results")
print("[3] Export report")
print("[4] Quit")
choice = input("Select option: ")
if choice == "1":
target = input("Enter target IP: ")
# ... scan logic
elif choice == "2":
# ... view results
pass
elif choice == "3":
# ... export
pass
elif choice == "4":
print("Exiting...")
break
else:
print("❌ Invalid option")
Break, Continue, and Pass
# break: Exit loop immediately
passwords = ["password", "admin", "correct_password", "123456"]
for pwd in passwords:
if try_login(username, pwd):
print(f"✅ Password found: {pwd}")
break # Stop trying more passwords
else:
# This runs if loop completes without break
print("❌ No valid password found")
# continue: Skip to next iteration
for ip in targets:
if ip.startswith("127."): # Skip localhost
continue
scan(ip)
# pass: Placeholder (do nothing)
def advanced_exploit():
pass # TODO: Implement later
for port in range(1, 65536):
# Scanning all ports takes too long, placeholder for now
pass
6) Real-World Security Examples
Example 1: Log Parser with Threat Detection
#!/usr/bin/env python3
"""
Security log analyzer - detects brute force attempts
"""
def analyze_logs(log_file):
"""
Analyze authentication logs for suspicious activity.
Returns:
dict: IP addresses with failed attempt counts
"""
failed_attempts = {}
suspicious_ips = []
with open(log_file, 'r') as f:
for line in f:
if "Failed password" in line or "authentication failure" in line:
# Extract IP address (simplified - real regex in Week 4)
parts = line.split("from")
if len(parts) > 1:
ip = parts[1].split()[0].strip()
# Count failures per IP
failed_attempts[ip] = failed_attempts.get(ip, 0) + 1
# Flag IPs with >5 failures
if failed_attempts[ip] > 5 and ip not in suspicious_ips:
suspicious_ips.append(ip)
print(f"⚠️ ALERT: {ip} has {failed_attempts[ip]} failed attempts")
return failed_attempts, suspicious_ips
# Usage
if __name__ == "__main__":
attempts, suspicious = analyze_logs("/var/log/auth.log")
print(f"\n📊 Summary:")
print(f"Total unique IPs with failures: {len(attempts)}")
print(f"Suspicious IPs (>5 failures): {len(suspicious)}")
print(f"\nTop offenders:")
sorted_ips = sorted(attempts.items(), key=lambda x: x[1], reverse=True)
for ip, count in sorted_ips[:10]:
print(f" {ip}: {count} attempts")
Example 2: Multi-Target Port Scanner with Progress
#!/usr/bin/env python3
"""
Advanced port scanner with multiple targets and progress tracking
"""
import socket
from datetime import datetime
def scan_port(host, port, timeout=1):
"""Check if a single port is open."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
except:
return False
def scan_host(host, ports):
"""
Scan multiple ports on a single host.
Returns:
dict: Scan results with open/closed status
"""
results = {"host": host, "open": [], "closed": [], "timestamp": str(datetime.now())}
total = len(ports)
for index, port in enumerate(ports, 1):
# Progress indicator
progress = (index / total) * 100
print(f"\r[{progress:5.1f}%] Scanning {host}:{port}...", end="", flush=True)
if scan_port(host, port):
results["open"].append(port)
else:
results["closed"].append(port)
print() # New line after progress
return results
def scan_network(targets, ports):
"""Scan multiple targets."""
all_results = {}
print(f"🔍 Scanning {len(targets)} targets on {len(ports)} ports...")
print(f"Started: {datetime.now()}\n")
start_time = datetime.now()
for target in targets:
print(f"\n--- Scanning {target} ---")
results = scan_host(target, ports)
all_results[target] = results
# Summary
print(f"✅ Open ports: {results['open'] if results['open'] else 'None'}")
elapsed = (datetime.now() - start_time).total_seconds()
print(f"\n⏱️ Total scan time: {elapsed:.2f} seconds")
return all_results
if __name__ == "__main__":
# Example usage
targets = ["scanme.nmap.org", "example.com"]
common_ports = [21, 22, 23, 80, 443, 3389, 8080]
results = scan_network(targets, common_ports)
# Find all hosts with port 80 open
web_servers = [host for host, data in results.items() if 80 in data["open"]]
print(f"\n🌐 Web servers found: {web_servers}")
Example 3: Password Strength Validator
#!/usr/bin/env python3
"""
Enterprise password policy enforcer
"""
def check_password_strength(password, username="", company=""):
"""
Validate password against security policy.
Returns:
tuple: (score out of 10, list of issues, list of suggestions)
"""
score = 0
issues = []
suggestions = []
# Length check
if len(password) < 8:
issues.append("Password is too short (minimum 8 characters)")
suggestions.append("Use at least 8 characters")
elif len(password) >= 12:
score += 2
elif len(password) >= 8:
score += 1
# Character variety
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
has_special = any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in password)
if has_upper:
score += 2
else:
issues.append("No uppercase letters")
suggestions.append("Add uppercase letters (A-Z)")
if has_lower:
score += 2
else:
issues.append("No lowercase letters")
suggestions.append("Add lowercase letters (a-z)")
if has_digit:
score += 2
else:
issues.append("No numbers")
suggestions.append("Add numbers (0-9)")
if has_special:
score += 2
else:
issues.append("No special characters")
suggestions.append("Add special characters (!@#$%)")
# Common password check
common_passwords = {
"password", "admin", "123456", "qwerty", "letmein",
"welcome", "monkey", "dragon", "master", "sunshine"
}
if password.lower() in common_passwords:
score = 0
issues.append("This password is in the top 100 most common passwords!")
suggestions.append("Use a unique, hard-to-guess password")
# Check if password contains username or company name
if username and username.lower() in password.lower():
score -= 2
issues.append(f"Password contains username '{username}'")
suggestions.append("Don't use your username in password")
if company and company.lower() in password.lower():
score -= 2
issues.append(f"Password contains company name '{company}'")
suggestions.append("Don't use company name in password")
# Sequential characters check
if "123" in password or "abc" in password.lower():
score -= 1
issues.append("Contains sequential characters")
suggestions.append("Avoid sequential patterns (123, abc)")
# Ensure score is between 0-10
score = max(0, min(10, score))
return score, issues, suggestions
# Test the validator
if __name__ == "__main__":
test_passwords = [
("admin", "admin", "AcmeCorp"),
("Password1!", "john", "AcmeCorp"),
("MyC0mp@nyP@ss", "john", "AcmeCorp"),
("xK9#mP2!qL5@", "john", "AcmeCorp")
]
for pwd, user, company in test_passwords:
score, issues, suggestions = check_password_strength(pwd, user, company)
print(f"\n{'='*60}")
print(f"Password: {'*' * len(pwd)} ({len(pwd)} chars)")
print(f"Strength: {score}/10", end="")
if score >= 8:
print(" ✅ STRONG")
elif score >= 6:
print(" ⚠️ MEDIUM")
else:
print(" ❌ WEAK")
if issues:
print(f"\n❌ Issues found ({len(issues)}):")
for issue in issues:
print(f" - {issue}")
if suggestions:
print(f"\n💡 Suggestions:")
for suggestion in suggestions:
print(f" - {suggestion}")
📝 Lab 2: Security Data Processing
Part 1: Multi-Target Scanner (45 minutes)
Objective: Build a production-ready scanner that tracks results across multiple targets.
Requirements:
- Create
lab2_network_scanner.py - Accept multiple target IPs from command line OR from a file
- Scan each target for a configurable list of ports
- Store results in a nested dictionary structure
- Display progress for each target
- Generate a summary report showing:
- Total hosts scanned
- Hosts with open ports
- Most common open port
- Hosts sorted by number of open ports
- Save results to JSON file
Example usage:
python3 lab2_network_scanner.py 192.168.1.1 192.168.1.5 192.168.1.10
# OR
python3 lab2_network_scanner.py --file targets.txt --ports 21,22,23,80,443
Part 2: Log Analysis Tool (35 minutes)
Objective: Parse security logs and detect patterns.
Create lab2_log_analyzer.py that processes this sample log:
2024-01-18 10:15:23 Failed login: user=admin from=10.0.0.5
2024-01-18 10:15:45 Failed login: user=admin from=10.0.0.5
2024-01-18 10:16:02 Failed login: user=admin from=10.0.0.5
2024-01-18 10:16:15 Successful login: user=admin from=10.0.0.5
2024-01-18 10:17:30 Failed login: user=root from=203.0.113.45
2024-01-18 10:17:45 Failed login: user=root from=203.0.113.45
2024-01-18 10:18:00 Failed login: user=test from=10.0.0.5
2024-01-18 10:19:15 Successful login: user=john from=192.168.1.100
Your tool should:
- Parse each log line into structured data (timestamp, event type, user, IP)
- Count failed attempts per IP address
- Identify IPs with >2 failed attempts (potential brute force)
- Detect successful logins from suspicious IPs (potential breach)
- List top 5 targeted usernames
- Generate an alert report
Expected output:
📊 Log Analysis Report
==================== ========
Total log entries: 8
Unique IPs: 3
Unique users: 4
⚠️ SUSPICIOUS ACTIVITY DETECTED
Potential Brute Force Attempts:
10.0.0.5: 4 failed attempts
203.0.113.45: 2 failed attempts
🚨 CRITICAL: Successful login from suspicious IP:
10.0.0.5 (user: admin) - Had 3 prior failures
Top Targeted Usernames:
1. admin: 4 attempts
2. root: 2 attempts
3. test: 1 attempt
4. john: 1 attempt
Part 3: Password Policy Tester (30 minutes)
Objective: Build an enterprise password validator.
Create lab2_password_checker.py with these rules:
- Minimum 10 characters
- Must have uppercase, lowercase, number, special char
- Cannot be in common password list (provide at least 20)
- Cannot contain username or company name
- Cannot have repeated characters (e.g., "aaa", "111")
Test with these passwords:
test_cases = [
("admin", "admin", "TechCorp"),
("TechCorp2024!", "john", "TechCorp"),
("MyP@ssw0rd", "john", "TechCorp"),
("Tr0ub4dor&3", "john", "TechCorp"),
("correct horse battery staple", "john", "TechCorp")
]
Part 4: Vulnerability Prioritizer (20 minutes)
Objective: Sort and filter vulnerability data.
Given this vulnerability list:
vulnerabilities = [
{"cve": "CVE-2023-1234", "cvss": 9.8, "type": "RCE", "asset": "webserver-01"},
{"cve": "CVE-2023-5678", "cvss": 7.5, "type": "SQLi", "asset": "db-01"},
{"cve": "CVE-2023-9012", "cvss": 6.1, "type": "XSS", "asset": "webapp-01"},
{"cve": "CVE-2023-3456", "cvss": 9.0, "type": "Auth Bypass", "asset": "api-01"},
{"cve": "CVE-2023-7890", "cvss": 4.3, "type": "Info Disc", "asset": "webserver-02"}
]
Create lab2_vuln_priority.py that:
- Sorts vulnerabilities by CVSS score (highest first)
- Filters to show only CRITICAL (CVSS >= 9.0)
- Groups vulnerabilities by asset
- Calculates average CVSS per asset
- Recommends patching order
Success Criteria
- ✅ Comfortable with lists, dictionaries, sets, tuples
- ✅ Can write complex if/for/while statements
- ✅ Can parse and analyze structured text data
- ✅ Can sort, filter, and transform collections
- ✅ Can generate formatted reports from data
- ✅ Understand when to use each data structure
📚 Resources & Further Reading
Essential Reading
- Python Data Structures - Official tutorial
- Common Python Data Structures - Real Python guide
- Control Flow Tools - Official docs
Security-Focused Tutorials
- Python for Cybersecurity: Basic Concepts
- Hacksplaining - Interactive security lessons
Practice Challenges
- HackerRank Python Challenges
- TryHackMe: Python Basics
- Cryptopals Set 1 - Data manipulation challenges
Week 02 Quiz
Test your understanding of Python data structures for security applications.
Format: 10 multiple-choice questions. Passing score: 70%. Time: Untimed.
Take Quiz