Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Full-stack web security workshop

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Full-stack web security workshop

In this 1-day workshop, we will set up a server to discuss and demonstrate security problems and solutions at every layer of the deployment stack, from cloud infrastructure all the way through firewalls, SSH & TLS config, SQLi, validation & escaping, XSS, CSRF, SSRF, cookies, and more, using a series of examples in vanilla PHP and JavaScript.

We will also look at numerous testing tools to help check what you're doing is actually working!

This version of the workshop was presented at the 2026 International PHP Conference in Munich on October 30th, 2026, as part of Agentic Web Week.

Avatar for Marcus Bointon

Marcus Bointon

October 31, 2026

More Decks by Marcus Bointon

Other Decks in Technology

Transcript

  1. Marcus Bointon Skier Songwriter Author of "The HTTP/3 Book" PHPMailer

    maintainer, Laravel dev Radically Open Security Pentests, code audits
  2. Workshop plan Infrastructure Server con g App back-end security App

    front-end security fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  3. fl Host names in hakr.lol 1. hiro 8. case 15.bishop

    2. acid 9. ash 16.kevin 3. zero 10. ynn 17. luther 4. solo 11.elliot 18.plague 5. robot 12.lisbeth 19.chloe 6. crash 13.mikael 7. trinity 14.david Full-stack web security – IPC Munich 2026 Marcus Bointon
  4. Prerequisites • Laptop with WiFi • macOS, Linux, Windows preferably

    with WSL • Terminal app • Up-to-date SSH client • Optional: IDE, Burp Suite, ZAP Full-stack web security – IPC Munich 2026 Marcus Bointon
  5. What we're not covering • General PKI • OAuth 2

    • CORS • DNSSEC, DANE, DoH & DoT • Running a CA, cert pinning • Windows servers • PHP app development! Full-stack web security – IPC Munich 2026 Marcus Bointon
  6. Why are we doing this? • So bad people (or

    people using bad AI) don’t break or abuse our stu • Moral obligation • Especially if it includes data about people • Reliability • Legal liability, due diligence, privacy by design ff Full-stack web security – IPC Munich 2026 Marcus Bointon
  7. Security & Privacy • Security – “The CIA triad” •

    Con dentiality • Integrity • Availability • Data protection • Using security to protect data • Privacy • Using security to protect data about people • Personal data (GDPR) fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  8. Threat modelling • Who and what are you defending against?

    • Admin accidents • Drive-by opportunists • Criminals • Malicious users or admins • Companies / competitors • Nation states Full-stack web security – IPC Munich 2026 Marcus Bointon
  9. Threat modelling – STRIDE Threat Defence Spoo ng Authenticity Tampering

    Integrity Repudiation Non-repudiation Information disclosure Con dentiality Denial of service Availability Escalation of privilege Authorization fi fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  10. Typical deployment stack Cloud provider AWS Azure GC Infrastructure Network

    Servers Storage Services Database Web Cache Applications NodeJS PHP Python Clients Browsers Apps Attackers Full-stack web security – IPC Munich 2026 Marcus Bointon
  11. Defence in depth • Multiple layers of defence • Avoiding

    single points of failure • Limiting lateral movement • Limiting damage • Limiting ex ltration fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  12. Hosting provider security • Security before you even have a

    server • Network isolation / VPCs / containers • Security groups • DDoS mitigation • Identity Access Management (IAM) Full-stack web security – IPC Munich 2026 Marcus Bointon
  13. Cloud admin demo • Amazon AWS • EC2 • Security

    groups • Route53 • AIM • Too easy to take the chmod 777 route! Full-stack web security – IPC Munich 2026 Marcus Bointon
  14. Remote admin? • Immutable servers? • SSH the default, but

    may not need to expose • Especially database servers • Use bastion / jump hosts • Rate limit, limit source IPs, port knocking Full-stack web security – IPC Munich 2026 Marcus Bointon
  15. Remote admin tools • ssh – secure shell • sftp,

    scp, rsync • mosh – mobile shell • Indestructible terminal sessions, SSH + UDP • tmux • Server-side terminal state: Never lose your place, share terminals • RDP for Windows servers Full-stack web security – IPC Munich 2026 Marcus Bointon
  16. Creating SSH keys • ssh-keygen -t ed25519 • Public key

    in ~/.ssh/id_ed25519.pub • Private key in ~/.ssh/id_ed25519 • Use ssh-agent to manage private keys • Can also use a password manager like 1Password • Require admins to use up to date software Full-stack web security – IPC Munich 2026 Marcus Bointon
  17. SSH config files • ~/.ssh/config • Local, set connection params,

    users, keys • ~/.ssh/known_hosts • Local, remembers servers you've used before • ~/.ssh/authorized_keys • On server, stores public keys that are allowed to connect Full-stack web security – IPC Munich 2026 Marcus Bointon
  18. SSH local config • Edit ~/.ssh/config: • Host * •

    IdentityFile ~/.ssh/id_ed25519 Full-stack web security – IPC Munich 2026 Marcus Bointon
  19. Are you sitting comfortably? • SSH client ready? • Windows:

    https://www.chiark.greenend.org.uk/ ~sgtatham/putty/latest.html • Optionally, install openssl locally • Windows: https://wiki.openssl.org/index.php/ Binaries Full-stack web security – IPC Munich 2026 Marcus Bointon
  20. Adding your key to the server • ssh-copy-id ubuntu@<hostname>.hakr.lol •

    You'll need your password, just this once: • <hostname>_0 • SSH passwords are bad! Full-stack web security – IPC Munich 2026 Marcus Bointon
  21. Connect! • ssh ubuntu@<hostname>.hakr.lol • mosh ubuntu@<hostname>.hakr.lol • tmux (

    rst time) • tmux at (reconnect) • Demo fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  22. Sudo • "Substitute user do" • Run commands as any

    user, but most usefully root • May require your password • Unlike su, which needs root's password • Con gured in /etc/sudoers and /etc/sudoers.d/ • Run a command as root with sudo <command> • Become root with sudo su fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  23. Firewall • ufw reset • ufw default deny • ufw

    limit from any to any app OpenSSH • ufw enable • ufw status Full-stack web security – IPC Munich 2026 Marcus Bointon
  24. Hardening SSH • Run ssh-audit <your host name> • less

    /etc/ssh/sshd_config • nano /etc/ssh/sshd_config.d/harden.conf • sshd -t • systemctl restart ssh Full-stack web security – IPC Munich 2026 Marcus Bointon
  25. fail2ban • Scans authentication log les • Creates rewall blocks

    for persistent failures • Can work with any auth system • Con gured for SSH by default • less /etc/fail2ban/jail.local • fail2ban-client status sshd • fail2ban-client unban <ip> Marcus Bointon fi fi fi Full-stack web security – IPC Munich 2026
  26. Updating system packages • apt update • apt list upgradeable

    • apt upgrade or apt full-upgrade • apt install unattended-upgrades - - Full-stack web security – IPC Munich 2026 Marcus Bointon
  27. Running nginx • nginx is already installed from the o

    cial nginx-mainline package archive • Shell script for this workshop: vhost • Symlinks les from /etc/nginx/sites-available to /etc/nginx/ sites-enabled • Checks nginx con g and reloads it • Run vhost 0 • Visit your site in a browser http: <hostname>.hakr.lol/ • ufw allow proto tcp from any to any port 80 • ufw allow proto tcp from any to any port 443 ffi / Marcus Bointon / fi fi Full-stack web security – IPC Munich 2026
  28. Securing services • Transport encryption – TLS • Content encryption

    – GPG email • Signatures – ACME, apt • Obfuscation – ACME, UUIDs Full-stack web security – IPC Munich 2026 Marcus Bointon
  29. What is TLS? • The Transport Layer Security Protocol •

    The "new" name for Secure Socket Layer (SSL) • Since 1999! • A set of standards for security & encryption • Can wrap around any higher-level protocol • HTTP, SMTP, FTP, IMAP, etc • Popular implementations: OpenSSL, LibreSSL, BoringSSL Full-stack web security – IPC Munich 2026 Marcus Bointon
  30. TLS history • SSLv2: 1995 – 2011 • SSLv3: 1996

    – 2015 • TLSv1.0: 1999 – 2020 • TLSv1.1: 2006 – 2020 • TLSv1.2: 2008: AEAD ciphers, SHA256 • TLSv1.3: 2018: ECC, 1/0-RTT, PFS, no more bad stuff! Full-stack web security – IPC Munich 2026 Marcus Bointon
  31. What's in TLS? • Protocols • Hashes • MACs •

    Ciphers • Key exchange Full-stack web security – IPC Munich 2026 Marcus Bointon
  32. Why use TLS? • Provides con dentiality, authenticity, and integrity

    • Better performance with HTTP/2 & HTTP/3 • Increasingly required by integrations, e.g. iOS and Android app back-ends fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  33. Key exchange analogy Alice + Secret colour = Random colour

    + + Exchange intermediate colours = = Secret colour + Common secret = Bob Full-stack web security – IPC Munich 2026 Marcus Bointon
  34. Changes in TLS 1.3 • Removal of weak and legacy

    algorithms & extensions • More encryption • Lower handshake overhead • PFS-only • Elliptic curve ciphers as standard • Downgrade protection Full-stack web security – IPC Munich 2026 Marcus Bointon
  35. TLS keys • RSA (Rivest-Shamir-Adleman): wide support, old, big, slow

    • EC (Elliptic Curve): new, small, fast, strong • Keys are general purpose – not just for HTTPS • Encrypt local les • Digital signatures fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  36. Making TLS keys • umask 077 • RSA key •

    openssl genrsa -out key.pem 4096 • EC key • openssl ecparam -name secp384r1 -genkey -noout -out eckey.pem Full-stack web security – IPC Munich 2026 Marcus Bointon
  37. Public keys • Derived from existing private keys • RSA

    key • openssl rsa -in key.pem -outform PEM -pubout -out public.pem • ECC key • openssl ec -in eckey.pem -pubout -out ecpublic.pem • PEM header same for both: -----BEGIN PUBLIC KEY----Full-stack web security – IPC Munich 2026 Marcus Bointon
  38. Requesting a certificate • Certi cate signing request — CSR

    • openssl req -new -key key.pem -out www.example.com.csr • answer questions • ...or use a con g le • Inspect contents of CSR • openssl req -noout -text -in www.example.com.csr fi fi fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  39. Signing a certificate • Self-signed: • openssl x509 -req -days

    365 -in www.example.com.csr -signkey key.pem -out cert.pem • Inspect the cert: • openssl x509 -text -noout -in cert.pem Full-stack web security – IPC Munich 2026 Marcus Bointon
  40. Signing a certificate • CA public certs (known as root

    certificates) are installed in browsers and OSs, updated frequently • All root certs are self-signed, but are trusted • Can't sign locally — we don't have the CA's private key • Need to send CSR to CA — web or email • Can verify using public key Full-stack web security – IPC Munich 2026 Marcus Bointon
  41. Certificate trust chains • Self-signed == no chain, no authority,

    no trust • But will still encrypt exactly the same way • CAs have trusted self-signed roots • Intermediate certificates • May be cross-signed Full-stack web security – IPC Munich 2026 Marcus Bointon
  42. Certificate trust chains Root CA certi cate Root CA certi

    Browser & OS certi cate store fi fi fi fi fi fi Full-stack web security – IPC Munich 2026 Intermediate CA certi cate Site certi cate Server certi cate store Marcus Bointon
  43. Obtaining a public key • echo | openssl s_client -connect

    www.apple.com:443 2>/dev/null | openssl x509 Full-stack web security – IPC Munich 2026 Marcus Bointon
  44. Certificate Transparency (CT) • CAs post issued certi cates to

    a public transparency log • Browsers now require CT • Security risk — anyone can watch the logs and nd newly-con gured servers, so x con g rst! • But the same mechanism helps defend against phishing fi fi fi fi Marcus Bointon fi fi Full-stack web security – IPC Munich 2026
  45. Certificate Revocation Lists • Revoked certs are added to a

    global CRL which browsers download frequently • The size of this list was growing exponentially, impossible to sustain • OCSP replacement was too hard on CAs • Shorter lifetimes – expired certs don't need revocation Full-stack web security – IPC Munich 2026 Marcus Bointon
  46. Certificate authority protection • Certi cate Authority Authorisation DNS records

    — CAA • Simply names your permitted CAs in your DNS • Mandatory from March 2027 • HTTP Public Key Pinning — HPKP • Di cult, prone to error, potential to cut your site o for months! • DO NOT USE! Marcus Bointon ff fi ffi Full-stack web security – IPC Munich 2026
  47. Let's Encrypt • Free TLS certi cates since 2015! •

    ACME protocol: Automated Certificate Management Environment • certbot – EFF's o cial LetsEncrypt client • acme.sh, acme-tiny.py, boulder (go) • Integrated: Apache mod_md, Caddy • Domain Validation ("DV") • DNS, web root, web module — only over http! ffi fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  48. Nginx verification config server { listen 80; listen [::]:80; server_name

    neo.hakr.lol; root /var/www/html; index index.html; location ^~ /.well-known/acme-challenge { default_type text/plain; root /var/www/letsencrypt; } } Full-stack web security – IPC Munich 2026 Marcus Bointon
  49. Requesting a certificate certbot certonly -w /var/www/letsencrypt -d <hostname>.hakr.lol -post-hook

    'systemctl reload nginx' Shortcut: ./requestcert.sh Full-stack web security – IPC Munich 2026 Marcus Bointon
  50. Using the certificate server { listen 443 ssl; listen [::]:443

    ssl; http2 on; ... ssl_certificate /etc/letsencrypt/live/<hostname>.hakr.lol/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<hostname>.hakr.lol/privkey.pem; location / { try_files $uri $uri/ index2.html; } } Full-stack web security – IPC Munich 2026 Marcus Bointon
  51. Redirect to secure site server { ...# As before in

    port 80 section location / { return 301 https://$host$request_uri; } } Full-stack web security – IPC Munich 2026 Marcus Bointon
  52. Enable the secure site vhost 2 Check the site in

    your browser Full-stack web security – IPC Munich 2026 Marcus Bointon
  53. What's the problem? • We're using a test certificate, so

    we get an error • But we can ignore that because we know why • Everything else will still work Full-stack web security – IPC Munich 2026 Marcus Bointon
  54. Testing TLS • https://www.ssllabs.com/ssltest/ • This takes a while! •

    We are using an untrusted certi cate! • But all other tests are still valid and useful • CLI alternative: https://testssl.sh Marcus Bointon fi Full-stack web security – IPC Munich 2026
  55. "Old" nginx TLS config • Select protocols & ciphers, e.g.

    for legacy browsers & apps: • ssl_protocols TLSv1.2 TLSv1.3; • ssl_prefer_server_ciphers on; • ssl_ciphers '@SECLEVEL=0 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA- AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCMSHA384 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 DHERSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-CHACHA20POLY1305 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSAAES128-SHA ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-RSAAES256-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSAAES128-SHA256 DHE-RSA-AES256-SHA256 AES128-GCM-SHA256 AES256-GCMSHA384 AES128-SHA256 AES256-SHA256 AES128-SHA AES256-SHA DES-CBC3-SHA'; • Mozilla's "old" con g : : : : : : : : : : : : : : : Marcus Bointon : : : : : fi : : : : : : Full-stack web security – IPC Munich 2026
  56. "Old" nginx TLS config vhost 3 Check the site in

    your browser Full-stack web security – IPC Munich 2026 Marcus Bointon
  57. Tightening nginx TLS config • Select protocols & ciphers, e.g.

    for non-legacy browsers & apps: • ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256 ECDHERSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCMSHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSACHACHA20-POLY1305 ECDHE-RSA-CHACHA20POLY1305 DHE-RSA-AES128-GCM-SHA256 DHE-RSAAES256-GCM-SHA384 DHE-RSA-CHACHA20-POLY1305; • ssl_ecdh_curve X25519:secp384r1:prime256v1 X448; • Mozilla's "intermediate" con g : : : : : Marcus Bointon fi : : : : Full-stack web security – IPC Munich 2026
  58. Tightening TLS config vhost 3 Check the site in your

    browser Full-stack web security – IPC Munich 2026 Marcus Bointon
  59. Strict Transport Security • A really important header • Strict-Transport-Security

    "max-age=15552000; includeSubDomains; preload" • Tells browsers to use HTTPS only for your domain until the max-age expires • Even if you include any http URLs — it will convert them (+ CSP) • preload solves the Trust On First Use problem (TOFU) Full-stack web security – IPC Munich 2026 Marcus Bointon
  60. HTTP security headers • X-Content-Type-Options: nosniff • X-XSS-Protection: "0" •

    X-Frame-Options: SAMEORIGIN • Referrer-Policy: no-referrer • Permissions-Policy midi=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), accelerometer=(), fullscreen=(self), payment=(), geolocation=(), usb=(), encrypted-media=() Full-stack web security – IPC Munich 2026 Marcus Bointon
  61. Content Security Policy • Content-Security-Policy: "default-src 'none'; script-src 'self' 'unsafe-inline'

    code.jquery.com 'report-sha256'; connectsrc 'self'; img-src 'self'; style-src 'self'; font-src 'self'; upgradeinsecure-requests; report-to csp-reports" • Lets you control where resources come from • Can block many XSS and malware vectors Full-stack web security – IPC Munich 2026 Marcus Bointon
  62. Header testing tools • https: report-uri.com • Somewhere to send

    reports generated by CSP, etc • https: securityheaders.com • For testing security headers separately from TLS con g / / / / fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  63. Testing secure headers vhost 5 Check the site in securityheaders.com

    Full-stack web security – IPC Munich 2026 Marcus Bointon
  64. Issue a real certificate edit /etc/letsencrypt/cli.ini # Comment out the

    "staging" line with a #, or delete it # Request a new certificate certbot certonly -w /var/www/letsencrypt -d <hostname>.hakr.lol -post-hook 'systemctl reload nginx' Shortcut: ./requestrealcert.sh Full-stack web security – IPC Munich 2026 Marcus Bointon
  65. Stricter TLS for admin sites server { # Limit protocols

    ssl_protocols TLSv1.3; # Allow the client to choose the cipher suite ssl_prefer_server_ciphers off; # Don't need to specify cipher suites # because all in TLSv1.3 are good # ssl_ciphers ... } Full-stack web security – IPC Munich 2026 Marcus Bointon
  66. TLS for admin sites vhost 6 Check the site using

    testssl.sh Full-stack web security – IPC Munich 2026 Marcus Bointon
  67. Certificate Transparency Logs • Every time they issue a cert,

    CAs publish that they have done so • Search for your hostname or domain • https://crt.sh • https://ctlogsearch.com/ • Hackers like this too Full-stack web security – IPC Munich 2026 Marcus Bointon
  68. QUIC & HTTP/3 – nginx server { listen 443 ssl;

    listen [::]:443 ssl; listen 443 quic; listen [::]:443 quic; http2 on; http3 on; add_header Alt-Svc 'h3=":443"; ma=86400' always; ... vhost 7 Full-stack web security – IPC Munich 2026 Marcus Bointon
  69. QUIC & HTTP/3 – firewall • ufw allow proto udp

    from any to any port 443 • ufw status • Also need to allow in cloud provider security group Full-stack web security – IPC Munich 2026 Marcus Bointon
  70. Testing & config tools • Qualys SSL Labs: https://www.ssllabs.com/ssltest/ •

    TestSSL.sh: https://testssl.sh • TLS con g generator: https://ssl-con g.mozilla.org • Mozilla Observatory: https://observatory.mozilla.org • Privacy checker: https://webbkoll.5july.net/ • SSH audit: https://github.com/jtesta/ssh-audit Marcus Bointon fi fi Full-stack web security – IPC Munich 2026
  71. Configuring PHP • PHP has SAPIs – server APIs •

    cgi – old and slow • mod_php for Apache – easiest, but slow • cli – for command line tools like composer • fpm – fastcgi process manager – fast • FrankenPHP – new and faster, but not today! Full-stack web security – IPC Munich 2026 Marcus Bointon
  72. PHP service structure Server Browser Reverse proxy PHP service nginx

    php-fpm app1 Full-stack web security – IPC Munich 2026 pool1 pool2 app2 app3 Marcus Bointon
  73. PHP-FPM pool config • /etc/php/8.5/fpm/pool.d/www.conf • listen = /run/php/php8.5-fpm.sock •

    /status – show PHP-FPM connection stats • /ping – healthcheck, responds with pong Full-stack web security – IPC Munich 2026 Marcus Bointon
  74. Connect PHP to nginx upstream php85 { server unix:/run/php/php8.5-fpm.sock; }

    location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) { return 404; } fastcgi_pass php85; } location /status { fastcgi_pass php85; } location /ping { fastcgi_pass php85; } Full-stack web security – IPC Munich 2026 Marcus Bointon
  75. Testing PHP config vhost 8 Check the site in your

    browser Full-stack web security – IPC Munich 2026 Marcus Bointon
  76. Time to celebrate! • We now have a nicely secured

    server! • Strict cloud and local rewalls • Strong SSH con g • Strong TLS con g • Web service over HTTP/3 • HTTP security headers • PHP working Marcus Bointon fi fi fi Full-stack web security – IPC Munich 2026
  77. Back-end application security • Outdated dependencies • CSP revisited •

    Sanitization, Validation, Escaping • SQL injection • Authentication • Cookies • Authorization Full-stack web security – IPC Munich 2026 Marcus Bointon
  78. Sync example source • Copy all the code examples from

    the server to your local machine: • rsync -avz ubuntu@<host>.hakr.lol:/var/ www/html/ ./examples/ • Open in your IDE Full-stack web security – IPC Munich 2026 Marcus Bointon
  79. Outdated PHP dependencies • Application packages • composer audit •

    composer update • Not usually on deployed apps • Run locally, updates composer.lock, commit and redeploy Full-stack web security – IPC Munich 2026 Marcus Bointon
  80. Outdated PHP dependencies • Pre-emptive updating • composer require dev

    roave/securityadvisories:dev-latest • Declares con icts with packages containing known vulnerabilities - Marcus Bointon - fl Full-stack web security – IPC Munich 2026
  81. Content security policy (CSP) • Content-Security-Policy: "default-src 'none'; script-src 'self'

    'unsafe-inline' code.jquery.com; connect-src 'self'; imgsrc 'self'; style-src 'self'; font-src 'self'; upgrade-insecure-requests; reportto csp-reports" • What does this mean? • Open dev tools, visit /csp.php in your domain Full-stack web security – IPC Munich 2026 Marcus Bointon
  82. CSP reporting • report-uri param lets you know when contraventions

    happen • https: report-uri.com Demo • Content-Security-Policy-Report-Only for testing • Reporting-Endpoints: "csp-reports=https: hakr.report-uri.com/r/d/csp/enforce" • Can also handle in your own apps / Marcus Bointon / / / Full-stack web security – IPC Munich 2026
  83. Sanitization & validation • Sanitize • Remove anything unexpected •

    e.g. non-numeric values, HTML markup • Validate • Check that inputs conform to expected formats • Can include deeper checks, like existence in DB Full-stack web security – IPC Munich 2026 Marcus Bointon
  84. Sanitization & validation //Sanitization $phone = substr(preg_replace('/[^+\d]/, '', $_POST['phone']), 0,

    20); $description = substr(strip_tags($_POST['description'), 0, 255); $email = substr(preg_replace('/[^a-zA-Z\d!#$%&'@*\.+\/=?^_`{|}~-]/', '', $_POST['email']), 0, 255); //Validation $email_valid = filter_var($email, FILTER_VALIDATE_EMAIL); $phone_valid = preg_match('/^[+0]\d{10,15}$/'); See /validation.php Full-stack web security – IPC Munich 2026 Marcus Bointon
  85. Escaping • Context is everything • URL • HTML •

    email • shell – which shell? what encoding? • SQL – which avour? fl Full-stack web security – IPC Munich 2026 Marcus Bointon
  86. Escaping in PHP • URL • rawurlencode($text) • Shell argument

    • escapeshellarg($text) • HTML • htmlspecialchars($text) • SQLite • SQLite3 escapeString($text) • MySQL • mysqli_real_escape_string($mysql, $text) : : Full-stack web security – IPC Munich 2026 Marcus Bointon
  87. Enumeration and IDOR • idor.php?id=5 • What's at idor.php?id=4 ?

    • My data, or someone else's? • Insecure Direct Object Reference: IDOR • Internal object IDs, le names • Apply authorisation checks, ownership • Obfuscate with unguessable UUID / HashID / ULID fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  88. Authentication & Authorisation • Who are you? • Are you

    allowed to do this? • Passwords • Source IP • OAuth 2.0 • Webauthn & PassKeys Full-stack web security – IPC Munich 2026 Marcus Bointon
  89. Passwords • if ($_POST['password'] 'mypassword') • Timing side channel •

    Example: timing.php • Use constant-time comparisons • = = Marcus Bointon = . . . Full-stack web security – IPC Munich 2026
  90. Password hashing • Use a password hash function • Not

    a generic hash like MD5, SHA256, Blake2b • bcrypt, Argon2id, PBKDF2 • Still subject to timing side-channels • PHP password_hash, password_verify, sodium_crypto_pwhash_str, hash_equals Full-stack web security – IPC Munich 2026 Marcus Bointon
  91. OAuth 2.0 • Numerous ows including: • Client credentials (

    xed ID and password) • Password ( xed client with dynamic ID & pass) • Authorisation code (social login) fi fi fl Full-stack web security – IPC Munich 2026 Marcus Bointon
  92. Authorisation • Really a framework feature • Principle of least

    responsibility • Only allow what needs to be allowed • Roles and abilities – RBAC • Assign roles, check abilities Full-stack web security – IPC Munich 2026 Marcus Bointon
  93. SQL injection • A very speci c escaping case... •

    with very bad consequences • /sqli.php?id=1 • $q = 'SELECT * FROM items WHERE id=' . $_GET['id']; • Loop over results, display in table fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  94. SQL injection • Visit /sqli.php • Expecting input to be

    a number, but what if we give something else with meaning in SQL? • Attack string 1 OR 1=1 results in this query: • SELECT id, name FROM items WHERE id=1 OR 1=1 • Edit the le at /var/www/html/sqli.php fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  95. SQL injection – escaping • Explicit escaping • $result =

    $db query('SELECT * FROM items WHERE id=' . $db quote($_GET['id'])); • Parameter binding • $st = $db prepare('SELECT * FROM items WHERE id=?'); $st bindValue(1, $_GET['id'], SQLITE3_NULL); $result = $st execute(); > - > > - - > - > - Full-stack web security – IPC Munich 2026 Marcus Bointon
  96. SQL injection • Avoid manual SQL operations • Use your

    Framework's ORM to provide abstraction • Test your app using https://sqlmap.org/ Full-stack web security – IPC Munich 2026 Marcus Bointon
  97. Cross-site scripting (XSS) • Allowing attackers to inject malicious scripts

    into web pages • Di erent avours • Re ected • Stored • Defend by sanitising, validating, escaping, and CSP fl fl ff Full-stack web security – IPC Munich 2026 Marcus Bointon
  98. Reflected XSS in PHP • Visit /xss.php • Attack string:

    <script>alert(1) script> • Type that into the "unsafe" input and submit it • Now try the same on the "safe" input / Marcus Bointon < Full-stack web security – IPC Munich 2026
  99. Reflected XSS in Javascript • Visit /xss.html • Attack string

    <script>alert(1) script> • Type that into the "unsafe" input and submit it • Now try using • <img src='x' onerror='alert(1)'> • Now try the same on the "safe" input / Marcus Bointon < Full-stack web security – IPC Munich 2026
  100. Reflected XSS in Javascript • Unsafe: • previewElement.innerHTML = userInput

    • Safe: • previewElement.textContent = userInput • Can also write your own escaping function • Use your framework Full-stack web security – IPC Munich 2026 Marcus Bointon
  101. Stored cross-site scripting • Visit /sqli.php • Attack string: <script>alert('boom')

    script> • Search for the new ID • The sqli.php script has two problems! / Marcus Bointon < Full-stack web security – IPC Munich 2026
  102. Cross-Site Request Forgery (CSRF) • A form on a site

    can receive submissions from other locations • If the user that sends it is not logged in, they will not be able to submit it... • But they could trick you into submitting it Full-stack web security – IPC Munich 2026 Marcus Bointon
  103. CSRF example • Visit /csrf.php • Click log in –

    login state saved in a cookie • Now we can submit entries that are added to the DB Full-stack web security – IPC Munich 2026 Marcus Bointon
  104. CSRF example – attacker • Copy the URL (contains form

    data) • Open an incognito window with this URL • Note that it fails as you're not logged in • Edit the URL to contain a new value • Open a new window (non-incognito) • Visit the URL – the amended value is submitted • Try the same thing using your neighbour's site Full-stack web security – IPC Munich 2026 Marcus Bointon
  105. CSRF defence: tokens • Every page load, generate a random

    token and expiry time and save it in the DB • Insert the token value into a hidden input tag • On submit, check that the token exists and has not expired, otherwise reject the request • After handling submission, delete the token in the DB Full-stack web security – IPC Munich 2026 Marcus Bointon
  106. CSRF defence: tokens • Visit /csrfsafe.php • Look at source

    code Full-stack web security – IPC Munich 2026 Marcus Bointon
  107. Other CSRF defences • CSRF can work because cross-origin requests

    will include cookies • Even if the link was presented somewhere else • SameSite cookies x this • Sec-Fetch-Site: same-origin • Set automatically by browsers if origin matches fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  108. Cookies • Open dev tools to the storage tab •

    Visit /cookies.php • Cookie ags: • HttpOnly – not visible to JS • Secure – only over HTTPS • SameSite – only to current domain fl Full-stack web security – IPC Munich 2026 Marcus Bointon
  109. • Secure- • Must have Secure ag • Only accepted

    over HTTPS • Set-Cookie: Secure-SESSIONID=MYSESSION; Secure • Host- • Must not set domain; will only match exactly • Path must be / • Set-Cookie: Host-SESSIONID=MYSESSION; Path=/; Secure fl _ _ _ _ _ Full-stack web security – IPC Munich 2026 _ _ _ Cookie Prefixes Marcus Bointon
  110. A Cookie With Everything Set-Cookie: Host-SESSIONID=MYSESSION; Path=/; Secure; HttpOnly; SameSite=Strict;

    Max-Age=3600; Expires=Fri, 31 Oct 2025 18 00 00 GMT : Marcus Bointon : _ _ Full-stack web security – IPC Munich 2026
  111. Server-Side Request Forgery (SSRF) • Cause a server to fetch

    something from a URL provided by an attacker • e.g. fetch logo image, pull RSS feed, play a music track • Open to abuse, need to be careful • Local le paths: /etc/passwd • Polyglot images, malicious PDFs • Resource consumption – DoS • Server may have access to other non-public servers fi Full-stack web security – IPC Munich 2026 Marcus Bointon
  112. SSRF example • Minimal PHP example: • echo file_get_contents($_GET['url']); •

    Visit /ssrf.php • Defend by strict validation • Block URLs for internal hosts Full-stack web security – IPC Munich 2026 Marcus Bointon
  113. Framing attacks – Clickjacking • Visit /framed.html • Visit /clickjacking.html

    • Looks the same until you click it • Edit clickjacking.html, point it at your neighbour's site • Defend with X-Frame-Options: SAMEORIGIN or CSP frame-ancestors: 'self' Full-stack web security – IPC Munich 2026 Marcus Bointon
  114. Cross-Origin Resource Sharing • Extends same-origin policy selectively e.g. •

    App on www.example.net • API on api.example.com • "You are allowed to see this response" • Only applies to scripted requests • May require pre- ight OPTIONS requests • Insecure: Access-Control-Allow-Origin * • Access-Control-Allow-Methods: GET fl Full-stack web security – IPC Munich 2026 Marcus Bointon
  115. CORS example • Visit /cors.html • Click the buttons; inspect

    the responses • Still works because of same origin rule • Now enter your neighbour's hostname and retry Full-stack web security – IPC Munich 2026 Marcus Bointon
  116. Trust your framework • Delegate everything possible to the framework

    • Reduces code you are responsible for • Improves quality – Framework code gets checked a lot, should have very good test coverage too • Need something slightly di erent? • Build it and make a PR so all can bene t fi Marcus Bointon ff Full-stack web security – IPC Munich 2026
  117. Final notes • This all sounds like a lot, and

    it is • You can't anticipate everything • but you might be able to do enough • Security is a moving target • Practice defence in depth Full-stack web security – IPC Munich 2026 Marcus Bointon
  118. Thank you • https://marcus.bointon.com • Buy my music! • Mastodon:

    @[email protected] • GitHub: Synchro Full-stack web security – IPC Munich 2026 Marcus Bointon