Alle indlæg

Atten en halv million dollars, svar hurtigst muligt

· Henning Kjær

Den 15. august landede der en “mail kunne ikke leveres”-besked i Tolkras indbakke. Det var en svindel mail sendt til en adresse der ikke fandtes — det klassiske brev fra en døende velgører, atten en halv million dollars, svar venligst hurtigst muligt — adresseret til 49 fremmede. Den var sendt fra tolkra.com domænet, signeret med vores mailsignatur, gennem vores mailudbyder.

Ingen var kommet indenfor muren. En tilfældig (genereret) gmail adresse havde oprettet en gratis konto og brugt en feature præcis som den var bygget.

Kort fortalt: en "Send testmail"-funktionalitet i vores flow-editor lod brugere der var logget ind bestemme, hvem de ville sende mailen til, og hvad emnefeltet skulle indeholde. Det var tilstrækkeligt til at forvandle en preview-funktion til en spam maskine.

Det, jeg egentlig gerne vil tale om

Jeg kunne skrive hele indlægget om detaljerne, og første version af indlægget her indeholdte også kode. Men det, der har siddet fast i mig i to uger, er ikke fejlen. Det er, hvad “kunne ikke leveres”-beskeden gjorde ved min fornemmelse af, hvad jeg har begivet mig ud i.

Jeg bygger Tolkra alene. Grunden til, at jeg overhovedet bygger noget, er, at jeg elsker at løse problemer med teknologi - nogen har et problem, man laver en general løsning, og nu er problemet løst for alle der bruger løsningen. Det er ærligt. Og jeg er god til det.

Sikkerhed er derimod en uendelig diskussion med alle på denne planet, og man skal helst vinde hver eneste runde, uden at fremstå som svag. Dem der har dårlige intentioner skal til gengæld blot vinde én gang. I det øjeblik man lægger en løsning på det åbne internet, giver man det ikke bare til sine brugere, men også til en automatiseret, utrættelig, global hær, der prikker til hvert eneste endpoint, man ejer, og for hvem ens produkt ikke er et produkt, men en attack surface. De fandt knappen hurtigere end mine ti første kunder!

Jeg kastede mig ud i at løse et problem for folk, der tager billeder af fakturaer og taster data ind i hånden. Jeg kastede mig ikke ud i at drive et sikkerhedsfirma. Men der findes ingen version af det første, uden et link til det andet — og er man én person, så er sikkerhedsteamet dig selv. Om aftenen, efter du er færdig med det betalende arbejde, uden nogen til at efterse alt hvad du har lavet og uden nogen til at sige, hvilken af de hundrede ting, du ikke har tænkt på, der betyder mest.

Det er crazy, og jeg synes, det er værd at sige ligeud i stedet for at lade som om, det hele var en rolig oplevelse uden bump på vejen. “Kunne ikke leveres”-beskeden fortalte mig ikke bare, at jeg havde et hul. Den fortalte mig, at mit domænes omdømme og mine kunders data var på spil. Jeg lukkede sitet helt i en dag, og havde ikke lyst til at kigge på kodebasen, fordi hver eneste del af koden kunne rumme lignende fejl. Noget af den gjorde.

Det, der fik mig på sporet igen, var at flytte målet. Mit site kan ikke være fejlfrit. Det, jeg kan være, er en, der reagerer hurtigt, retter fejl på minutter og lærer hvor jeg skal være ekstra opmærksom på den funktionalitet jeg bygger - læring er hvad dette indlæg er.

Hvad der faktisk gik galt

Flow-editoren lader dig sætte en mail op til at modtage et eksempel af dit flow. Du trykker "Send test" for at se, hvordan det kommer til at se ud. Tre ting: hvem der skulle sendes til, hvad emnefeltet skulle sige, og hvilket flow det handlede om.

Tjekket var at personen, var logget ind. Den tjekkede ikke andet.

Ikke om flowet fandtes. Ikke om workspacet fandtes. Ikke om personen havde nogen som helst forbindelse til nogen af delene. Det er gratis at oprette sig og kræver én mailbekræftelse, og derefter ville funktionen sende hvad som helst til hvem som helst, så ofte man havde lyst, fra et domæne med et godt omdømme og en gyldig signatur.

Svindelteksten stod i emnefeltet, polstret med usynlige tegn, så den læsbare del faldt uden for forhåndsvisningen. Netop det er afsløringen: selve mailens indhold var en skabelon, der ikke kunne ændres, så emnefeltet var det eneste tekstfelt, de havde.

Hvorfor den var der

Det er den del, der er værd at dvæle ved, for fejlen sidder ikke i funktionaliteten. Jeg synes det var super smart at man kunne teste og se et eksempel på sit flow uden at skulle skanne et billede, det var en god feature. Dog var jeg for flink og åbnede for op til 50 mail adresser og et fritekstfelt, her skal man altid tænke hvad er det værste der kan ske.

En indlogget session beviser, at nogen er logget ind. Den siger intet relationen til det, vedkommende prøver at gøre.

Hvad der blev ændret

Testmailen sendes nu udelukkende til den, der er logget ind — dig. Ikke en valideret modtagerliste - slet ingen liste. Den, du konfigurerer, bliver ignoreret. En forhåndsvisning er til den, der sætter flowet op; der var aldrig nogen grund til, at den skulle nå andre.

Enhver operation, der tager imod et id, fastslår nu, hvem der spørger, før den handler. Server side, ud fra den verificerede session, aldrig ud fra noget, browseren har sendt med. Det er den rettelse, der faktisk betyder noget, og det er lige så meget en regel for al fremtidig kode, som det er en ændring af eksisterende kode.

Data er nu isoleret, ikke kun i brugerfladen. Databasen afviser read og write, der bevæger sig uden om dine data, så en fejl i en enkelt funktion ikke længere kan blive til et læk.

Guadrails håndhæves, så de ikke kan springes over. Browser tjeks er dekorative - enhver, der talte direkte med API'et, gik lige forbi dem. Antal mails og antal kørsler tælles og begrænses nu server side. Emnefelter bliver renset og forkortet. Links i udgående mail bliver tjekket.

Tre ting jeg tog med mig

Alt, der sender mail på dine vegne, er åbent, indtil du har bevist det modsatte. Spørgsmålet er ikke "kan det her misbruges?" — alt kan misbruges. Spørgsmålet er "hvem må angive modtageren, og hvad forhindrer dem i at angive en anden?"

Fri tekst havner der, hvor du giver den plads. Jeg kontrollerede indholdet, så i stedet brugte de emnefeltet. At begrænse ét felt flytter bare åbningen til det næste ubegrænsede felt. Alt skal valideres og begrænses.

At være logget ind er ikke det samme som at have lov. De to ting kan nemt blandes sammen. Enhver operation, der tager imod et id på noget, den derefter skal behandle, skal finde ud af hvilken relation den, der spørger, faktisk har til den ting - hver gang, server side.

Solo founders

Det var ikke for at skræmme dig. Du kommer til at sende noget ud med huller i, og nogen kommer til udnytte det, og der bliver ikke skrevet en høflig mail til dig.

Vær åben om det. Jeg har udgivet det her, fordi den version af historien, hvor en solo founder stille og roligt lapper et hul og ikke siger noget, er den version, der lader den næste lære det på samme måde, som jeg gjorde.

Rettelsen var nær blevet et nedbrud

At sætte lodrette skodder op om data krævede en migrering: sæt skodder op, og tjek derefter de eksisterende rækker, så de lander på den rigtige side af skodderne.

Så pushede jeg til en branch, der deployer automatisk ved push. De nye regler trådte i kraft med det samme, og alle eksisterende brugere var låst ude af deres egne data, indtil migreringen indhentede det.

"Husk at køre den her først" ville aldrig overleve mødet med en automatisk pipeline. Formen, der virker, er to deploys: tilføj den nye struktur, mens de gamle regler stadig gælder, migrer op imod et system, der fungerer fuldt ud, og slå så de nye regler til. Så er intet nogensinde i stykker, og ingen behøver at huske noget - hvilket, når hele teamet er én person sidst på dagen, er den eneste form for sikkerhed, der faktisk holder.

I alt blev der sendt næsten 2500 mails, mange af dem fik “kunne ikke leveres”. Ingen henvendte sig eller kontaktede mig. En lektie blev lært, og et site blev opdateret.