Odoo je na naših pet web-stranica dostupan iz otvorenog interneta, i to nije izuzetak, nego uobičajen slučaj: ko vodi ponudu, web-shop ili prijavu klijenata, ima javni server. Jedna ranjiva lozinka, zaboravljena konfiguracijska datoteka ili preširoko dodijeljena dozvola dovoljni su da javni server postane otvoren.
Ovaj članak pokazuje kako možete pravilno osigurati Odoo 19 — ne jednom pojedinačnom mjerom, nego više slojeva koji se međusobno dopunjuju: firewall i reverse proxy, naš open-source modul Web RBL, dvofaktorska autentifikacija, politika lozinki i dozvole — te koje pokušaje napada svaka od njih zaista zaustavlja. Na kraju slijede upute korak po korak, prema kojima se može doraditi svaka vlastita Odoo instalacija.
Sadržaj ovog članka
- Odbrana u dubini: zašto jedna mjera nikada nije dovoljna
- Sloj 1: firewall i reverse proxy
- Sloj 2: Web RBL — most prema firewallu
- Sloj 3: osigurati sam Odoo (2FA, politika lozinki, dozvole)
- Sloj 4: baza podataka i rad sistema
- Put prijave u cjelini
- Scenariji napada i odbrana od njih
- Upute korak po korak
- Česta pitanja
Odbrana u dubini: zašto jedna mjera nikada nije dovoljna
Svaka pojedinačna sigurnosna mjera ima slabu tačku. Firewall ne vidi šta se dešava u Odoo obrascu za prijavu. Jaka lozinka ne štiti ako je već ukradena negdje drugdje. Struktura dozvola ne pomaže protiv napadača koji se još nije ni prijavio. Princip koji zatvara ove rupe zove se odbrana u dubini (defense in depth): više nezavisnih slojeva, od kojih bi se svaki pojedinačno mogao zaobići — ali svi zajedno ne.
Kod nas postoje četiri sloja, svaki s drugačijim zadatkom:
- Firewall / reverse proxy — drži podalje očigledno zlonamjerno prije nego što uopće stigne do servera
- Web RBL — povezuje obje strane: Odoo iz vlastitog aplikacijskog zapisnika saznaje ono što firewall uopće ne može vidjeti i vraća mu to
- Sam Odoo — dvofaktorska autentifikacija, politika lozinki, dozvole, upravljanje sesijama
- Baza podataka & rad sistema — sigurnosne kopije, zaštita pristupa upravljanju, tajne izvan svakog zapisnika
Sljedeći odjeljci prolaze kroz svaki sloj pojedinačno.
Sloj 1: firewall i reverse proxy
Firewall je prva instanca koja vidi zahtjev i jedina koja može napadača držati podalje od svake usluge na serveru — ne samo od web-stranice, nego i od mail-servera, VPN pristupa i vlastitog sučelja za upravljanje. Šta se na ovom mjestu smisleno aktivira zavisi od proizvođača, ali su osnovni oblici kod OPNsense, pfSense, HAProxy, FortiGate, Sophos ili Check Point isti:
| Funkcija | Protiv čega pomaže |
|---|---|
| Aktuelna TLS verzija i ograničeni postupci šifriranja | Prisluškivanje i manipulacija vezom; zastarjeli postupci godinama se smatraju probijenim ili slabim |
| Liste reputacije i porijekla (RBL) | Poznate mreže napadača, Tor izlazni čvorovi, cijele zemlje bez vlastitih klijenata — vidi dolje |
| Ograničenje učestalosti po adresi | Isprobavanje lozinki i skeneri direktorija koji za nekoliko sekundi postave desetke zahtjeva |
| Odvajanje upravljanja i saobraćaja podataka | Sučelje firewalla samo ne smije biti dostupno preko iste adrese kao javna web-stranica |
| IDS/IPS (prepoznavanje/odbrana od napada) | Poznati obrasci napada na nivou mreže, bez obzira koja aplikacija radi iza |
| Automatska sigurnosna ažuriranja za sam firewall | Firewall bez zakrpa više nije firewall, nego dodatna meta |
RBL liste: standardni put kojim se isporučuje reputacija
RBL znači Real-time Blackhole List, pojam iz svijeta e-pošte: jedna adresa u svakom redu, dostupna putem HTTP-a, redovno iznova učitavana. Praktično svaki firewall može pročitati takvu listu i od nje 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 isti princip.
Upravo tu počinje naš vlastiti modul — i upravo tu počinje drugi sloj.
Sloj 2: Web RBL — most između aplikacije i firewalla
Firewall vidi pakete, a ne aplikacijsku logiku. Ne zna da je zahtjev za /xmlrpc/2/common pokušaj prijave, da dvadeset različitih putanja u četrnaest sekundi znači skener, niti 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 upotrebljivim — za sam Odoo i, isporučen kao RBL lista, i za firewall ispred njega.
Liste prijetnji se neprestano usklađuju, svaka s vlastitim nivoom.
Ukratko, ono što je u prethodnom članku detaljno opisano:
- Prepoznavanje uzoraka u putanjama:
.envdatoteke,.gitdirektoriji, konfiguracijske datoteke, WordPress i PHP sonde, path traversal, izvršavanje naredbi putem novih AI sučelja - Odbrana od neovlaštenih prijava koja broji i preko ponovnih pokretanja — za razliku od Odooovog 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) se prepoznaju i nikada ne blokiraju, jer blokada kvar ne otklanja, nego ga samo skriva
- Tuđe liste prijetnji poput Spamhaus, FireHOL i Tor izlaznih čvorova, neprestano usklađivane
- Bijela lista za adrese koje se nikada ne smiju blokirati
Za ovaj članak su dvije osobine posebno važne, jer su neposredno povezane s firewallom i s prijavom.
Trom lista je lista kojoj se može vjerovati
Bijela lista — adrese koje se nikada ne blokiraju, npr. vlastiti priključci lokacija — u pravilu se mijenja rijetko. Upravo to je njena vrijednost, a ne nedostatak: kad se mirna lista danima jedva pomakne, svaka rijetka promjena odmah upada u oči. Dnevno automatsko ažuriranje ne postoji zato što bi se mnogo mijenjalo, nego da se rijetka promjena ne mora ručno dopisivati — a upravo je to tač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 onog jednog koji niko nije poznavao, sve dok QNAP web-API jednog klijenta nije greškom blokiran. Od tada je QNAP na listi pogrešnih konfiguracija koje se nikada ne blokiraju, nego se samo prijavljuju.
Prijava je mjesto koje firewall ne vidi
Firewall 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 može: ocjena od podesivog praga nadalje u potpunosti zabranjuje prijavu, a uspješna prijava sa sumnjive adrese se prijavljuje — to je veza prema sljedećem sloju.
Sloj 3: osigurati sam Odoo
Dvofaktorska autentifikacija: druga tajna koja se ne može ponovo koristiti
Najveći problem lozinki nije njihov kvalitet, nego njihovo ponovno korištenje. Lozinka ukradena kod neke druge usluge kod nas radi na isti način, dokle god je ista. Dvofaktorska autentifikacija (2FA, zvana i TOTP) tome suprotstavlja drugu tajnu: šestocifreni kod 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 modul koji se može instalirati, Two-Factor Authentication (TOTP), dopunjen opcijom povratka putem e-pošte. Svaki korisnik to postavlja sam za sebe, putem QR koda, s bilo kojom uobičajenom authenticator aplikacijom:
Postavljanje: skenirati QR kod, jednom potvrditi šestocifreni kod, gotovo.
To samo po sebi pomaže, međutim, samo onima koji to sami postave — a iskustvo pokazuje da bez prisile to ostaje manjina. Odoo zato poznaje politiku obaveznosti: ili samo za zaposlenike (interne korisnike) ili za sve, uključujući korisnike portala. Bez postavljene druge tajne niko više ne prolazi pored obrasca za prijavu a da je barem ne potvrdi kodom putem e-pošte.
Politika lozinki: minimalna dužina nije samorazumljiva
Bez dodatnog modula Odoo Community se ne oslanja ni na kakvu minimalnu dužinu lozinki — korisnik može zadati lozinku od tri znaka ako ga niko u tome ne spriječi. Vlastiti modul Password Policy zatvara upravo tu rupu: minimalna dužina koja se provodi na strani servera, a ne samo predlaže u pregledniku. Ko želi više — obavezan rok isteka, historiju protiv ponovnog korištenja — za to treba OCA ili modul trećeg proizvođača; u Community verziji to je namjerno držano jednostavnim.
Dozvole: pristup dobija samo ko ga treba
Odoo od kuće razdvaja tri nivoa: korisnici portala (samo vlastiti portal klijenata ili dobavljača), interni korisnici (backend, s pravima po aplikaciji) i administratori (neograničen pristup uključujući tehničke postavke). Najčešća greška nije preslaba lozinka, nego preširoko dodijeljena administratorska uloga: ko treba samo izdavati račune, ne treba pristup postavkama sistema.
Dva načela nose najveći dio tereta:
API ključ umjesto lozinke: svako vanjsko povezivanje (računovodstveni softver, evidencija vremena, vlastite skripte) dobija vlastiti ključ koji se u svakom trenutku može opozvati, nikada 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: ko je trenutno prijavljen
Isti prikaz pokazuje i s kojih uređaja je račun trenutno prijavljen — i omogućava odjavu jednog ili svih odjednom. Nakon izgubljenog laptopa ili sumnje na kompromitovanu lozinku to je najbrži djelotvoran korak: sesija se odmah završava, bez obzira je li lozinka već promijenjena.
Sloj 4: baza podataka i rad sistema
Četvrti sloj je najmanje vidljiv i istovremeno najneoprostiviji, jer greška ovdje može poništiti sve prethodno izgrađeno.
/web/database/manager nudi sučelje kojim se baze podataka mogu kreirati, sigurnosno kopirati, vraćati i brisati — zaštićeno samo jednom glavnom lozinkom. Ovo sučelje treba biti dostupno isključivo interno ili potpuno isključeno.
- Redovne, provjerene sigurnosne kopije, pohranjene odvojeno od samog servera. Sigurnosna kopija koja nikada nije vraćena je pretpostavka, a ne sigurnosna kopija.
- Tajne ne pripadaju ni u jednu datoteku zapisnika. Lozinke, API ključevi, licenčni podaci — ko piše vlastita proširenja, treba ih tretirati kao i samu glavnu lozinku: nigdje ih ne bilježiti, čak ni „samo za debugiranje“.
- Održavati module ažurnim, i to posebno module trećih proizvođača. Slobodni dodatni moduli (OCA i drugi) prirodno zaostaju za novim verzijama Odooa; prije svake instalacije vrijedi pogledati koje zavisnosti dolaze automatski.
Put prijave u cjelini
Četiri sloja ne djeluju jedan za drugim u odvojenim prostorijama, nego na istom zahtjevu, stepenicu po stepenicu. Na primjeru prijave to je najjasnije:
Pet mjesta na kojima zlonamjerni 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 odbrana od njih
Sljedeći pregled razvrstava stvarne obrasce napada prema slojevima koji ih zaista zaustavljaju. Nekoliko njih nije teorija, nego vlastita zapažanja iz sedamnaest dana stvarnog prometa na naših pet web-stranica.
| Scenarij napada | Kako se odvija | Šta ga zaustavlja |
|---|---|---|
| Isprobavanje lozinki | Skripta pokušava stotine kombinacija na obrascu za prijavu ili XML-RPC | Ograničenje učestalosti na firewallu, Web RBL brojač koji traje preko ponovnih pokretanja, blokada nakon deset pokušaja, trenutna blokada pri ignorisanoj poruci o čekanju |
| Ponovo korišteni pristupni podaci ukradeni drugdje | Napadač već poznaje korisničko ime i lozinku — iz neke druge, hakovane usluge | Dvofaktorska autentifikacija zaustavlja prijavu uprkos tačnoj lozinci; Web RBL dodatno prijavljuje uspješnu prijavu sa sumnjive adrese |
| Traženje zaboravljenih tajni | Automatizirani zahtjevi za .env, .git, pristupnim ključevima za cloud — kod nas 57.721 zahtjev u sedamnaest dana samo za .env |
Web RBL blokira pri prvom pogotku; firewall zatim adresu dobija kao RBL unos za sve ostale usluge |
| Skeneri direktorija i putanja | Desetine izmišljenih putanja u nekoliko sekundi, u potrazi za zaboravljenim aplikacijama | Prepoznavanje ponašanja: mnogo stranica s greškom, jedva neki pogodak, u kratkom vremenu — bez obzira pogađa li putanja poznati uzorak |
| Pogrešno konfigurisan vlastiti uređaj | Sync klijent ili program za e-poštu greškom pokazuje na pogrešnu adresu i kuca svake minute | Prepoznavanje kao pogrešna konfiguracija umjesto kao napad, tiket umjesto blokade — blokada kvar ne bi otklonila, nego samo odgodila |
| Automatizirano prikupljanje obaveznih podataka | Sakupljač poziva stranice impressuma pod tuđim načinima pisanja, često pripremljen za val opomena | Kanonska putanja uvijek ostaje dostupna (pravno nužno), tuđi načini pisanja se prepoznaju i prijavljuju ili blokiraju |
| Izgubljen ili ukraden uređaj | Prijavljeni notebook ili mobitel dospijeva u tuđe ruke | Pregled sesija s trenutnom odjavom svih uređaja, bez obzira na lozinku |
| Preširoko postavljena interna dozvola | Korisnički račun s više prava nego što je potrebno biva kompromitovan ili zloupotrijebljen | Najmanje potrebno pravo po aplikaciji unaprijed ograničava štetu na ono što račun zaista treba |
| Zloupotreba vanjskog sučelja | Ukraden API ključ ili kompromitovan sistem trećeg lica 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 | Legitiman crawler stvara toliko prometa da izgleda kao distribuirani napadač — na jednoj od naših stranica to je bilo preko sedamdeset posto ukupnog prometa, a uzrokovao ga je GPTBot | Bijela lista s objavljenim opsezima adresa poznatih tražilica sprječava pogrešnu blokadu koja bi vlastitu stranicu uklonila iz indeksiranja |
| Zastarjeli modul trećeg proizvođača s poznatom ranjivošću | Sigurnosna rupa u slobodnom dodatnom modulu postaje javna, a ažuriranje stiže tek nedjeljama kasnije | Prije svake instalacije provjeriti šta dolazi automatski; 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 da se baze podataka obrišu ili kopiraju | Sučelje se nikada ne izlaže javno, glavna lozinka ostaje duga, slučajna i nigdje zabilježena |
Korak po korak: osigurati vlastitu Odoo instalaciju
Sljedeći redoslijed je onaj kojim bismo i sami postupali — od najvećeg učinka do najfinije postavke.
1. Nametnuti dvofaktorsku autentifikaciju
- Ako već nije instalirano: otvoriti Apps, potražiti „Two-Factor Authentication“ i instalirati (kod više web-stranica preporučuje se dodatno „Two-Factor Authentication by Mail“ kao opcija povratka).
- Otvoriti Postavke → Opće postavke → Dozvole.
- Aktivirati „Nametnuti dvofaktorsku autentifikaciju“.
- Odabrati politiku: „Samo zaposlenici“ za interne korisnike, „Svi korisnici“ ako se žele obuhvatiti i korisnici portala (klijenti s pristupom).
- Spremiti. Od sljedećeg pokušaja prijave Odoo od svakog korisnika bez postavljene druge tajne traži barem kod putem e-pošte, dok ne postavi authenticator aplikaciju.
2. Odrediti minimalnu dužinu lozinki
- Otvoriti Apps, potražiti „Password Policy“ i instalirati.
- Otvoriti Postavke → Opće postavke → Dozvole.
- Postaviti „Minimalna dužina lozinke“ — dvanaest znakova je razumna polazna vrijednost.
- Spremiti. Pravilo vrijedi odmah za svako novo ili promijenjeno zadavanje lozinke, ali ne retroaktivno za postojeće lozinke.
3. Pregledati dozvole
- Otvoriti Postavke → Korisnici & kompanije → Korisnici.
- Otvoriti svakog korisnika pojedinačno i provjeriti karticu s pravima pristupa po aplikaciji: Treba li ta osoba zaista „Menadžer“ ili „Administrator“, ili je dovoljan „Korisnik“?
- Posebno provjeriti: Ko ima pristup samim „Postavkama“? To treba biti vrlo mala grupa.
- Za svako vanjsko povezivanje (računovodstvo, vlastite skripte, evidencija vremena) u kartici „Sigurnost računa“ odgovarajućeg tehničkog korisnika kreirati vlastiti API ključ, umjesto da se prosljeđuje korisnička lozinka.
4. Instalirati Web RBL i posmatrati prije aktiviranja
- Modul sa github.com/Alex0176/odoo-web-rbl staviti u addon putanju i instalirati.
- Posmatrati nekoliko dana: meni Web RBL → Analiza pokazuje koji uzorci zaista djeluju.
- Tek nakon toga uključiti
web_rbl.sperren_aktiv(Postavke → Tehničko → Sistemski parametri) — od tada se prepoznate sonde zaista odbijaju. - Listu blokiranih na adresi navedenoj u modulu, zaštićenoj tokenom, uključiti u firewall kao RBL listu (kod OPNsense/pfSense kao URL Table Alias, kod HAProxy kao ACL datoteku).
5. Osigurati sam firewall
- Sučelje za upravljanje firewallom učiniti dostupnim isključivo iz interne mreže, nikada preko iste javne adrese kao web-stranica.
- Aktivirati automatska sigurnosna ažuriranja za firewall softver, ako proizvođač to nudi.
- Provjeriti TLS konfiguraciju: samo aktuelne verzije protokola, deaktivirati zastarjele postupke šifriranja.
- Ako je dostupno: poznatu listu reputacije (npr. Spamhaus DROP) uključiti direktno na firewallu — nezavisno od Web RBL, jer firewall time vidi i saobraćaj prema uslugama do kojih Odoo nikada ne dopire.
6. Zatvoriti upravljanje bazom podataka
- Provjeriti je li
/web/database/managerdostupan izvana — ako jest, u Odoo konfiguraciji postavitilist_db = Falseili blokirati putanju na nivou firewalla. - Glavnu lozinku upravljanja bazom podataka postaviti dugu i slučajnu i ne bilježiti je ni na jednom mjestu koje bi iko drugi mogao pročitati.
7. Provjeriti sigurnosnu kopiju, ne samo je postaviti
- Postaviti automatsku, redovnu sigurnosnu kopiju, pohranjenu odvojeno od Odoo servera.
- Barem jednom je zaista vratiti i provjeriti funkcioniše li obnova — neprovjerena sigurnosna kopija je pretpostavka.
Nijedan od ovih koraka ne zamjenjuje drugi. Ko provede samo jedan, pojačao je jedna vrata, a sva ostala ostavio otvorena — ko provede svih sedam, ima odbranu koja izdržava i onda kada jedan pojedinačni sloj zakaže.
Šta ova arhitektura ne zamjenjuje
Nijedna od opisanih mjera ne čini pažnju suvišnom. Modul koji odbija .env sonde ne čini greškom objavljenu .env datoteku bezopasnom. Dvofaktorska autentifikacija ne štiti od korisnika koji svoj kod pročita pozivatelju na telefonu. A firewall ne zamjenjuje odluku o tome ko zaista treba koju dozvolu. Sigurnosna arhitektura stvara uvjete u kojima pojedinačna greška ne postaje odmah incident — ona nikoga ne oslobađa pažnje.
Česta pitanja
Je li jaka lozinka dovoljna za osiguranje Odooa 19?
Ne. Lozinka može biti ukradena drugdje, potpuno nezavisno od svog kvaliteta, i tada radi kod svake usluge koja prihvata istu lozinku. Tek kombinacija s dvofaktorskom autentifikacijom, firewallom ispred i smislenom strukturom dozvola daje zaštitu koja izdržava i nakon ukradene lozinke.
Kako aktivirati dvofaktorsku autentifikaciju u Odoo 19?
Modul „Two-Factor Authentication (TOTP)“ instalirati putem upravljanja aplikacijama, zatim pod Postavke → Opće postavke → Dozvole aktivirati obaveznost i birati između „Samo zaposlenici“ i „Svi korisnici“. Svaki korisnik nakon toga postavlja vlastiti drugi faktor putem QR koda.
Šta je RBL lista i zašto je Odoo treba?
RBL (Real-time Blackhole List) je lista adresa dostupna putem HTTP-a koju praktično svaki firewall može pročitati. Sam Odoo ne isporučuje takvu listu — naš modul Web RBL zatvara tu rupu tako što prepoznaje napadački promet iz vlastitog aplikacijskog zapisnika i vraća ga kao RBL listu firewallu ispred.
Je li Odoo 19 Community bez dodatnih modula dovoljno osiguran?
Ne u potpunosti. Bez modula Password Policy nema minimalne dužine 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 se mogu besplatno naknadno dodati.
Dostupnost
Web RBL je javno dostupan pod licencom AGPL-3 i kod nas radi produktivno na pet web-stranica:
github.com/Alex0176/odoo-web-rbl
Cjelovit opis funkcija sa svim uzorcima, ocjenom i listama prijetnji nalazi se u prethodnom članku: Web RBL – lista blokiranih za napadački promet na vlastitim web-stranicama.
Pitanja, napomene i izvještaje o greškama rado primamo — najradije kao issue na GitHubu.