Kildekode: github.com/Alex0176/odoo-web-rbl — AGPL-3, frit tilgængeligt til brug.
Driver man en Odoo-server på internettet, får man besøg. Ikke en gang imellem, men uafbrudt. Over sytten dage loggede og analyserede vi 731.297 forespørgsler på vores fem websteder. 110.511 af dem kom ikke fra besøgende, men fra automatiserede søgninger efter sårbarheder, loginoplysninger og konfigurationsfiler.
Denne artikel beskriver Web RBL, et open source-modul til Odoo 19 Community, der genkender, vurderer, registrerer og afviser denne trafik — og offentliggør blokeringslisten som en RBL-liste, altså i det format, som firewalls og reverse proxyer kan læse direkte. Alle tal stammer fra den faktiske drift.
Hvad modulet kan — overblik over funktionerne
| Funktion | Hvad den gør | Standardindstilling |
|---|---|---|
| Mønstergenkendelse | Genkender sonderinger ud fra sti og filendelse: .env, .git, konfigurationsfiler, cloudnøgler, CI/CD-buildfiler, WordPress, PHP, stitraversering, databaseadministration, GraphQL, kommandoafvikling via /api/fs/exec og lignende grænseflader | blokér |
| Tre niveauer pr. mønster | blokér, tæl eller giv besked — kan ændres for hvert mønster uden kode | pr. mønster |
| Tærskler | Antal registreringer af samme mønster, før der blokeres; ti for loginforsøg | 10 ved login |
| Beskyttelse mod loginangreb | Mislykkede loginforsøg via formular og XML-RPC/JSON-RPC, mislykkede sessionskontroller og adgangsforsøg til databaseadministrationen — gemmes i databasen, ikke i hukommelsen | til |
| Botregistrering ved login | Den, der ignorerer beskeden om at vente efter ti mislykkede forsøg og fortsætter, blokeres straks | blokér |
| Adfærdsregistrering | Adresser, der på fem minutter udløser tyve fejlsider og næsten ingen vellykkede sidevisninger — altså gætter i stedet for at læse | giv besked |
| Score 0–100 | Hvor sikkert er det, at der står en angriber bag adressen? Beregnes ud fra mønstrets alvor, antallet af forskellige mønstre, dage med mistænkelig aktivitet, berørte domæner og antal registreringer — med en begrundelse i klart sprog | til |
| Loginblokering ud fra score | Fra en indstillelig score blokeres login, mens webstedet stadig kan læses | fra 40 |
| Mistanke om stjålne loginoplysninger | Et vellykket login fra en mistænkelig adresse udløser en besked og kan efter ønske tildeles som en opgave — én gang pr. adresse pr. dag | til |
| Trusselslister | Tor-udgangsnoder, Spamhaus DROP, FireHOL Level 1 og blocklist.de er forudkonfigureret; enhver anden RBL-liste kan tilføjes via sin adresse, daglig opdatering og særskilt niveau for hver liste | giv besked |
| Ingen adgang til login | Det fjerde niveau for lister og lande: Webstedet kan læses, men loginformularen og grænsefladerne er lukket — den passende løsning til Tor | Valgfrit |
| Oprindelsesland | Land for hver registrering og adresse via GeoLite2; modulet holder selv databasen opdateret med en gratis licensnøgle | vis |
| Landeregler | Blokér, ingen adgang til login, giv besked eller tillad udtrykkeligt — for hvert land, bevidst uden standardindstillinger | ingen |
| Fejlkonfigurationer | QNAP, Synology, Exchange-Autodiscover, ActiveSync og WebDAV/CalDAV/CardDAV genkendes, blokeres aldrig og føjes til en arbejdsliste med en beskrivelse af fundet og det berørte domæne | giv besked |
| Én supportsag pr. adresse | Et fund kan efter ønske blive til en supportsag — præcis én pr. adresse; en lukket sag genåbnes i stedet for at blive oprettet igen | fra |
| Lovpligtige sider og dataindsamlere | Den kanoniske sti til siden med lovpligtige virksomhedsoplysninger er altid tilgængelig; automatiseret afprøvning af andre stavemåder genkendes og kan blokeres efter ønske | giv besked |
| Tilladelsesliste | Adresser og netværk, der aldrig blokeres; opdateres dagligt med oplysninger fra firewallen (VPN-modparter) og de offentliggjorte adresseområder for Googlebot og Bingbot | til |
| Kundetilknytning | En registrering fra en kundes netværk knyttes til kunden — ud fra tilladelseslisten, aldrig ud fra manuelle gæt | til |
| Domæne og identifikation pr. registrering | Hvilket websted blev kontaktet, og med hvilken User-Agent — begge oplysninger mangler i adgangsloggen | til |
| Analyse | Diagram og pivottabel over alle registreringer: efter mønster, dag, domæne, land og adresse | til |
| Lokkemad | Sonderinger får opdigtede svar med en sporingsværdi; den, der senere forespørger på den, har læst svarene | fra |
| RBL-distribution | Blokeringslisten som en ren adresseliste eller JSON på en særskilt, tokenbeskyttet adresse — til HAProxy, OPNsense og enhver firewall, der læser URL-lister | til |
Alt, der som standard står på giv besked, fra eller Valgfrit, er indstillet sådan med vilje: Den, der aktiverer en blokering, skal gøre det efter i nogle dage at have set, hvem den rammer — ikke fordi standardindstillingen bestemte det.
Analysen: registreringer pr. mønster over syv dage. Den højeste søjle er søgningen efter .env-filer.
RBL-lister: en standardiseret måde at distribuere blokeringer på
RBL står for Real-time Blackhole List. Begrebet stammer fra mailverdenen, hvor Spamhaus og andre siden halvfemserne har offentliggjort lister over ondsindede afsenderadresser. Princippet er ganske enkelt og netop derfor så udbredt: én adresse pr. linje, tilgængelig via HTTP, genindlæst regelmæssigt. Intet format, der først skal parses, ingen grænseflade, der kræver et værktøj.
Stort set alle firewalls og reverse proxyer kan indlæse sådan en liste og danne regler ud fra den. Producenterne bruger forskellige navne, men mekanismen er den samme overalt:
- OPNsense og pfSense — URL Table Alias: Hent adresselisten via HTTP, brug den som alias i firewallregler, og opdater hver time eller dag
- HAProxy — ACL-filer og Maps:
src -f sperrliste.txti enhttp-request deny-regel; kan genindlæses via runtime-API'en uden genstart - nginx — geo-modul med en tilknyttet adressefil eller
deny-direktiver fra en genereretinclude-fil - Fortinet FortiGate — External Block List eller Threat Feed: en URL, som firewallen henter en IP-liste fra og bruger i politikker
- Palo Alto Networks — External Dynamic List (EDL): samme princip, som en særskilt objekttype i sikkerhedspolitikkerne
- Check Point — Custom Intelligence Feeds og IP Block Lists via en URL
- Cisco Secure Firewall (Firepower) — Security Intelligence Feeds med egne listekilder
- Sophos Firewall — Third-Party Threat Feeds: adresselister fra en URL som grundlag for blokeringsregler
- Juniper SRX — Dynamic Address Entries fra feeds
- MikroTik RouterOS — Address Lists, udfyldt fra en URL via et script og
fetch - CrowdSec — egne lister som kilde til bouncers på alle understøttede systemer
Web RBL distribuerer sin blokeringsliste i netop dette format. Firewallen kasserer pakkerne, før de når webserveren — og dermed også alle andre forsøg fra samme adresse, eksempelvis mod mailserveren eller VPN-gatewayen.
Begge retninger, men på det rette sted
Det fungerer også den anden vej: I Web RBL kan man tilføje en hvilken som helst RBL-liste — en URL, et niveau, færdig. Tor-udgangsnoder, Spamhaus DROP, FireHOL og blocklist.de er forudkonfigureret, og flere kan tilføjes med tre klik. Modulet opdeler hver liste i adresseområder og kontrollerer hver forespørgsel mod dem på få mikrosekunder.
Alligevel: Det giver mere mening at bruge eksterne lister på firewallen foran serveren. Af tre grunde. Firewallen ser alle tjenester, ikke kun HTTP — en adresse på Spamhaus-listen skal også afvises af mailserveren og VPN'et. Den kasserer trafikken på pakkeniveau, før der overhovedet oprettes en forbindelse, så applikationsserveren ikke belastes. Og det er dér, den slags lister alligevel vedligeholdes; endnu en kopi i applikationen er endnu et sted, hvor de kan blive forældede.
Hvad listerne så stadig kan bruges til i modulet: det, en firewall ikke kan. Den kender ikke til loginformularer. Web RBL kan nægte en adresse på Tor-listen adgang til login og stadig vise webstedet — den, der vil læse anonymt, skal have lov; den, der vil afprøve adgangskoder anonymt, skal ikke. Og modulet kan give besked om et vellykket login fra en adresse på listen som en mistænkelig hændelse. Begge dele kræver, at listen findes dér, hvor login foregår.
En score frem for mavefornemmelse
En adresse, der én gang har forespurgt på /wp-login.php, er noget andet end en, der over to dage har afprøvet fem forskellige mønstre på tværs af tre domæner. Web RBL omsætter det til en score fra 0 til 100 — ud fra det, modulet selv har set, uden eksterne tjenester eller forespørgsler ud af systemet.
En post: 99 registreringer, en score på 84 og begrundelsen i klart sprog — et mønster i den alvorligste kategori, fem forskellige alvorlige mønstre, to dage med mistænkelig aktivitet og over tyve registreringer.
Scoren afgør to ting. Fra en indstillelig værdi blokeres login — webstedet kan stadig læses, men den, der allerede har ledt efter loginoplysninger, får ikke mulighed for at afprøve dem, der er fundet. Og et vellykket login fra en adresse med en score udløser en besked: Så er der nogen, der ikke længere har gættet, men har kendt oplysningerne. Enten har den retmæssige bruger været på farten, eller også er loginoplysningerne kommet i de forkerte hænder — modulet afgør det ikke, men forelægger det for en, der kan spørge ind til det. Selve adgangskoden bliver ikke berørt på noget tidspunkt.
Blokeringslisten, filtreret efter en score på mindst 40: antal registreringer, dage med mistænkelig aktivitet, berørte domæner og seneste sti for hver adresse.
Hvad Web RBL beskytter — beskyttelsen i detaljer
1. Loginoplysninger forbliver uopdagede
Den største målte angrebskategori leder ikke efter sårbarheder i Odoo, men efter efterladte hemmeligheder. Over sytten dage:
- 57.721 forespørgsler efter
.env-filer — her ligger databaseadgangskoder, API-nøgler og sessionshemmeligheder - 5.535 forespørgsler efter konfigurationsfiler
- 4.388 forespørgsler efter loginoplysninger til cloudtjenester:
credentials.json,service-account.json,firebase-adminsdk.json,rclone.conf,.git-credentials - 2.811 forespørgsler efter
.git-mapper — den, der finder en, downloader hele kildekoden inklusive historik - 1.907 forespørgsler efter buildfiler som
.github/workflows/deploy.ymleller.gitlab-ci.yml, der indeholder registre og nøglenavne
Det afgørende er ikke antallet af forespørgsler, men antallet af forskellige adresser: Forespørgsler efter /credentials.json kom fra 98 adresser, og efter /.git-credentials fra 92. Det er ikke en enkelt scanner, men et standardrepertoire, der kører samtidig over hele verden.
2. Loginforsøg fører ingen vegne — permanent
Odoo har sin egen mekanisme til at bremse afprøvning af adgangskoder. Den har tre begrænsninger, som er dokumenteret i selve Odoo-kildekoden: Tælleren ligger i arbejdsprocessens hukommelse og nulstilles ved hver genstart, den forsinker kun i stedet for at blokere, og den tæller udelukkende forsøg, der når frem til kontrollen af adgangskoden.
Web RBL griber ind de samme steder, men skriver til databasen. Det betyder:
- Tællerstanden bevares ved hver genstart og gælder på tværs af alle arbejdsprocesser
- Begge adgangsveje registreres: loginformularen
/web/loginog grænsefladerne/xmlrpc/2/commonog/jsonrpc - Også forsøg, der aldrig når frem til kontrollen af adgangskoden, registreres — eksempelvis loginforsøg uden et gyldigt sessionstoken
- Et mislykket adgangsforsøg til databaseadministrationen tælles med; det er det alvorligste loginforsøg overhovedet
Tærsklen for loginforsøg er sat til ti, og det skyldes en måling: Af ni mislykkede loginforsøg over sytten dage kom de fleste fra kunder, som selv var ved at konfigurere adgang på endnu en enhed og indtastede det forkerte domæne — i ét tilfælde deres eget, blot med bindestreg i stedet for punktum. En blokering ved første mislykkede forsøg ville derfor have ramt kunder under opsætningen frem for angribere.
Den, der derimod fortsætter, selv om serveren allerede har svaret »vent venligst et øjeblik«, blokeres straks. Et menneske læser beskeden og venter; den, der ignorerer den, er et program. Et særskilt mønster med en tærskel på nul fanger netop dette tilfælde, og det kan ikke ramme en kollega: Man når kun dertil, hvis man allerede har ti mislykkede forsøg bag sig og derefter fortsætter.
3. Angrebet belaster ikke længere serveren
Før modulet blev indført, var en sondering mod en sti som /@fs/../../.env ressourcekrævende: Odoo finder fejlsiden, renderer den, snubler over punktsegmenterne under opbygningen af adressen og fejler derefter også på fejlsidens fejlside. To stacktraces pr. sondering. Der blev målt 28.401 af den slags fejl over sytten dage samt 9.467 følgefejl.
Web RBL griber ind i ir.http._match, altså før routing. Svaret sendes uden skabelon, uden databaseadgang ud over blokeringskontrollen og uden en linje i loggen. Kontrollen mod tilladelseslisten, trusselslister og landeregler foregår fra cachen via sorterede adresseområder — på få mikrosekunder, selv med over tredive tusind områder.
4. Firewallen afviser angriberen, før trafikken når frem
Spærrelisten udgives som RBL-liste, som HAProxy og OPNsense læser direkte. Angriberen når dermed slet ikke webserveren længere — og heller ingen anden tjeneste på samme vært. En adgang, der én gang er genkendt som ondsindet, beskytter således med tilbagevirkende kraft hele maskinen.
Tre niveauer: blokér, tæl, giv besked
Ikke alle forespørgsler, der rammer ved siden af, er angreb. Derfor skelner Web RBL mellem tre niveauer, og niveauet kan ændres for hvert mønster uden at røre koden.
| Niveau | Den udløsende forespørgsel | Konsekvens for adressen |
|---|---|---|
| blokér | afvises | blokeret i 24 timer, permanent efter tre dage med mistænkelig aktivitet |
| tæl | slipper igennem | registreres kun, ingen blokering |
| giv besked | slipper igennem | registreres med en beskrivelse af fundet, blokeres aldrig |
For trusselslister og lande findes der et fjerde niveau: ingen adgang til login. Webstedet kan stadig læses, men loginformularen og grænsefladerne er lukket. Det er mellemvejen for alt, der er mistænkeligt uden nødvendigvis at være ondsindet — Tor, et datacenters adresseområde eller et land uden kunder.
Hvilke angreb der genkendes
Alle mønstre er afprøvet på virkelig trafik. Antallet af forskellige adresser er bevidst angivet ved siden af — det viser, om et mønster rammer en enkelt scanner eller en udbredt fremgangsmåde.
| Angrebskategori | Forespørgsler | Adresser |
|---|---|---|
Forsøg på at hente .env | 57.721 | 223 |
| PHP-sonderinger | 12.237 | 256 |
| Stitraversering mod et værdifuldt mål | 10.046 | 64 |
| Konfigurationsfiler | 5.535 | 114 |
| Adgangsnøgler til cloudtjenester | 4.388 | 152 |
| WordPress-sonderinger | 3.366 | 385 |
Forsøg på at hente .git | 2.811 | 255 |
| Rekognoscering mod Odoo (databaseadministration, versionsforespørgsel) | 2.500 | 213 |
AI-værktøjskæder og kommandoafvikling (/mcp, /api/fs/exec) | 2.450 | 74 |
| Buildfiler (CI/CD) | 1.907 | 88 |
| GraphQL-endepunkter | 1.878 | 71 |
Den nyeste kategori er bemærkelsesværdig. /api/fs/exec blev forespurgt 369 gange fra 54 forskellige adresser — det er ikke læseadgang, men forsøg på at udføre kommandoer. Den slags mål fandtes ikke for to år siden; de stammer fra grænseflader til nye AI-værktøjer og opgavekøer. Hvis man kun retter sit forsvar mod WordPress og PHP, opdager man intet af det. Kategorien vægter derfor tungt i vurderingen.
Trusselslister og oprindelsesland
Fire lister, 32.851 adresseintervaller, alle på »kun indberette«. Hver yderligere liste er en adresse og et niveau.
En fremmed liste er en påstand, som en anden
opstiller, af grunde, vi ikke kender, om trafik, vi
aldrig har set. Den kan være forkert, forældet eller tænkt til et
andet formål: blocklist.de samler især
adresser, der andre steder har afprøvet SSH-logins, og det
siger ikke meget om en webserver. Derfor fører Web RBL fremmede lister
adskilt fra den egen spærreliste, og derfor er standardværdien
indberette. Og den egen positivliste vinder altid: En kunde, som
vi kender, vejer tungere end en tredjeparts vurdering.
Oprindelseslandet vises ved hver registrering og hver adresse. Det er uundværligt i vurderingen — et loginforsøg fra ens eget land klokken ti om formiddagen er noget andet end et fra et land, hvor man ikke har en eneste kunde. Til generel blokering er det mindre egnet, og det viser vores egne tal: Angriberne på vores liste kom overvejende fra cloud-adresseområder i Belgien, Finland og Nederlandene. En blokering af alt uden for det tysksprogede område ville ikke have ramt dem — men derimod vores egne medarbejdere på ferie og kunder på forretningsrejse.
Landereglerne er tomme som standard, og visningen forklarer hvorfor.
Rapportér fejlkonfigurationer i stedet for at blokere
Det hyppigste tilfælde i den faktiske trafik er hverken et angreb eller en besøgende, men software med fejl, der forveksler webserveren med noget andet:
- 1.367 kald til webgrænsefladen på en QNAP-NAS — en synkroniseringsklient, hvis destinationsadresse ikke længere passer. En enkelt forbindelse henvendte sig 962 gange.
- 65 Autodiscover-forespørgsler — en Outlook-klient, der tror, at webdomænet er dens Exchange-server
Sådanne adresser bliver aldrig blokeret. En blokering retter ikke fejlen, men skjuler den — og rammer den person, hvis enhed allerede er forkert konfigureret. I stedet oprettes en post med en beskrivelse af problemet og de berørte domæner. Den kan efter ønske automatisk blive til en supportsag: præcis én pr. adresse. Hvis sagen lukkes, og adressen igen gør sig bemærket, genåbnes samme sag i stedet for, at der oprettes en ny.
Systemet genkender QNAP, Synology, Exchange-Autodiscover, ActiveSync samt WebDAV-, CalDAV- og CardDAV-klienter. Mønstrene angiver præcise filnavne og mapper, aldrig blot filendelser: I samme mappe, /cgi-bin/, ligger de harmløse synkroniseringskald side om side med klassiske sonderinger som printenv.pl.
Tilladelseslisten: adresser, der aldrig bliver blokeret
Prisen for en fejl er ikke den samme for alle adresser. For en scanner fra et datacenter koster en falsk alarm ingenting. For modparten i en tunnel til en lokation koster den forbindelsen til hele lokationen.
Derfor findes der en anden liste, som har forrang for den første: adresser og netværk, der aldrig bliver blokeret. Listen slår ingen registrering fra — adresserne bliver stadig kontrolleret og registreret, men konsekvensen udebliver. Det er forskellen fra en undtagelse i firewallen: Den gør systemet blindt, mens denne blot gør det tålmodigt.
Listen opdateres dagligt fra to kilder: dels fra selve firewallen med alle VPN-modparter, så en nyoprettet tunnel ikke er afhængig af, at nogen husker blokeringslisten, dels fra Googles og Microsofts offentliggjorte adresseområder til deres crawlere. Kun sådan kan man skelne en ægte Googlebot fra en scanner, der kalder sig det. Søgemaskiner må aldrig blokeres; hvis man lukker dem ude, fjerner man sit websted fra indekseringen uden mulighed for at vende tilbage.
Her gælder en regel, som er vigtigere end selve synkroniseringen: Et tomt svar sletter aldrig noget. Hvis kilden ikke svarer, eller svaret er tomt eller uforståeligt, forbliver listen uændret. En tilladelsesliste, der tømmer sig selv ved en driftsfejl, river alle tunneler med sig på det værst tænkelige tidspunkt.
Hvis en post på tilladelseslisten er knyttet til en kunde, bliver hver registrering fra kundens netværk tilknyttet denne kunde. Dermed har en fejlkonfiguration straks en kontaktperson, uden at nogen skal slå adresser op.
Lovpligtige oplysninger og automatiserede dataindsamlere
Siden med lovpligtige virksomhedsoplysninger er ikke en almindelig side. Den skal forblive tilgængelig for mennesker, for en blokering skaber netop den overtrædelse, som en dataindsamler leder efter. Samtidig er det siden med navn og adresse — og dermed et mål for automatiseret datahøst.
Under den østrigske bølge af juridiske påkrav om indlejrede Google-skrifttyper viste logfilerne, at brevene ikke byggede på enkeltstående besøg, men på en automatiseret bred scanning: forskellige værter uden indbyrdes forbindelse, besøgt med millisekunders mellemrum.
Web RBL løser det med nedklassificering frem for undtagelser. Den kanoniske sti /impressum matcher intet mønster og er altid tilgængelig. Alternative stavemåder som /impressum.php — der ikke kan findes på et Odoo-websted — bliver rapporteret, og hvis man ikke vil acceptere automatiseret datahøst, ændrer man en parameter. sitemap og robots er undtaget og kan slet ikke blokeres: De indeholder ingen personoplysninger, og det er enhver søgemaskinecrawlers opgave at hente dem.
Domæne og identifikation: det, der mangler i adgangsloggen
Adgangsloggen i werkzeug registrerer hverken den vært, der kaldes, eller klientens identifikation. Odoo modtager naturligvis begge dele — uden værtsnavnet ville systemet slet ikke kunne vælge det rigtige websted, hvis der er flere. Men oplysningerne kan ikke slås op bagefter.
Web RBL gemmer begge dele ved hver registrering. Det besvarer to spørgsmål, som ellers ikke kan besvares: hvilket websted en fejlkonfigureret klient henvender sig til — og dermed hvilken kunde domænet tilhører — og om en adresse besøger ét websted eller dem alle. Besøg på flere domæner uden indbyrdes forbindelse fra samme adresse er kendetegnet på en bred scanning og øger risikoscoren.
En analyse af et af vores websteder viste, hvor stor betydning identifikationen har: Over halvfjerds procent af al trafikken kom fra én enkelt klient, fordelt på mere end hundrede adresser. Uden identifikationen ville det have lignet en distribueret scraper. Det var GPTBot, OpenAI's crawler — den forespurgte gentagne gange på robots.txt og opførte sig helt korrekt.
Sikkerhedsaspekterne i detaljer
1. Proxygenkendelse — det farligste punkt overhovedet
Hvis Odoo kører bag en reverse proxy, og proxy_mode er indstillet forkert, ser modulet samme adresse ved hver forespørgsel: proxyens. En blokering ville så lukke alle besøgende ude på én gang.
Derfor kontrollerer Web RBL før hver blokering, om adressen kan bestemmes pålideligt. Det kræver proxy_mode sammen med en videresendelsesheader, nægter at arbejde, hvis en videresendt forespørgsel ankommer uden proxy_mode, og gør det samme, hvis der er mere end én mellemliggende proxy. Ved tvivl bliver der ikke blokeret.
2. Aldrig egne netværk
Private adresseområder, loopback, link-local og CGNAT er permanent undtaget. De kan under ingen omstændigheder ende på listen, heller ikke manuelt. Det samme gælder eksterne lister: Private og reserverede områder samt urimeligt store netværk kasseres ved indlæsning.
3. En intern fejl må ikke lægge webstedet ned
Hele kontrollen kører i en beskyttet ramme, der fanger alle fejl. Det, der går galt her, bliver logget, og forespørgslen fortsætter uændret. Et beskyttelsesmodul, der lægger webstedet ned på grund af en intern fejl, er værre end slet intet. Alle databaseforespørgsler under behandlingen køres desuden uden den besøgendes browsersprog og uden sortering efter oversatte felter — en besøgende med et sprog, der ikke er installeret, må ikke få kontrollen til at fejle.
4. Observér før blokering
Efter installationen er blokering af adresser på listen ved almindelige forespørgsler slået fra. Sonderinger afvises og registreres, mens alt andet slipper igennem. Så kan man i nogle dage følge med i, hvem der faktisk ender på listen, før nogen lukkes ude. Det samme gælder adfærdsregistrering, trusselslister og landeregler: først rapportering, derefter blokering efter gennemgang.
5. Præcise mønstre frem for brede net
En besøgende, der fejlagtigt klassificeres som angriber, koster mere end en overset sondering. Derfor har hvert mønster sit eget niveau, som kan ændres individuelt. En filendelse alene er sjældent nok: For .php står 14.012 reelle sonderinger over for en håndfuld gamle links, mens forholdet er omvendt for .asp. Den slags beslutninger skal bygge på målinger, ikke skøn.
6. En manuel tilladelse bliver stående
Den, der tillader en adresse, har haft en grund til det. En ny registrering ophæver ikke stiltiende den beslutning.
7. Listen er beskyttet, men ikke hemmelig
Endepunktet kræver et token og svarer med 404 uden et gyldigt token, ikke med 403 — dermed bliver det slet ikke bekræftet, at adressen findes. Sammenligningen sker i konstant tid. Selve listen indeholder intet fortroligt: Den består af adresser, som selv har henvendt sig til os.
8. Ingen hemmeligheder i registreringerne
Ved mislykkede loginforsøg registreres det anvendte brugernavn, aldrig adgangskoden. I databaseadministrationen læses intet som helst fra de indsendte værdier: Her står hovedadgangskoden først, og en post på en blokeringsliste kommer med i hver sikkerhedskopi af databasen. Licensnøglen til GeoLite2 står kun i systemparameteren og aldrig i en loglinje.
9. Lokkemidlet afslører intet brugbart
Web RBL kan valgfrit besvare sonderinger med opdigtet indhold, der indeholder en entydig kanarieværdi. Den, der senere forespørger på denne værdi, har læst det falske svar og handlet på det — her er en falsk alarm udelukket. Lokkemidlerne indeholder ingen brugbare oplysninger, ingen rigtige stier og ingen gyldige loginoplysninger. Funktionen er slået fra som standard, fordi den ændrer adfærden på en måde, der er synlig udefra.
Hvad modulet ikke kan
Det erstatter hverken en firewall eller en Web Application Firewall. Det genkender kendte sonderingsmønstre i stier, mislykkede logins og påfaldende adfærd — ikke angreb på formularer, ikke indsmuglingsforsøg i parametre.
Det ser desuden kun det, der kommer tilbage via HTTP. Hvad en angriber foretager sig med stjålne adgangsoplysninger til databaser eller postkasser, forbliver usynligt — og netop derfor er kanarieværdierne stier og ikke loginoplysninger.
Og det erstatter ikke omhu: Et modul, der afviser .env-sonderinger, gør ikke en .env-fil, der ved en fejl er gjort tilgængelig, ufarlig.
Tilgængelighed
Web RBL er offentligt tilgængeligt under AGPL-3 og kører hos os i produktion på fem websteder:
github.com/Alex0176/odoo-web-rbl
Modulet kræver Odoo 19 Community og har ingen andre afhængigheder end base og web. Integrationen med et supportsystem er valgfri og kræver ikke et bestemt system; uden et sådant sker der ganske enkelt ingenting. Oprindelseslandet kræver den gratis GeoLite2-database fra MaxMind. Hvis den mangler, forbliver feltet tomt, og alt andet fungerer som før.
Læs mere: Sådan indgår Web RBL i en samlet sikkerhedsarkitektur -- sammen med firewall, tofaktorgodkendelse og adgangsrettigheder, inklusive en trinvis vejledning: Kombinér Odoo 19-sikkerhedsarkitekturen rigtigt.
Vi modtager gerne spørgsmål, kommentarer og fejlrapporter — helst som et issue på GitHub.