Denne artikel er den første i en række indlæg, jeg skriver om at drive forskellige SaaS-produkter og -websteder i de sidste 8 år. Jeg vil dele nogle af de problemer, jeg har beskæftiget mig med, erfaringer, jeg har lært, fejl, jeg har begået, og måske et par ting, der gik rigtigt. Lad mig vide hvad du tror!
Tilbage i 2019 eller 2020 havde jeg besluttet at omskrive hele backend til Bloker afsender, en SaaS-applikation, der blandt andet hjælper brugere med at skabe bedre e-mail-blokeringer. I processen tilføjede jeg et par nye funktioner og opgraderede til meget mere moderne teknologier. Jeg kørte testene, implementerede koden, testede manuelt alt i produktionen, og bortset fra et par tilfældige odds og ender, så alt ud til at fungere godt. Jeg ville ønske, at dette var slutningen på historien, men...
Et par uger senere fik jeg besked af en kunde (hvilket er pinligt i sig selv), at tjenesten ikke virkede, og de fik masser af e-mails, der burde blokeres, i deres indbakke, så jeg undersøgte. Mange gange skyldes dette problem, at Google har fjernet forbindelsen fra vores tjeneste til brugerens konto, som systemet håndterer ved at give brugeren besked via e-mail og bede dem om at oprette forbindelse igen, men denne gang var det noget andet.
Det så ud som om, at backend-arbejderen, der håndterer kontrol af e-mails mod brugerblokeringer, blev ved med at gå ned hvert 5.-10. minut. Den mærkeligste del - der var ingen fejl i logfilerne, hukommelsen var fin, men CPU'en sprang af og til på tilsyneladende tilfældige tidspunkter. Så i de næste 24 timer (med en 3-timers pause til at sove – undskyld kunder 😬), var jeg nødt til manuelt at genstarte arbejderen, hver gang den styrtede ned. Af en eller anden grund ventede Elastic Beanstalk-tjenesten alt for længe på at genstarte, hvorfor jeg var nødt til at gøre det manuelt.
Fejlretning af problemer i produktionen er altid en smerte, især da jeg ikke kunne genskabe problemet lokalt, endsige finde ud af, hvad der forårsagede det. Så som enhver "god" udvikler er jeg lige begyndt at logge at alt og ventede på, at serveren gik ned igen. Da CPU'en spikede med jævne mellemrum, regnede jeg med, at det ikke var et makroproblem (som når du løber tør for hukommelse) og sandsynligvis var forårsaget af en bestemt e-mail eller bruger. Så jeg prøvede at indsnævre det:
- Var det gået ned på et bestemt e-mail-id eller type?
- Var det gået ned for en given kunde?
- Var det styrtet med et eller andet regelmæssigt interval?
Efter timer med dette, og efter at have stirret på logs længere end jeg ville have lyst til, indsnævrede jeg det til sidst til en bestemt kunde. Derfra blev søgerummet indsnævret en del – det var højst sandsynligt en blokeringsregel eller en specifik e-mail, som vores server blev ved med at prøve igen. Heldigvis for mig var det førstnævnte, hvilket er et langt nemmere problem at fejlfinde, da vi er et meget privatlivsfokuseret firma og ikke gemmer eller ser nogen e-mail-data.
Før vi kommer ind på det nøjagtige problem, lad os først tale om en af Block Senders funktioner. På det tidspunkt havde jeg mange kunder, der bad om blokering af jokertegn, som ville give dem mulighed for at blokere visse typer e-mail-adresser, der fulgte det samme mønster. Hvis du f.eks. ønskede at blokere alle e-mails fra marketing-mailadresser, kunne du bruge jokertegnet marketing@*
og det ville blokere alle e-mails fra enhver adresse, der startede med marketing@
.
En ting, jeg ikke tænkte over, er, at ikke alle forstår, hvordan jokertegn fungerer. Jeg antog, at de fleste ville bruge dem på samme måde, som jeg gør som udvikler, ved at bruge en *
at repræsentere et vilkårligt antal tegn. Desværre havde denne særlige bruger antaget, at du skulle bruge et jokertegn for hver karakter, du vil matche. I deres tilfælde ønskede de at blokere alle e-mails fra et bestemt domæne (hvilket er en indbygget funktion Block Sender har, men de må ikke have indset det, hvilket er et helt problem i sig selv). Så i stedet for at bruge *@example.com
, brugte de **********@example.com
.
POV: Ser dine brugere bruge din app...
Til at håndtere jokertegn på vores arbejderserver bruger vi Node.js-biblioteket match, som hjælper med glob-matching ved at gøre det til et regulært udtryk. Dette bibliotek ville så vende **********@example.com
til noget som følgende regex:
/[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*@example.com/i
Hvis du har nogen erfaring med regex, ved du, at de kan blive meget komplicerede meget hurtigt, især på et beregningsmæssigt niveau. At matche ovenstående udtryk til enhver rimelig længde af tekst bliver meget beregningsmæssigt dyrt, hvilket endte med at binde CPU'en på vores arbejdsserver. Dette er grunden til, at serveren ville gå ned med få minutters mellemrum; det ville sidde fast ved at prøve at matche et komplekst regulært udtryk til en e-mail-adresse. Så hver gang denne bruger modtog en e-mail, ud over alle de genforsøg, vi indbyggede for at håndtere midlertidige fejl, ville den crashe vores server.
Så hvordan fik jeg rettet dette? Det er klart, at den hurtige løsning var at finde alle blokke med flere jokertegn i rækkefølge og rette dem. Men jeg skulle også gøre et bedre stykke arbejde med at rense brugerinput. Enhver bruger kan indtaste et regex og fjerne hele systemet med en ReDoS angreb.
Tjek vores praktiske, praktiske guide til at lære Git, med bedste praksis, brancheaccepterede standarder og inkluderet snydeark. Stop med at google Git-kommandoer og faktisk lærer det!
Håndteringen af denne særlige sag var ret enkel – fjern på hinanden følgende jokertegn:
block = block.replace(/*+/g, '*')
Men det efterlader stadig appen åben for andre typer ReDoS-angreb. Heldigvis er der en række pakker/biblioteker til at hjælpe os med disse typer også:
Ved at bruge en kombination af ovenstående løsninger og andre sikkerhedsforanstaltninger har jeg været i stand til at forhindre, at dette sker igen. Men det var en god påmindelse om, at du aldrig kan stole på brugerinput, og du bør altid rense det, før du bruger det i din applikation. Jeg var ikke engang klar over, at dette var et potentielt problem, før det skete for mig, så forhåbentlig hjælper dette en anden med at undgå det samme problem.
Har du spørgsmål, kommentarer eller vil du dele din egen historie? Ræk ud på Twitter!
- SEO Powered Content & PR Distribution. Bliv forstærket i dag.
- PlatoData.Network Vertical Generative Ai. Styrk dig selv. Adgang her.
- PlatoAiStream. Web3 intelligens. Viden forstærket. Adgang her.
- PlatoESG. Kulstof, CleanTech, Energi, Miljø, Solenergi, Affaldshåndtering. Adgang her.
- PlatoHealth. Bioteknologiske og kliniske forsøgs intelligens. Adgang her.
- Kilde: https://stackabuse.com/behind-the-scenes-never-trust-user-input/
- :har
- :er
- :ikke
- $OP
- 1
- 20
- 2019
- 2020
- 24
- 8
- a
- I stand
- Om
- over
- Konto
- faktisk
- tilføjet
- Desuden
- adresse
- adresser
- igen
- mod
- Alle
- tillade
- alene
- også
- altid
- blandt
- an
- ,
- enhver
- app
- Anvendelse
- ER
- artikel
- AS
- spørge
- antaget
- At
- Angreb
- undgå
- opmærksom på
- Bagende
- BE
- Beanstalk
- bliver
- været
- før
- bag
- bag scenen
- være
- Bedre
- Bit
- Bloker
- blokering
- Blocks
- grænse
- Pause
- bygget
- men
- by
- CAN
- Kan få
- hvilken
- tilfælde
- forårsagede
- forårsager
- vis
- karakter
- tegn
- kontrol
- kode
- kombination
- kommentarer
- selskab
- komplekse
- kompliceret
- beregningsmæssige
- tilslutning
- korrigere
- kunne
- couldn
- Crash
- Kørt galt
- Crashing
- skabe
- kunde
- Kunder
- data
- behandlet
- besluttede
- indsat
- Udvikler
- DID
- gjorde ikke
- do
- domæne
- Don
- ned
- grund
- hver
- lettere
- andet
- emails
- ende
- sluttede
- ender
- Indtast
- Hele
- fejl
- især
- Endog
- til sidst
- Hver
- alle
- at alt
- eksempel
- dyrt
- erfaring
- udtryk
- fejl
- retfærdigt
- langt
- Feature
- Funktionalitet
- få
- Figur
- regnede
- Finde
- ende
- Fornavn
- Fix
- Fokus
- efterfulgt
- efter
- Til
- Tidligere
- fra
- få
- få
- gif
- Git
- given
- godt
- stor
- vejlede
- havde
- håndtere
- Håndterer
- hands-on
- skete
- Happening
- Have
- hjælpe
- hjælper
- Forhåbentlig
- HOURS
- hover
- Hvordan
- HTTPS
- i
- ID
- if
- in
- medtaget
- indgang
- i stedet
- ind
- spørgsmål
- spørgsmål
- IT
- selv
- Job
- lige
- holdt
- Kend
- Efternavn
- senere
- lærte
- læring
- Længde
- Lessons
- lad
- Niveau
- LG
- Bibliotek
- ligesom
- Sandsynlig
- ll
- lokalt
- logning
- Lang
- længere
- kiggede
- masser
- Makro
- lavet
- manuelt
- mange
- Marketing
- Match
- matchende
- kan være
- me
- Hukommelse
- minutter
- fejl
- Moderne
- moderne teknologier
- mere
- mest
- meget
- flere
- skal
- smal
- indfødte
- behov
- aldrig
- Ny
- Nye funktioner
- næste
- ingen
- node
- node.js
- bemyndigende
- nummer
- Odds
- of
- on
- ONE
- åbent
- or
- Andet
- vores
- ud
- egen
- Smerte
- del
- særlig
- Mønster
- Mennesker
- plato
- Platon Data Intelligence
- PlatoData
- Indlæg
- potentiale
- Praktisk
- forhindre
- sandsynligvis
- Problem
- behandle
- produktion
- Produkter
- Spørgsmål
- Hurtig
- hurtigt
- helt
- tilfældig
- RE
- nå
- gik op for
- grund
- rimelige
- modtaget
- tilslut
- regulært udtryk
- fast
- påmindelse
- Fjern
- fjernelse
- repræsentere
- højre
- ring
- Herske
- Kør
- kører
- s
- SaaS
- sikkerhedsforanstaltninger
- samme
- scener
- Søg
- syntes
- tilsyneladende
- afsender
- Series
- server
- tjeneste
- Shadow
- Del
- deling
- ark
- bør
- Simpelt
- siden
- søvn
- So
- Løsninger
- nogle
- Nogen
- noget
- Space
- specifikke
- spike
- Stablemisbrug
- standarder
- påbegyndt
- Stadig
- Stands
- butik
- Story
- systemet
- Tag
- Tal
- Teknologier
- midlertidig
- afprøvet
- tests
- tekst
- end
- at
- deres
- Them
- derefter
- Der.
- Disse
- de
- ting
- ting
- tror
- denne
- tid
- gange
- til
- også
- overgang
- forsøgte
- Stol
- forsøger
- TUR
- Drejning
- typen
- typer
- forstår
- desværre
- indtil
- opgraderet
- us
- brug
- anvendte
- Bruger
- brugere
- ved brug af
- forskellige
- Ve
- meget
- via
- Specifikation
- Venter
- ønsker
- ønskede
- var
- var ikke
- ser
- Vej..
- we
- websites
- uger
- GODT
- gik
- var
- Hvad
- hvornår
- som
- Hele
- hvorfor
- Wikipedia
- ønsker
- med
- Arbejde
- arbejdstager
- arbejder
- ville
- skrivning
- år
- Du
- Din
- zephyrnet