Auth-Token System | jQuery
lima-city → Forum → Die eigene Homepage → HTML, CSS & Javascript
aufruf
benutzer
bob
code
datei
ende
form
formular
frage
funktion
http
idee
jemand
not
null
problem
session
tabelle
url
versuchen
-
Hallo,
ich habe micht bereits vor längerem nach einem Script für ein Auth-Token System hier im Forum erkundigt und auch eines bekommen. Da ich durch dieses Script aber nicht komplett durchgestiegen bin, habe ich mir ein eigenes erstellt und das ursprüngliche Script dabei als Grundidee verwendet. Ich wollte nun wissen, ob es noch Sicherheitslücken gibt, um die ich mich kümmern sollte. Sinn der Sache ist es, eine Datenbank zu aktuallisieren, ohne die Seite neu zu laden:
index.php:
<?php session_start(); include('Funktionen.php'); //Funktionen für den Token ?> <html> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <script type="text/javascript"> <?php $Token = ErstelleToken(); //Token zum ersten mal erstellen ?> var Token = '<?php echo $Token; ?>'; </script> <script type="text/javascript" src="Javascript.js"> </script> <script type="text/javascript" src="jquery-1.8.2.js"><?php //Einbindung der jQuery Datei ?> </script> <title> Token </title> </head> <body> <a href="#" onclick="DatenbankAktuallisieren()"> <?php //Link zu der Funktion ?> Aktuallisieren </a> <div id="Div"> </div> </body> </html>
Javascript.js:
function DatenbankAktuallisieren(ID) { $(document).ready(function() { $.ajax({ type: "POST", url: "Aktuallisieren.php", data : "Token=" + Token, //gegebenenfalls werden noch weitere Parameter uebergeben success: function(Rueckmeldung) { $("#Div").html(Rueckmeldung); $.ajax({ type: "POST", url: "ErstelleNeuenToken.php", //Ein neuer Token wird erstellt success: function(Rueckmeldung) { Token = Rueckmeldung; } }); } }); }); }
Aktuallisieren.php:
<?php session_start(); include('Funktionen.php'); if(StimmtToken($_POST["Token"])) { //Wenn der Token stimmt, wird dieser Teil ausgeführt. Hier steht die Datenbankverbindung echo "Hat geklappt"; //Meldung, die bei erfolgreicher Ausfuehrung des Auftrags angezeigt wird } else { echo "Bitte versuche es in ein paar Minuten erneut!"; } ?>
Funktionen.php:
<?php function ErstelleZufaelligenText($Laenge) { //Diese Funktion erstellt einen zufaelligen Text der Laenge "$Laenge" und schreibt ihn in die Variabel "$Text". //Den Inhalt dieser Funktion habe ich ausgelassen, damit nicht klar ist, wie genau der Text erstellt wird. return $Text; } function ErstelleToken() { $Token = ErstelleZufaelligenText(32); $_SESSION["Token"] = $Token; return $Token; } function StimmtToken($Token) { if($_SESSION["Token"] == $Token) { return true; } else { return false; } } ?>
ErstelleNeuenToken.php:
<?php session_start(); include('Funktionen.php'); echo ErstelleToken(); ?>
Das Script funktioniert so weit, es wird jedesmal ein neuer Token erstellt und der alte überschrieben, aber ist dieses Script wirklich sicher? Ich hoffe das sich jemand die Arbeit macht und den gesammten Text durchkaut,
MFG THWBM
Beitrag zuletzt geändert: 23.1.2013 17:36:25 von thwbm -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hi,
was ich nicht ganz verstehe ist, weshalb du nachdem ja durch die `Aktuallisieren.php` bereits auf jeden fall am ende ein neuer token erstellt und in der session eingetragen wurde dann nochmals einen aufruf startest (ErstelleNeuenToken.php) um wiederum einen neuen token zu erstellen...
könntest du nicht gleich den während des ersten aufrufs eh schon neu-erstellten token als teil der rückmeldung abgreifen ?
oder halt auf die erstellung eines neuen token innerhalb der `Aktuallisieren.php` verzichten ? -
Du bist Dir sicher, dass der Zufallstoken zufällig ist?
Eigentlich sollte es nämlich kein Problem sein, den Algorithmus zu verraten, wenn der erzeugte Wert wirklich zufällig und nicht rekonstruierbar ist. -
Hallo und danke für die schnellen Antworten,
hcms schrieb:
Hi,
was ich nicht ganz verstehe ist, weshalb du nachdem ja durch die `Aktuallisieren.php` bereits auf jeden fall am ende ein neuer token erstellt und in der session eingetragen wurde dann nochmals einen aufruf startest (ErstelleNeuenToken.php) um wiederum einen neuen token zu erstellen...
Auf den zweiten Blick hast du Recht. Danke, ich werde die Erstellung in der "Aktuallisieren.php" weglassen.
tobiworlds schrieb:
Du bist Dir sicher, dass der Zufallstoken zufällig ist?
Eigentlich sollte es nämlich kein Problem sein, den Algorithmus zu verraten, wenn der erzeugte Wert wirklich zufällig und nicht rekonstruierbar ist.
Ja, ich bin mir Sicher, dass der Token NICHT absolut zufällig ist, denn das hat meines Wissens noch kein Programm geschafft. Ich habe aber mein bestes getan.
Sieht irgendjemand noch Sicherheitslücken? Ich wäre für weitere Antworten sehr dankbar,
MFG THWBM -
nun ich denke die php-session an sich ist ja schon nicht so super-sicher... stichwort `Session Hijacking`,`Session Fixation`, ...das kann zusammen mit irgendeiner kleinen xxs lücke irgendwo auf deinen seiten schon zum overkill führen - und da du ja jquery benutzt kannst du dir dann nie ganz sicher sein wie sicher zb deine ajax-requests sind...
aber was soll man machen ?!
...eine 100%ige sicherheit erreicht man ja nicht mal mit ssl und rsa-verschlüsselung :( -
hcms schrieb:
nun ich denke die php-session an sich ist ja schon nicht so super-sicher... stichwort `Session Hijacking`,`Session Fixation`, ...das kann zusammen mit irgendeiner kleinen xxs lücke irgendwo auf deinen seiten schon zum overkill führen
Gibt es einen Weg das zu umgehen? Also ein Auth-Token-System ohne Session, das sicherer ist? Wenn ja, wie ist das Grundsystem? Gibt es etwas anderes (außer SSL), was ich machen kann, um die Internetseite sicherer zu machen?
hcms schrieb:
und da du ja jquery benutzt kannst du dir dann nie ganz sicher sein wie sicher zb deine ajax-requests sind...
Dass man die Ajax Abfragen leicht fälschen kann, ist mir klar, aber solange man den Token in der Session nicht ändern kann, ist das doch egal, oder?
hcms schrieb:
aber was soll man machen ?!
...eine 100%ige sicherheit erreicht man ja nicht mal mit ssl und rsa-verschlüsselung :(
Doch, es gibt eine 100%ige Möglichkeit, dass niemand über das Internet auf die privaten Daten zugreifen kann, aber da ich nur bedingt lust habe, mir ein 50 Meter tiefes Loch mitten in der Sahara zu graben und mich da für den rest meines Lebens zu verstecken, ist diese Möglichkeit hinfällig . Eine andere Möglichkeit wäre mir auch nicht bekannt,
MFG THWBM -
wenn Du in dem Loch Internet hast macht das kein unterschied ;) ^^
aber mal zurück zu der Frage
wenn einer wissen will was Du da tust kann er es vielleicht schon erahnen wenn er das HTML und Javascript liest
wenn Du die Seite also neu lädst soll der Token da auch geändert werden ja? -
coopfungamers schrieb:
wenn einer wissen will was Du da tust kann er es vielleicht schon erahnen wenn er das HTML und Javascript liest
Ja, das kann er, aber ohne Zugriff auf die Session hilft ihm das noch nicht. Er müsste erst noch die Session eines Fremden auslesen.
coopfungamers schrieb:
wenn Du die Seite also neu lädst soll der Token da auch geändert werden ja?
Soll das "ja" am ende eine Antwort auf die Frage darstellen? Der Token wird beim Seite neu laden erneuert. Oder sollte das "ja" am ende heißen, dass das so nicht sein sollte?
MFG THWBM -
Hallo,
bin zufällig auf deinen Beitrag gestoßen und frage mich ob du jetzt eine relativ sichere Lösung gefunden hast.
Ich habe das gleiche Problem. Würde mich über eine Antwort freuen.
gruß -
Hallo,
ello123 schrieb:
[ich] frage mich ob du jetzt eine relativ sichere Lösung gefunden hast.
Nein, leider habe ich bisher keine bessere Lösung gefunden. Dieses Thema hier hat sich ja ein bisschen im Sand verlaufen.
Wenn du eine Möglichkeit findest, um solche Datenbankaktuallisierungen sicher zu realisieren, könntest du sie ja hier veröffentlichen.
MFG THWBM -
Schade.
Ich bin hier auf einen interessanten Beitrag gestoßen, ist aber auf english:
You can use a php script on all of your pages.
It takes the values of the data you are passing to the php script via ajax, concatenates them adds a "secret" word to the end and then md5 encrypts the string. You then pass the md5 hash as a query paramater through the ajax call. In the receiving php script you receive all the variable values passed concatenate them add the secret word to the end and md5 encode it. Then your script compares this md5 hash with the one passed to it. If they match you execute the php code to update the database. If not, you exit or error out. That way someone hitting the php script directly can only resubmit legitimate data. Since they don't know the secret word they can not recreate a hash that will match. If they change any of the query string values when the receiving php script recreates the md5 hash it will be different than the one passed to it.
Verstehe den Ablauf nicht 100%ig. -
Wäre es nicht einfacher das mit dem Zufallstext dem Client zu überlassen?
-
Nee das macht doch kein Sinn, jeder könnte dann sehen wie dieser Zufallswert generiert wird.
Ich habe eine andere Variante programmiert, wo über eine separate ajax Anfrage an token.php Datei erst mal ein Token generiert wird, dieser Token wird dann in eine session hinterlegt und auch als rückgabewert zurückgegeben.
Dann erfolgt die eigentliche ajax Anfrage, wo unter anderem auch der generierte Token als Parameter übergeben wird.
In der PHP Datei wird dann der Wert aus Session mit dem übergebenen Token verglichen.
Am Ende wird dann die Session geleert, sodass für jede Ajax Anfrage ein neuer Token generiert wird.
Dadurch kann keiner direkt auf eine Datei zugreifen.
Schwachstelle ist, dass jeder über Direktaufruf auf token.php sich einen gültigen Token generieren kann. -
Hallo,
ello123 schrieb:
Schwachstelle ist, dass jeder über Direktaufruf auf token.php sich einen gültigen Token generieren kann.
ich bin mir nicht mehr Hundertprozentig sicher, da es schon etwas länger her ist, dass ich mich mit dem Quelltext genauer auseinandergesetzt habe, aber ich denke, dass ich genau das Problem auch habe. Durch diese Lücke, ist der gesammt Versuch, die Übertragung abzusichern hinfällig, oder? Eine dritte Seite könnte sich einen validen Token erstellen, wenn sie vom Benutzer aufgerufen wird. Diese Seite könnte dann Änderungen an der Datenbank im Namen des Benutzers machen.
MFG THWBM -
Ich versuche mal meine Idee zu skizzieren:
1) Benutzer Authentifizierung:
Anmeldedaten werden gesendet -> Überprüfen -> bei Erfolg: zufälligen Auth-Token mit valid date (also bis zu dem der Token gültig ist) in die DB eintragen und dem Benutzer geben (via Session, eigener Cookie oder ähnliches)
2) Aufruf eines wichtigen Formulars zur Datenmanipulierung:
a) Auth-Token überprüfen (ist er richtig und noch gültig, wenn ja das valid date hochsetzen)
b) Form-Token mit valid date (5 Minuten oder so) generieren, der nur für den Auth-Token gültig ist. Konkret würde ich es so umsetzen:
Form-Token, valid date und parent key auf den Auth-Token in die DB
Dieser Form-Token wird dann im Formular als hidden input gespeichert oder entsprechend im Ajax Aufruf mitübergeben.
3) Aufruf der Funktion zur Datenmanipulierung
a) Auth-Token überprüfen
b) Form-Token überprüfen
Beispiel SQL Tabelle:
DROP TABLE IF EXISTS `token`; CREATE TABLE `token` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `token` varchar(32) NOT NULL, `validDatetime` datetime NOT NULL, `pID` int(11) NOT NULL, `pType` enum('user','token') DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Auth-Token für Benutzer mit ID 1 aus Tabelle user einfügen:
INSERT INTO... ('TOKEN', '2014-03-16 00:45:00', 1, 'user')
=> hat ID 1
Form-Token für Token mit ID 1 aus Tabelle token einfügen:
INSERT INTO ... ('TOKEN', '2014-03-16 00:35:00', 1, 'token')
Auth-Token für Benutzer mit ID 32 aus Tabelle user einfügen:
INSERT INTO... ('TOKEN', '2014-03-16 00:45:00', 32, 'user')
=> hat ID 215
Form-Token für Token mit ID 215 aus Tabelle token einfügen:
INSERT INTO ... ('TOKEN', '2014-03-16 00:35:00', 215, 'token')
Ein Problem bleibt aber weiterhin:
Bei dieser Art der Generierung wird der Token zwar Benutzer gebunden generiert, allerdings nicht Funktionsgebunden. D.h. man könnte als authentifizierter Benutzer X das Formular A aufrufen, sich den Token schnappen, und damit als authentifizierter Benutzer X das Formular B absenden.
Solltest du die Generierung der Token auch noch Funktionsgebunden nutzen, würde ich dir auf jeden Fall empfehlen das von mir vorgeschalgene Datenbankdesign noch weiter zu überarbeiten und mit fest definierten Routen etc. zu arbeiten. Aber ich denke, das schießt über das gewünschte Ziel hinaus :) -
Hallo,
lucas9991 schrieb:
Ich versuche mal meine Idee zu skizzieren:
[...]
wenn ich deine Idee richtig verstanden habe, bleibt aber doch das Problem, dass sich jemand anders als der Benutzer ausgeben kann. Wenn der Benutzer beginnt, das Formular auszufüllen und dann in einer anderen Registerkarte eine dritte Seite aufruft, könnte sich diese dritte Seite doch neue Tokens generieren lassen, oder? Mit diesen Tokens könnte sie dann das Formular abschicken, und zwar mit dem Inhalt, den die Seite für richtig hält. Wenn ich da jetzt etwas falsch verstanden habe, bitte ich um Berichtigung.
MFG THWBM -
thwbm schrieb:
Hallo,
ello123 schrieb:
Schwachstelle ist, dass jeder über Direktaufruf auf token.php sich einen gültigen Token generieren kann.
ich bin mir nicht mehr Hundertprozentig sicher, da es schon etwas länger her ist, dass ich mich mit dem Quelltext genauer auseinandergesetzt habe, aber ich denke, dass ich genau das Problem auch habe. Durch diese Lücke, ist der gesammt Versuch, die Übertragung abzusichern hinfällig, oder? Eine dritte Seite könnte sich einen validen Token erstellen, wenn sie vom Benutzer aufgerufen wird. Diese Seite könnte dann Änderungen an der Datenbank im Namen des Benutzers machen.
MFG THWBM
Genau dadurch ist alles hinfällig.
wie meinst du das über eine dritte Seite? Im Endeffekt wird der Token sowieso als Rückgabewerte angezeigt, es hilft daher nichts…es kann auch sein, dass dieser Ansatz überhaupt falsch ist. Könnte ein Token-Paar eine Lösung sein? -
thwbm schrieb:
Hallo,
lucas9991 schrieb:
Ich versuche mal meine Idee zu skizzieren:
[...]
wenn ich deine Idee richtig verstanden habe, bleibt aber doch das Problem, dass sich jemand anders als der Benutzer ausgeben kann. Wenn der Benutzer beginnt, das Formular auszufüllen und dann in einer anderen Registerkarte eine dritte Seite aufruft, könnte sich diese dritte Seite doch neue Tokens generieren lassen, oder? Mit diesen Tokens könnte sie dann das Formular abschicken, und zwar mit dem Inhalt, den die Seite für richtig hält. Wenn ich da jetzt etwas falsch verstanden habe, bitte ich um Berichtigung.
MFG THWBM
Benutzer Alice: die Gute
Benutzer Bob: der Böse
Benutzer Alice ruft die Seite example.org auf. Benutzer Bob soll sich jetzt wie als Benutzer Alice ausgeben?
Bob könnte sich nur als Alice ausgeben, wenn er an den Auth-Token kommt. Dieser wird aber von Alice Browser per Cookie an example.org gesendet. Das wäre dann ein Session Hijacking durch z.B. einen Man-in-the-middle-Angriff. Eher schwierig Durchzuführen für Privatpersonen. Für einen Provider, Geheimdienst etc. sicherlich eine einfache und elegante Methode.
Wenn Alice nun das Formular von example.org aufruft und ausfüllt, soll eine weitere Seite im Hintergrund geöffnet werden?!
Was für eine Seite und wie? Wie soll die andere Seite dann an das Form-Token das an das Auth-Token gebunden ist und im Formular steht dran kommen?
Wenn Bob das Formular example.org aufruf bekommt er einen Form-Token der an seinen Auth-Token gebunden ist. Damit kann er selbst wenn er den Auth-Token von Alice danach hat das Formular nicht absenden. Er braucht den Auth- und den Form-Token.
Angenommen Bob hat den Auth-Token per Session Hijacking von Alice übernommen, dann kann er sich beliebig viele neue Tokens generieren lassen, aber ich glaube dann sind die Tokens das kleinere Problem... Er hat dann den gesamten Account.
Ich verstehe überhaupt nicht, was du meinst. Vielleicht zeichnest du sonst einfach mal eine kurze Skizze/Ablaufplan was du genau nicht verstehst.
http://de.wikipedia.org/wiki/Cross-Site-Request-Forgery#Abwehrma.C3.9Fnahmen -
lucas9991 schrieb:
Ich verstehe überhaupt nicht, was du meinst.
Ich versuche mal deinen Ansatz mit Alice und Bob zu übernehmen:
Alice hat ein Benutzerkonto bei example.com. Bob will eine Datenbank im Namen von Alice so verändern, wie er es gerne hätte.
Um das zu verhindern existiert auf dem Server von example.com eine Datei namens "Token.php":
<?php //Gibt eine belibige Zeichenkette aus echo ErstelleToken(); ?>
Dieser Token wird nun erstellt, wenn das Formular geladen wird. Der Token wird an das Formular gehängt, und es wird beim Abschicken serverseitig überprüft, ob die übergebene Zeichenkette der vom Server generierten Zeichenkette entspricht. So weit sollte noch alles klar sein, oder?
Wenn Bob jetzt einen Gültigen Token haben will, müsste er doch nur eine Seite veröffentlichen, die Allice aufruft, währenddessen sie bei example.com angemeldet ist, beispielsweise in einem zweiten Tab. Diese Seite kann dann einen belibigen Inhalt haben.
Im Hintergrund ruft die Seite von Bob dann über Ajax die Token.php von example.com auf, erhält einen gültigen Token und kann diesen dann so verwenden, wie Bob es gerne hätte.
MFG THWBM
Beitrag zuletzt geändert: 19.3.2014 16:14:56 von thwbm -
Ach so meinst du das. Ok, ich denke ich habe dein Problem verstanden. Nicht schlecht, dass du von alleine darauf kommst!
Stell dir aber mal vor, jemand würde im Hintergrund einfach die Website vom Onlinebanking aufrufen und dort alles auslesen. Das wäre in der Tat sehr gefährlich.
Deshalb geht es bewußt nicht von foo.example.org via clientseitigem JavaScript ein Ajax Request an bar.example.org zu senden. Allerdings wird diese Regelung mittlerweile "aufgeweicht", aber der Betreiber von bar.example.org muss explizit angeben, dass es erlaubt ist.
http://de.wikipedia.org/wiki/Cross-Origin_Resource_Sharing
http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
Folglich solltest du dir darum keine Sorgen machen, da es einfach nicht in deiner Hand liegt.
Nichts desto trotz ist es sinnig in Formularen einem Benutzerspezifischen Token zu hinterlegen.
Als Beispiel: Vor Jahren habe ich diese "Lücke" mal bei lima ausgenutzt. Damals musste man nur eingeloggt sein und konnte dann Gästebucheinträge per HTTP GET posten.
Da habe ich eine Seite gebastelt, die alle Besucher einfach auf mein Gästebuch weitergeleitet hat mit einem zufälligen Gästebuchbeitrag per GET mit übergeben hat. Ergo, jeder Benutzer der zu dem Zeitpunkt bei lima eingeloggt war und meine Seite besucht hat, hat unfrewillig einen Gästebucheinträge in meinem Profil hinterlassen. -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage