Bezbednost web aplikacija: osnove

Lekcija 7 od 8 · Osnove weba

Web aplikaciju koristi mnogo ljudi – a neki od njih pokušavaju da je zloupotrebe. Ova lekcija objašnjava najčešće napade i osnovna pravila zaštite: HTTPS, čuvanje lozinki, proveru podataka i zašto se nikada ne veruje onome što stigne iz pregledača.

Pre nego što počneš: potrebno predznanje – HTTP protokol, frontend i backend.
Kako da učiš: svaki primer isprobaj u pregledaču ili komandnoj liniji i uradi vežbe iz lekcije. Primeri su u HTML-u, JavaScript-u i Python-u; za većinu je dovoljan pregledač, a za Python primere instaliran Python 3.

HTTPS i sertifikati

Bez HTTPS-a podaci putuju kao razglednica – svako na putu (npr. u javnoj Wi-Fi mreži) može da ih pročita. HTTPS ih šifruje protokolom TLS i dokazuje da je server pravi:

  • server ima sertifikat koji je potpisalo poverljivo telo (npr. besplatni Let's Encrypt);
  • pregledač proverava sertifikat i prikazuje katanac; ako nešto ne valja – upozorenje preko cele strane;
  • katanac znači da je veza sigurna, a ne da je sajt pošten – i lažni sajtovi imaju HTTPS.

Lozinke se ne čuvaju – čuva se heš

Ispravna aplikacija ne zna tvoju lozinku. U bazi čuva heš: rezultat jednosmerne funkcije iz koje se lozinka ne može vratiti. Pri prijavi se heš upisane lozinke poredi sa sačuvanim.

import hashlib, os

def napravi_hes(lozinka, so=None):
    so = so or os.urandom(16)                                  # slučajna "so" za svakog korisnika
    h = hashlib.pbkdf2_hmac("sha256", lozinka.encode(), so, 200_000)
    return so, h

so, sacuvan = napravi_hes("tajna123")          # pri registraciji: u bazu idu so i heš
_, provera = napravi_hes("tajna123", so)       # pri prijavi: isti postupak sa istom solju
print(provera == sacuvan)                      # True – lozinka je ispravna
_, pogresna = napravi_hes("tajna124", so)
print(pogresna == sacuvan)                     # False

„So“ (salt) obezbeđuje da dva korisnika sa istom lozinkom imaju različit heš, a mnogo ponavljanja (200 000) usporava napadača koji pogađa lozinke. Framework-ovi (Django, ASP.NET Core Identity) ovo rade sami – ne treba pisati svoje.

Najčešći napadi

NapadŠta napadač radiZaštita
SQL injekcijau polje forme upiše deo SQL komande (npr. ' OR '1'='1) koji promeni upit nad bazomparametrizovani upiti / ORM – nikada ne spajati tekst korisnika u SQL
XSS (ubacivanje skripte)u komentar upiše <script> koji se izvrši kod drugih korisnika i ukrade im kolačić„escape“ korisničkog teksta pre prikaza (šabloni to rade automatski), zaglavlje CSP
CSRFlažna stranica natera tvoj pregledač da pošalje zahtev sajtu na kome si prijavljen/aCSRF token u formama, kolačići sa SameSite
pogađanje lozinkiautomatski isprobava hiljade lozinkiograničenje broja pokušaja, jake lozinke, dvofaktorska prijava
phishinglažna stranica koja izgleda kao prava i traži lozinkuproveri adresu, menadžer lozinki, dvofaktorska prijava

Spisak najvažnijih rizika web aplikacija redovno objavljuje organizacija OWASP (Top 10).

Primer: SQL injekcija i ispravan upit

import sqlite3

baza = sqlite3.connect(":memory:")
baza.execute("CREATE TABLE korisnici (ime TEXT, lozinka_hes TEXT)")
baza.execute("INSERT INTO korisnici VALUES ('ana', 'x1'), ('marko', 'x2')")

unos = "nepostojeci' OR '1'='1"          # zlonamerni unos iz forme

# POGREŠNO: tekst korisnika postaje deo SQL komande
upit = f"SELECT ime FROM korisnici WHERE ime = '{unos}'"
print("ranjivo:", baza.execute(upit).fetchall())

# ISPRAVNO: parametar (?) – baza ga tretira samo kao podatak
print("bezbedno:", baza.execute("SELECT ime FROM korisnici WHERE ime = ?", (unos,)).fetchall())

Ranjivi upit je vratio sve korisnike, jer je uslov postao „ime = 'nepostojeci' ILI 1 = 1“, a to je uvek tačno. Parametrizovani upit traži korisnika baš sa tim (čudnim) imenom – i ne nalazi ga.

Pravila za svakog programera

  1. Ne veruj ulazu. Sve što dolazi iz pregledača (forme, URL, kolačići, zaglavlja) može biti izmenjeno – proveri na serveru.
  2. Najmanja prava. Korisnik i program dobijaju samo onoliko pristupa koliko im treba.
  3. Tajne van koda. Lozinke baze i API ključevi idu u podešavanja servera (promenljive okruženja), ne u kod na GitHub-u.
  4. Ažuriraj. Framework-ovi i biblioteke redovno dobijaju bezbednosne zakrpe.
  5. Koristi gotova rešenja. Prijava, heširanje i zaštita formi već postoje u framework-u – ne izmišljaj svoje.
Česte greške i saveti
  • Katanac (HTTPS) štiti vezu, ali ne garantuje da je sajt pošten.
  • Nikada ne spajaj tekst korisnika u SQL upit ili HTML bez obrade.
  • Probaj napade samo na sopstvenoj aplikaciji na svom računaru – na tuđim sajtovima je to zabranjeno i kažnjivo.

Proveri znanje

Otvori kviz

Bezbednost web aplikacija

1. Šta aplikacija čuva u bazi umesto lozinke?




2. Kako se sprečava SQL injekcija?




3. Šta znači katanac u adresnoj liniji?