WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Bästa sätt att identifiera sig över ett HTTP GET anrop? (https://www.wn.se/forum/showthread.php?t=1037748)

RickardP 2009-08-30 11:09

Bästa sätt att identifiera sig över ett HTTP GET anrop?
 
Jag håller på att ska bygga up ett API för kunder att använda tjänst jag startar up och vill kolla hur man gör det säkert att identifiera sig över ett HTTP GET anrop?

Kunden ska tex för att få en viss information skriva http://api.mindoman.se/getinfo/

Detta görs med ett enkelt HTTP GET anrop men jag måste låta kunden identifiera sig frö att få rätt information och jag har sätt många bara låter sina kunder skicka med användarnamn och lösenord i klartext i url:en men det är ju så osäkert det kan bli att göra så om någon sitter och avlyssnar sin traffik.

SSL har jag fått tips om och ska kolla på men finns det någon som har en bra lösning?

V-Me 2009-08-30 12:08

Jag brukar skicka med idet i md5.

elitasson 2009-08-30 12:19

Varför inte generera en nyckel till varje användare som enbart används för API-tjänsten?

RickardP 2009-08-30 12:28

Hmm, jag har varit inne på det också men ville se om någon hade någon bättre lösning, för kommer dem åt den nyckeln kan dem ju använda API:et vilket i denna tjänst är ganska så värdefull men inte övriga tjänsten.

Jag var ett tag inne på att man skulle få göra någon hash mellan username + password + datum bara för att få det så det endast fungerar en dag om någon får tag på nyckeln.

V-Me 2009-08-30 12:29

Gör en ny nyckel hela tiden?

Jine 2009-08-30 13:41

https://kund:[email protected]/getinfo/

Borde lösa... allt?

RickardP 2009-08-30 13:44

Citat:

Ursprungligen postat av Jine (Inlägg 20320212)

Hur löser man det där då?

Jine 2009-08-30 13:53

https, dvs ingen kan avlyssna och se lösenordet.
och sjukt användarvänligt.

RickardP 2009-08-30 13:57

Citat:

Ursprungligen postat av Jine (Inlägg 20320215)
https, dvs ingen kan avlyssna och se lösenordet.
och sjukt användarvänligt.

Jo HTTPS fattade jag men det där med användarnamn och lösenord?

Jine 2009-08-30 14:16

Citat:

Ursprungligen postat av RickardP (Inlägg 20320192)
jag har sätt många bara låter sina kunder skicka med användarnamn och lösenord i klartext i url:en men det är ju så osäkert det kan bli att göra så om någon sitter och avlyssnar sin traffik.

Det är inte osäkert om det går över SSL/HTTPS?
Precis det jag menade.

crazzy 2009-08-30 17:39

Citat:

Ursprungligen postat av RickardP (Inlägg 20320217)
Jo HTTPS fattade jag men det där med användarnamn och lösenord?

Det skickas som en helt vanlig http auth.
Här står det lite om auth: http://httpd.apache.org/docs/2.0/howto/htaccess.html

edit: Och här står lite om att använda php till authen: http://us3.php.net/manual/en/features.http-auth.php

Onkelborg 2009-08-30 20:00

Om man sätter kravet GET så är det crazzy säger säkrast, eller i alla fall någonting som går i någon header, att sätta en cookie skulle säkert fungera lika bra det med. Det som är viktigt att tänka på är att allt som följer med i url:en kan loggas, t.ex. på webbservern, en proxy, någon mystisk brandvägg etc. Beroende på config med certifikat etc. så ger inte ssl något skydd mot sådan loggning. (POST klarar sig bättre där..)

SimonP 2009-08-30 20:18

Det är bättre att använda engångsnycklar, ett exempel:
Klienten skickar UserID + hashsumman SHA1(hemlignyckel+salt) , servern läser UserID och verifierar sen hashsumman på samma sätt. Den hemliga nyckeln behöver då aldrig skickas över nätet. Saltet kan bestå av dagens datum. Om nån avlyssnar får dom bara en kod som fungerar en kort tid.

Jonas 2009-08-31 02:25

Det som Jine skickade först är HTTP AUTH, och lägger sig under "$_SERVER" i PHP, tror det är HTTP_AUTH_USER & HTTP_AUTH_PASS. Men det skickas i klartext här med.

Det bästa är nog att skicka ut User, Pass + unikt SALT och kräva att det saltas med tex. datumet.

Tex. sha1(USERNAME + SALT + DATUM + PASS)

att blanda in HTTPS här är nog bara overkill.

Jine 2009-08-31 02:50

Nej, det skickas inte i klartext om HTTPS är inblandat?
Precis det som var poängen.

Onkelborg 2009-08-31 12:31

Säkrast för GET är:
* HTTPS
* HTTP Auth/Cookie/etc med någon "apinyckel" skiljd från inloggningsuppgifter (vid ev. intrång på klient-sidan så är det bara api:t man kommer åt, man kommer inte längre)
* Ingenting i URL:en eftersom att det troligtvis fastnar i någon rolig logg någonstans, vilket minskar säkerheten lite eftersom att nyckel/inloggningsuppgifter fastnar där "permanent". Förslagsvis är nyckeln hashad i databasen så ev. läsning i databasen ger ingen nyckel. Men om man även kan få tag på loggen så..

BjörnJ 2009-08-31 14:46

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320295)
Förslagsvis är nyckeln hashad i databasen så ev. läsning i databasen ger ingen nyckel.

Om man vill skicka nyckeln hashad (t.ex. sha1(datum + nyckel)) måste man väl spara den i klartext på serversidan. Finns det några bra sätt att skydda nyckeln på serversidan? Det går ju att få lite extra skydd genom att spara den krypterad i databasen och ha en statisk nyckel i skriptet, men frågan är om det är värt besväret.

I det här fallet bör man nog skapa en nyckel automatiskt, och inte låta användaren ändra nyckel på annat sätt än att skapa en ny slumpmässig nyckel. Detta för att dels få en stark nyckel, och dels för att skydda användaren; det är inte möjligt att ange en nyckel (som sparas i klartext hos både klienten och servern) som användaren använder på något annat ställe. Denna nyckel används enbart för api. För vanlig inloggning används ett annat lösenord på vanligt sätt.

Om man använder datum som salt, tänk på att klienten och servern ska ange datumet enligt samma tidszon.

Vad sägs om en lösning i stil med följande?
$salt=round(timestamp/100);
User-id samt sha1($salt + nyckel) skickas som http auth.

Det kräver att klockorna på båda sidor går någorlunda rätt. För ökad säkerhet, dela med 10 istället om man är säker på att klockorna går nästan exakt rätt.

Servern kontrollerar:
$salt=round(timestamp/100);
if($http_pass==sha1($salt + nyckel) || $http_pass==sha1(($salt+1) + nyckel) || $http_pass==sha1(($salt-1) + nyckel))

Alternativ:
Använd hela timestamp som salt. Skicka med även salt i requesten (tillsammans med user-id och hash). Servern kontrollerar att salt inte skiljer sig för mycket från aktuell timestamp.

iXam 2009-08-31 14:59

Krypterad nyckel / hash som dels är baserad på användarens tillåtna IP/IP-range och lösen + salt.
Då kan nyckeln komma på vift utan att den kan användas. Sen kan man även langa in en datumrestricter så nyckeln enbart fungerar i X-antal dagar.

RickardP 2009-08-31 16:14

Stort tack för alla förslag, fortsätt gärna, bra för andra också.

Jag ska fundera över vad som blir bäst för detta.

Onkelborg 2009-08-31 21:46

Citat:

Ursprungligen postat av BjörnJ (Inlägg 20320311)
Om man vill skicka nyckeln hashad (t.ex. sha1(datum + nyckel)) måste man väl spara den i klartext på serversidan. Finns det några bra sätt att skydda nyckeln på serversidan? Det går ju att få lite extra skydd genom att spara den krypterad i databasen och ha en statisk nyckel i skriptet, men frågan är om det är värt besväret.

I det här fallet bör man nog skapa en nyckel automatiskt, och inte låta användaren ändra nyckel på annat sätt än att skapa en ny slumpmässig nyckel. Detta för att dels få en stark nyckel, och dels för att skydda användaren; det är inte möjligt att ange en nyckel (som sparas i klartext hos både klienten och servern) som användaren använder på något annat ställe. Denna nyckel används enbart för api. För vanlig inloggning används ett annat lösenord på vanligt sätt.

Om man använder datum som salt, tänk på att klienten och servern ska ange datumet enligt samma tidszon.

Vad sägs om en lösning i stil med följande?
$salt=round(timestamp/100);
User-id samt sha1($salt + nyckel) skickas som http auth.

Det kräver att klockorna på båda sidor går någorlunda rätt. För ökad säkerhet, dela med 10 istället om man är säker på att klockorna går nästan exakt rätt.

Servern kontrollerar:
$salt=round(timestamp/100);
if($http_pass==sha1($salt + nyckel) || $http_pass==sha1(($salt+1) + nyckel) || $http_pass==sha1(($salt-1) + nyckel))

Alternativ:
Använd hela timestamp som salt. Skicka med även salt i requesten (tillsammans med user-id och hash). Servern kontrollerar att salt inte skiljer sig för mycket från aktuell timestamp.

Mja, alltså, det är något sådant jag tänker. Nyckeln ska vara slumpmässig, skulle användaren tappa bort sin nyckel så genererar man bara en ny. Nyckeln bör vara sparad hashad på servern.

Att börja greja med datum och hasha en nyckel känns overkill, man kommer fortfarande inte ifrån problemet med att nyckeln finns fullt läsbar i klienten. Om man skyddar själva överföringen mellan klient och server med SSL så fyller ett sådant hash ingen funktion.

Däremot, om man inte nyttjar SSL så kan det finnas en poäng med hashad nyckel. Det skyddar dock bara mot framtida attacker, en attack som man-in-the-middle är dock fortfarande utsatt - bara att ändra innehållet on-the-fly. (Även om det går att skaffa sig skydd där också: signera all data som skickas över med nyckel + datum, kontrollera på servern..)

Personligen så tror jag dock att det inte är så realistiskt att man kan räkna med att klockorna går särskilt rätt i båda ändarna..

Kan man köra med SSL så fixar man många problem :)

SimonP 2009-09-01 01:17

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320354)
Mja, alltså, det är något sådant jag tänker. Nyckeln ska vara slumpmässig, skulle användaren tappa bort sin nyckel så genererar man bara en ny. Nyckeln bör vara sparad hashad på servern.
Att börja greja med datum och hasha en nyckel känns overkill, man kommer fortfarande inte ifrån problemet med att nyckeln finns fullt läsbar i klienten.

Fast tanken är att man ska skydda trafiken, att skydda data som finns lokalt på klientens dator är en annan avdelning.

Citat:

Om man skyddar själva överföringen mellan klient och server med SSL så fyller ett sådant hash ingen funktion.
Jo, det gör det, serverloggarna kommer bara att innehålla en engångsnyckel, inte nån permanent fungerande nyckel. HTTPS skyddar inte loggarna vid GET anrop.

Citat:

Däremot, om man inte nyttjar SSL så kan det finnas en poäng med hashad nyckel. Det skyddar dock bara mot framtida attacker
Nej, det skyddar både framtida och gamla, så länge det förflutit X antal minuter i tid, eftersom man hashat med en tidsstämpel/datum.

Citat:

en attack som man-in-the-middle är dock fortfarande utsatt - bara att ändra innehållet on-the-fly. (Även om det går att skaffa sig skydd där också: signera all data som skickas över med nyckel + datum, kontrollera på servern..)
En nyckel som man hittar genom en MITM attack kommer bara att fungera under en begränsad tid, eftersom man hashar allt tillsammans med datumstämpeln. En MITM kan inte ändra innehållet on-the-fly eftersom han inte vet userkey:n som genererade den slutliga hashsumman.

Jag tror det är dags att förklara förslaget lite bättre, åtminstone det protokoll som jag tänkt mig:

Serverns databas innehåller:
-UserID = en vanlig unik counter
-userkey = en lång slumpmässigt genererad "nyckel"

Klienten skickar detta:
GET domain?UserID=1234&requestKey=BBBBBBBBBBBBBBBBBBBB &timezone=4

"requestKey" skapas genom SHA1(userkey+datumstämpel) på klientsidan. Här får inte datumstämplarna vara för hårt satta, klientens klocka kan diffa med många minuter, kanske en stämpel som innehåller YYYYMMDDHH eller ännu mer noggrannt, men allt beror på klienterna och vilka krav man har. Serverns klocka synkas enkelt med NTP, så den går alltid rätt.

Servern verifierar med denna pseudokod:
$time=time(YYYYMMDDHH)(+-timezone);
$userkey = hämtas ifrån databasen, UserID används för att söka
if (requestKey == SHA1($userkey+$time) process_client_request();
else die("Wrong passhash or wrong timestamp!");

Summering:
-Userkey skickas aldrig i klartext
-Det går ej att modifiera keys som blivit sniffade
-Sniffade nycklar fungerar bara under en kort period
-Genom att lägga på SSL försvårar man avlyssning (men det är knappt värt det eftersom man ändå använder tidsbegränsade nycklar)
-SQL injections är egentligen det enda farliga hotet utifrån, men det är mkt enkelt att skydda sig mot genom att filtrera indata
-Säkerheten går som sagt att förbättra ytterligare genom att lägga på en IP-nr koll, men det beror på hur systemet skall användas om det fungerar eller ej

BjörnJ 2009-09-01 06:18

Citat:

Ursprungligen postat av SimonP (Inlägg 20320373)
GET domain?UserID=1234&requestKey=BBBBBBBBBBBBBBBBBBBB &timezone=4

timezone behövs inte om man har specat att tiden alltid ska anges i UTC, eller om man använder sig av unix timestamp oformaterad (som ska vara lika hos klient och server även om det är olika tidszoner).

Citat:

Ursprungligen postat av SimonP (Inlägg 20320373)
Servern verifierar med denna pseudokod:
$time=time(YYYYMMDDHH)(+-timezone);
$userkey = hämtas ifrån databasen, UserID används för att söka
if (requestKey == SHA1($userkey+$time) process_client_request();
else die("Wrong passhash or wrong timestamp!");

Här har man problemet att man kan få "false negative" om t.ex. klientens tid är 20090901055959 och serverns tid är 20090901060000. I mitt exempel löste jag det genom att även kolla tiden +/-1 om den första hashen inte matchar.

SimonP 2009-09-01 08:11

Citat:

Ursprungligen postat av BjörnJ (Inlägg 20320383)
timezone behövs inte om man har specat att tiden alltid ska anges i UTC, eller om man använder sig av unix timestamp oformaterad (som ska vara lika hos klient och server även om det är olika tidszoner).

Just ja, det verkar fungera, trodde att det skulle bli problem med sommartid då, men att köra UTC är bättre och enklare.

Citat:

Här har man problemet att man kan få "false negative" om t.ex. klientens tid är 20090901055959 och serverns tid är 20090901060000. I mitt exempel löste jag det genom att även kolla tiden +/-1 om den första hashen inte matchar.
Sjävklart måste man ta hänsyn till detta, det var därför jag fetmarkerade ordet pseudokod, det var ingen fullständig kod.

Onkelborg 2009-09-01 08:43

Nje, det där köper jag inte. Du har inget skydd mot MITM-attacker med ditt förslag. Och jag tycker inte att det är en bra idé att ha nyckeln fullt läslig i serverns databas, vid ev. intrång (även om det kanske bara blir en dumpning av databasen) så blir skadan lätt stor iom. fullt läsliga nycklar, som då även fungerar till api:t.

För att få ofarliga url:er i loggen är det ju bara att lägga auth i någon header istället för i url:en.

Att börja knöla med tidsbegränsade hash skulle väl möjligtvis vara om man saknar ssl, men då tycker jag iofs. att man kanske borde börja fundera på en lösning med public/private key istället.. RSA?

SimonP 2009-09-01 10:34

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320392)
Nje, det där köper jag inte. Du har inget skydd mot MITM-attacker med ditt förslag.

Jo, läs igen, skyddet ligger i att MITM inte kan sniffa nycklar som fungerar någon längre tidperiod, om man tillåter klientens klocka att diffa 20 minuter så kommer nyckeln bara att fungera i 20 minuter. MITM kan heller inte generera egna nycklar.

Citat:

Och jag tycker inte att det är en bra idé att ha nyckeln fullt läslig i serverns databas, vid ev. intrång (även om det kanske bara blir en dumpning av databasen) så blir skadan lätt stor iom. fullt läsliga nycklar, som då även fungerar till api:t.
Vid ett riktigt intrång i servern har dom full kontroll ändå. Eftersom userkeys är slumpmässiga nummer är skadan inte så stor, bara att generera nya nycklar till användarna. Det är ju inte direkt några kreditkortsnr som lagras i userkeys. Sen är det är oftast lättare att avlyssna trafik än att göra intrång i en server.

Citat:

Att börja knöla med tidsbegränsade hash skulle väl möjligtvis vara om man saknar ssl, men då tycker jag iofs. att man kanske borde börja fundera på en lösning med public/private key istället.. RSA?
Att använda SSL belastar servern mkt mer och kostar även pengar, om man kan hitta ett sätt som skyddar tillräckligt utan SSL är det bra. Sen är SSL inte supersäkert heller:
http://www.computerworld.com/s/artic...urity_protocol

Det är väldigt många som gör misstaget att enbart förlita sig på SSL, bättre att först bygga säkerhet så långt det går utan SSL, och sen kan man lägga på SSL som ett ytterligare skydd.

Onkelborg 2009-09-01 23:42

Nej, MITM kommer inte sniffa nycklar som gäller ett bra tag, det vet jag, men nycklarna gäller _nu_. Om man som MITM vet exakt vad man vill uträtta så är det bara att hänga på låset.. När nyckeln kommer så kör man.

SimonP 2009-09-02 09:18

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320471)
Nej, MITM kommer inte sniffa nycklar som gäller ett bra tag, det vet jag, men nycklarna gäller _nu_. Om man som MITM vet exakt vad man vill uträtta så är det bara att hänga på låset.. När nyckeln kommer så kör man.

Det är stor skillnad på att få tag på en nyckel/lösenord som fungerar permanent och få tag på en som bara fungerar en kort period. Varje gång som MITM kopplar in sig ökar risken för upptäckt.

Onkelborg 2009-09-02 11:08

Klart risken ökar, men det är fortfarande inte säkert. Vem man vad man vill göra så spelar det ingen roll om man får tag på en nyckel som fungerar 30 sekunder till eller en som fungerar i all evighet.

Vill man skippa ssl så föreslår jag rsa eller något liknande

SimonP 2009-09-02 11:26

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320519)
Klart risken ökar, men det är fortfarande inte säkert. Vem man vad man vill göra så spelar det ingen roll om man får tag på en nyckel som fungerar 30 sekunder till eller en som fungerar i all evighet.

Det finns inget som är 100% säkert. Men vi har olika syn på säkerhet, själv föredrar jag när man gjort så mkt som man kan för att för att försvåra för en eventuell attack.

Onkelborg 2009-09-02 13:20

Jag har iofs samma åsikt, därav att jag inte skulle nöja mig med att hasha ihop nyckel och tid..

RickardP 2009-09-02 13:27

Jag har fått ett tips som jag tycker låter väldigt smart, att man borde hasha alla paramterar man skickar till API:et med en api nyckel.

På detta sätt blir det alltid olika hashar på samtliga api anrop, för i detta fall är det ett sms api som skickar sms ;-)

SimonP 2009-09-02 13:31

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320537)
Jag har iofs samma åsikt, därav att jag inte skulle nöja mig med att hasha ihop nyckel och tid..

Märkligt, för du skrev detta förut :)
Citat:

Att börja greja med datum och hasha en nyckel känns overkill...

Onkelborg 2009-09-03 23:34

Det jag försöker få fram: ditt förslag ger bara falsk säkerhet. Det är ett hål, även om det, under normala förutsättningar, inte går att utnyttja mer än kort tid efter attacktillfället. Men under den korta tiden så kan man å andra sidan utnyttja det fullt ut..

Onkelborg 2009-09-03 23:36

RickardP: Mjo, jag skrev någonting sådant förut i tråden. Finns dock ett problem som inte blir löst på det sättet: Man kan skicka det sms:et om och om igen och belasta nyttjaren av api:t tungt ekonomiskt sätt, samt spamma ganska rejält. För att lösa det problemet så får man titta på annat håll, t.ex. även skicka med ett unikt löpnummer som aldrig får förekomma dubbelt, eller börja snegla på ssl.

SimonP 2009-09-04 00:36

Citat:

Ursprungligen postat av Onkelborg (Inlägg 20320710)
Det jag försöker få fram: ditt förslag ger bara falsk säkerhet. Det är ett hål, även om det, under normala förutsättningar, inte går att utnyttja mer än kort tid efter attacktillfället. Men under den korta tiden så kan man å andra sidan utnyttja det fullt ut..

Nej, det är ingen falsk säkerhet, det är en klar förbättring av säkerheten. Ett system som skickar nycklar som bara fungerar under en kort period kommer alltid vara bättre än ett system som skickar permanent fungerande nycklar. Borde inte vara så svårt att förstå...

Onkelborg 2009-09-06 18:23

Det är klart det är bättre, men det är inte bra.. Vid en MITM attack så skyddar inte ditt förslag vilket https gör (förutsatt rätt konfigurerat, dvs. bara acceptera trusted certifikat.) Sedan kan man ju blanda båda metoderna så man har visst skydd mot hål i ssl-ledet, grundskyddet står dock fortfarande ssl för.

Om man inte har sådan lyx som ssl så finns det andra vägar att gå, om än dock knöliga. Se mitt svar till RickardP


Alla tider är GMT +2. Klockan är nu 15:50.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson