Odoo je na naših pet web-stranica dostupan iz otvorenog interneta, a to nije iznimka, nego uobičajen slučaj: tko nudi ponudu, web-trgovinu ili prijavu kupaca, ima javni poslužitelj. Jedna ranjiva lozinka, zaboravljena konfiguracijska datoteka ili preširoko dodijeljena ovlast dovoljni su da javni poslužitelj postane otvoren.
Ovaj članak pokazuje kako ispravno zaštititi Odoo 19 — ne jednom jedinom mjerom, nego više slojeva koji se međusobno nadopunjuju: vatrozid i reverse proxy, naš open-source modul Web RBL, dvofaktorska autentifikacija, pravila o lozinkama i ovlasti — te koje pokušaje napada svaki od njih doista presreće. Na kraju slijede upute korak po korak kojima se može nadograditi svaka vlastita Odoo instalacija.
Sadržaj ovog članka
- Obrana u dubini: zašto jedna mjera nikad nije dovoljna
- Sloj 1: vatrozid i reverse proxy
- Sloj 2: Web RBL — most prema vatrozidu
- Sloj 3: zaštita samog Odooa (2FA, pravila o lozinkama, ovlasti)
- Sloj 4: baza podataka i rad sustava
- Put prijave u cjelini
- Scenariji napada i protumjere
- Upute korak po korak
- Česta pitanja
Obrana u dubini: zašto jedna mjera nikad nije dovoljna
Svaka pojedina sigurnosna mjera ima slabost. Vatrozid ne vidi što se događa u Odoo obrascu za prijavu. Jaka lozinka ne štiti ako je već ukradena negdje drugdje. Struktura ovlasti ne pomaže protiv napadača koji se još uopće nije prijavio. Načelo koje zatvara te slabosti zove se obrana u dubini (defense in depth): više neovisnih slojeva, od kojih bi se svaki pojedinačno mogao zaobići — ali svi zajedno ne.
Kod nas su to četiri sloja, svaki s drugom zadaćom:
- Vatrozid / reverse proxy — drži podalje očito zlonamjerno prije nego što uopće stigne do poslužitelja
- Web RBL — povezuje obje strane: Odoo iz vlastitog aplikacijskog zapisnika uči ono što vatrozid uopće ne može vidjeti i to prosljeđuje natrag vatrozidu
- Sam Odoo — dvofaktorska autentifikacija, pravila o lozinkama, ovlasti, upravljanje sesijama
- Baza podataka & rad sustava — sigurnosne kopije, zaštita pristupa upravljanju, tajne izvan svakog zapisnika
U sljedećim odjeljcima prolazimo kroz svaki sloj zasebno.
Sloj 1: vatrozid i reverse proxy
Vatrozid je prva instanca koja vidi zahtjev i jedina koja napadača može držati podalje od svake usluge na poslužitelju — ne samo od web-stranice, nego i od poslužitelja e-pošte, VPN pristupa i vlastitog sučelja za upravljanje. Što se na tom mjestu smisleno aktivira, ovisi o proizvođaču, ali su osnovni oblici kod OPNsensea, pfSensea, HAProxyja, FortiGatea, Sophosa ili Check Pointa isti:
| Funkcija | Protiv čega pomaže |
|---|---|
| Aktualna TLS verzija i ograničeni postupci šifriranja | Prisluškivanje i manipulacija vezom; zastarjeli postupci godinama se smatraju probijenima ili slabima |
| Popisi reputacije i podrijetla (RBL) | Poznate mreže napadača, Tor izlazni čvorovi, cijele zemlje bez vlastitih kupaca — vidi dolje |
| Ograničenje brzine po adresi | Isprobavanje lozinki i skeneri direktorija koji u sekundama šalju desetke zahtjeva |
| Odvajanje upravljanja i podatkovnog prometa | Sučelje vatrozida ne smije biti dostupno putem iste adrese kao javna web-stranica |
| IDS/IPS (otkrivanje/sprječavanje napada) | Poznati obrasci napada na mrežnoj razini, neovisno o tome koja aplikacija radi iza njih |
| Automatska sigurnosna ažuriranja za sam vatrozid | Vatrozid bez zakrpa više nije vatrozid, nego dodatna meta |
RBL popisi: standardni put kojim se isporučuje reputacija
RBL znači Real-time Blackhole List, pojam iz svijeta e-pošte: jedna adresa u svakom retku, dostupna putem HTTP-a, redovito iznova učitavana. Praktički svaki vatrozid može pročitati takav popis i iz njega izgraditi pravila — OPNsense i pfSense kao URL Table Alias, HAProxy kao ACL datoteku, FortiGate kao External Block List, Palo Alto kao External Dynamic List, Cisco, Sophos, Juniper i MikroTik s vlastitim nazivima za isto načelo.
Upravo tu počinje naš vlastiti modul — i upravo tu počinje drugi sloj.
Sloj 2: Web RBL — most između aplikacije i vatrozida
Vatrozid vidi pakete, a ne aplikacijsku logiku. Ne zna da je zahtjev za /xmlrpc/2/common pokušaj prijave, da je dvadeset različitih putanja u četrnaest sekundi skener ili da je neka adresa upravo uspješno pogodila lozinku. Sve to zna samo sam Odoo. Web RBL, naš vlastiti open-source modul (AGPL-3), čini to znanje iskoristivim — za sam Odoo i, isporučen kao RBL popis, također za vatrozid ispred njega.
Popisi prijetnji stalno se usklađuju, svaki sa zasebnom razinom.
Ukratko, ono što je opširno opisano u prethodnom članku:
- Prepoznavanje obrazaca u putanjama:
.envdatoteke,.gitdirektoriji, konfiguracijske datoteke, WordPress i PHP sonde, path traversal, izvršavanje naredbi putem novih AI sučelja - Obrana od neovlaštenih prijava koja broji i preko ponovnih pokretanja — za razliku od Odoo vlastitog brojača koji živi u radnoj memoriji
- Ocjena svake adrese od 0 do 100, s obrazloženjem običnim jezikom
- Pogrešne konfiguracije (QNAP, Autodiscover, Synology) prepoznaju se i nikad se ne blokiraju, jer blokada kvar ne uklanja, nego ga samo skriva
- Tuđi popisi prijetnji poput Spamhausa, FireHOL-a i Tor izlaznih čvorova, stalno usklađivani
- Popis izuzetaka za adrese koje se nikad ne smiju blokirati
Za ovaj su članak posebno važna dva svojstva, jer su izravno povezana s vatrozidom i s prijavom.
Troma lista je lista kojoj se može vjerovati
Popis izuzetaka — adrese koje se nikad ne blokiraju, primjerice vlastite veze lokacija — u pravilu se rijetko mijenja. Upravo je to njegova vrijednost, a ne nedostatak: kad se miran popis danima jedva pomiče, svaka rijetka promjena odmah upada u oči. Dnevno automatsko osvježavanje ne postoji zato što bi se mnogo mijenjalo, nego da rijetku promjenu ne bi trebalo ručno dopisivati — a upravo je to točka na kojoj se to zaboravlja. Jedna od naših vlastitih pogrešnih konfiguracija prošlog mjeseca primijećena je upravo tako: ne zbog mnogo događaja, nego zbog jednog koji nitko nije poznavao, sve dok QNAP web-API jednog kupca nije greškom bio blokiran. Od tada je QNAP na popisu pogrešnih konfiguracija koje se nikad ne blokiraju, nego samo prijavljuju.
Prijava je mjesto koje vatrozid ne vidi
Vatrozid može blokirati adresu. Ne može znati je li prijava uspjela, a pogotovo ne dolazi li s adrese koja je malo prije još tražila pristupne podatke. Web RBL to može: ocjena od podesivog praga nadalje potpuno zabranjuje prijavu, a uspješna prijava s upadljive adrese se prijavljuje — to je poveznica prema sljedećem sloju.
Sloj 3: zaštita samog Odooa
Dvofaktorska autentifikacija: druga tajna koja se ne može ponovno upotrijebiti
Najveći problem lozinki nije njihova kvaliteta, nego njihova ponovna upotreba. Lozinka ukradena kod neke druge usluge kod nas funkcionira jednako, sve dok je ista. Dvofaktorska autentifikacija (2FA, zvana i TOTP) tome suprotstavlja drugu tajnu: šesteroznamenkasti kôd koji se mijenja svakih trideset sekundi i računa se iz tajne koju poznaje samo vlastiti pametni telefon. Sama ukradena lozinka tako više nije dovoljna.
Odoo 19 Community to donosi ugrađeno — kao instalabilni modul Two-Factor Authentication (TOTP), dopunjen mogućnošću rezervne opcije e-poštom. Svaki korisnik to postavlja sam za sebe, putem QR kôda, s bilo kojom uobičajenom aplikacijom za autentifikaciju:
Postavljanje: skenirati QR kôd, jednom potvrditi šesteroznamenkasti kôd, gotovo.
To samo po sebi, međutim, pomaže samo onima koji to postave sami — a iskustvo pokazuje da bez prisile to ostaje manjina. Odoo zato poznaje politiku prisilnog uvođenja: ili samo za zaposlenike (interne korisnike) ili za sve, uključujući korisnike portala. Bez postavljene druge tajne nitko više ne može proći obrazac za prijavu a da je barem ne potvrdi kôdom iz e-pošte.
Pravila o lozinkama: minimalna duljina nije samorazumljiva
Bez dodatnog modula Odoo Community se ne oslanja ni na kakvu minimalnu duljinu lozinki — korisnik može zadati lozinku od tri znaka ako ga u tome nitko ne spriječi. Vlastiti modul Password Policy zatvara upravo tu slabost: minimalna duljina koja se provodi na strani poslužitelja, a ne samo predlaže u pregledniku. Tko želi više — prisilni rok isteka, povijest protiv ponovne upotrebe — za to treba OCA ili modul treće strane; u Community verziji to je namjerno ostavljeno slabijim.
Ovlasti: pristup dobiva samo tko ga treba
Odoo od početka razdvaja tri razine: korisnike portala (samo vlastiti portal kupaca ili dobavljača), interne korisnike (backend, s pravima po aplikaciji) i administratore (neograničen pristup uključujući tehničke postavke). Najčešća pogreška nije preslaba lozinka, nego preširoko dodijeljena administratorska uloga: tko treba samo izrađivati račune, ne treba pristup postavkama sustava.
Dva načela nose najveći dio tereta:
API ključ umjesto lozinke: svako vanjsko povezivanje (računovodstveni softver, evidencija vremena, vlastite skripte) dobiva vlastiti ključ koji se u svakom trenutku može opozvati, nikad korisničku lozinku.
Oboje se može provjeriti u istom prikazu u kojem se postavlja i dvofaktorska autentifikacija:
Jedan pregled, četiri poluge: lozinka, drugi faktor, API ključevi, prijavljeni uređaji.
Sesije i uređaji: tko je trenutačno prijavljen
Isti prikaz pokazuje i s kojih je uređaja račun trenutačno prijavljen — i omogućuje odjavu pojedinog ili svih odjednom. Nakon izgubljenog prijenosnog računala ili sumnje na kompromitiranu lozinku to je najbrži učinkovit korak: sesija završava odmah, neovisno o tome je li lozinka već promijenjena.
Sloj 4: baza podataka i rad sustava
Četvrti je sloj najmanje vidljiv i ujedno najneoprostiviji, jer pogreška ovdje može uništiti sve prethodno izgrađeno.
/web/database/manager nudi sučelje kojim se baze podataka mogu izrađivati, sigurnosno kopirati, vraćati i brisati — zaštićeno samo jednom jedinom glavnom lozinkom. To sučelje mora biti dostupno isključivo interno ili potpuno isključeno.
- Redovite, provjerene sigurnosne kopije, pohranjene odvojeno od samog poslužitelja. Sigurnosna kopija koja nikad nije vraćena je pretpostavka, a ne sigurnosna kopija.
- Tajne ne pripadaju ni u jednu datoteku zapisnika. Lozinke, API ključevi, licencni podaci — tko piše vlastita proširenja, treba ih tretirati kao samu glavnu lozinku: nigdje ih ne bilježiti, ni „samo za otklanjanje pogrešaka“.
- Održavati module aktualnima, osobito i treće module. Slobodni dodatni moduli (OCA i drugi) prirodno kasne za novim verzijama Odooa; prije svake instalacije isplati se provjeriti koje se ovisnosti automatski instaliraju.
Put prijave u cjelini
Četiri sloja ne djeluju jedan za drugim u odvojenim prostorijama, nego na istom zahtjevu, stupanj po stupanj. Na primjeru prijave to je najjasnije:
Pet mjesta na kojima zlonamjeran zahtjev može završiti prije nego što stigne do pravog cilja — i samo jedno na kojem ih ovlašteni korisnik sve prolazi.
Scenariji napada i protumjere
Sljedeći pregled razvrstava stvarne obrasce napada prema slojevima koji ih doista zaustavljaju. Nekoliko ih nije teorija, nego vlastita opažanja iz sedamnaest dana stvarnog prometa na našim pet web-stranica.
| Scenarij napada | Kako se odvija | Što ga zaustavlja |
|---|---|---|
| Isprobavanje lozinki | Skripta isprobava stotine kombinacija na obrascu za prijavu ili XML-RPC-u | Ograničenje brzine na vatrozidu, Web RBL brojač koji traje preko ponovnih pokretanja, blokada nakon deset pokušaja, trenutačna blokada kod zanemarene poruke o čekanju |
| Ponovno upotrijebljeni, drugdje ukradeni pristupni podaci | Napadač već poznaje korisničko ime i lozinku — iz neke druge, hakirane usluge | Dvofaktorska autentifikacija zaustavlja prijavu unatoč ispravnoj lozinci; Web RBL dodatno prijavljuje uspješnu prijavu s upadljive adrese |
| Traženje zaboravljenih tajni | Automatizirani zahtjevi za .env, .git, ključevima za pristup oblaku — kod nas 57.721 zahtjev u sedamnaest dana samo za .env |
Web RBL blokira već pri prvom pogotku; vatrozid zatim adresu dobiva kao RBL unos za sve ostale usluge |
| Skeneri direktorija i putanja | Desetke izmišljenih putanja u nekoliko sekundi, u potrazi za zaboravljenim aplikacijama | Prepoznavanje ponašanja: mnogo stranica s pogreškom, jedva koji pogodak, u kratkom vremenu — neovisno o tome pogađa li putanja poznati obrazac |
| Pogrešno konfiguriran vlastiti uređaj | Sinkronizacijski klijent ili program za e-poštu greškom pokazuje na pogrešnu adresu i kuca svake minute | Prepoznavanje kao pogrešne konfiguracije umjesto napada, tiket umjesto blokade — blokada ne bi uklonila kvar, nego ga samo odgodila |
| Automatizirano prikupljanje obveznih podataka | Skupljač dohvaća stranice s impresumom pod tuđim načinima pisanja, često pripremajući val opomena | Kanonska putanja uvijek ostaje dostupna (pravno nužno), tuđi načini pisanja prepoznaju se i prijavljuju ili blokiraju |
| Izgubljen ili ukraden uređaj | Prijavljeno prijenosno računalo ili mobitel dospije u tuđe ruke | Pregled sesija s trenutačnom odjavom svih uređaja, neovisno o lozinci |
| Preširoka interna ovlast | Korisnički račun s više prava nego što je potrebno biva kompromitiran ili zloupotrijebljen | Najmanje potrebno pravo po aplikaciji unaprijed ograničava štetu na ono što račun doista treba |
| Zloupotreba vanjskog sučelja | Ukradeni API ključ ili kompromitirani sustav treće strane pristupa putem XML-RPC/JSON-RPC | Vlastiti API ključevi koji se mogu opozvati umjesto korisničke lozinke; Web RBL nadzire i neuspjele RPC prijave |
| Pogrešno procijenjen crawler tražilice | Legitimni crawler stvara toliko prometa da izgleda kao distribuirani napadač — na jednoj od naših stranica bilo je to više od sedamdeset posto ukupnog prometa, a uzrokovao ga je GPTBot | Popis izuzetaka s objavljenim adresnim rasponima poznatih tražilica sprječava pogrešnu blokadu koja bi vlastitu stranicu uklonila iz indeksiranja |
| Zastarjeli modul treće strane s poznatom ranjivošću | Sigurnosna ranjivost u slobodnom dodatnom modulu postaje javna, ažuriranje stiže tek nakon tjedana | Prije svake instalacije provjeriti što se automatski instalira; ažuriranja prvo na testnoj instanci, a ne na otvorenom srcu |
| Otvoreno upravljanje bazom podataka | Sučelje za upravljanje dostupno je putem otvorenog interneta; pogođena ili slaba glavna lozinka dovoljna je za brisanje ili kopiranje baza podataka | Sučelje se nikad ne izlaže javno, glavna lozinka ostaje duga, nasumična i nigdje zabilježena |
Korak po korak: zaštita vlastite Odoo instalacije
Sljedeći redoslijed onaj je kojim bismo i sami postupali — od najvećeg učinka do najfinije postavke.
1. Prisilno uvesti dvofaktorsku autentifikaciju
- Ako već nije instalirano: otvoriti Apps, potražiti „Two-Factor Authentication“ i instalirati (kod više web-stranica dodatno se preporučuje „Two-Factor Authentication by Mail“ kao rezervna opcija).
- Otvoriti Postavke → Opće postavke → Ovlasti.
- Aktivirati „Prisilno uvesti dvofaktorsku autentifikaciju“.
- Odabrati politiku: „Samo zaposlenici“ za interne korisnike, „Svi korisnici“ ako se žele uključiti i korisnici portala (kupci s pristupom).
- Spremiti. Od sljedećeg pokušaja prijave Odoo od svakog korisnika bez postavljene druge tajne zahtijeva barem kôd iz e-pošte, dok ne postavi aplikaciju za autentifikaciju.
2. Odrediti minimalnu duljinu lozinki
- Otvoriti Apps, potražiti „Password Policy“ i instalirati.
- Otvoriti Postavke → Opće postavke → Ovlasti.
- Postaviti „Minimalna duljina lozinke“ — dvanaest znakova razumna je početna vrijednost.
- Spremiti. Pravilo od sada vrijedi za svaku novu ili promijenjenu lozinku, ali ne retroaktivno za postojeće lozinke.
3. Pregledati ovlasti
- Otvoriti Postavke → Korisnici & tvrtke → Korisnici.
- Otvoriti svakog korisnika pojedinačno i provjeriti karticu s pravima pristupa po aplikaciji: Treba li ta osoba doista „Manager“ ili „Administrator“, ili je dovoljan „Korisnik“?
- Posebno provjeriti: Tko ima pristup samim „Postavkama“? To bi trebala biti vrlo mala skupina.
- Za svako vanjsko povezivanje (računovodstvo, vlastite skripte, evidencija vremena) na kartici „Sigurnost računa“ odgovarajućeg tehničkog korisnika izraditi vlastiti API ključ, umjesto da se prosljeđuje korisnička lozinka.
4. Instalirati Web RBL i promatrati prije nego što se aktivira blokiranje
- Modul s github.com/Alex0176/odoo-web-rbl staviti u putanju za addone i instalirati.
- Promatrati nekoliko dana: izbornik Web RBL → Analiza pokazuje koji obrasci doista djeluju.
- Tek nakon toga uključiti
web_rbl.sperren_aktiv(Postavke → Tehnički → Sistemski parametri) — od tada se prepoznate sonde doista odbijaju. - Popis blokiranih na adresi navedenoj u modulu, zaštićenoj tokenom, uključiti u vatrozid kao RBL popis (kod OPNsensea/pfSensea kao URL Table Alias, kod HAProxyja kao ACL datoteku).
5. Zaštititi sam vatrozid
- Sučelje za upravljanje vatrozidom učiniti dostupnim isključivo iz interne mreže, nikad putem iste javne adrese kao web-stranica.
- Aktivirati automatska sigurnosna ažuriranja za softver vatrozida, ako ih proizvođač nudi.
- Provjeriti TLS konfiguraciju: samo aktualne verzije protokola, deaktivirati zastarjele postupke šifriranja.
- Ako je dostupno: poznati popis reputacije (primjerice Spamhaus DROP) uključiti izravno na vatrozidu — neovisno o Web RBL, jer vatrozid tako vidi i promet prema uslugama do kojih Odoo nikad ne dolazi.
6. Zatvoriti upravljanje bazom podataka
- Provjeriti je li
/web/database/managerdostupan izvana — ako jest, u Odoo konfiguraciji postavitilist_db = Falseili blokirati putanju na razini vatrozida. - Glavnu lozinku za upravljanje bazom podataka postaviti dugu i nasumičnu te je ne zapisivati ni na jedno mjesto koje bi itko drugi mogao pročitati.
7. Provjeriti sigurnosnu kopiju, a ne samo je postaviti
- Postaviti automatsku, redovitu sigurnosnu kopiju, pohranjenu odvojeno od Odoo poslužitelja.
- Barem jednom je doista vratiti i provjeriti funkcionira li obnova — neprovjerena sigurnosna kopija je pretpostavka.
Nijedan od ovih koraka ne zamjenjuje drugi. Tko provede samo jedan, ojačao je jedna vrata, a sva ostala ostavio otvorenima — tko provede svih sedam, ima obranu koja drži i kad zakaže pojedini sloj.
Što ova arhitektura ne zamjenjuje
Nijedna od opisanih mjera ne čini pažnju suvišnom. Modul koji odbija .env sonde ne čini bezopasnom greškom objavljenu .env datoteku. Dvofaktorska autentifikacija ne štiti od korisnika koji svoj kôd pročita pozivatelju na telefonu. A vatrozid ne zamjenjuje odluku o tome tko doista treba koju ovlast. Sigurnosna arhitektura stvara uvjete u kojima pojedina pogreška ne postaje odmah incident — ona nikoga ne oslobađa pažnje.
Česta pitanja
Je li jaka lozinka dovoljna za zaštitu Odoo 19?
Ne. Lozinka se može ukrasti drugdje, sasvim neovisno o njezinoj kvaliteti, i tada funkcionira kod svake usluge koja prihvaća istu lozinku. Tek kombinacija s dvofaktorskom autentifikacijom, vatrozidom ispred i smislenom strukturom ovlasti daje zaštitu koja drži i nakon ukradene lozinke.
Kako aktivirati dvofaktorsku autentifikaciju u Odoo 19?
Instalirati modul „Two-Factor Authentication (TOTP)“ putem upravljanja aplikacijama, zatim pod Postavke → Opće postavke → Ovlasti aktivirati prisilno uvođenje i odabrati između „Samo zaposlenici“ i „Svi korisnici“. Svaki korisnik nakon toga postavlja vlastiti drugi faktor putem QR kôda.
Što je RBL popis i zašto ga Odoo treba?
RBL (Real-time Blackhole List) je popis adresa dostupan putem HTTP-a koji može pročitati praktički svaki vatrozid. Sam Odoo ne isporučuje takav popis — naš modul Web RBL zatvara tu prazninu tako što prepoznaje napadački promet iz vlastitog aplikacijskog zapisnika i vraća ga kao RBL popis vatrozidu ispred.
Je li Odoo 19 Community bez dodatnih modula dovoljno zaštićen?
Ne u potpunosti. Bez modula Password Policy nema minimalne duljine lozinki, bez Two-Factor Authentication nema drugog faktora, a bez modula poput Web RBL Odoo ne prepoznaje ni pokušaje sondiranja ni ponovljene pokušaje prijave preko ponovnog pokretanja. Sva četiri mogu se besplatno naknadno dodati.
Dostupnost
Web RBL javno je dostupan pod licencom AGPL-3 i kod nas produktivno radi na pet web-stranica:
github.com/Alex0176/odoo-web-rbl
Cjelovit opis funkcija sa svim obrascima, ocjenjivanjem i popisima prijetnji nalazi se u prethodnom članku: Web RBL – popis blokiranih za napadački promet na vlastitim web-stranicama.
Pitanja, primjedbe i izvješća o pogreškama rado primamo — najradije kao issue na GitHubu.