Skip to content
CSY105 Week 02 Beginner

Week Content

Programming for Security

Track your progress through this week's content

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:

  1. Create lab2_network_scanner.py
  2. Accept multiple target IPs from command line OR from a file
  3. Scan each target for a configurable list of ports
  4. Store results in a nested dictionary structure
  5. Display progress for each target
  6. Generate a summary report showing:
    • Total hosts scanned
    • Hosts with open ports
    • Most common open port
    • Hosts sorted by number of open ports
  7. 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:

  1. Parse each log line into structured data (timestamp, event type, user, IP)
  2. Count failed attempts per IP address
  3. Identify IPs with >2 failed attempts (potential brute force)
  4. Detect successful logins from suspicious IPs (potential breach)
  5. List top 5 targeted usernames
  6. 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:

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:

  1. Sorts vulnerabilities by CVSS score (highest first)
  2. Filters to show only CRITICAL (CVSS >= 9.0)
  3. Groups vulnerabilities by asset
  4. Calculates average CVSS per asset
  5. Recommends patching order

Success Criteria

📚 Resources & Further Reading

Essential Reading

Security-Focused Tutorials

Practice 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