API je sučelje preko kojeg dvije aplikacije razmjenjuju podatke bez ljudskog posrednika. Mobilna aplikacija dohvaća stanje računa preko API-ja, web sučelje šalje narudžbu preko API-ja, a vanjska integracija sinkronizira korisnike preko API-ja. Moderni softver gotovo je u potpunosti sastavljen od API poziva, pa je danas više prometa usmjereno na API-je nego na klasične web stranice. Za napadača to znači da je glavna meta upravo taj sloj, a ne lijepo dizajnirano sučelje koje korisnik vidi.
Za reguliranu hrvatsku tvrtku iz financija, zdravstva, kritične infrastrukture ili SaaS-a API je istovremeno najosjetljiviji i najnevidljiviji dio sustava. Najosjetljiviji je jer kroz njega teku osobni podaci, financijske transakcije i poslovna logika. Najnevidljiviji je jer ga ne vidi krajnji korisnik, pa propust koji bi se na web stranici odmah primijetio na API-ju mjesecima prolazi neopaženo. Većina ozbiljnih curenja podataka zadnjih godina nije probila vatrozid, nego je iskoristila API koji je vraćao previše podataka ili nije provjeravao tko što smije vidjeti. Ovaj tekst objašnjava zašto je tako i kako se API-ji sustavno testiraju i osiguravaju.
Ovo je dio našeg pregleda sigurnosti aplikacija. API testiranje pružamo kroz penetracijsko testiranje API-ja i širu ofenzivnu sigurnost.
Zašto su API-ji najosjetljiviji a najnevidljiviji sloj
Web sučelje vidi i čovjek. Ako stranica prikaže tuđe podatke ili omogući radnju koja ne bi trebala biti dostupna, netko će to prije ili kasnije primijetiti. API je namijenjen strojevima. Njegovi odgovori su JSON ili XML poruke koje korisnik nikad ne otvara, pa propust u logici pristupa može trajati godinama bez ijedne pritužbe. Napadač, za razliku od korisnika, gleda upravo te sirove odgovore i sustavno ih ispituje.
Drugi problem je opseg. Organizacije gotovo uvijek imaju mnogo više API-ja nego što misle. Postoje produkcijski API-ji, testni API-ji, stare verzije koje nitko nije ugasio, interni API-ji izloženi greškom i API-ji partnerskih integracija. Svaka od tih krajnjih točaka je potencijalni ulaz. API koji nitko ne nadzire i ne testira naziva se neprijavljeni ili zaboravljeni API, i upravo je on čest izvor incidenata jer ne prolazi kroz iste kontrole kao glavna aplikacija.
Treći problem je što API izlaže poslovnu logiku izravno. Web sučelje vodi korisnika kroz definirani tok, korak po korak. API prima zahtjev na bilo kojoj točki tog toka, pa napadač može preskočiti korake, mijenjati redoslijed i slati vrijednosti koje sučelje nikad ne bi poslalo. Ako se provjera ovlasti oslanja na sučelje, a ne na poslužitelj, ta zaštita ne postoji.
OWASP API Security Top 10 kao okosnica
OWASP, neprofitna organizacija za sigurnost aplikacija, održava zaseban popis najčešćih rizika API sigurnosti pod nazivom OWASP API Security Top 10.1 Taj je popis odvojen od općeg OWASP Top 10 za web jer se rizici API-ja razlikuju. Težište nije na klasičnim ranjivostima poput ubacivanja koda, nego na propustima u autorizaciji i poslovnoj logici. To je dobra okosnica za razvojni tim i obavezna referenca pri testiranju.
Najvažnije kategorije s popisa odnose se na kontrolu pristupa na razini objekta i funkcije, autentifikaciju, prekomjerno trošenje resursa i prekomjerno izlaganje podataka. Ostatak teksta obrađuje upravo te kategorije jer one čine većinu stvarnih incidenata. Cilj nije zapamtiti popis napamet, nego razumjeti obrazac: gotovo svaki ozbiljan propust API-ja svodi se na to da poslužitelj nije provjerio smije li ovaj korisnik vidjeti ili napraviti ono što traži.
BOLA: slaba kontrola pristupa na razini objekta
Slaba kontrola pristupa na razini objekta, na engleskom Broken Object Level Authorization ili BOLA, najčešći je i najopasniji propust API-ja.1 Nastaje kad API provjeri da je korisnik prijavljen, ali ne provjeri da li je upravo taj objekt njegov. Korisnik je autenticiran, ali nije autoriziran za traženi podatak, a API mu ga svejedno vraća.
Konkretan primjer. Zamislite zahtjev oblika GET /api/racuni/1042 koji vraća podatke o računu broj 1042. Korisnik koji je prijavljen otvori razvojne alate u pregledniku, vidi taj poziv i ručno ga promijeni u GET /api/racuni/1043. Ako poslužitelj samo provjeri da je netko prijavljen i vrati račun 1043 bez provjere da li taj račun pripada baš tom korisniku, napadač sustavnim mijenjanjem broja može povući sve račune u sustavu. Identifikator ne mora biti redni broj, ali i nasumični identifikatori ne pomažu ako provjera vlasništva ne postoji na poslužitelju.
Obrana je jednostavna za opisati, a zahtjevna za dosljedno provesti. Pri svakom pozivu, za svaki objekt, poslužitelj mora provjeriti da li prijavljeni korisnik ima pravo na baš taj objekt. Provjera mora biti na poslužitelju, ne u sučelju, i mora pokrivati svaku krajnju točku. Jedna zaboravljena ruta dovoljna je da cijela obrana padne.
BFLA: slaba kontrola pristupa na razini funkcije
Slaba kontrola pristupa na razini funkcije, na engleskom Broken Function Level Authorization ili BFLA, srodan je propust ali se odnosi na radnje, ne na pojedinačne objekte. Nastaje kad obični korisnik može pozvati funkciju koja je namijenjena samo administratoru ili drugoj povlaštenoj ulozi. Primjer je korisnik koji pogodi ili pronađe rutu poput POST /api/admin/korisnici i kroz nju briše ili stvara korisnike, iako njegova uloga to ne dopušta.
BFLA se često otkrije jer aplikacije skrivaju administrativne radnje u sučelju, ali ne provode istu provjeru na API razini. Sučelje običnom korisniku ne prikaže gumb za brisanje, no sama ruta i dalje odgovara na zahtjev. Obrana je provjera uloge i ovlasti za svaku funkciju na poslužitelju, posebno za sve radnje koje mijenjaju podatke ili stanje sustava.
Prekomjerno izlaganje podataka
Prekomjerno izlaganje podataka nastaje kad API vraća više polja nego što sučelje prikazuje. Razvojni tim često vrati cijeli objekt iz baze i pusti sučelje da prikaže samo dio. Problem je što napadač ne gleda sučelje, nego sirovi odgovor API-ja. Ako odgovor za javni profil korisnika sadrži i email, OIB, hash lozinke ili interne oznake, sve je to dostupno svakome tko pogleda mrežni promet.
Srodan propust je masovno pridruživanje, kad API prihvati sva polja iz zahtjeva i upiše ih u objekt bez filtriranja. Korisnik tada može poslati polje poput "uloga": "admin" u običnom zahtjevu za izmjenu profila i podići si ovlasti. Obrana za oboje je ista: API mora eksplicitno definirati koja polja vraća i koja prima, a nikad slijepo serijalizirati cijeli objekt iz baze.
Autentifikacija, tokeni, istek i opseg
Autentifikacija odgovara na pitanje tko je korisnik, autorizacija na pitanje što smije. API-ji se obično autenticiraju tokenima, najčešće u obliku JWT-a koji se šalje u zaglavlju svakog zahtjeva. Slaba autentifikacija obuhvaća tokene bez roka valjanosti, slabo potpisane tokene, API ključeve ugrađene u kod mobilne aplikacije i izostanak dvofaktorske autentifikacije na osjetljivim računima.
Dobro upravljanje tokenima počiva na tri pravila. Token mora imati kratak rok valjanosti i mehanizam obnove, da ukradeni token brzo postane bezvrijedan. Token mora imati definiran opseg, takozvani scope, koji ograničava na koje krajnje točke i radnje daje pravo. Token mora biti opoziv, da se kompromitirani pristup može odmah ukinuti. Tajne i ključeve nikad se ne smije ugraditi u klijentski kod jer ga svatko može pročitati.
Ograničenje prometa i zlouporaba
Bez ograničenja broja zahtjeva API je otvoren za zlouporabu. Napadač može slati tisuće zahtjeva u sekundi i pogađati lozinke, povlačiti podatke u velikim količinama ili jednostavno preopteretiti sustav i izazvati prekid usluge. Ograničenje prometa, na engleskom rate limiting, postavlja gornju granicu broja zahtjeva po korisniku, ključu ili IP adresi u zadanom razdoblju.
Uz ograničenje broja zahtjeva važno je i ograničiti potrošnju resursa po pojedinom pozivu. API koji dopušta dohvat neograničenog broja zapisa u jednom zahtjevu omogućuje napadaču da povuče cijelu bazu jednim pozivom. Stranicenje, gornje granice veličine odgovora i zaštita od skupih upita dio su iste obrane. Ovo je posebno važno za API-je izložene internetu i one koji koriste vanjski partneri.
REST i GraphQL: razlike u napadnoj površini
REST je najčešći stil API-ja, gdje svaka krajnja točka i metoda predstavlja jednu radnju nad jednim resursom. GraphQL je drugačiji pristup, gdje klijent jednim upitom traži točno onaj skup podataka koji mu treba, kombinirajući više resursa odjednom. Oba stila dijele iste temeljne rizike autorizacije, ali im se napadna površina razlikuje.
| Svojstvo | REST | GraphQL |
|---|---|---|
| Krajnje točke | Mnogo ruta, svaka jedna radnja. | Najčešće jedna ulazna točka za sve upite. |
| Autorizacija | Provjera po ruti i objektu. | Provjera po polju i tipu, složenija za pokriti. |
| Glavni rizik prometa | Mnoštvo poziva. | Jedan dubok ili ugniježđen upit može preopteretiti sustav. |
| Izlaganje podataka | Ovisi o pojedinom odgovoru. | Introspekcija sheme može otkriti cijeli model podataka. |
| Testiranje | Mapiranje svih ruta. | Analiza sheme, dubine upita i kontrole po polju. |
Kod GraphQL-a posebnu pažnju traže ugniježđeni i rekurzivni upiti koji mogu izazvati prekid usluge, te introspekcija koja u produkciji može otkriti cijelu shemu napadaču. Autorizacija se mora provoditi na razini pojedinog polja, što je teže nego kod REST-a gdje je dovoljno pokriti rutu.
Kako se API-ji testiraju
API testiranje nije isto što i penetracijsko testiranje web aplikacija. Težište je na autorizaciji i poslovnoj logici, a ne na sučelju. Postupak slijedi nekoliko jasnih koraka.
- 01Popisivanje krajnjih točakaPrikupljamo dokumentaciju, OpenAPI ili GraphQL shemu i mrežni promet da utvrdimo sve rute, uključujući stare verzije i neprijavljene API-je.
- 02Mapiranje uloga i tokovaDefiniramo uloge, prikupljamo tokene za različite razine pristupa i bilježimo kako izgleda legitiman zahtjev za svaku radnju.
- 03Testiranje autorizacijeSustavno provjeravamo BOLA i BFLA: mijenjamo identifikatore objekata i pozivamo funkcije tuđim i nižim tokenima.
- 04Analiza odgovoraTražimo prekomjerno izlaganje podataka, osjetljiva polja i masovno pridruživanje u svakom odgovoru.
- 05Autentifikacija i tokeniProvjeravamo istek, opseg, potpis i opozivost tokena te tražimo ugrađene tajne i ključeve.
- 06Ograničenja i otpornostTestiramo ograničenje prometa, veličinu odgovora i ponašanje pod velikim brojem zahtjeva.
- 07Izvještaj i ponovna provjeraDajemo nalaze s dokazom i preporukama, a nakon ispravaka radimo ponovnu provjeru da potvrdimo zatvaranje.
Česti propusti i njihove posljedice
Sljedeća tablica sažima najčešće propuste API-ja, što ih uzrokuje i kakvu štetu donose ako se ne otkriju na vrijeme.
| Propust | Posljedica |
|---|---|
| Slaba kontrola pristupa objektu (BOLA) | Napadač dohvaća tuđe podatke mijenjanjem identifikatora. |
| Slaba kontrola pristupa funkciji (BFLA) | Obični korisnik izvodi administrativne radnje. |
| Prekomjerno izlaganje podataka | Curenje osjetljivih polja koja sučelje ne prikazuje. |
| Masovno pridruživanje | Korisnik si podiže ovlasti slanjem dodatnih polja. |
| Slaba autentifikacija | Krađa ili zlouporaba tokena i ključeva. |
| Nedostatak ograničenja prometa | Pogađanje lozinki, masovni dohvat i prekid usluge. |
| Neprijavljeni stari API-ji | Nenadziran ulaz koji zaobilazi sve kontrole. |
Gotovo svaki ozbiljan propust API-ja svodi se na isto: poslužitelj nije provjerio smije li ovaj korisnik vidjeti ili napraviti ono što traži.
Česte greške u praksi
Najčešća greška je provjera ovlasti u sučelju umjesto na poslužitelju. Sučelje sakrije gumb, ali API i dalje odgovara na zahtjev, pa zaštita zapravo ne postoji. Druga je greška oslanjanje na nepoznavanje: skrivanje ruta i nasumični identifikatori usporavaju napadača, ali ne zaustavljaju ga.
Treća čest greška je tretirati API testiranje kao dodatak web testiranju, a ne kao zaseban posao. Automatizirani alati za skeniranje web aplikacija slabo pokrivaju propuste u autorizaciji i poslovnoj logici jer ne razumiju koji objekt pripada kojem korisniku. Te propuste pronalazi samo testiranje koje ručno provjerava autorizaciju s više različitih uloga, što je sasvim drugačiji posao od procjene ranjivosti.
Usklađenost: GDPR i NIS2
Propusti API-ja izravno dotiču regulatorne obveze. Prekomjerno izlaganje podataka i BOLA mogu dovesti do curenja osobnih podataka, što je povreda po GDPR-u. Povredu osobnih podataka u pravilu treba prijaviti AZOP-u u roku od 72 sata, a kazne mogu biti znatne. API kroz koji cure osobni podaci nije samo tehnički problem, nego i pravna izloženost.
Za regulirane subjekte pod NIS2, koji je u Hrvatskoj prenesen kroz Zakon o kibernetičkoj sigurnosti, API-ji su dio mjera upravljanja rizicima i sigurnosti razvoja. Financijske institucije pod DORA-om, Uredbom (EU) 2022/2554, moraju testirati otpornost svojih ključnih sustava, a API-ji su gotovo uvijek dio toga. Redovito testiranje API-ja i sigurnost ugrađena u dizajn, primjerice prema NIST okviru za siguran razvoj softvera,2 dio su dokaza o usklađenosti.
Kako Raptoric pomaže
Testiramo API-je na kontrolu pristupa na razini objekta i funkcije, izlaganje podataka, autentifikaciju i ograničenje prometa, za REST i GraphQL. Pomažemo razvojnim timovima ugraditi autorizaciju i provjere u dizajn API-ja, ne tek pred lansiranje. Sve to pružamo kroz penetracijsko testiranje API-ja, uz povezanu sigurnost aplikacija i clouda. Po našem iskustvu opseg testiranja ovisi o broju krajnjih točaka i složenosti uloga, a stvarna procjena ovisi o opsegu. Dogovorite uvodni razgovor.
