Ett mer fullständigt svar från http://hueniverse.com/2015/07/08/on-securing-web-session-ids/
Ansvarsfriskrivning: som alla säkerhetsråd från någon som inte känner till detaljerna i ditt eget system, detta är endast för utbildningsändamål. Säkerhet är ett komplext och mycket specifikt område och om du är orolig för säkerheten i ditt system bör du anställa en expert som kan granska ditt system tillsammans med en hotanalys och ge lämplig rådgivning.
Brute Force
Brute force-attacker är de där angriparen försöker få tillgång till systemet genom att göra upprepade förfrågningar med olika referenser (tills en fungerar). Det vanligaste exemplet är en angripare som försöker gissa ett användarlösenord. Det är därför lösenord bör vara långa och undvika att använda ordboksord för att göra det svårare att gissa. Korrekt utformade system håller reda på misslyckade autentiseringsförfrågningar och eskalerar problemet när det verkar som om en attack pågår.
Lösenord är inte den enda referensen som används vid webbautentisering. Den vanligaste implementeringen inkluderar en inloggningssida som vid framgångsrik autentisering sätter en sessionscookie på klienten. Sessionscookien fungerar som bärartoken - den som dyker upp med token anses vara den autentiserade användaren. Att ställa in en sessionskaka tar bort behovet av att ange ditt användarnamn och lösenord på varje sida. Denna session cookie fungerar dock nu som den enda autentiseringsnyckeln och alla som får tillgång till den här nyckeln kommer att få åtkomst till systemet. Cookies är trots allt bara en enkel teckensträng.
Ett session-ID-gissningsattack är en typ av brute force-attack. I stället för att försöka gissa lösenordet försöker angriparen gissa sessionens id och smida autentiseringscookien. Angriparen genererar session-id: n och försöker göra förfrågningar med hjälp av dessa id: er, i hopp om att de kommer att matcha faktiska aktiva sessioner. Till exempel, om ett webbapplikationssession-ID genereras i följd, kan en angripare slå upp sitt eget sessions-id och baserat på smidda förfrågningar med närliggande session-id-värden. För att skydda mot denna attack måste vi göra gissnings-session-ID opraktiskt. Obs! Jag säger "opraktiskt", inte "omöjligt".
Opraktiskhet
Det första steget är att se till att sessions-ID: n är tillräckligt långa och inte sekventiella. Precis som lösenord, ju längre session-id är, desto svårare är det att hitta ett giltigt genom att gissa. Det är också viktigt att session-ID inte genereras med hjälp av en förutsägbar algoritm, såsom en räknare, för om sådan logik existerar, gissar inte angriparen längre utan genererar sessions-ID. Att använda en kryptografiskt säker slumptalsgenerator för att producera tillräckligt långa session-ID är den bästa vanliga praxisen. Vad är "tillräckligt långt"? Det beror på ditt systems natur. Storleken måste översättas till ett opraktiskt försök att gissa ett giltigt session-id.
Ett annat sätt att förhindra att en angripare gissar session-id: n är att bygga integritet i token genom att lägga till en hash eller signatur till sessionskakan. Hur Express-sessionens mittprogram gör detta är genom att beräkna en hash över kombinationen av sessions-id och en hemlighet. Eftersom beräkning av hash kräver hemligheten kan en angripare inte generera giltiga session-ID utan att gissa hemligheten (eller bara försöka gissa hash). Precis som starka slumpmässiga session-id: ar måste hashstorleken matcha säkerhetskraven för den specifika applikationen som den är avsedd att skydda. Detta beror på att sessionskakan i slutet fortfarande bara är en sträng och öppen för gissningsattacker.
Sessions-id: n måste vara tillräckligt långa och opraktiska för att gissa. Det finns några sätt att uppnå detta. Slumpmässigheten och hashteknikerna ovan är de två vanligaste sätten men inte de enda.
Lager
Om vi genererar starka slumpmässiga sessions-ID: ar, behöver vi fortfarande hash? Absolut!
Kärnsäkerhetsprincipen är lager. Detta är också känt som att inte lägga alla dina ägg i en korg. Om du litar på en enda säkerhetskälla får du ingen säkerhet alls om den enda källan misslyckas. Till exempel, om någon hittar ett fel i din slumptalsgenerator? Vad händer om de hittar ett sätt att hacka den delen av ditt system och ersätta det? Det finns otaliga kända attacker som utnyttjar exakt detta - genereringen av slumpmässiga siffror som trots allt inte visar sig vara så slumpmässiga.
Att kombinera ett starkt slumpmässigt session-ID med hash för integritet skyddar mot brister i slumptalsgeneratorn. Det kommer också att skydda mot utvecklarfel som att använda fel funktion för slumptalsgenerator (t.ex. den inte så slumpmässiga metoden som varje system erbjuder tillsammans med den starka metoden). Vi skriver alla dålig kod oavsett hur bra vår process är eller hur erfaren vi är. Det är en del av programvaruteknik. Det är därför det är så viktigt att lagra din säkerhet. En vallgrav räcker inte, du vill också ha en mur bakom den, och förmodligen några vakter bakom muren.
Om du tror att du använder fel slumpmässig funktion eller ett djupt fel i OpenSSL är de enda två frågorna här den vanliga praxis för apa-lappkod i JavaScript och andra dynamiska språk. Om någon någonstans i en hel applikationsdistribution trasslar med de globala slumpmässiga faciliteterna (för testning, loggning, etc.) och bryter den (eller det är en del av en skadlig kodinjektion), är session-id: er som enbart är beroende av slumpmässighet inte längre säkra.
Larm
En viktig skillnad mellan gissningslösenord och gissnings-id: er är att lösenord är associerade med ett konto (t.ex. användarnamn). Kontolösenordsparet gör det lättare att hålla reda på brute force-attacker eftersom det ger ett relativt enkelt sätt att hålla reda på misslyckade försök. Men när det gäller session-ID är det inte så enkelt eftersom sessioner löper ut och inte inkluderar ett kontokontext. Det betyder att ett ogiltigt session-ID kan komma från en utgången session eller från en angripare, men utan ytterligare data (t.ex. IP-adress) skulle det vara svårt att se skillnaden i ett storskaligt system.
Genom att inkludera en integritetskomponent i sessionens id (via en hash eller signatur) kan servern omedelbart se skillnaden mellan en utgången session, en otilldelad session-id och en ogiltig session. Även om du bara loggar in ogiltiga autentiseringsförsök (och det borde du göra) vill du logga en utgången session annorlunda än en ogiltig. Förutom säkerhetsvärdet av att känna till skillnaden, kommer det också att ge användbar inblick i hur dina användare beter sig.
Hygien
Inloggningsuppgifterna ska upphöra och därför ska sessions-ID ha en begränsad livslängd (där varaktighet är mycket ett systemspecifikt värde). Medan cookies har en utgångspolicy finns det inget sätt att säkerställa att de faktiskt följs. En angripare kan ställa in kakans utgång till något värde utan att servern kan upptäcka det. En vanlig bästa praxis är att inkludera en tidsstämpel i varje utfärdad referens, vilket kan vara så enkelt som att lägga till ett tidsstämpelsuffix i det slumpmässigt genererade session-id. För att förlita oss på den här tidsstämpeln måste vi kunna verifiera att den inte har tempererats och sättet att åstadkomma är med en hash eller signatur.
Om du lägger till en tidsstämpel till sessionens id kan server för att snabbt hantera utgångna sessioner utan att behöva göra en dyr databasuppsökning. Även om detta kanske låter oberoende av säkerhet, är det faktiskt väldigt viktigt för att upprätthålla en säker applikation. att konsumera för mycket resurser på servern och antingen stänga av den eller göra den otillgänglig för andra. Om varje begäranverifiering kräver en fullständig databasuppslagning i applikationsnivån, kan en angripare använda förfalskade sessions-ID för att enkelt göra en DoS-attack. Genom att inkludera en integritetskomponent i kakan kan servern omedelbart identifiera förfalskade eller upphörda autentiseringsuppgifter utan någon sökningskostnad för backend.
Kill Switch
Ibland går det fel. Och när de går väldigt fel måste du ha ett sätt att omedelbart ogiltigförklara hela klasser av sessioner. Eftersom att generera en hash eller signatur kräver en hemlighet eller nyckel på serversidan kommer alla session-id: er att omedelbart ersätta hemligheten att valideringen misslyckas. Genom att använda olika hemligheter för olika typer av sessions-ID kan hela klasser av sessioner separeras och hanteras. Utan en sådan mekanism måste själva applikationen fatta ett beräknat beslut om tillståndet för varje session eller utföra massdatabasuppdateringar.
Dessutom i stora distribuerade system med databasreplikering över olika geografiska platser, ogiltigt sessionsposten på en plats kan ta sekunder och till och med minuter att replikera. Det betyder att sessionen förblir aktiv tills hela systemet är synkroniserat igen. Jämfört med ett självbeskrivande och självvaliderande session-ID är fördelarna uppenbara.
Allmänt syfte
En viktig egenskap hos Express-sessionens mellanprogram är dess stöd för användargenererad session id. Detta gör det möjligt för utvecklare att distribuera mellanvaran i en befintlig miljö där sessions-ID skapas av en befintlig enhet som kan finnas på en helt annan plattform. Utan att lägga till en hash till användar-tillhandahållna session-id: er, flyttas bördan med att bygga ett säkert system från experten (modulförfattaren) till användaren (vilket sannolikt kommer att vara en säkerhetsnybörjare). Att använda en hash är ett mycket bättre tillvägagångssätt än att tvinga en intern session-ID-generator.
Krokodiler
Att lägga till en hash till ett starkt slumpmässigt session-ID är inte allt du borde göra. Om din vallgrav kan dra nytta av krokodiler är återigen ett slottsspecifikt beslut. Utan att gå för långt från ämnet finns det många andra lager som du kan lägga till i ditt sessionhanteringsnivå. Du kan till exempel använda två sessioners referenser, en långlivad (varar så länge som sessionen) och en annan kortlivad (bra i minuter eller timmar). För att uppdatera den kortlivade använder du den långlivade men genom att göra det minskar du exponeringen för den långlivade referensen i nätverket (särskilt när du inte använder TLS).
En annan vanlig praxis är att ha en cookie med allmän information om användaren (t.ex. förnamn, nyligen visade objekt etc.) vid sidan av sessionen och för att sedan inkludera något från den cookien i hash för att skapa en bindning mellan användarens aktiva tillstånd till autentiseringen. Det är ett sätt att få tillbaka "användarnamnet" i arbetsflödet.
För att gå ännu längre kan hashing ersättas med signaturer och cookieinnehåll kan krypteras (och sedan hashas eller signeras ovanpå). Säkerhetsnivån måste matcha hotet.