Den här artikeln är den första i en serie inlägg jag skriver om att driva olika SaaS-produkter och webbplatser under de senaste 8 åren. Jag kommer att dela med mig av några av de problem jag har hanterat, lärdomar jag har lärt mig, misstag jag har gjort och kanske några saker som gick rätt. Låt mig veta vad tycker du!
Tillbaka 2019 eller 2020 hade jag bestämt mig för att skriva om hela backend för Blockera avsändare, en SaaS-applikation som bland annat hjälper användare att skapa bättre e-postblock. Under processen lade jag till några nya funktioner och uppgraderade till mycket mer modern teknik. Jag körde testerna, distribuerade koden, testade manuellt allt i produktionen, och förutom några slumpmässiga odds och mål verkade allt fungera utmärkt. Jag önskar att detta var slutet på historien, men...
Några veckor senare fick jag besked av en kund (vilket är pinsamt i sig) att tjänsten inte fungerade och de fick massor av e-postmeddelanden som borde blockeras i sin inkorg, så jag undersökte. Många gånger beror detta problem på att Google tagit bort anslutningen från vår tjänst till användarens konto, vilket systemet hanterar genom att meddela användaren via e-post och be dem att återansluta, men den här gången var det något annat.
Det såg ut som att backend-arbetaren som hanterar att kontrollera e-postmeddelanden mot användarblockeringar kraschade var 5-10:e minut. Det konstigaste - det fanns inga fel i loggarna, minnet var bra, men CPU:n spikade ibland vid till synes slumpmässiga tidpunkter. Så under de kommande 24 timmarna (med en 3-timmars paus att sova – förlåt kunder 😬), var jag tvungen att manuellt starta om arbetaren varje gång den kraschade. Av någon anledning väntade Elastic Beanstalk-tjänsten alldeles för länge på att starta om, varför jag var tvungen att göra det manuellt.
Att felsöka problem i produktionen är alltid jobbigt, särskilt eftersom jag inte kunde återskapa problemet lokalt, än mindre ta reda på vad som orsakade det. Så som alla "bra" utvecklare började jag bara logga allt och väntade på att servern skulle krascha igen. Eftersom CPU:n spikade med jämna mellanrum, tänkte jag att det inte var ett makroproblem (som när du får ont om minne) och att det förmodligen orsakades av ett specifikt e-postmeddelande eller en användare. Så jag försökte begränsa det:
- Kraschade det på ett visst e-post-ID eller typ?
- Har det kraschat för en viss kund?
- Krockade det med något jämnt mellanrum?
Efter timmar av detta, och stirrat på stockar längre än jag skulle vilja, så begränsade jag till slut det till en specifik kund. Därifrån minskade sökutrymmet ganska mycket – det var troligtvis en blockeringsregel eller ett specifikt e-postmeddelande som vår server fortsatte att använda. Lyckligtvis för mig var det det förra, vilket är ett mycket lättare problem att felsöka med tanke på att vi är ett mycket integritetsfokuserat företag och inte lagrar eller visar någon e-postdata.
Innan vi kommer in på det exakta problemet, låt oss först prata om en av Block Senders funktioner. På den tiden hade jag många kunder som bad om jokerteckenblockering, vilket skulle göra det möjligt för dem att blockera vissa typer av e-postadresser som följde samma mönster. Om du till exempel vill blockera alla e-postmeddelanden från marknadsföringsadresser kan du använda jokertecken marketing@*
och det skulle blockera alla e-postmeddelanden från vilken adress som helst som började med marketing@
.
En sak jag inte tänkt på är att alla inte förstår hur jokertecken fungerar. Jag antog att de flesta skulle använda dem på samma sätt som jag gör som utvecklare, med en *
för att representera valfritt antal tecken. Tyvärr hade just den här användaren antagit att du behövde använda ett jokertecken för varje karaktär du ville matcha. I deras fall ville de blockera alla e-postmeddelanden från en viss domän (vilket är en inbyggd funktion Block Sender har, men de måste inte ha insett det, vilket är ett helt problem i sig). Så istället för att använda *@example.com
, de brukade **********@example.com
.
POV: Se dina användare använda din app...
För att hantera jokertecken på vår arbetarserver använder vi Node.js-biblioteket passare, vilket hjälper till med globmatchning genom att göra det till ett reguljärt uttryck. Detta bibliotek skulle sedan vända **********@example.com
till något i stil med följande regex:
/[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*@example.com/i
Om du har någon erfarenhet av regex så vet du att de kan bli väldigt komplicerade väldigt snabbt, speciellt på beräkningsnivå. Att matcha uttrycket ovan med vilken som helst rimlig längd av text blir mycket beräkningsmässigt dyrt, vilket slutade med att processorn knöts på vår arbetsserver. Det är därför servern kraschar med några minuter; det skulle fastna när man försöker matcha ett komplext reguljärt uttryck med en e-postadress. Så varje gång den här användaren fick ett e-postmeddelande, utöver alla försök som vi byggde in för att hantera tillfälliga fel, kraschade den vår server.
Så hur fixade jag detta? Uppenbarligen var den snabba lösningen att hitta alla block med flera jokertecken i följd och korrigera dem. Men jag behövde också göra ett bättre jobb med att sanera användarnas input. Vilken användare som helst kan ange ett regex och ta ner hela systemet med en ReDoS-attack.
Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!
Att hantera just det här fallet var ganska enkelt – ta bort på varandra följande jokertecken:
block = block.replace(/*+/g, '*')
Men det lämnar fortfarande appen öppen för andra typer av ReDoS-attacker. Lyckligtvis finns det ett antal paket/bibliotek för att hjälpa oss med dessa typer också:
Genom att använda en kombination av lösningarna ovan och andra skyddsåtgärder har jag kunnat förhindra att detta händer igen. Men det var en bra påminnelse om att du aldrig kan lita på användarinmatning, och du bör alltid rensa den innan du använder den i din applikation. Jag var inte ens medveten om att detta var ett potentiellt problem förrän det hände mig, så förhoppningsvis hjälper detta någon annan att undvika samma problem.
Har du frågor, kommentarer eller vill dela med dig av din egen historia? Nå ut på Twitter!
- SEO-drivet innehåll och PR-distribution. Bli förstärkt idag.
- PlatoData.Network Vertical Generative Ai. Styrka dig själv. Tillgång här.
- PlatoAiStream. Web3 Intelligence. Kunskap förstärkt. Tillgång här.
- Platoesg. Kol, CleanTech, Energi, Miljö, Sol, Avfallshantering. Tillgång här.
- PlatoHealth. Biotech och kliniska prövningar Intelligence. Tillgång här.
- Källa: https://stackabuse.com/behind-the-scenes-never-trust-user-input/
- : har
- :är
- :inte
- $UPP
- 1
- 20
- 2019
- 2020
- 24
- 8
- a
- Able
- Om oss
- ovan
- Konto
- faktiskt
- lagt till
- Dessutom
- adress
- adresser
- igen
- mot
- Alla
- tillåter
- ensam
- också
- alltid
- bland
- an
- och
- vilken som helst
- app
- Ansökan
- ÄR
- Artikeln
- AS
- be
- antas
- At
- Attacker
- undvika
- medveten
- backend
- BE
- beanstalken
- blir
- varit
- innan
- bakom
- bakom kulisserna
- Där vi får lov att vara utan att konstant prestera,
- Bättre
- Bit
- Blockera
- blockering
- Block
- gränsen
- Ha sönder
- byggt
- men
- by
- KAN
- Kan få
- vilken
- Vid
- orsakas
- orsakar
- vissa
- karaktär
- tecken
- kontroll
- koda
- kombination
- kommentarer
- företag
- komplex
- komplicerad
- beräkningar
- anslutning
- korrekt
- kunde
- couldn
- Crash
- kraschade
- Crashing
- skapa
- kund
- Kunder
- datum
- behandlas
- beslutade
- utplacerade
- Utvecklare
- DID
- didn
- do
- domän
- donation
- ner
- grund
- varje
- lättare
- annars
- e
- änden
- avslutades
- slutar
- ange
- Hela
- fel
- speciellt
- Även
- så småningom
- Varje
- alla
- allt
- exempel
- dyra
- erfarenhet
- Uttrycket
- misslyckanden
- ganska
- långt
- Leverans
- Funktioner
- få
- Figur
- figured
- hitta
- änden
- Förnamn
- Fast
- Fokus
- följt
- efter
- För
- Tidigare
- från
- skaffa sig
- få
- gif
- gå
- ges
- god
- stor
- styra
- hade
- hantera
- Handtag
- praktisk
- hänt
- Happening
- Har
- hjälpa
- hjälper
- Förhoppningsvis
- ÖPPETTIDER
- hovring
- Hur ser din drömresa ut
- HTTPS
- i
- ID
- if
- in
- ingår
- ingång
- istället
- in
- fråga
- problem
- IT
- sig
- Jobb
- bara
- hålls
- Vet
- Efternamn
- senare
- lärt
- inlärning
- Längd
- Lärdomar
- Låt
- Nivå
- LG
- Bibliotek
- tycka om
- sannolikt
- ll
- lokalt
- skogsavverkning
- Lång
- längre
- såg
- Föremål
- Makro
- gjord
- manuellt
- många
- Marknadsföring
- Match
- matchande
- kanske
- me
- Minne
- minuter
- misstag
- Modern Konst
- modern teknik
- mer
- mest
- mycket
- multipel
- måste
- smal
- nativ
- behövs
- aldrig
- Nya
- Nya funktioner
- Nästa
- Nej
- nod
- node.js
- anmälande
- antal
- Odds
- of
- on
- ONE
- öppet
- or
- Övriga
- vår
- ut
- egen
- Smärta
- del
- särskilt
- Mönster
- Personer
- plato
- Platon Data Intelligence
- PlatonData
- inlägg
- potentiell
- Praktisk
- förhindra
- förmodligen
- Problem
- process
- Produktion
- Produkter
- frågor
- Snabbt
- snabbt
- ganska
- slumpmässig
- RE
- nå
- insåg
- Anledningen
- rimlig
- mottagna
- återansluta
- regex
- regelbunden
- påminnelse
- ta bort
- bort
- representerar
- höger
- Ringa
- Regel
- Körning
- rinnande
- s
- SaaS
- skyddsåtgärder
- Samma
- scener
- Sök
- verkade
- till synes
- avsändare
- Serier
- server
- service
- skugga
- Dela
- delning
- ark
- skall
- Enkelt
- eftersom
- sova
- So
- Lösningar
- några
- någon
- något
- Utrymme
- specifik
- spik
- Stackabuse
- standarder
- igång
- Fortfarande
- Sluta
- lagra
- Historia
- system
- Ta
- Diskussion
- Tekniken
- temporär
- testade
- tester
- text
- än
- den där
- Smakämnen
- deras
- Dem
- sedan
- Där.
- Dessa
- de
- sak
- saker
- tror
- detta
- tid
- gånger
- till
- alltför
- övergång
- försökte
- Litar
- försöker
- SVÄNG
- Vrida
- Typ
- typer
- förstår
- tyvärr
- tills
- uppgraderad
- us
- användning
- Begagnade
- Användare
- användare
- med hjälp av
- olika
- Ve
- mycket
- via
- utsikt
- väntar
- vill
- ville
- var
- var inte
- tittar
- Sätt..
- we
- webbsidor
- veckor
- VÄL
- begav sig
- były
- Vad
- när
- som
- Hela
- varför
- wikipedia
- önskar
- med
- Arbete
- arbetstagaren
- arbetssätt
- skulle
- skrivning
- år
- Om er
- Din
- zephyrnet