LEVEL 3

Web Security Fundamentals

Beginner

🎯 Learning Objectives

📋 OWASP Top 10 Overview

The OWASP (Open Web Application Security Project) Top 10 is a standard awareness document for developers and web application security. It represents a broad consensus about the most critical security risks to web applications.

A01:2021

Broken Access Control

Users acting outside their intended permissions.

A02:2021

Cryptographic Failures

Failures related to cryptography leading to data exposure.

A03:2021

Injection

SQL, NoSQL, OS command injection flaws.

A04:2021

Insecure Design

Missing or ineffective security controls.

A05:2021

Security Misconfiguration

Improperly configured permissions or settings.

A06:2021

Vulnerable Components

Using components with known vulnerabilities.

A07:2021

Auth Failures

Broken authentication mechanisms.

A08:2021

Data Integrity Failures

Software and data integrity failures.

A09:2021

Logging Failures

Insufficient logging and monitoring.

A10:2021

SSRF

Server-Side Request Forgery.

💉 SQL Injection Defense

SQL Injection occurs when user input is incorrectly filtered or not strongly typed. Attackers can manipulate SQL queries to access unauthorized data.

⚠️ Vulnerable Code Example

# VULNERABLE - Never use this!
# Python with string formatting (DANGEROUS)
query = f"SELECT * FROM users WHERE username = '{username}'"

# This allows attackers to inject malicious SQL:
# Input: ' OR '1'='1
# Result: SELECT * FROM users WHERE username = '' OR '1'='1'

✅ Secure Code Example

# SECURE - Using Parameterized Queries
# Python with SQLite
import sqlite3

def get_user_by_username(username):
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    
    # Parameterized query - user input is treated as data, not code
    query = "SELECT * FROM users WHERE username = ?"
    cursor.execute(query, (username,))
    
    result = cursor.fetchone()
    conn.close()
    return result

# Even if attacker inputs: ' OR '1'='1
# It's treated as a literal string, not SQL code
# SECURE - Using an ORM (SQLAlchemy)
from sqlalchemy.orm import Session

def get_user_by_username(session: Session, username: string):
    # SQLAlchemy automatically parameterizes queries
    user = session.query(User).filter(
        User.username == username
    ).first()
    return user

🛡️ SQL Injection Defenses

  • Use Parameterized Queries - Always use prepared statements
  • Use ORM - Object-Relational Mapping frameworks
  • Input Validation - Validate and sanitize all user input
  • Least Privilege - Database accounts should have minimal permissions
  • Use Stored Procedures - Pre-compiled SQL in the database
  • Escape Special Characters - If parameterization isn't possible

🔴 XSS (Cross-Site Scripting) Defense

XSS attacks inject malicious scripts into web pages viewed by other users. It occurs when applications include untrusted data in web pages without proper validation or escaping.

Types of XSS

💾 Stored XSS

Malicious script is permanently stored on the target server (e.g., in a database).

Example: Malicious script saved in a comment or user profile.

🔄 Reflected XSS

Malicious script is reflected off the web server, e.g., in error messages or search results.

Example: Malicious URL with script in query parameter.

⚡ DOM-based XSS

Occurs entirely on the client side, manipulating the DOM.

Example: JavaScript reading from URL and writing to page.

⚠️ Vulnerable Code


Welcome,

✅ Secure Code


Welcome,
Welcome, {{ name | escape }}
Welcome, {name}
{/* React automatically escapes content */}
// SECURE - JavaScript Context
// Use textContent instead of innerHTML
const userInput = '';
element.textContent = userInput; // Safe!

// AVOID: element.innerHTML = userInput; // Dangerous!

🛡️ XSS Defenses

  • Output Encoding - Encode data before displaying
  • Content Security Policy (CSP) - Restrict script sources
  • HTTPOnly Cookies - Prevent JavaScript access to cookies
  • Input Validation - Validate but don't rely on it alone
  • Use Modern Frameworks - Most handle escaping automatically

🎣 CSRF (Cross-Site Request Forgery) Defense

CSRF tricks authenticated users into submitting malicious requests without their knowledge. The browser automatically sends cookies, making the forged request appear legitimate.

⚠️ How CSRF Works

# Attack Scenario:
# 1. User logs into bank.com and has valid session cookie
# 2. User visits attacker.com (in another tab)
# 3. attacker.com contains:


# 4. Browser sends the request WITH bank.com cookies
# 5. Bank processes the transfer thinking it's legitimate

✅ CSRF Defense Implementation

# Python/Flask - CSRF Token
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])

# In templates:
{{ form.hidden_tag() }} {# CSRF token #} {{ form.username() }} {{ form.password() }}
// JavaScript - Double Submit Cookie Pattern
// 1. Server sets CSRF cookie
document.cookie = "csrftoken=abc123; SameSite=Strict";

// 2. JavaScript reads cookie and adds to request
function makeRequest(url, data) {
    const csrfToken = getCookie('csrftoken');
    
    return fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': csrfToken
        },
        body: JSON.stringify(data)
    });
}

🛡️ CSRF Defenses

  • CSRF Tokens - Unique per-session tokens
  • SameSite Cookies - Set Cookie: SameSite=Strict
  • Referer Validation - Check request origin
  • Custom Headers - Require custom header for state-changing requests
  • Re-authentication - Require password for sensitive actions

✅ Input Validation

All user input should be validated and sanitized. This is the first line of defense against many attacks.

Validation Strategies

# Python - Input Validation Example
import re
from typing import Optional

def validate_email(email: str) -> bool:
    """Validate email format."""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

def validate_username(username: str) -> Optional[str]:
    """Validate username and return error message if invalid."""
    if len(username) < 3:
        return "Username must be at least 3 characters"
    if len(username) > 20:
        return "Username must be at most 20 characters"
    if not re.match(r'^[a-zA-Z0-9_]+$', username):
        return "Username can only contain letters, numbers, and underscores"
    return None  # Valid

def sanitize_input(user_input: str) -> str:
    """Remove potentially dangerous characters."""
    # Remove null bytes
    sanitized = user_input.replace('\x00', '')
    # Strip leading/trailing whitespace
    sanitized = sanitized.strip()
    return sanitized

🔒 Security Headers

HTTP security headers help protect browsers against certain types of attacks.

Header Purpose Recommended Value
Content-Security-Policy Prevents XSS by controlling resource sources default-src 'self'
X-Content-Type-Options Prevents MIME-type sniffing nosniff
X-Frame-Options Prevents clickjacking DENY or SAMEORIGIN
Strict-Transport-Security Enforces HTTPS max-age=31536000
X-XSS-Protection Legacy XSS filter (deprecated) 1; mode=block
Referrer-Policy Controls referrer information strict-origin-when-cross-origin
# Example: Apache Configuration (.htaccess)

    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted.cdn.com"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"

🎯 Mini Project: Security Scanner

Build a Python script that checks for common security misconfigurations:

import requests
from urllib.parse import urlparse

def check_security_headers(url: str) -> dict:
    """Check for security headers on a website."""
    headers_to_check = {
        'Content-Security-Policy': 'Content Security Policy',
        'X-Content-Type-Options': 'X-Content-Type-Options',
        'X-Frame-Options': 'X-Frame-Options',
        'ecurity': 'HSTS',
        'Referrer-Policy': 'Referrer Policy',
Strict-Transport-S        'X-XSS-Protection': 'X-XSS-Protection'
    }
    
    result = {'url': url, 'headers': {}, 'issues': []}
    
    try:
        response = requests.get(url, timeout=10)
        
        for header, name in headers_to_check.items():
            if header in response.headers:
                result['headers'][name] = '✅ Present'
            else:
                result['headers'][name] = '❌ Missing'
                result['issues'].append(f"Missing: {name}")
        
        # Check HTTPS
        if url.startswith('http://'):
            result['issues'].append("Not using HTTPS")
            
    except Exception as e:
        result['issues'].append(f"Error: {str(e)}")
    
    return result

# Example usage
url = "https://example.com"
result = check_security_headers(url)
print(f"Security Check for: {result['url']}")
print("\nHeaders:")
for header, status in result['headers'].items():
    print(f"  {header}: {status}")
print("\nIssues Found:")
for issue in result['issues']:
    print(f"  ⚠️ {issue}")

Requirements:

  • Check for security headers
  • Verify HTTPS is enabled
  • Check for common vulnerabilities
  • Generate a security report

🏋️ Practice Challenge

Challenge: Secure a Web Application

Given a vulnerable Flask application, implement proper security controls:

  1. Add CSRF protection to all forms
  2. Implement parameterized queries
  3. Add output encoding for user data
  4. Configure security headers
  5. Add input validation

📝 Summary

Key Takeaways:

  • OWASP Top 10 lists the most critical web application security risks
  • SQL Injection is prevented by using parameterized queries
  • XSS is prevented by output encoding and CSP headers
  • CSRF is prevented by using tokens and SameSite cookies
  • Security headers provide additional layers of protection
  • Input validation should be used but never relied upon as sole defense

Vocabulary:

  • OWASP - Open Web Application Security Project
  • SQLi - SQL Injection attack
  • XSS - Cross-Site Scripting
  • CSRF - Cross-Site Request Forgery
  • CSP - Content Security Policy