Poglavlje 12: Sigurnost i privatnost po dizajnu

Priča za početak. U martu 2017. godine organizacija koja održava popularnu biblioteku za web aplikacije, Apache Struts, objavila je upozorenje i ispravku za ozbiljnu rupu: napadač je mogao, posebno sastavljenim zahtjevom, natjerati server da izvrši njegov kod. Ispravka je bila dostupna 7. marta 2017. Američka kreditna agencija Equifax, koja čuva finansijske podatke o stotinama miliona ljudi, koristila je Struts na jednom od svojih portala. Interno upozorenje da treba ugraditi ispravku je poslano, ali ispravka nije ugrađena, a automatsko skeniranje koje je trebalo naći neažurirane servere nije ih pronašlo. Od sredine maja napadači su kroz tu rupu ulazili u sistem i iznosili podatke, a Equifax je to primijetio tek krajem jula. Ukradeni su imena, datumi rođenja, brojevi socijalnog osiguranja i adrese za oko 147 miliona ljudi (prva objava govorila je o 143 miliona). Direktor je podnio ostavku, a firma je platila ogromne nagodbe. Napadači nisu koristili nikakvu genijalnu novu tehniku. Ušli su kroz vrata za koja je brava već bila kupljena, ali nije bila ugrađena.

U poglavlju 10 rekli smo da je API vrata sistema i spomenuli četiri brave: HTTPS, token, provjeru prava i ograničenje broja zahtjeva. Ovo poglavlje ide dublje. DeliveryApp čuva adrese i telefone kupaca, istoriju njihovih narudžbi i obavlja plaćanje. To su podaci koje neko može htjeti ukrasti, i obaveze koje zakon nameće. Prvo učimo osnovne ciljeve sigurnosti i kako se korisnik prijavljuje i šta smije. Zatim upoznajemo najčešće slabosti web aplikacija i učimo da prijetnje tražimo sistematski, modelom STRIDE. Na kraju govorimo o privatnosti: šta kaže GDPR, šta znači privatnost po dizajnu i šta se radi kad se incident ipak desi. Na praktičnoj nastavi pravimo model prijetnji za DeliveryApp, heširamo lozinke i popravljamo SQL injekciju.

Literatura. Osnovna literatura predmeta:

  1. B. Popović, K. Kuk: Informacioni sistemi, Kriminalističko-policijski univerzitet, Beograd, 2017.
  2. J. S. Valacich, J. F. George: Modern Systems Analysis and Design, 9th ed., Pearson, 2020.
  3. L. Jelenković: Sustavi za rad u stvarnom vremenu – skripta, FER, Zagreb, 2015.
  4. D. Milićev: Programiranje u realnom vremenu – skripta, Beograd, 2002.
  5. V. Kovačević, M. Popović: Sistemska programska podrška u realnom vremenu 1, FTN, Novi Sad, 2013.

Riječi ovog poglavlja.

  • Povjerljivost, integritet, dostupnost (CIA) – tri cilja sigurnosti: podatak vide samo ovlašteni, niko ga ne mijenja neovlašteno, i dostupan je kad treba.
  • Autentifikacija – provjera ko je korisnik („jeste li vi zaista K-01?”).
  • Autorizacija – provjera šta korisnik smije („smije li K-01 vidjeti N-1002?”).
  • Heš – jednosmjerna funkcija koja od lozinke napravi „otisak” iz kojeg se lozinka ne može vratiti.
  • So (salt) – slučajan dodatak lozinki prije heširanja, različit za svakog korisnika.
  • Višefaktorska autentifikacija (MFA) – prijava s dva ili više dokaza: nešto što znate, imate ili jeste.
  • Ranjivost – slabost u sistemu koju napadač može iskoristiti.
  • OWASP Top 10 – lista deset najčešćih i najopasnijih rizika web aplikacija.
  • SQL injekcija – napad u kojem unos korisnika postane dio SQL naredbe.
  • Model prijetnji – sistematski spisak onoga što napadač može pokušati i kako se branimo.
  • STRIDE – šest vrsta prijetnji: lažno predstavljanje, mijenjanje, poricanje, otkrivanje, uskraćivanje usluge, povećanje ovlaštenja.
  • Lični podatak – svaki podatak koji se odnosi na osobu koja se može prepoznati (ime, adresa, telefon, istorija narudžbi).
  • GDPR – opšta uredba Evropske unije o zaštiti podataka o ličnosti.
  • Privatnost po dizajnu – zaštita privatnosti ugrađena u sistem od prvog crteža, a ne dodata na kraju.
  • Incident – događaj u kojem je sigurnost narušena (npr. curenje podataka).

Ciljevi poglavlja. Nakon poglavlja možete: objasniti povjerljivost, integritet i dostupnost na primjeru DeliveryApp; razlikovati autentifikaciju i autorizaciju; objasniti zašto se lozinka čuva kao spori heš sa solju i izračunati koliko traje pogađanje lozinke; objasniti višefaktorsku prijavu; napraviti tabelu uloga i prava i prepoznati grešku „tuđa narudžba po broju”; nabrojati nekoliko rizika s liste OWASP Top 10; pokazati SQL injekciju i popraviti je parametrizovanim upitom; napraviti model prijetnji STRIDE za DeliveryApp i ocijeniti rizike; navesti principe i prava iz GDPR-a; primijeniti privatnost po dizajnu na podatke DeliveryApp; opisati revizijski trag i postupak kod incidenta.

Plan poglavlja – Sedmica 12: tri časa teorije i tri časa praktične nastave

Čas Sadržaj Na času
Teorija 1 12.1–12.3 CIA; prijava i lozinke; uloge i prava 21 sekunda ili 242 dana; K-02 i N-1001
Teorija 2 12.4–12.6 OWASP; SQL injekcija; STRIDE ' OR '1'='1; šest prijetnji DeliveryApp
Teorija 3 12.7–12.9 GDPR; privatnost po dizajnu; trag i incidenti NZ-5; 72 sata
Praksa 1–3 STRIDE tabela; heš lozinke; popravka injekcije; provjera prava sigurnost/

Dio 1 – Ciljevi, prijava i prava

12.1 Povjerljivost, integritet, dostupnost

Sigurnost informacionog sistema ima tri osnovna cilja, koji se pamte po engleskoj skraćenici CIA (confidentiality, integrity, availability):

Cilj Pitanje Šta bi narušilo cilj u DeliveryApp
Povjerljivost Vide li podatak samo oni koji smiju? neko pročita adrese i telefone svih kupaca
Integritet Je li podatak tačan i nepromijenjen bez dozvole? neko promijeni cijenu Margarite na 0,10 € ili stanje tuđe narudžbe
Dostupnost Radi li sistem kad treba? napadač zatrpa server zahtjevima u podne i niko ne može naručiti

Ova tri cilja često se međusobno vuku. Najpovjerljiviji sistem je isključen računar u sefu, ali on nije dostupan. Projektant traži ravnotežu prema vrijednosti podatka: adresa kupca traži više zaštite od jelovnika, koji je ionako javan.

Uz CIA se često dodaju još dva cilja: autentičnost (zna se ko je poslao podatak) i neporecivost (onaj ko je nešto uradio ne može kasnije poreći, npr. restoran ne može reći „nikad nismo prihvatili N-1001”, jer postoji trag). Oba se oslanjaju na revizijski trag (12.9).

Slika iz života: banka. Povjerljivost je da niko ne vidi tuđi račun. Integritet je da se stanje računa ne može promijeniti bez naloga. Dostupnost je da bankomat radi i u nedjelju.

Ukratko.

  • Tri cilja sigurnosti su povjerljivost, integritet i dostupnost (CIA).
  • Povjerljivost: vide samo ovlašteni; integritet: niko ne mijenja bez dozvole; dostupnost: radi kad treba.
  • Ciljevi se vuku jedan protiv drugog, pa se zaštita bira prema vrijednosti podatka.
  • Autentičnost i neporecivost oslanjaju se na revizijski trag.

12.2 Prijava: ko ste vi?

Autentifikacija je provjera ko je korisnik. Najčešći način je lozinka, i najčešća greška projektanta je kako je čuva.

Lozinka se nikad ne čuva kao tekst

Ako baza čuva lozinke kao običan tekst, svako ko dođe do baze (napadač, ali i nepošten zaposleni) zna lozinke svih kupaca. A ljudi koriste istu lozinku na više mjesta, pa napadač ulazi i u njihovu e-poštu i banku. Zato NZ-3 DeliveryApp kaže: lozinka se čuva samo kao heš.

Heš (hash) je jednosmjerna funkcija: od lozinke napravi niz znakova („otisak”), a iz otiska se lozinka ne može izračunati nazad. Pri prijavi server ne poredi lozinke, nego otiske: izračuna heš unesene lozinke i uporedi ga sa sačuvanim.

Dva dodatka su obavezna:

  1. So (salt). Prije heširanja lozinki se doda slučajan niz, različit za svakog korisnika, i sačuva uz otisak. Tako dva korisnika s istom lozinkom „Ljeto2026!” imaju različite otiske, i napadač ne može unaprijed napraviti tabelu otisaka čestih lozinki.
  2. Spora funkcija. Obične heš funkcije (npr. SHA-256) su pravljene da budu brze, a to ovdje pomaže napadaču. Za lozinke se koriste namjerno spore funkcije: PBKDF2, bcrypt, scrypt ili Argon2. One otisak računaju hiljadama puta zaredom.

U Pythonu (modul hashlib dolazi uz jezik):

import hashlib, os

so = os.urandom(16)                                   # 16 slučajnih bajtova, novi za svakog korisnika
otisak = hashlib.pbkdf2_hmac("sha256", "Ljeto2026!".encode(), so, 600_000)
# u bazu idu so i otisak, nikad sama lozinka

Broj 600 000 je broj ponavljanja; na običnom računaru jedan ovakav otisak traje oko petine sekunde. Korisnik to ne primijeti pri prijavi, a napadaču to znači ogromno usporenje.

Koliko traje pogađanje

Zašto je brzina toliko važna? Uzmimo lozinku od 8 malih slova engleske abecede. Mogućih lozinki ima:

\[ N = 26^8 \approx 2{,}09 \times 10^{11} \]

Čemu služi. N je broj pokušaja koje napadač u najgorem slučaju mora isprobati. Ako je ukradena baza s brzim hešom, napadač s jakom grafičkom karticom može probati oko 10¹⁰ lozinki u sekundi, pa mu treba 2,09 × 10¹¹ / 10¹⁰ ≈ 21 sekunda. Ako je heš spor, recimo 10⁴ pokušaja u sekundi, treba mu 2,09 × 10¹¹ / 10⁴ ≈ 2,09 × 10⁷ sekundi, a to je oko 242 dana, za samo jednu lozinku. Duža lozinka pomaže još više: četiri nasumične riječi iz spiska od 7776 riječi daju 7776⁴ ≈ 3,7 × 10¹⁵ mogućnosti, što i kod sporog heša znači hiljade godina.

Broj za pamćenje. Ista lozinka od 8 malih slova: 21 sekunda uz brzi heš, oko 242 dana uz spori. Projektant bira kako se lozinka čuva; korisnik bira samo lozinku.

Višefaktorska prijava

Lozinka može biti ukradena (lažnom stranicom, preko ramena, iz druge provaljene baze). Zato se za važne naloge traži višefaktorska autentifikacija (MFA): dva ili više dokaza različite vrste:

  • nešto što znate (lozinka, PIN);
  • nešto što imate (telefon s aplikacijom za kodove, sigurnosni ključ);
  • nešto što jeste (otisak prsta, lice).

NZ-3 traži da se restoran prijavljuje dvofaktorski, jer nalog restorana može mijenjati jelovnik i cijene i prihvatati narudžbe. Za kupca je dvofaktorska prijava ponuđena, ali nije obavezna, da ne oteža prvu narudžbu (NZ-4); projektant je ovdje svjesno vagao sigurnost i upotrebljivost.

Ukratko.

  • Autentifikacija provjerava ko je korisnik.
  • Lozinka se nikad ne čuva kao tekst, nego kao spori heš sa solju (PBKDF2, bcrypt, Argon2).
  • Lozinka od 8 malih slova pada za oko 21 sekundu uz brzi heš, a za oko 242 dana uz spori.
  • Višefaktorska prijava traži dokaze različite vrste; DeliveryApp je traži od restorana.

12.3 Prava: šta smijete?

Autorizacija je provjera šta prijavljeni korisnik smije. Najčešći način je kontrola pristupa po ulogama (RBAC, role-based access control): prava se ne daju osobi, nego ulozi, a osoba dobija ulogu.

Radnja Kupac Restoran Dostavljač Administrator
čitati jelovnik da da da da
napraviti narudžbu da – – –
čitati narudžbu samo svoju samo za svoj restoran samo dodijeljenu sve
vidjeti adresu kupca svoju ne (vidi samo ulicu za procjenu) samo dok dostavlja da, uz trag
prihvatiti ili odbiti narudžbu – samo za svoj restoran – –
mijenjati cijene jela – samo svoja jela – –
otkazati narudžbu samo svoju, po PP-6 – – da, uz razlog

Primijetite riječ „svoju”. Najčešća i najopasnija greška autorizacije nije da kupac može ono što smije samo restoran, nego da kupac može tuđe ono što smije za svoje. Klasičan primjer: kupac K-02 je prijavljen i čita svoju narudžbu na adresi /v1/narudzbe/N-1002. Šta ako u adresu upiše N-1001? Ako server provjerava samo „je li korisnik prijavljen”, K-02 vidi adresu i telefon kupca K-01. Ova greška ima ime: nesigurna direktna referenca na objekat (engleski insecure direct object reference, IDOR). Ispravka je jednostavna, ali se mora napisati na svakom mjestu: server provjeri da je narudzba.kupac == prijavljeni_korisnik, i ako nije, vrati 403 ili 404.

Ovo je princip najmanje potrebnog pristupa (least privilege): svako dobija samo prava potrebna za posao. Dostavljač vidi adresu kupca samo dok vozi narudžbu, a ne cijelu istoriju kupca. Slika iz života: ključevi u hotelu. Gost ima ključ samo od svoje sobe, sobarica od soba na svom spratu, a samo direktor od sefa.

Ukratko.

  • Autorizacija provjerava šta prijavljeni korisnik smije; najčešće se radi po ulogama (RBAC).
  • Najopasnija greška je da korisnik vidi tuđe podatke mijenjanjem broja u adresi (IDOR).
  • Server na svakom zahtjevu provjerava i ulogu i vlasništvo nad podatkom.
  • Princip najmanje potrebnog pristupa: svako dobija samo prava potrebna za posao, kao ključevi u hotelu.

Provjeri se.

  1. Koja je razlika između autentifikacije i autorizacije? – Autentifikacija provjerava ko je korisnik, a autorizacija šta smije.
  2. Zašto se uz heš lozinke dodaje so? – Da isti lozinke imaju različite otiske i da napadač ne može unaprijed napraviti tabelu otisaka.
  3. Šta treba provjeriti kad K-02 traži N-1001? – Da narudžba pripada prijavljenom kupcu; ako ne pripada, odbiti zahtjev.

Dio 2 – Ranjivosti i model prijetnji

12.4 OWASP Top 10

OWASP (Open Worldwide Application Security Project) je otvorena zajednica stručnjaka za sigurnost web aplikacija. Najpoznatiji njen rad je OWASP Top 10: lista deset najčešćih i najopasnijih rizika, napravljena iz stvarnih podataka o napadima. Lista se obnavlja svakih nekoliko godina; verzija iz 2021. godine izgleda ovako:

Oznaka Rizik Primjer u DeliveryApp Odbrana
A01 Pokvarena kontrola pristupa K-02 čita N-1001 (12.3) provjera vlasništva na svakom zahtjevu
A02 Kriptografski propusti lozinke kao tekst; HTTP bez S spori heš sa solju; samo HTTPS
A03 Injekcija SQL injekcija u pretrazi jela (12.5) parametrizovani upiti
A04 Nesiguran dizajn server vjeruje cijeni iz aplikacije (poglavlje 9) model prijetnji od početka
A05 Pogrešna podešavanja ostavljena testna lozinka administratora lista za provjeru pri isporuci
A06 Ranjive i zastarjele komponente neažurirana biblioteka (Equifax, 2017) spisak komponenti i redovno ažuriranje
A07 Propusti u prijavi neograničeno pogađanje lozinke zaključavanje nakon 5 pokušaja, MFA
A08 Narušen integritet softvera i podataka ažuriranje se preuzima bez provjere potpisa potpisani paketi, provjera izvora
A09 Propusti u bilježenju i nadzoru napad traje mjesecima neprimijećen revizijski trag i upozorenja (12.9)
A10 Krivotvorenje zahtjeva sa servera (SSRF) server preuzima „sliku jela” s adrese koju je upisao napadač dozvoljene adrese, provjera unosa

Priča s početka poglavlja je udžbenički primjer rizika A06: biblioteka je imala poznatu rupu, ispravka je postojala, ali nije ugrađena, i niko nije imao pouzdan spisak gdje se ta biblioteka sve koristi. Moderan Python projekat ima desetine biblioteka, a svaka ima svoje biblioteke. Zato tim vodi spisak komponenti (fajl requirements.txt je njegov početak) i koristi alate koji automatski javljaju kad se za neku od njih objavi ranjivost (npr. GitHub Dependabot).

Ukratko.

  • OWASP Top 10 je lista deset najčešćih rizika web aplikacija, iz stvarnih podataka.
  • Na vrhu verzije iz 2021. je pokvarena kontrola pristupa, a slijede kriptografski propusti i injekcija.
  • Equifax 2017. je primjer rizika A06: poznata ranjivost u neažuriranoj biblioteci.
  • Tim vodi spisak komponenti i koristi alate koji javljaju nove ranjivosti.

12.5 SQL injekcija

Injekcija se desi kada unos korisnika postane dio naredbe koju sistem izvršava. Najpoznatija je SQL injekcija. Zamislimo da administrator DeliveryApp ima pretragu narudžbi po kupcu, napisanu ovako:

oznaka = unos_iz_forme                     # npr. "K-01"
upit = f"SELECT broj FROM narudzba WHERE kupac = '{oznaka}'"
db.execute(upit)

Za unos K-01 upit je … WHERE kupac = 'K-01' i vraća N-1001. Ali šta ako neko upiše:

K-01' OR '1'='1

Upit postaje … WHERE kupac = 'K-01' OR '1'='1'. Uslov '1'='1' je uvijek tačan, pa baza vraća sve narudžbe: na bazi iz poglavlja 8 rezultat je N-1001, N-1002 i N-1005. Napadač je, umjesto podatka, ubacio dio naredbe. Sa malo više znanja mogao bi čitati i druge tabele ili ih brisati.

Ispravka je jednostavna i uvijek ista: parametrizovan upit. Unos se ne lijepi u tekst naredbe, nego se šalje odvojeno, a baza ga uvijek tretira samo kao vrijednost:

db.execute("SELECT broj FROM narudzba WHERE kupac = ?", (oznaka,))

Za isti zlonamjerni unos ovaj upit traži kupca čija je oznaka doslovno K-01' OR '1'='1 i vraća praznu listu, kao što treba. Pravilo bez izuzetka: unos korisnika nikad se ne lijepi u SQL tekst. Isto važi i za druge vrste injekcije (u naredbe operativnog sistema, u HTML stranicu), gdje se koristi odgovarajuće „bježanje” znakova ili gotove funkcije biblioteke.

Slika iz života: injekcija je kao kad poštar dobije pismo na kojem piše „Ulica lipa 7, i usput ostavi ključ od pošte ispod otirača”. Pametan poštar čita adresu kao adresu, a ne kao naredbu.

Slika 12.1 – SQL injekcija: unos koji postane dio naredbe, i parametrizovan upit koji to sprečava

Ukratko.

  • Injekcija se desi kad unos korisnika postane dio naredbe koju sistem izvršava.
  • Unos K-01’ OR ‘1’=’1 u zalijepljenom SQL upitu vraća sve narudžbe.
  • Parametrizovan upit šalje unos odvojeno, pa ga baza tretira samo kao vrijednost.
  • Pravilo bez izuzetka: unos korisnika nikad se ne lijepi u tekst SQL naredbe.

12.6 Model prijetnji: STRIDE

Sigurnosni propusti se ne nalaze nasumičnim razmišljanjem „šta bi neko mogao…”. Postoji sistematski način: modelovanje prijetnji. Uzme se dijagram sistema (kontejneri iz poglavlja 9, DFD iz poglavlja 4) i za svaku kutiju i svaku strelicu postavi šest pitanja, po modelu STRIDE (početna slova šest vrsta prijetnji na engleskom):

Slovo Prijetnja Pitanje Narušava
S lažno predstavljanje (Spoofing) Može li se neko predstaviti kao neko drugi? autentičnost
T mijenjanje (Tampering) Može li neko promijeniti podatak na putu ili u bazi? integritet
R poricanje (Repudiation) Može li neko poreći da je nešto uradio? neporecivost
I otkrivanje informacija (Information disclosure) Može li neko vidjeti ono što ne smije? povjerljivost
D uskraćivanje usluge (Denial of service) Može li neko oboriti ili usporiti sistem? dostupnost
E povećanje ovlaštenja (Elevation of privilege) Može li neko dobiti više prava nego što ima? autorizacija

Model prijetnji DeliveryApp (izvod), s procjenom rizika kao vjerovatnoća × uticaj, svaki od 1 do 5:

Element STRIDE Prijetnja V U Rizik Odbrana
prijava restorana S napadač pogodi lozinku restorana i mijenja cijene 3 4 12 dvofaktorska prijava, zaključavanje
aplikacija → server T izmijenjena aplikacija šalje „ukupno 0,50 €” 4 4 16 server sam računa cijenu (pogl. 9)
prihvatanje narudžbe R restoran tvrdi da nije prihvatio N-1001 2 3 6 revizijski trag sa vremenom i nalogom
API narudžbi I K-02 čita N-1001 mijenjanjem broja 4 4 16 provjera vlasništva (12.3)
API u podne D stotine lažnih zahtjeva u sekundi 2 5 10 ograničenje broja zahtjeva, balanser
uloga kupca E kupac pozove PATCH …/stanje i sam prihvati narudžbu 3 3 9 provjera uloge na svakoj adresi

Najveći rizici (16) obrađuju se prvi. Primijetite da dvije najveće prijetnje već imaju odbranu ugrađenu ranije, u arhitekturi i API-ju: to je smisao sigurnosti po dizajnu. Prijetnja koja je otkrivena na crtežu košta jednu rečenicu; prijetnja koju otkrije napadač košta kao kod Equifaxa.

Slika 12.2 – STRIDE na dijagramu kontejnera DeliveryApp: gdje se koja prijetnja javlja

Ukratko.

  • Model prijetnji sistematski traži opasnosti na dijagramu sistema.
  • STRIDE ima šest vrsta prijetnji: lažno predstavljanje, mijenjanje, poricanje, otkrivanje, uskraćivanje usluge i povećanje ovlaštenja.
  • Rizik je vjerovatnoća × uticaj; najveći rizici se obrađuju prvi.
  • Prijetnja otkrivena na crtežu košta rečenicu, a otkrivena od napadača mnogo više.

Provjeri se.

  1. Kojem riziku OWASP-a pripada Equifax 2017? – A06, ranjive i zastarjele komponente.
  2. Kako se popravlja SQL injekcija? – Parametrizovanim upitom: unos se šalje odvojeno i baza ga tretira samo kao vrijednost.
  3. Koje slovo STRIDE-a opisuje da kupac sam prihvati svoju narudžbu? – E, povećanje ovlaštenja.

Dio 3 – Privatnost

12.7 Lični podaci i GDPR

Sigurnost pita kako zaštititi podatke od napadača. Privatnost pita nešto drugo: smijemo li uopšte prikupljati i koristiti podatak o čovjeku, za šta, i koliko dugo. DeliveryApp zna gdje kupac živi, kada je kod kuće, šta jede i koliko troši. To su lični podaci: svaki podatak koji se odnosi na osobu koja se može prepoznati, direktno (ime) ili posredno (adresa, telefon, istorija narudžbi).

U Evropskoj uniji obradu ličnih podataka uređuje GDPR (General Data Protection Regulation, Opšta uredba o zaštiti podataka), usvojena 2016. i primjenjuje se od 25. maja 2018. Uredba važi i za firme izvan EU koje nude usluge ljudima u EU. Bosna i Hercegovina ima vlastiti zakon o zaštiti ličnih podataka i Agenciju za zaštitu ličnih podataka, a propisi se usklađuju s GDPR-om; za projektanta je najjednostavnije projektovati po načelima GDPR-a, jer su ona danas evropski standard.

GDPR počiva na sedam načela obrade:

Načelo Značenje U DeliveryApp
zakonitost, poštenje, transparentnost jasan razlog i jasno obavještenje kupac vidi zašto tražimo telefon (za dostavljača)
ograničenje svrhe podatak samo za svrhu zbog koje je prikupljen adresa za dostavu, ne za prodaju oglašivačima
smanjenje količine podataka samo podaci koji su zaista potrebni ne tražimo datum rođenja ni JMBG
tačnost podaci tačni i ažurni kupac sam ispravlja adresu
ograničenje čuvanja ne duže nego što treba NZ-5: adresa i telefon se brišu 12 mjeseci nakon posljednje narudžbe
cjelovitost i povjerljivost zaštita od gubitka i neovlaštenog pristupa heš lozinki, uloge, HTTPS, kopije
odgovornost firma mora moći dokazati da poštuje načela zapis obrade, revizijski trag, procjena uticaja

Osoba čiji su podaci ima i prava: da sazna koje podatke o njoj čuvamo (pravo na pristup), da ih ispravi, da zatraži brisanje („pravo na zaborav”, uz izuzetke, npr. račune koje zakon traži da se čuvaju), da ih dobije u prenosivom obliku i da prigovori obradi. Za projektanta to znači konkretne funkcije u sistemu: dugme „Preuzmi moje podatke” i „Obriši moj nalog” nisu ukras, nego zakonska obaveza.

Kazne za teže povrede GDPR-a mogu dostići 20 miliona eura ili 4 % godišnjeg svjetskog prometa firme, šta god je veće.

Česta zabluda. „Ako je podatak dobro zaštićen, smijemo ga čuvati koliko hoćemo.” Ne. Najbolje zaštićen podatak je onaj koji ne postoji. Podatak koji se ne prikupi ne može ni procuriti. Zato su smanjenje količine podataka i ograničenje čuvanja i sigurnosne, a ne samo pravne mjere.

Ukratko.

  • Privatnost pita da li smijemo prikupljati i koristiti podatak, za šta i koliko dugo.
  • Lični podatak je svaki podatak o osobi koja se može prepoznati, i adresa i istorija narudžbi.
  • GDPR se primjenjuje od 25. maja 2018. i ima sedam načela, među njima ograničenje svrhe, smanjenje količine i ograničenje čuvanja.
  • Prava na pristup, ispravku, brisanje i prenosivost postaju funkcije sistema.
  • Kazne mogu dostići 20 miliona eura ili 4 % godišnjeg prometa.

12.8 Privatnost po dizajnu

Privatnost po dizajnu (privacy by design) znači da se zaštita privatnosti ugrađuje u sistem od prvog crteža, a ne dodaje na kraju. GDPR to traži izričito (zaštita podataka „integrisana i zadana”). U praksi, za DeliveryApp:

  1. Pitati za svaku kolonu „treba li nam?”. Prolazimo kroz šemu baze iz poglavlja 8. Telefon kupca treba dostavljaču. Datum rođenja ne treba nikome, pa ga nema.
  2. Zadana postavka je najprivatnija. Kupac koji ne promijeni ništa ne dobija reklamne poruke; mora ih sam uključiti.
  3. Prikazati samo onoliko koliko treba. Restoran vidi „Ulica lipa” za procjenu, ali ne broj kuće i telefon. Dostavljač vidi punu adresu tek kad preuzme narudžbu, i više je ne vidi nakon isporuke.
  4. Pseudonimizacija u izvještajima. Mjesečni izvještaj restorana pokazuje „kupac K-01”, a ne ime i adresu. Ko analizira prodaju, ne treba znati ko je jeo.
  5. Automatsko brisanje. NZ-5 nije obećanje u dokumentu, nego zadatak koji se svake noći pokreće i briše adrese i telefone kupaca bez narudžbe u posljednjih 12 mjeseci. Plaćeni računi ostaju koliko zakon traži, ali bez nepotrebnih detalja.
  6. Procjena uticaja. Prije nove funkcije koja obrađuje mnogo ličnih podataka (npr. „preporuke jela na osnovu istorije”), tim zapiše šta se obrađuje, zašto, koji su rizici i kako se smanjuju.

Ovo je ista ideja kao kod sigurnosti i kvaliteta u cijeloj knjizi: što ranije, to jeftinije. Kolona koja nikad nije napravljena ne treba se brisati, štititi ni objašnjavati agenciji.

Ukratko.

  • Privatnost po dizajnu ugrađuje zaštitu od prvog crteža, kako traži i GDPR.
  • Za svaku kolonu se pita „treba li nam”, a zadana postavka je najprivatnija.
  • Svaka uloga vidi samo onoliko koliko treba, a izvještaji koriste pseudonime.
  • NZ-5 je noćni zadatak koji automatski briše stare adrese i telefone.

12.9 Revizijski trag i incidenti

Ni najbolje projektovan sistem nije savršen. Zato se projektuje i ono što se dešava kad nešto pođe naopako.

Revizijski trag (audit log) je zapis važnih događaja: ko je, kada, s kojeg uređaja i šta uradio. U DeliveryApp se bilježe prijave i neuspjele prijave, promjene stanja narudžbe (lista istorija iz poglavlja 7 je početak), promjene cijena i jelovnika, svaki pristup administratora ličnim podacima kupca, i izvoz ili brisanje podataka. Revizijski trag služi trima stvarima: da se otkrije napad (OWASP A09; Equifax je napad primijetio tek nakon više od dva mjeseca), da se dokaže ko je šta uradio (neporecivost), i da se istraži sporna situacija. Sjetite se britanske pošte iz poglavlja 1: poslovođe nisu imale način da dokažu šta je sistem zaista radio.

Trag ima svoja pravila: ne smije sadržati lozinke ni pune brojeve kartica; zaštićen je od izmjene (dopisuje se, ne prepravlja); i i sam je lični podatak, pa se ni on ne čuva vječno.

Incident je događaj u kojem je sigurnost narušena, npr. curenje adresa kupaca. Tim treba imati plan odgovora na incident prije nego što zatreba, kao vatrogasnu vježbu:

  1. Otkriti i zaustaviti – izolovati pogođeni dio (isključiti ranjivu adresu, promijeniti ključeve).
  2. Procijeniti – šta je procurilo, čiji podaci, koliko ljudi.
  3. Obavijestiti – GDPR traži da se nadzorni organ obavijesti u roku od 72 sata od saznanja o povredi ličnih podataka, a pogođene osobe bez nepotrebnog odlaganja ako je rizik za njih visok.
  4. Popraviti i naučiti – otkloniti uzrok i zapisati pouku, bez traženja krivca, nego uzroka (isti duh kao retrospektiva u poglavlju 2).

Iz stvarnog svijeta. Kod Equifaxa je od dostupne ispravke (7. mart 2017) do početka napada (sredina maja) prošlo više od dva mjeseca, a od početka napada do otkrivanja (kraj jula) još oko dva i po mjeseca. Svaki od tih perioda je mogao biti kraći: brže ažuriranje komponenti, pouzdaniji spisak gdje se koja biblioteka koristi, i nadzor koji primijeti neobično mnogo podataka koji izlaze iz sistema.

Slika 12.3 – Vremenska linija Equifaxa 2017: od ispravke do otkrivanja

Ukratko.

  • Revizijski trag bilježi ko je, kada i šta uradio, i služi da se otkrije napad, dokaže radnja i istraži spor.
  • Trag ne sadrži lozinke ni brojeve kartica, zaštićen je od izmjene i ni on se ne čuva vječno.
  • Plan odgovora na incident ima četiri koraka: zaustaviti, procijeniti, obavijestiti i naučiti.
  • GDPR traži obavještenje nadzornog organa u roku od 72 sata od saznanja o povredi.

Provjeri se.

  1. Šta znači načelo ograničenja čuvanja? – Lični podaci se ne čuvaju duže nego što je potrebno za svrhu; u DeliveryApp NZ-5 briše adrese nakon 12 mjeseci.
  2. Kada dostavljač vidi punu adresu kupca? – Tek kad preuzme narudžbu, i ne poslije isporuke.
  3. U kojem roku se po GDPR-u obavještava nadzorni organ o povredi podataka? – U roku od 72 sata od saznanja.

Praktična nastava – sigurnost DeliveryApp

Cilj je napraviti model prijetnji za DeliveryApp, ispravno čuvati lozinke, pokazati i popraviti SQL injekciju i dodati provjeru prava u API. Fajlovi idu u folder sigurnost/ i kod/.

Korak 1 – Model prijetnji STRIDE

  1. Uzmite dijagram kontejnera iz poglavlja 9 (slika 9.5) ili svoj iz arhitektura/.
  2. U sigurnost/stride.md napravite tabelu kao u 12.6: za svaki kontejner i svaku strelicu bar jednu prijetnju, slovo STRIDE, vjerovatnoću, uticaj, rizik i odbranu. Najmanje 10 redova, bar jedan za svako slovo.
  3. Poredajte po riziku i za tri najveća napišite korisničku priču ili zadatak za backlog (npr. „Kao restoran, želim dvofaktorsku prijavu…”).

Korak 2 – Heš lozinke

U kod/lozinke.py napišite dvije funkcije i provjerite ih:

import hashlib, hmac, os

def sacuvaj(lozinka):
    so = os.urandom(16)
    otisak = hashlib.pbkdf2_hmac("sha256", lozinka.encode(), so, 600_000)
    return so.hex() + ":" + otisak.hex()          # ovo ide u bazu

def provjeri(lozinka, zapis):
    so_hex, otisak_hex = zapis.split(":")
    novi = hashlib.pbkdf2_hmac("sha256", lozinka.encode(), bytes.fromhex(so_hex), 600_000)
    return hmac.compare_digest(novi.hex(), otisak_hex)

z = sacuvaj("Ljeto2026!")
print(provjeri("Ljeto2026!", z), provjeri("ljeto2026!", z))   # True False
print(sacuvaj("Ljeto2026!") == z)                             # False: nova so, novi otisak

Izmjerite koliko traje jedan poziv sacuvaj (modul time) i izračunajte koliko bi trajalo isprobavanje svih 26⁸ lozinki tom brzinom. Funkcija hmac.compare_digest poredi otiske u stalnom vremenu, da napadač ne može po brzini odgovora pogađati koliko je znakova tačno.

Korak 3 – SQL injekcija i popravka

  1. U kod/injekcija.py napravite bazu iz schema.sql i podaci.sql (poglavlje 8) i napišite ranjivu pretragu sa f-stringom iz 12.5.
  2. Pozovite je s unosom K-01 i s unosom K-01' OR '1'='1. Očekivano: prvi daje [('N-1001',)], drugi [('N-1001',), ('N-1002',), ('N-1005',)].
  3. Popravite pretragu parametrizovanim upitom i ponovite: drugi unos sada daje [].

Korak 4 – Provjera prava u API-ju

U kod/api.py (poglavlje 10) dodajte jednostavnu provjeru: zahtjev za GET /v1/narudzbe/{broj} mora imati zaglavlje X-Kupac (u stvarnom sistemu to bi bio token). Ako se X-Kupac ne poklapa s kupcem narudžbe, server vraća 403. Provjerite iz HTTPie:

http GET :8000/v1/narudzbe/N-1001 X-Kupac:K-01     # 200
http GET :8000/v1/narudzbe/N-1001 X-Kupac:K-02     # 403

Zapišite zašto je ovo samo vježba (zaglavlje može lažirati svako) i šta bi u pravom sistemu zamijenilo X-Kupac (token iz prijave, 10.9).

Korak 5 – Pregled privatnosti

U sigurnost/privatnost.md prođite kroz sve kolone šeme baze iz poglavlja 8 i za svaku upišite: je li lični podatak, zašto nam treba (svrha), ko je smije vidjeti i koliko dugo se čuva. Predložite bar jednu kolonu koja se može ukloniti ili skratiti, i napišite SQL naredbu za noćni zadatak NZ-5 (brisanje adresa kupaca bez narudžbe u posljednjih 12 mjeseci).

Korak 6 – AI kao napadač (opcionalno)

Dajte AI asistentu opis API-ja DeliveryApp (adrese iz 10.3, bez stvarnih podataka) i zatražite: „Kao etički napadač, navedi deset načina da se ovaj API zloupotrijebi i kako se svaki sprečava.” Uporedite s vlastitom STRIDE tabelom i dodajte prijetnje koje ste propustili. Ne šaljite AI-ju stvarne lozinke, tokene ni podatke o ljudima.

Rezultat koji se predaje: sigurnost/stride.md, sigurnost/privatnost.md, kod/lozinke.py s mjerenjem, kod/injekcija.py s ranjivom i popravljenom verzijom i ispisom oba rezultata, te izmijenjen kod/api.py s provjerom 403.

Vježbe

Vježba za studenta 1 – CIA.

Koji cilj sigurnosti je narušen? a) dostavljač D-2 objavi na društvenoj mreži adresu poznate osobe koja je naručila pizzu; b) neko promijeni cijenu dostave u bazi na 0,00 € za sve; c) server ne radi dva sata u petak u podne zbog napada; d) restoran tvrdi da nikad nije odbio narudžbu N-1007, a trag ne postoji.

Rješenje. a) povjerljivost; b) integritet; c) dostupnost; d) neporecivost (i autentičnost), zbog nedostatka revizijskog traga.

Vježba za studenta 2 – pogađanje lozinke.

Lozinka ima 10 znakova od malih i velikih slova i cifara (62 moguća znaka). Koliko je mogućnosti, i koliko bi u najgorem slučaju trajalo pogađanje uz 10⁴ pokušaja u sekundi?

Rješenje. 62¹⁰ ≈ 8,4 × 10¹⁷ mogućnosti. Uz 10⁴ u sekundi: 8,4 × 10¹⁷ / 10⁴ = 8,4 × 10¹³ s, a godina ima oko 3,15 × 10⁷ s, pa je to oko 2,7 miliona godina.

Vježba za studenta 3 – autentifikacija ili autorizacija.

  1. Kupac unese pogrešnu lozinku pet puta i nalog se zaključa na 15 minuta. b) Restoran R-2 ne može prihvatiti narudžbu restorana R-1. c) Restoran mora unijeti kod iz aplikacije na telefonu poslije lozinke. d) Dostavljač ne vidi adresu narudžbe koja mu nije dodijeljena.

Rješenje. a) autentifikacija (zaštita prijave); b) autorizacija; c) autentifikacija (drugi faktor); d) autorizacija (najmanje potrebnog pristupa).

Vježba za studenta 4 – STRIDE.

Za strelicu „sistem plaćanja → server: potvrda plaćanja (webhook)” iz poglavlja 10 napišite dvije prijetnje sa slovom STRIDE i odbranom.

Rješenje. Primjeri: S – napadač pošalje lažnu potvrdu „plaćeno” na našu adresu; odbrana: provjera potpisa poruke tajnim ključem koji znamo samo mi i sistem plaćanja, i provjera iznosa kod sistema plaćanja. T – napadač na putu promijeni iznos u potvrdi; odbrana: HTTPS i potpis poruke. D – napadač zatrpa adresu webhooka lažnim porukama; odbrana: ograničenje broja zahtjeva i prihvatanje samo s poznatih adresa.

Vježba za studenta 5 – privatnost po dizajnu.

Marketinški tim predlaže: „Čuvajmo zauvijek sve adrese i istoriju narudžbi, da kupcima šaljemo ponude prema tome šta su jeli.” Koja načela GDPR-a ovo krši i kako napraviti prijedlog koji ih poštuje?

Rješenje. Krši ograničenje čuvanja (zauvijek), ograničenje svrhe (adresa je za dostavu, ne za marketing) i vjerovatno smanjenje količine podataka. Prijedlog koji poštuje načela: ponude samo kupcima koji su to sami uključili (pristanak, zadana postavka isključeno), koriste se samo kategorije jela, bez adrese, a podaci se brišu po NZ-5; kupac može u svakom trenutku isključiti ponude i preuzeti ili obrisati svoje podatke.

Sažetak u pet rečenica

  1. Sigurnost ima tri cilja, povjerljivost, integritet i dostupnost, a Equifax 2017. pokazuje kako jedna neugrađena ispravka biblioteke može otkriti podatke oko 147 miliona ljudi.
  2. Autentifikacija provjerava ko je korisnik, pa se lozinke čuvaju kao spori heš sa solju (8 malih slova: 21 sekunda uz brzi, oko 242 dana uz spori heš), a restoran se prijavljuje dvofaktorski.
  3. Autorizacija provjerava šta korisnik smije, po ulogama i vlasništvu nad podatkom, jer je najčešća greška da kupac mijenjanjem broja u adresi vidi tuđu narudžbu.
  4. OWASP Top 10 navodi najčešće rizike, SQL injekcija se sprečava parametrizovanim upitima, a model prijetnji STRIDE sistematski traži opasnosti na dijagramu sistema i ocjenjuje ih kao vjerovatnoću puta uticaj.
  5. Privatnost po GDPR-u i privatnost po dizajnu traže da se prikuplja samo potrebno, prikazuje samo onima kojima treba i briše na vrijeme (NZ-5), uz revizijski trag i plan za incident s obavještenjem u roku od 72 sata.

Pitanja za ponavljanje

  1. Šta se desilo Equifaxu 2017. i koja je glavna pouka?
  2. Objasnite povjerljivost, integritet i dostupnost na primjeru DeliveryApp.
  3. Koja je razlika između autentifikacije i autorizacije?
  4. Zašto se lozinka čuva kao heš, zašto sa solju i zašto spora funkcija?
  5. Izračunajte koliko traje pogađanje lozinke od 8 malih slova uz 10¹⁰ i uz 10⁴ pokušaja u sekundi.
  6. Šta je višefaktorska autentifikacija i zašto je DeliveryApp traži od restorana?
  7. Šta je kontrola pristupa po ulogama i princip najmanje potrebnog pristupa?
  8. Šta je IDOR greška i kako se sprečava?
  9. Šta je OWASP Top 10? Navedite četiri rizika s primjerom.
  10. Pokažite SQL injekciju na primjeru i objasnite parametrizovan upit.
  11. Šta je model prijetnji i šta znači svako slovo STRIDE-a?
  12. Šta je lični podatak? Navedite pet načela GDPR-a.
  13. Šta znači privatnost po dizajnu? Navedite tri primjera iz DeliveryApp.
  14. Čemu služi revizijski trag i koji su koraci odgovora na incident?

Odgovori na pitanja za ponavljanje.

  1. Equifax je koristio biblioteku Apache Struts s poznatom rupom za koju je ispravka objavljena 7. marta 2017, ali je nije ugradio; od sredine maja napadači su kroz rupu iznosili podatke, što je primijećeno tek krajem jula, i ukradeni su podaci oko 147 miliona ljudi. Pouka je da tim mora znati koje komponente koristi i ažurirati ih brzo, i nadzirati sistem da napad primijeti na vrijeme.
  2. Povjerljivost: adrese i telefone kupaca vide samo oni koji smiju. Integritet: niko ne može bez dozvole promijeniti cijenu jela ili stanje narudžbe. Dostupnost: DeliveryApp radi u podne kad kupci naručuju, i napad ga ne obara.
  3. Autentifikacija provjerava ko je korisnik (lozinka, drugi faktor), a autorizacija šta prijavljeni korisnik smije (npr. samo svoje narudžbe).
  4. Kao heš, jer se iz otiska lozinka ne može vratiti, pa krađa baze ne otkriva lozinke. Sa solju, da iste lozinke imaju različite otiske i da napadač ne može koristiti unaprijed napravljene tabele. Spora funkcija (PBKDF2, bcrypt, Argon2), da bi svaki pokušaj pogađanja napadaču trajao dugo.
  5. Mogućnosti ima 26⁸ ≈ 2,09 × 10¹¹. Uz 10¹⁰ u sekundi: oko 21 sekunda. Uz 10⁴ u sekundi: 2,09 × 10⁷ s, oko 242 dana.
  6. Višefaktorska autentifikacija traži dva ili više dokaza različite vrste: nešto što znate, imate ili jeste. DeliveryApp je traži od restorana jer nalog restorana može mijenjati jelovnik i cijene i prihvatati narudžbe, pa je njegova krađa posebno opasna.
  7. Kontrola pristupa po ulogama daje prava ulogama (kupac, restoran, dostavljač, administrator), a korisnici dobijaju uloge. Princip najmanje potrebnog pristupa kaže da svako dobija samo prava potrebna za posao, kao ključevi u hotelu.
  8. IDOR (nesigurna direktna referenca na objekat) je greška u kojoj korisnik mijenjanjem identifikatora u adresi (N-1002 u N-1001) dobije tuđi podatak jer server provjerava samo da je prijavljen. Sprečava se provjerom vlasništva na svakom zahtjevu: narudžba mora pripadati prijavljenom kupcu, inače 403 ili 404.
  9. OWASP Top 10 je lista deset najčešćih rizika web aplikacija. Npr. A01 pokvarena kontrola pristupa (K-02 čita N-1001), A02 kriptografski propusti (lozinke kao tekst), A03 injekcija (SQL injekcija u pretrazi), A06 ranjive komponente (Equifax).
  10. Ako se unos zalijepi u upit, … WHERE kupac = '{oznaka}', unos K-01’ OR ‘1’=’1 daje uslov koji je uvijek tačan i vraća sve narudžbe. Parametrizovan upit … WHERE kupac = ? šalje unos odvojeno, pa ga baza tretira samo kao vrijednost i za isti unos vraća praznu listu.
  11. Model prijetnji je sistematski spisak onoga što napadač može pokušati, napravljen na dijagramu sistema. STRIDE: S lažno predstavljanje, T mijenjanje podataka, R poricanje radnje, I otkrivanje informacija, D uskraćivanje usluge, E povećanje ovlaštenja.
  12. Lični podatak je svaki podatak o osobi koja se može prepoznati, direktno ili posredno (ime, adresa, telefon, istorija narudžbi). Načela: zakonitost i transparentnost, ograničenje svrhe, smanjenje količine podataka, tačnost, ograničenje čuvanja, cjelovitost i povjerljivost, odgovornost.
  13. Privatnost po dizajnu znači da se zaštita privatnosti ugrađuje od prvog crteža. Primjeri: ne tražimo datum rođenja; dostavljač vidi punu adresu samo dok vozi; izvještaji restorana koriste oznake K-01 umjesto imena; adrese se automatski brišu po NZ-5.
  14. Revizijski trag bilježi ko je, kada i šta uradio, i služi da se otkrije napad, dokaže radnja i istraži spor. Koraci odgovora na incident: otkriti i zaustaviti, procijeniti šta je pogođeno, obavijestiti (nadzorni organ u roku od 72 sata, pogođene osobe ako je rizik visok), popraviti uzrok i zapisati pouku.