Odoo je na našim pet veb-sajtova dostupan sa otvorenog interneta, i to nije izuzetak, nego uobičajen slučaj: ko vodi ponudu, prodavnicu ili prijavu klijenata, ima javni server. Jedna ranjiva lozinka, zaboravljena konfiguraciona datoteka ili preširoko dodeljeno ovlašćenje dovoljni su da javni server postane otvoren.
Ovaj članak pokazuje kako da pravilno obezbedite Odoo 19 — ne jednom pojedinačnom merom, nego sa više slojeva koji se međusobno dopunjuju: zaštitni zid i reverzni proksi, naš open-source modul Web RBL, dvofaktorska autentifikacija, politika lozinki i ovlašćenja — i koje pokušaje napada svaki od njih zaista hvata. Na kraju sledi uputstvo korak po korak kojim se može doterati svaka sopstvena Odoo instalacija.
Sadržaj ovog članka
- Odbrana u dubini: zašto jedna mera nikada nije dovoljna
- Sloj 1: zaštitni zid i reverzni proksi
- Sloj 2: Web RBL — most ka zaštitnom zidu
- Sloj 3: obezbeđivanje samog Odoo-a (2FA, politika lozinki, ovlašćenja)
- Sloj 4: baza podataka i rad sistema
- Put prijave u celini
- Scenariji napada i odbrana od njih
- Uputstvo korak po korak
- Česta pitanja
Odbrana u dubini: zašto jedna mera nikada nije dovoljna
Svaka pojedinačna bezbednosna mera ima rupu. Zaštitni zid ne vidi šta se dešava u Odoo obrascu za prijavu. Jaka lozinka ne štiti ako je već ukradena negde drugde. Struktura ovlašćenja 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 svaki za sebe mogao da se zaobiđe — ali svi zajedno ne mogu.
Kod nas su to četiri sloja, svaki sa drugačijim zadatkom:
- Zaštitni zid / reverzni proksi — drži podalje očigledno zlonamerno, pre nego što uopšte stigne do servera
- Web RBL — povezuje obe strane: Odoo iz sopstvenog aplikativnog zapisnika uči ono što zaštitni zid uopšte ne može da vidi, i to vraća njemu
- Sam Odoo — dvofaktorska autentifikacija, politika lozinki, ovlašćenja, upravljanje sesijama
- Baza podataka & rad sistema — rezervne kopije, zaštita pristupa upravljanju, tajne van svakog zapisnika
U sledećim odeljcima prolazi se kroz svaki sloj pojedinačno.
Sloj 1: zaštitni zid i reverzni proksi
Zaštitni zid je prva instanca koja vidi zahtev i jedina koja može napadača da drži podalje od svakog servisa na serveru — ne samo od veb-sajta, nego i od mejl servera, VPN pristupa i sopstvenog interfejsa za administraciju. Šta se na ovom mestu 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 šifrovanja | Prisluškivanje i manipulacija vezom; zastareli postupci se godinama smatraju probijenim ili slabim |
| Liste reputacije i porekla (RBL) | Poznate mreže napadača, Tor izlazni čvorovi, cele zemlje bez sopstvenih klijenata — vidi dole |
| Ograničenje učestalosti po adresi | Isprobavanje lozinki i skeneri direktorijuma koji u sekundi postave desetine zahteva |
| Razdvajanje administracije i saobraćaja podataka | Sam interfejs zaštitnog zida ne sme biti dostupan preko iste adrese kao javni veb-sajt |
| IDS/IPS (otkrivanje/sprečavanje napada) | Poznati obrasci napada na mrežnom nivou, bez obzira na to koja aplikacija radi iza |
| Automatska bezbednosna ažuriranja za sam zaštitni zid | Zaštitni zid bez zakrpa više nije zaštitni zid, nego dodatna meta |
RBL liste: standardni put kojim se isporučuje reputacija
RBL znači Real-time Blackhole List, pojam iz sveta e-pošte: jedna adresa u svakom redu, dostupna preko HTTP-a, redovno ponovo učitavana. Praktično svaki zaštitni zid može da učita takvu listu i od nje napravi 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 sa sopstvenim nazivima za isti princip.
Upravo tu se nadovezuje naš sopstveni modul — i upravo tu počinje drugi sloj.
Sloj 2: Web RBL — most između aplikacije i zaštitnog zida
Zaštitni zid vidi pakete, a ne aplikativnu logiku. On ne zna da je zahtev za /xmlrpc/2/common pokušaj prijave, da dvadeset različitih putanja za četrnaest sekundi znači skener, niti da je neka adresa upravo uspešno pogodila lozinku. Sve to zna samo sam Odoo. Web RBL, naš sopstveni open-source modul (AGPL-3), čini to znanje upotrebljivim — za sam Odoo i, isporučeno kao RBL lista, i za zaštitni zid ispred njega.
Liste pretnji se neprekidno upoređuju, svaka sa sopstvenim nivoom.
Ukratko, ono što je detaljno opisano u prethodnom članku:
- Prepoznavanje obrazaca u putanjama:
.envdatoteke,.gitdirektorijumi, konfiguracione datoteke, WordPress i PHP sonde, path traversal, izvršavanje komandi preko novih KI interfejsa - Odbrana prijave koja broji i preko restartovanja — za razliku od Odoo-ovog sopstvenog brojača koji živi u radnoj memoriji
- Ocena svake adrese od 0 do 100, sa obrazloženjem običnim jezikom
- Pogrešne konfiguracije (QNAP, Autodiscover, Synology) se prepoznaju i nikada ne blokiraju, jer blokada ne otklanja kvar, nego ga samo skriva
- Tuđe liste pretnji kao Spamhaus, FireHOL i Tor izlazni čvorovi, neprekidno upoređivane
- Lista izuzetaka za adrese koje nikada ne treba blokirati
Za ovaj članak su dve osobine posebno važne, jer su neposredno povezane sa zaštitnim zidom i sa prijavom.
Troma lista je lista kojoj se može verovati
Lista izuzetaka — adrese koje se nikada ne blokiraju, na primer sopstvene veze lokacija — po pravilu se menja retko. Upravo to je njena vrednost, a ne nedostatak: kada se mirna lista danima jedva pomera, svaka retka promena odmah upadne u oči. Dnevno automatsko ažuriranje ne postoji zato što bi se mnogo menjalo, nego da se retka promena ne bi morala ručno naknadno upisivati — a upravo je to tačka u kojoj se zaboravlja. Jedna od naših sopstvenih pogrešnih konfiguracija prošlog meseca primećena je upravo tako: ne kroz mnogo događaja, nego kroz onaj jedan koji niko nije poznavao, sve dok QNAP veb-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 mesto koje zaštitni zid ne vidi
Zaštitni zid može da blokira adresu. Ne može da zna da li je prijava uspela, a još manje da li je stigla sa adrese koja je malo pre toga još tražila pristupne podatke. Web RBL može: ocena od podesivog praga nadalje u potpunosti zabranjuje prijavu, a uspešna prijava sa upadljive adrese se prijavljuje — to je spona ka sledećem sloju.
Sloj 3: obezbeđivanje samog Odoo-a
Dvofaktorska autentifikacija: druga tajna koja se ne može ponovo upotrebiti
Najveći problem lozinki nije njihov kvalitet, nego njihova ponovna upotreba. Lozinka ukradena kod drugog servisa kod nas funkcioniše isto, sve dok je ista. Dvofaktorska autentifikacija (2FA, zvana i TOTP) tome suprotstavlja drugu tajnu: šestocifreni kod koji se menja svakih trideset sekundi i računa se iz tajne koju zna samo sopstveni 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 rezervnom opcijom preko e-pošte. Svaki korisnik ga podešava sam za sebe, preko QR koda, sa bilo kojom uobičajenom aplikacijom za autentifikaciju:
Podešavanje: skenirati QR kod, jednom potvrditi šestocifreni kod, gotovo.
To samo po sebi, međutim, pomaže samo onima koji ga sami podese — a iskustvo pokazuje da bez prinude to ostaje manjina. Zato Odoo poznaje politiku nametanja: ili samo za zaposlene (interni korisnici) ili za sve, uključujući korisnike portala. Bez podešene druge tajne niko više ne prolazi pored obrasca za prijavu a da je bar kodom iz e-pošte ne potvrdi.
Politika lozinki: minimalna dužina nije samo po sebi razumljiva
Bez dodatnog modula Odoo Community se ne oslanja ni na kakvu minimalnu dužinu lozinki — korisnik može postaviti lozinku od tri znaka ako ga niko u tome ne spreči. Sopstveni modul Password Policy zatvara upravo tu rupu: minimalna dužina koja se sprovodi na strani servera, a ne samo predlaže u pregledaču. Ko želi više — nametnut rok važenja, istoriju protiv ponovne upotrebe — za to mu je potreban OCA ili modul trećeg lica; u Community verziji je to namerno ostavljeno skromnim.
Ovlašćenja: pristup dobija samo ko ga treba
Odoo od početka razdvaja tri nivoa: korisnike portala (samo sopstveni portal klijenata ili dobavljača), interne korisnike (backend, sa pravima po aplikaciji) i administratore (neograničen pristup uključujući tehnička podešavanja). Najčešća greška nije preslaba lozinka, nego preširoko dodeljena uloga administratora: ko treba samo da izdaje račune, ne treba pristup sistemskim podešavanjima.
Dva načela nose najveći deo tereta:
API ključ umesto lozinke: svako spoljno povezivanje (računovodstveni softver, evidencija vremena, sopstvene skripte) dobija sopstveni ključ koji se može opozvati u svakom trenutku, nikada korisničku lozinku.
Oboje se može proveriti u istom prikazu u kom se podešava 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 sa kojih uređaja je nalog trenutno prijavljen — i omogućava da se odjavi jedan ili svi odjednom. Posle izgubljenog laptopa ili sumnje na kompromitovanu lozinku to je najbrži delotvoran korak: sesija se završava odmah, bez obzira na to da li je lozinka već promenjena.
Sloj 4: baza podataka i rad sistema
Četvrti sloj je najmanje vidljiv i istovremeno najneoprostiviji, jer greška ovde može poništiti sve prethodno izgrađeno.
/web/database/manager nudi interfejs kojim se baze podataka mogu praviti, kopirati, vraćati i brisati — zaštićen samo jednom jedinom glavnom lozinkom. Ovaj interfejs treba da bude dostupan isključivo interno ili potpuno isključen.
- Redovne, proverene rezervne kopije, čuvane odvojeno od samog servera. Rezervna kopija koja nikada nije vraćena je pretpostavka, a ne rezervna kopija.
- Tajne ne pripadaju nijednoj datoteci zapisnika. Lozinke, API ključevi, licencni podaci — ko piše sopstvena proširenja, treba da ih tretira kao samu glavnu lozinku: nigde ih ne beležiti, ni „samo za debagovanje“.
- Održavati module ažurnim, i to naročito module trećih lica. Slobodni dodatni moduli (OCA i drugi) po prirodi stvari kasne za novim Odoo verzijama; pre svake instalacije vredi pogledati koje zavisnosti dolaze automatski.
Put prijave u celini
Četiri sloja ne deluju jedan za drugim u odvojenim prostorijama, nego na istom zahtevu, stepenik po stepenik. Na primeru prijave to je najjasnije:
Pet mesta na kojima zlonameran zahtev može da završi pre nego što stigne do stvarnog cilja — i samo jedno na kome ih ovlašćeni korisnik sve prolazi.
Scenariji napada i odbrana od njih
Sledeći pregled razvrstava stvarne obrasce napada po slojevima koji ih zaista zaustavljaju. Nekoliko njih nije teorija, nego naša sopstvena zapažanja iz sedamnaest dana stvarnog saobraćaja na našim pet veb-sajtova.
| Scenario napada | Kako se odvija | Šta ga zaustavlja |
|---|---|---|
| Isprobavanje lozinki | Skripta pokušava stotine kombinacija na obrascu za prijavu ili XML-RPC-u | Ograničenje učestalosti na zaštitnom zidu, Web RBL brojač preko restartovanja, blokada posle deset pokušaja, trenutna blokada pri ignorisanoj poruci o čekanju |
| Ponovo korišćeni, negde drugde ukradeni pristupni podaci | Napadač već zna korisničko ime i lozinku — iz nekog drugog, hakovanog servisa | Dvofaktorska autentifikacija zaustavlja prijavu uprkos tačnoj lozinci; Web RBL dodatno prijavljuje uspešnu prijavu sa upadljive adrese |
| Potraga za zaboravljenim tajnama | Automatizovani zahtevi za .env, .git, pristupnim ključevima za oblak — kod nas 57.721 zahtev u sedamnaest dana samo za .env |
Web RBL blokira pri prvom pogotku; zaštitni zid zatim dobija adresu kao RBL unos za sve ostale servise |
| Skeneri direktorijuma i putanja | Desetine izmišljenih putanja u nekoliko sekundi, u potrazi za zaboravljenim aplikacijama | Prepoznavanje ponašanja: mnogo stranica sa greškom, jedva neki pogodak, za kratko vreme — bez obzira na to da li putanja pogađa poznati obrazac |
| Pogrešno konfigurisan sopstveni uređaj | Sinhronizacioni klijent ili program za e-poštu greškom pokazuje na pogrešnu adresu i kuca u minutskom ritmu | Prepoznavanje kao pogrešna konfiguracija umesto kao napad, tiket umesto blokade — blokada ne bi otklonila kvar, samo bi ga odlagala |
| Automatizovana žetva obaveznih podataka | Skupljač poziva stranice impresuma pod tuđim načinima pisanja, često pripremljen za talas opomena | Kanonska putanja uvek ostaje dostupna (pravno neophodno), tuđi načini pisanja se prepoznaju i prijavljuju ili blokiraju |
| Izgubljen ili ukraden uređaj | Prijavljeni notebook ili mobilni telefon dospeva u tuđe ruke | Pregled sesija sa trenutnom odjavom svih uređaja, nezavisno od lozinke |
| Preširoko postavljeno interno ovlašćenje | Korisnički nalog sa više prava nego što je potrebno biva kompromitovan ili zloupotrebljen | Najmanje potrebno pravo po aplikaciji unapred ograničava štetu na ono što nalog zaista treba |
| Zloupotreba spoljnog interfejsa | Ukraden API ključ ili kompromitovan sistem trećeg lica pristupa preko XML-RPC/JSON-RPC | Sopstveni API ključevi koji se mogu opozvati umesto korisničke lozinke; Web RBL nadzire i neuspele RPC prijave |
| Pogrešno procenjen crawler pretraživača | Legitiman crawler stvara toliko saobraćaja da izgleda kao distribuirani napadač — na jednom od naših sajtova bilo je to preko sedamdeset procenata celokupnog saobraćaja, a izazvao ga je GPTBot | Lista izuzetaka sa objavljenim opsezima adresa poznatih pretraživača sprečava pogrešnu blokadu koja bi sopstveni sajt izbacila iz indeksiranja |
| Zastareo modul trećeg lica sa poznatom ranjivošću | Bezbednosna ranjivost u slobodnom dodatnom modulu postaje javna, ažuriranje stiže tek nedeljama kasnije | Pre svake instalacije proveriti šta dolazi automatski; ažuriranja prvo na test instanci, a ne na živom sistemu |
| Otvoreno upravljanje bazom podataka | Administrativni interfejs je dostupan preko otvorenog interneta; pogođena ili slaba glavna lozinka dovoljna je da se baze podataka obrišu ili kopiraju | Interfejs se nikada ne izlaže javno, glavna lozinka ostaje duga, nasumična i nigde zabeležena |
Korak po korak: obezbeđivanje sopstvene Odoo instalacije
Sledeći redosled je onaj kojim bismo i sami postupali — od najvećeg dejstva do najfinijeg podešavanja.
1. Nametnuti dvofaktorsku autentifikaciju
- Ako još nije instalirano: otvoriti Apps, potražiti „Two-Factor Authentication“ i instalirati (kod više veb-sajtova preporučuje se dodatno „Two-Factor Authentication by Mail“ kao rezervna opcija).
- Otvoriti Podešavanja → Opšta podešavanja → Ovlašćenja.
- Aktivirati „Nametnuti dvofaktorsku autentifikaciju“.
- Izabrati politiku: „Samo zaposleni“ za interne korisnike, „Svi korisnici“ ako treba uključiti i korisnike portala (klijente sa pristupom).
- Sačuvati. Od sledećeg pokušaja prijave Odoo od svakog korisnika bez podešene druge tajne traži najmanje kod iz e-pošte, dok ne podesi aplikaciju za autentifikaciju.
2. Odrediti minimalnu dužinu lozinki
- Otvoriti Apps, potražiti „Password Policy“ i instalirati.
- Otvoriti Podešavanja → Opšta podešavanja → Ovlašćenja.
- Postaviti „Minimalna dužina lozinke“ — dvanaest znakova je razumna početna vrednost.
- Sačuvati. Pravilo važi odmah za svako novo ili promenjeno postavljanje lozinke, a unazad ne važi za postojeće lozinke.
3. Pregledati ovlašćenja
- Otvoriti Podešavanja → Korisnici & kompanije → Korisnici.
- Otvoriti svakog korisnika pojedinačno i proveriti karticu sa pravima pristupa po aplikaciji: Da li ovoj osobi zaista treba „Menadžer“ ili „Administrator“, ili je dovoljno „Korisnik“?
- Posebno proveriti: Ko ima pristup samim „Podešavanjima“? To bi trebalo da bude veoma mala grupa.
- Za svako spoljno povezivanje (računovodstvo, sopstvene skripte, evidencija vremena) na kartici „Bezbednost naloga“ odgovarajućeg tehničkog korisnika napraviti poseban API ključ, umesto da se prosleđuje korisnička lozinka.
4. Instalirati Web RBL i posmatrati pre uključivanja oštre blokade
- Modul sa github.com/Alex0176/odoo-web-rbl staviti u putanju za dodatke (addon path) i instalirati.
- Posmatrati nekoliko dana: meni Web RBL → Analiza pokazuje koji obrasci zaista deluju.
- Tek nakon toga uključiti
web_rbl.sperren_aktiv(Podešavanja → Tehničko → Sistemski parametri) — od tada se prepoznate sonde zaista odbijaju. - Listu blokiranih, sa adrese navedene u modulu i zaštićene tokenom, uključiti u zaštitni zid kao RBL listu (kod OPNsense/pfSense kao URL Table Alias, kod HAProxy kao ACL datoteku).
5. Obezbediti sam zaštitni zid
- Administrativni interfejs zaštitnog zida učiniti dostupnim isključivo iz interne mreže, nikada preko iste javne adrese kao veb-sajt.
- Aktivirati automatska bezbednosna ažuriranja za softver zaštitnog zida, ako ih proizvođač nudi.
- Proveriti TLS konfiguraciju: samo aktuelne verzije protokola, deaktivirati zastarele postupke šifrovanja.
- Ako je dostupno: poznatu listu reputacije (na primer Spamhaus DROP) uključiti direktno na zaštitnom zidu — nezavisno od Web RBL, jer zaštitni zid tako vidi i saobraćaj ka servisima do kojih Odoo nikada ne dopire.
6. Zatvoriti upravljanje bazom podataka
- Proveriti da li je
/web/database/managerdostupan spolja — ako jeste, u Odoo konfiguraciji postavitilist_db = Falseili blokirati putanju na nivou zaštitnog zida. - Glavnu lozinku upravljanja bazom podataka postaviti dugu i nasumičnu i ne beležiti je nigde gde bi je iko drugi mogao pročitati.
7. Proveriti rezervnu kopiju, a ne samo je podesiti
- Podesiti automatsku, redovnu rezervnu kopiju, čuvanu odvojeno od Odoo servera.
- Bar jednom je zaista vratiti i proveriti da li vraćanje funkcioniše — neproverena rezervna kopija je pretpostavka.
Nijedan od ovih koraka ne zamenjuje nijedan drugi. Ko sprovede samo jedan od njih, ojačao je jedna vrata, a sva ostala ostavio otvorena — ko sprovede svih sedam, ima odbranu koja izdržava i kada jedan sloj zakaže.
Šta ova arhitektura ne zamenjuje
Nijedna od opisanih mera ne čini pažnju suvišnom. Modul koji odbija .env sonde ne čini bezopasnom slučajno objavljenu .env datoteku. Dvofaktorska autentifikacija ne štiti od korisnika koji svoj kod pročita pozivaocu preko telefona. A zaštitni zid ne zamenjuje odluku o tome ko zaista treba koje ovlašćenje. Bezbednosna arhitektura stvara uslove u kojima pojedinačna greška ne postaje odmah incident — ona nikoga ne oslobađa pažnje.
Česta pitanja
Da li je jaka lozinka dovoljna da se obezbedi Odoo 19?
Ne. Lozinka može biti ukradena negde drugde, sasvim nezavisno od svog kvaliteta, i tada funkcioniše kod svakog servisa koji prihvata istu lozinku. Tek kombinacija sa dvofaktorskom autentifikacijom, zaštitnim zidom ispred i smislenom strukturom ovlašćenja daje zaštitu koja izdržava i posle ukradene lozinke.
Kako da aktiviram dvofaktorsku autentifikaciju u Odoo 19?
Instalirati modul „Two-Factor Authentication (TOTP)“ preko upravljanja aplikacijama, zatim pod Podešavanja → Opšta podešavanja → Ovlašćenja aktivirati nametanje i izabrati između „Samo zaposleni“ i „Svi korisnici“. Svaki korisnik potom podešava svoj drugi faktor preko QR koda.
Šta je RBL lista i zašto je Odoo-u potrebna?
RBL (Real-time Blackhole List) je lista adresa dostupna preko HTTP-a koju može da učita praktično svaki zaštitni zid. Sam Odoo ne isporučuje takvu listu — naš modul Web RBL zatvara tu rupu tako što prepoznaje napadački saobraćaj iz sopstvenog aplikativnog zapisnika i vraća ga kao RBL listu zaštitnom zidu ispred.
Da li je Odoo 19 Community bez dodatnih modula dovoljno obezbeđen?
Ne u potpunosti. Bez modula Password Policy nema minimalne dužine lozinki, bez Two-Factor Authentication nema drugog faktora, a bez modula kao što je Web RBL Odoo ne prepoznaje ni pokušaje sondiranja ni ponovljene pokušaje prijave preko restartovanja. Sva četiri se mogu besplatno naknadno dodati.
Dostupnost
Web RBL je javno dostupan pod AGPL-3 licencom i kod nas radi produktivno na pet veb-sajtova:
github.com/Alex0176/odoo-web-rbl
Potpuni opis funkcija sa svim obrascima, ocenom i listama pretnji nalazi se u prethodnom članku: Web RBL – lista blokiranih za napadački saobraćaj na sopstvenim veb-sajtovima.
Pitanja, napomene i izveštaje o greškama rado primamo — najradije kao Issue na GitHub-u.