🎁 Startovací workshop ZDARMAMáte SW problém?
Zpět na blog
Webový vývojBezpečnostOWASPWebBackend

Bezpečnost webových aplikací: OWASP Top 10 v praxi

Lukáš Huso31. března 20269 min čtení
Bezpečnost webových aplikací: OWASP Top 10 v praxi
Photo: Markus Spiske / Unsplash

Bezpečnost webových aplikací není téma, které si může dovolit ignorovat kdokoli, kdo vytváří software pro internet. Každý rok jsou zveřejněny tisíce bezpečnostních incidentů -- od úniků osobních údajů až po kompletní kompromitaci systémů. Většině z nich se dalo předejít dodržením základních bezpečnostních principů.

OWASP (Open Web Application Security Project) publikuje seznam deseti nejkritičtějších bezpečnostních rizik webových aplikací. Aktuální verze z roku 2021 reflektuje současný stav hrozeb. V tomto článku si projdeme každé riziko s reálným příkladem a praktickou prevencí v moderních frameworcích jako Next.js, React a Node.js.

4,88 mil. $
průměrné náklady na únik dat (2024)
43 %
útoků cílí na webové aplikace
200+ dnů
průměrná doba detekce narušení

A01: Broken Access Control (Narušené řízení přístupu)

Řízení přístupu určuje, co může který uživatel dělat. Když selže, uživatelé mohou přistupovat k datům nebo funkcím, ke kterým nemají oprávnění.

Reálný příklad

Uživatel změní ID v URL z /api/orders/123 na /api/orders/124 a získá přístup k objednávce jiného uživatele. Toto se nazývá IDOR (Insecure Direct Object Reference) a je to jedna z nejčastějších zranitelností vůbec.

Prevence

// Špatně -- kontroluje jen, jestli je uživatel přihlášený
app.get('/api/orders/:id', authMiddleware, async (req, res) => {
  const order = await Order.findById(req.params.id);
  res.json(order);
});

// Správně -- ověřuje, že objednávka patří přihlášenému uživateli
app.get('/api/orders/:id', authMiddleware, async (req, res) => {
  const order = await Order.findOne({
    _id: req.params.id,
    userId: req.user.id
  });
  if (!order) return res.status(404).json({ error: 'Not found' });
  res.json(order);
});

Zásady: Vždy ověřujte na serveru, že uživatel má právo k požadované operaci. Nedůvěřujte klientským datům. Používejte deny-by-default přístup -- vše je zakázané, pokud není explicitně povoleno.

A02: Cryptographic Failures (Kryptografické chyby)

Dříve označované jako "Sensitive Data Exposure." Zahrnuje nedostatečnou ochranu citlivých dat -- hesla v plain textu, nezašifrovaná komunikace, slabé hashovací algoritmy.

Reálný příklad

Databáze uložená s hesly hashovanými pomocí MD5 bez salt. Po úniku databáze jsou všechna hesla prolomena během hodin.

Prevence

  • Hesla: Používejte bcrypt nebo Argon2 s dostatečným cost factorem
  • Komunikace: Vždy HTTPS, nastavte HSTS header
  • Citlivá data: Šifrování at rest (AES-256), minimalizujte uchovávání citlivých dat
  • Tokeny: JWT podepisujte silnými klíči, nastavte expiraci
// Hashování hesla s bcrypt v Node.js
import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

async function hashPassword(password) {
  return bcrypt.hash(password, SALT_ROUNDS);
}

async function verifyPassword(password, hash) {
  return bcrypt.compare(password, hash);
}

A03: Injection (Injekce)

SQL injection, NoSQL injection, command injection -- všechny varianty fungují na stejném principu: neošetřený uživatelský vstup je interpretován jako kód nebo příkaz.

Reálný příklad

Přihlašovací formulář, kde uživatelské jméno admin' OR '1'='1 obejde autentizaci, protože se vstup přímo vloží do SQL dotazu.

Prevence

Parametrizované dotazy jsou jediné spolehlivé řešení pro SQL injection:

// Špatně -- přímo vložený vstup (SQL injection)
const query = `SELECT * FROM users WHERE email = '${email}'`;

// Správně -- parametrizovaný dotaz
const query = 'SELECT * FROM users WHERE email = $1';
const result = await pool.query(query, [email]);

V moderních ORM jako Prisma nebo TypeORM je parametrizace automatická, ale pozor na raw queries, které tyto ochrany obcházejí.

Pro NoSQL databáze (MongoDB): Validujte typy vstupu, používejte $eq operátor explicitně a nikdy nepředávejte uživatelský vstup přímo do operátorů dotazu.

A04: Insecure Design (Nezabezpečený návrh)

Toto je nová kategorie v OWASP 2021 a zaměřuje se na chyby v návrhu, ne v implementaci. Žádný počet bezpečnostních oprav nemůže zachránit špatně navržený systém.

Reálný příklad

E-shop umožňuje neomezený počet pokusů o zadání slevového kódu. Útočník brute-force vyzkouší miliony kombinací a najde platné kódy.

Prevence

  • Threat modeling na začátku projektu -- identifikujte, co se může pokazit
  • Rate limiting na všechny kritické endpointy
  • Byznysová logika musí mít bezpečnostní mantinely (maximální počet pokusů, časové limity, ověřování stavu)
  • Princip nejmenších privilegií -- každá komponenta má jen ta oprávnění, která skutečně potřebuje

A05: Security Misconfiguration (Chybná konfigurace)

Nejčastější zranitelnost v praxi. Zahrnuje výchozí hesla, otevřené cloud storage buckety, zbytečně zapnuté služby, verbose chybové zprávy v produkci.

Reálný příklad

Next.js aplikace s ponechaným DEBUG=true, která uživateli zobrazuje kompletní stack trace včetně cest k souborům a názvů databázových tabulek.

Prevence

// next.config.js -- bezpečná konfigurace
const nextConfig = {
  poweredBy: false,  // Odstraní X-Powered-By header
  headers: async () => [
    {
      source: '/(.*)',
      headers: [
        { key: 'X-Frame-Options', value: 'DENY' },
        { key: 'X-Content-Type-Options', value: 'nosniff' },
        { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
        { key: 'Permissions-Policy', value: 'camera=(), microphone=()' },
      ],
    },
  ],
};

Další opatření: Pravidelně aktualizujte závislosti, odstraňte nepotřebné funkce a endpointy, používejte různé konfigurace pro development a produkci, automatizujte kontrolu konfigurace.

A06: Vulnerable and Outdated Components (Zranitelné a zastaralé komponenty)

Moderní aplikace používají desítky až stovky knihoven třetích stran. Každá z nich je potenciálním zdrojem zranitelností.

Reálný příklad

Knihovna log4j v roce 2021 (Log4Shell) -- kritická zranitelnost v jedné z nejpoužívanějších Java knihoven postihla miliony aplikací po celém světě.

Prevence

# Pravidelná kontrola zranitelností v npm závislostech
npm audit

# Automatická oprava známých zranitelností
npm audit fix

# Nástroj pro kontinuální monitoring
npx snyk test
  • Automatizujte kontroly pomocí GitHub Dependabot nebo Snyk
  • Aktualizujte pravidelně -- nechejte si zapnout automatické PR s aktualizacemi
  • Odstraňte nepoužívané závislosti -- každá knihovna navíc je potenciální riziko
  • Zamykejte verze v produkci pomocí lock file (package-lock.json)

A07: Identification and Authentication Failures (Chyby identifikace a autentizace)

Zahrnuje slabá hesla, chybějící víceúrovňové ověření, nesprávné řízení session.

Reálný příklad

Aplikace umožňuje neomezený počet pokusů o přihlášení bez jakéhokoli omezení. Útočník použije credential stuffing (databáze uniklých hesel) a získá přístup k účtům.

Prevence

  • Implementujte rate limiting na přihlašovací endpointy (např. 5 pokusů za 15 minut)
  • Vyžadujte silná hesla (minimálně 8 znaků, kontrola vůči databázi uniklých hesel)
  • Podporujte MFA (vícefaktorové ověření), ideálně jako povinné pro administrátory
  • Bezpečný session management: httpOnly cookies, secure flag, SameSite atribut, rozumná expirace
// Bezpečné nastavení session cookie
const sessionConfig = {
  httpOnly: true,     // Nepřístupné z JavaScriptu
  secure: true,       // Jen přes HTTPS
  sameSite: 'strict', // Ochrana proti CSRF
  maxAge: 24 * 60 * 60 * 1000, // 24 hodin
  path: '/',
};

A08: Software and Data Integrity Failures (Chyby integrity softwaru a dat)

Zahrnuje situace, kdy aplikace spoléhá na nedůvěryhodné zdroje -- nezajištěné CI/CD pipelines, neověřené aktualizace, deserializace nedůvěryhodných dat.

Reálný příklad

Útok na SolarWinds v roce 2020 -- útočníci kompromitovali build pipeline a vložili malware do legitimní aktualizace, která byla distribuována tisícům organizací.

Prevence

  • Ověřujte integritu závislostí pomocí kontrolních součtů (lock files, Subresource Integrity pro CDN)
  • Zabezpečte CI/CD pipeline -- minimální oprávnění, audit log, oddělení prostředí
  • Neprovádějte deserializaci nedůvěryhodných dat bez validace
  • Code review pro všechny změny před merge do hlavní větve

A09: Security Logging and Monitoring Failures (Nedostatečné logování a monitoring)

Bez správného logování a monitoringu nemáte šanci zjistit, že byl váš systém kompromitován. Průměrný čas detekce narušení je 200+ dnů.

Reálný příklad

Útočník postupně exfiltruje data po dobu šesti měsíců. Nikdo si nevšimne, protože aplikace neloguje neúspěšné přihlášení, přístup k citlivým datům ani neobvyklé vzorce chování.

Prevence

  • Logujte všechny bezpečnostně relevantní události: přihlášení (úspěšná i neúspěšná), změny oprávnění, přístup k citlivým datům, chyby validace
  • Nelogujte citlivá data: hesla, tokeny, osobní údaje do logů nepatří
  • Nastavte alerting: automatická upozornění na podezřelé aktivity (např. 100 neúspěšných přihlášení za minutu)
  • Centralizujte logy a chraňte je před manipulací
// Příklad bezpečnostního logu
function logSecurityEvent(event) {
  const logEntry = {
    timestamp: new Date().toISOString(),
    type: event.type,     // 'auth_failure', 'access_denied', 'rate_limit'
    userId: event.userId,
    ip: event.ip,
    userAgent: event.userAgent,
    resource: event.resource,
    details: event.details,
  };
  // Odeslat do centralizované logovací služby
  securityLogger.warn(logEntry);
}

A10: Server-Side Request Forgery (SSRF)

SSRF umožňuje útočníkovi přimět server, aby odeslal HTTP požadavek na libovolnou adresu -- včetně interních služeb, které nejsou přístupné z internetu.

Reálný příklad

Funkce "import z URL" umožňuje uživateli zadat URL obrázku. Útočník zadá http://169.254.169.254/latest/meta-data/ a získá AWS metadata včetně přístupových klíčů.

Prevence

  • Validujte a sanitizujte všechny URL zadané uživateli
  • Používejte allowlist povolených domén a protokolů
  • Blokujte privátní IP rozsahy (10.x.x.x, 172.16-31.x.x, 192.168.x.x, 169.254.x.x)
  • Nepředávejte raw odpovědi zpět uživateli
import { URL } from 'url';

function isUrlSafe(input) {
  try {
    const url = new URL(input);
    // Povolit jen HTTPS
    if (url.protocol !== 'https:') return false;
    // Blokovat privátní IP
    const hostname = url.hostname;
    if (hostname === 'localhost' || hostname === '127.0.0.1') return false;
    if (hostname.startsWith('10.')) return false;
    if (hostname.startsWith('192.168.')) return false;
    if (hostname.startsWith('169.254.')) return false;
    // Další kontroly...
    return true;
  } catch {
    return false;
  }
}

Bezpečnost jako proces, ne jednorázový úkol

Nejdůležitější poznatek z OWASP Top 10 je, že bezpečnost není něco, co vyřešíte jedním auditem nebo jedním nástrojem. Je to kontinuální proces:

  1. Threat modeling při návrhu -- identifikujte rizika ještě před začátkem vývoje
  2. Bezpečné kódovací standardy -- celý tým musí znát a dodržovat základní pravidla
  3. Automatizované testování -- SAST (statická analýza), DAST (dynamické testování), kontrola závislostí
  4. Code review se zaměřením na bezpečnost -- každý PR by měl projít kontrolou bezpečnostních aspektů
  5. Penetrační testování -- pravidelné testování externím týmem
  6. Incident response plan -- víte, co dělat, když se něco stane

Vybudujte kulturu security-first vývoje. Bezpečnost nesmí být úkol na konec projektu — musí být součástí každého code review, každého návrhu a každého sprintu. Začněte threat modelingem při návrhu, automatizujte bezpečnostní testy v CI/CD a pravidelně školte celý tým. Jedna hodina prevence ušetří stovky hodin řešení incidentu.

Závěr

OWASP Top 10 není vyčerpávající seznam všech možných hrozeb, ale pokrývá naprostou většinu reálných útoků. Pokud vaše aplikace eliminuje tato rizika, je zabezpečena lépe než 90 % webu.

Klíčové je nezacházet s bezpečností jako s checklistem, který si odškrtnete před spuštěním. Bezpečnost musí být součástí každé fáze vývoje -- od návrhu přes implementaci, testování až po provoz. A protože bezpečnostní krajina se neustále vyvíjí, je dobré mít v týmu nebo po ruce někoho, kdo se v této oblasti orientuje a drží krok s aktuálním vývojem.

Spočítejte si cenu na míru

Konfigurátor vám za 2 minuty ukáže orientační cenu přesně pro váš projekt.

Související články

Performance optimalizace webových aplikací
Webový vývojPerformanceWeb

Performance optimalizace webových aplikací

Praktický průvodce optimalizací výkonu webových aplikací. Core Web Vitals, optimalizace obrázků, code splitting, caching a měření reálného výkonu.

5. května 20269 min čtení
SEO katastrofy: Weby, které Google nenajde

SEO katastrofy: Weby, které Google nenajde

Skutečné příběhy SEO katastrof — od neviditelných SPA po nákup tisíců zpětných odkazů. Jak nezničit svůj web v očích Googlu.

9. dubna 20266 min čtení
Hostingové horory: Proč záleží, kde běží vaše appka
Webový vývojHostingServer

Hostingové horory: Proč záleží, kde běží vaše appka

Aplikace na notebooku pod stolem, hosting za 50 Kč co nezvládne 100 uživatelů, poskytovatel co zkrachoval přes noc. Příběhy z praxe.

7. května 20266 min čtení