Secure by Default: XSS/CSRF/SQLi Crash Course for Coders — copy-paste sanitization & middleware.

Dive into this ultimate guide to web security fundamentals. From understanding the threats of Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), and SQL Injection (SQLi) to implementing copy-paste ready sanitization functions and middleware solutions. Designed for coders who want to secure their applications by default, with clear logic, real-world examples, and code in multiple languages like JavaScript, Python, and PHP.

Sep 12, 2025 - 23:24
Sep 14, 2025 - 21:38
 0  2
Secure by Default: XSS/CSRF/SQLi Crash Course for Coders — copy-paste sanitization & middleware.

Secure by Default: XSS/CSRF/SQLi Crash Course for Coders — copy‑paste sanitization & middleware.

```

Safety note for this article: All potentially dangerous payloads are shown as escaped text inside blocks. There are no live One‑off execution via crafted link. Stored Payload is saved in a database and served to other users. Persistent impact across many views. DOM‑based Vulnerability exists purely in client‑side JS manipulating the DOM unsafely. // avoid: document.write(location.hash) Client‑side execution without server round‑trip.

Examples & gotchas

  • Context matters: HTML text, attributes, JS strings, CSS, and URLs all require different escaping.
  • Frameworks like React/Angular/Vue auto‑escape by default. Avoid raw HTML sinks (e.g., dangerouslySetInnerHTML, v-html).
  • Unicode/encoding tricks exist. Normalize to UTF‑8 and prefer vetted libraries.

Copy‑Paste Sanitization for XSS

Node.js (server‑side) using DOMPurify + JSDOM: ```

const DOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = new JSDOM('').window;
const purify = DOMPurify(window);

function sanitizeHTML(input) {
  if (typeof input !== 'string') return input;
  return purify.sanitize(input, {
    ALLOWED_TAGS: ['p','b','i','em','strong','ul','ol','li','code','pre','a'],
    ALLOWED_ATTR: { a: ['href','rel','target'] }
  });
}
```

Python (Flask) using markupsafe / bleach: ```

from markupsafe import escape
from flask import Flask, request
import bleach

app = Flask(__name__)

ALLOWED_TAGS = ['p','b','i','em','strong','ul','ol','li','code','pre','a']
ALLOWED_ATTRS = { 'a': ['href','rel','target'] }

def sanitize_rich(text: str) -> str:
    return bleach.clean(text or '', tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRS)

@app.route('/search')
def search():
    q = request.args.get('q','')
    # Plain text context:
    return f"You searched for: {escape(q)}"
```

PHP: use context‑aware escaping when outputting untrusted data. ```


```

Middleware for XSS Protection

Express.js — global headers + on‑write sanitization: ```

const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(express.json());
app.use(helmet({ contentSecurityPolicy: { useDefaults: true } }));

app.use((req, res, next) => {
  if (req.body && typeof req.body === 'object') {
    for (const k of Object.keys(req.body)) {
      req.body[k] = sanitizeHTML(req.body[k]);
    }
  }
  next();
});
```

CodeIgniter 4 — enable the built‑in ContentSecurityPolicy filter and set auto‑escape in views: ```

// app/Config/Filters.php
public $globals = [
  'before' => ['csrf'],
  'after'  => ['toolbar', 'csp'],
];

// In your views, use esc() for variables:

```

Demystifying CSRF Attacks

What is CSRF?

CSRF abuses the browser’s automatic credential sending (cookies, HTTP auth) to submit unintended state‑changing requests on behalf of an authenticated user.

CSRF Attack Scenarios (escaped)

Escaped example of an auto‑submitting form (do not run as live HTML): ```






```

Tokens & Cookie Defenses

  • Include a unique, unpredictable token with each state‑changing request and verify it server‑side.
  • Set session cookies with SameSite=Lax (or Strict if UX allows), HttpOnly, and Secure.
  • Validate Origin/Referer headers where feasible.

Express + csurf (cookie‑based tokens): ```

const csurf = require('csurf');
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(csurf({ cookie: true }));

app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});
```

Flask (custom): ```

import secrets
from flask import session, request, abort

def get_csrf_token():
    session.setdefault('csrf', secrets.token_urlsafe(32))
    return session['csrf']

def require_csrf():
    token = request.form.get('csrf') or request.headers.get('X-CSRF-Token')
    if not token or token != session.get('csrf'):
        abort(403)
```

Django: enable CsrfViewMiddleware and add {% csrf_token %} in forms (on by default in new projects).

CSRF Middleware Implementation

Apply tokens globally to all non‑idempotent methods (POST/PUT/PATCH/DELETE). For APIs used by SPAs or mobile apps, send the token in a custom header.

SQL Injection: The Silent Killer

What is SQLi?

SQLi occurs when user input is concatenated into SQL, altering query structure. The defense is simple: parameterized queries everywhere, every time.

Types of SQL Injection

Type Description Escaped Example Primary Defense
In‑band (Union/Error) Data returned in the same response. ' UNION SELECT username,password FROM users -- Prepared statements.
Blind Infer via booleans or time delays. AND 1=1 /* or SLEEP(5) */ Input validation + params.
Out‑of‑band Exfiltration via a separate channel. LOAD_FILE(...) INTO OUTFILE ... Least privilege DB user.

SQLi Exploitation Examples (escaped)

Vulnerable pattern (do not use): ```

// ❌ Vulnerable PHP (example only)
// $id = $_GET['id'];
// $sql = "SELECT * FROM users WHERE id = '$id'";
```

Safe patterns: ```

// PHP (PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
$rows = $stmt->fetchAll();

// Node (mysql2)
const [rows] = await conn.execute('SELECT * FROM users WHERE id = ?', [id]);

// Python (sqlite3)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
```

Prepared Statements & Validation

  • Always bind parameters; never concatenate.
  • Whitelist expected formats (e.g., is_int for IDs; enum checks for status fields).
  • Use ORM layers (SQLAlchemy, Sequelize, Eloquent) which parametrize by default.
  • Limit DB privileges for the app user (avoid DROP/ALTER).

Middleware & WAF Patterns

Middleware can enforce schema validation at the edge. A WAF (e.g., ModSecurity/OWASP CRS) can provide an additional safety net for obvious injection patterns. ```

// Express + express-validator
const { body } = require('express-validator');
app.post('/user', [ body('id').isInt(), body('name').trim().escape() ], handler);
```

Best Practices & Secure Coding Habits

  1. Least privilege: restrict DB and filesystem permissions.
  2. Defense in depth: combine escaping, CSP, CSRF tokens, and parameterized queries.
  3. Secure headers: use HSTS, CSP, X‑Content‑Type‑Options, Referrer‑Policy.
  4. Logging & monitoring: centralize logs; alert on anomalies.
  5. Patch management: keep dependencies up to date (npm audit, pip‑audit, composer audit).
  6. Reviews & tests: threat‑model, code review checklists, and automated security scans.
Checklist XSS CSRF SQLi
Input validation Context‑aware escaping Token present/verified Params used everywhere
Middleware/filters CSP + sanitizers Global token enforcement Schema/validators
Testing ZAP active scan Origin/Referer checks sqlmap on dev

Tools & Testing Strategies

  • Static: ESLint Plugin Security, Bandit (Python), Psalm (PHP).
  • Dynamic: OWASP ZAP, Burp Suite Community/Pro, sqlmap (dev only).
  • CI/CD: include security linters and dependency audits in pipelines.

Additional Resources

  • OWASP Cheat Sheet Series: XSS, CSRF, SQL Injection
  • PortSwigger Web Security Academy labs
  • OWASP ModSecurity Core Rule Set (CRS)

This is a clean, production‑safe version with all live payloads removed or escaped, generic domains (example.com) only, and no external calls. ```

What's Your Reaction?

Like Like 0
Dislike Dislike 0
Love Love 0
Funny Funny 0
Angry Angry 0
Sad Sad 0
Wow Wow 0