Secure Coding - Input Validation, SQL Injection Prevention

SecuritySecure CodingFree Lesson

Advertisement

Introduction

Secure coding practices protect applications from common vulnerabilities. This tutorial covers input validation, SQL injection prevention, and other essential security measures.

Input Validation

import re
from typing import Any, List
from pydantic import BaseModel, validator, Field

class UserInput(BaseModel):
    username: str = Field(..., min_length=3, max_length=50)
    email: str
    age: int = Field(..., ge=0, le=150)
    password: str = Field(..., min_length=8)
    
    @validator('username')
    def validate_username(cls, v):
        if not re.match(r'^[a-zA-Z0-9_]+$', v):
            raise ValueError('Username can only contain letters, numbers, and underscores')
        return v
    
    @validator('email')
    def validate_email(cls, v):
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(pattern, v):
            raise ValueError('Invalid email format')
        return v

def validate_input(value: str, pattern: str) -> bool:
    """Validate input against regex pattern."""
    return bool(re.match(pattern, value))

def sanitize_input(text: str) -> str:
    """Remove potentially dangerous characters."""
    return re.sub(r'[<>\"\'%;()&+]', '', text)

SQL Injection Prevention

# Using parameterized queries - SAFE
def get_user_by_id(user_id: int):
    query = "SELECT * FROM users WHERE id = %s"
    cursor.execute(query, (user_id,))

# Using ORM - SAFE
def get_user_by_username(username: str):
    return User.query.filter_by(username=username).first()

# Dynamic query construction - DANGEROUS
def get_user_dangerous(username: str):
    query = f"SELECT * FROM users WHERE username = '{username}'"  # NEVER DO THIS
    return cursor.execute(query)

# Using SQLAlchemy with proper escaping
from sqlalchemy import text

def search_users(search_term: str):
    query = text("SELECT * FROM users WHERE username LIKE :search")
    result = session.execute(query, {"search": f"%{search_term}%"})
    return result.fetchall()

Command Injection Prevention

import subprocess
import shlex

# Using list arguments - SAFE
def list_files_safe(directory: str):
    result = subprocess.run(
        ['ls', '-la', directory],
        capture_output=True,
        text=True,
        shell=False
    )
    return result.stdout

# Using shell=True - DANGEROUS
def list_files_dangerous(directory: str):
    result = subprocess.run(
        f'ls -la {directory}',  # NEVER DO THIS
        shell=True,
        capture_output=True
    )
    return result.stdout

# Using shlex for shell commands
def safe_shell_command(cmd: str, args: List[str]):
    escaped_args = [shlex.quote(arg) for arg in args]
    full_cmd = f"{cmd} {' '.join(escaped_args)}"
    return subprocess.run(full_cmd, shell=True, capture_output=True)

Path Traversal Prevention

import os
from pathlib import Path

def safe_read_file(base_dir: str, filename: str):
    """Safely read a file preventing path traversal."""
    base_path = Path(base_dir).resolve()
    target_path = (base_path / filename).resolve()
    
    # Check if resolved path is under base directory
    if not target_path.is_relative_to(base_path):
        raise ValueError("Invalid file path")
    
    return target_path.read_text()

def validate_filename(filename: str) -> bool:
    """Validate filename to prevent path traversal."""
    dangerous_patterns = ['..', '~', '/', '\\', '\x00']
    return not any(pattern in filename for pattern in dangerous_patterns)

Practice Problems

  1. Implement a comprehensive input validation middleware
  2. Create a safe file upload handler with type checking
  3. Add CSRF token validation to forms
  4. Implement rate limiting for API endpoints
  5. Create a security header middleware

Advertisement

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement