Vad är Cross-Site Scripting och hur hindrar jag det?

Det här inlägget publicerades ursprungligen på bloggen Entreprenörd 15 december 2009.

Cross-Site Scripting (förkortas XSS) är ett säkerhetshål som tillåter en hacker att injicera Javascript på din webbplats och därigenom komma över andra användares känsliga uppgifter, exempelvis lösenord.

I Wikipedias artikel om Cross-Site Scripting kan vi läsa att XSS har blivit det vanligaste säkerhetshålet över huvud taget för programvara, och att vissa forskare hävdar att 68% av alla webbplatser är öppna för XSS-attacker. Historiskt har både Google (sökmotorn), GMail, Facebook och Wikipedia haft problem med XSS.

Fortsätt läsa Vad är Cross-Site Scripting och hur hindrar jag det?

Hur lagrar man användarnas lösenord säkert?

Det här inlägget publicerades ursprungligen på bloggen Entreprenörd 9 mars 2009.

Det skrivs ibland om webbtjänster som blir hackade och lösenord som läcker ut. Då är det en fördel om lösenorden är skyddade på något sätt, men så är det inte alltid. Hur kan man då göra för att säkra lösenorden för den händelse att ens tjänst skulle bli hackad? Jag har definierat tre säkerhetsnivåer nedan.

Fortsätt läsa Hur lagrar man användarnas lösenord säkert?

Smartphones ger sämre lösenord

Föreställ dig att lösenordet till ditt Facebook-konto är Bo4!p&kK=LsG. (Du har väl säkra och unika lösenord till alla dina konton, eller hur?) Nu har du köpt en smartphone och ska logga in för första gången. Vad gör du?

Jag gissar att du loggar in på Facebook på datorn och byter till ett enklare lösenord, ett som du snabbt och enkelt kan skriva in på din smartphones tangentbord.

På iPhone är det enklast att skriva tecknen a-ö (gemener) och mellanslag. För att få fram en uppsättning specialtecken måste du trycka på ”123” för att byta tangentbordslayout. För vissa specialtecken måste du byta ännu en gång genom att trycka på ”#+=”.

Tyvärr är det alltså lite besvärligare att skriva in säkra lösenord på smartphones (framförallt iPhone, Android är bättre på specialtecken), vilket får mig att dra en slutsats och göra en förutsägelse:

Kvaliteten på lösenord kommer försämras framöver, i takt med att pekskärmar används mer och mer. Lösenord kommer bestå av enbart bokstäver och inte vara tillräckligt långa.

Men du som vill ha hyfsat säkra lösenord som är iPhone-vänliga, tänk på detta:

  • Använd bokstäver med accenter och andra tecken, ex. áõêüß, som du snabbt får fram genom att hålla inne respektive bokstav på tangentbordet.
  • Håll inne tangenten ”123” och dra fingret till en siffra eller ett specialtecken och släpp för att komma tillbaka till ”ABC”-tangenterna direkt.
  • Kompensera för dålig variation mellan tecknen med extra långa lösenord, ex. så kallade pass phrases.

Har du tänkt på att det är besvärligt att skriva in lösenord på din smartphone? Har du några knep eller tankar om det? Dela gärna med dig i kommentarerna.

Använd inte MD5 eller SHA-1

Det är egentligen ganska enkelt: använd inte md5 eller sha-1 för att hasha dina användares lösenord. Inte ens om du använder salt.

United States Computer Emergency Readiness Team skrev 2008:

Software developers, Certification Authorities, website owners, and users should avoid using the MD5 algorithm in any capacity. As previous research has demonstrated, it should be considered cryptographically broken and unsuitable for further use.

Computer Security Division vid NIST skrev 2006:

Federal agencies should stop using SHA-1 for digital signatures, digital time stamping and other applications that require collision resistance as soon as practical, and must use the SHA-2 family of hash functions for these applications after 2010.

Säkerhetsgurun Ron Rivest skrev 2005: ”… now that md5 and sha1 are both clearly broken (in terms of collision-resistance).”

Förutom att algoritmerna har påvisade säkerhetsbrister går det väldigt snabbt att skapa uppslagstabeller för att ta reda på vilket lösenord som döljer sig bakom ett hash.

Med optimerade algoritmer och genom att använda grafikkort för att beräkna hashsummorna (de är snabbare än vanliga processorer på detta), har man kommit upp i 700 miljoner hashar per sekund för SHA-1. Mina tester visar att MD5 går ännu snabbare.

Det betyder att ditt ”säkra” lösenord på 8 tecken (ex. ”LvZ49l3U”, ”ibOQ3sjL”, ”LwL5opHp”) knäcks på en vecka. Om du är som de flesta och har lösenord på max 6 tecken, är det knäckt på under en halvtimme.

(Det finns också färdiga sådana uppslagstabeller som kallas rainbow tables som man kan använda för att blixtsnabbt knäcka alla tänkbara lösenord.)

Jag skrev tidigare en kort introduktion till hur man lagrar lösenord säkert, men sedan dess har jag lärt mig mer och kan sammanfatta det så här:

Använd SHA-256 med key stretching och dynamiskt salt för varje användare eller bcrypt med Blowfish (PHP-kodare bör använda PHPass). Då klarar du dig rätt bra.

Säkrare PHP-sessioner

PHP genererar ju ofta ett sessions-id som lagras som en cookie i webbläsaren. Jag läste just att man kan säga åt PHP att generera säkrare/bättre sessions-idn genom att ändra några inställningar i PHP.ini (alternativt ändra dem i ditt skript med functionen ini_set):

session.hash_function = 1

Default är 0, vilket betyder att MD5 används. Sätt värdet till 1 för att istället använda den bättre funktionen SHA-1.

session.entropy_file = /dev/urandom
session.entropy_length = 16

Då läser PHP 16 bytes från den ganska bra slumpkällan /dev/urandom istället för att som standard bara använda timestamp, IP-adress och något mer. Det gör det mycket svårare att gissa sig till ett sessions-id.

Om du vill ha extremt säkra sessioner, bör du förstås inte nöja dig med detta. Då bör du istället sätta inställningarna så här (rekommenderas ej om du inte har extrema säkerhetskrav då det ger sämre prestanda):

session.hash_function = sha512
session.entropy_file = /dev/random
session.entropy_length = 512

Läsarfråga: sessioner med AJAX

Jag fick en fråga från en av bloggens läsare:

Säg att jag har en AJAX-funktion som gör något i min MySQL-databas (t ex raderar en rad). AJAX-funktionen kallas från ett Javascript. Hela webbsajten är skyddad med https, session etc, men det hindrar ju inte att någon oinloggad kan kolla på mina scripts-filer om man råkar veta URL:en (eller gissar den), eller hur? Så vad är det som hindrar att man som oinloggad gör AJAX-calls direkt i adressfältet? Hur skyddar man i så fall känsliga operationer i AJAX-script?

Frågan baseras på ett missförstånd, och jag gör själv samma tankevurpa ibland, så jag tänkte försöka reda ut det här.

AJAX använder webbläsarens funktion XMLHttpRequest för att anropa webbservern och returnera svaret till en Javascript-funktion istället för att rendera om sidan i webbläsaren. Det är sedan upp till Javascript-koden att göra något med svaret.

Men själva AJAX-anropen och svaren är helt vanliga http- eller https-anrop, precis som när användaren klickar på en länk och webbläsaren hämtar en ny html-sida. Webbläsaren skickar även med samma cookies!

Eftersom webbläsarens session på servern identifieras med en sessions-cookie, kan du verifiera att besökaren är inloggad även om anropen görs med AJAX.

Inte ens cookie-flaggan HttpOnly ställer till det. (Flaggan ska göra så att cookien inte kan läsas av Javascript och bara skickas fram och tillbaka med http-anrop. Det spelar ingen roll, eftersom webbläsaren lägger till cookien vid AJAX-anrop.)