kostenloser Webspace werbefrei: lima-city


PHP über JS sicher abrufen

lima-cityForumDie eigene HomepageHTML, CSS & Javascript

  1. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Hallo,
    da ich mir immoment ein Browsergame zusammenprogrammiere habe ich eine Frage:
    ich rufe über diesen Link:
    <a onclick="datenbankupdate('?ID=I1')" href="#">
      Datenbank updaten
    </a>

    diese Javascript Funktionen hier auf, um ein Item zu kaufen:
    function createXMLHttpRequest() {
      if(window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        return new XMLHttpRequest();
        } else {
        // code for IE6, IE5
        return new ActiveXObject("Microsoft.XMLHTTP");
      }
    }
    function datenbankupdate(data) {
      var request = createXMLHttpRequest();
      request.open('GET', 'Update.php' + data, true);
      request.send();
    }
    // Dieses Script habe ich nicht selbstgeschrieben, es ist von hackyourlife

    was auch fehlerfrei funktioniert, aber mein Problem dabei ist jetzt, dass das ja sehr unsicher ist, oder irre ich mich da jetzt? Theoretisch könnte doch jeder die Funktionen "datenbankupdate(data)" bei sich einbauen und somit die Datenbank individuell mapulieren, also einen Spieler unter irgendeinem Vorwand auf eine Seite, in der das Script automatisch ausgeführt wird, locken, oder? Kennt jemand eine möglichkeit das ganze sicher zu machen? Danke für alle Lösungsansätze,
    mfG THWBM
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. g****e

    Naja, das wichtigste ist, dir die Fälle anzuschauen: Wann darf so ein Update passieren? Wer kann es aufrufen?
    Du musst dir anschauen, wann ist eine solche Anfrage erlaubt, und wann nicht, und solltest dann in deiner Update.php prüfen, ob der Aufruf valide war, oder nicht. Etwa durch Sessions, Timer, oder ähnliches.
    Kannst du vllt ein bisschen mehr von dem Hintergrund erzählen? Was macht das Update? Wann wird das aufgerufen? Und was bewirkt es?
    Das wäre relativ wichtig, ansonsten sind Lösungsansätze schwer zu geben.

    Liebe Grüße
  4. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Hallo ggame, erstmal danke für die schnelle antwort,
    ggamee schrieb:
    Wann darf so ein Update passieren?

    Nur wenn man auf den Link klickt, ich habe mir auch schon etwas einfallen lassen, doch das war absoluter Mist. Ich hatte mir einfallen lassen, den Link in einen Div zu packen und dann mit onmouseover und onmouseout zu arbeiten, also das die Funktion nur ausgeführt wird, wenn man die Maus an der eichtigen stelle hat, doch das geht so ja auch nicht, da es sich einfach fälschen lässt.
    ggamee schrieb:
    Wer kann es aufrufen?

    Jeder, der sich registriert hat, falls du das meinst.
    ggamee schrieb:
    Du musst dir anschauen, wann ist eine solche Anfrage erlaubt, und wann nicht, und solltest dann in deiner Update.php prüfen, ob der Aufruf valide war, oder nicht. Etwa durch Sessions, Timer, oder ähnliches.

    Eine SESSION gibt es, aber wovor ich mich schützen will ist, dass jemand in einem Tab meine Seite geöffnet hat und in einem Anderen dann über Google auf eine Seite kommt, die die Updatefunktion eingebaut hat und somit auch wieder auf meine Update.php verlinkt, bei der dann die Abfrage
    if($_SESSION["BenutzerID"] == XY) {    }

    wider richtig beantwortet wird. Wie meinst du dass mit einem Timer?
    ggamee schrieb:
    Kannst du vllt ein bisschen mehr von dem Hintergrund erzählen? Was macht das Update? Wann wird das aufgerufen? Und was bewirkt es?
    Das wäre relativ wichtig, ansonsten sind Lösungsansätze schwer zu geben.

    Das Update bewirkt, dass man in einer art Shop ein Item kaufen kann. Meine angst ist, dass jetzt jemand um andere Spieler zu ärgern oder ähnliches das Geld der Spieler gegen irgendwelche Items, die sie gar nicht brauchen, einzutauscht.
    mfG THWBM

    Beitrag zuletzt geändert: 3.10.2012 14:51:45 von thwbm
  5. Sessions o.ä. wurden ja schon genannt. Wenn du verhindern möchtest, dass Bots die Funktion automatisiert aufrufen helfen einmalige Codes, die du als Parameter anhängst und hinterher ungültig machst. Bspw. ein Set von ein paar Tausend gültigen Codes in der Datenbank vorhalten und sobald einer benutzt wurde diesen ungültig machen (durch Löschen aus der Datenbank) und einen neuen einfügen.

    Gleichzeitig kannst du damit auch Cross Site Request Forgerys ( http://de.wikipedia.org/wiki/Cross-Site_Request_Forgery ) unterbinden.

    Das verhindert natürlich nicht, dass ein Bot die Software über die Oberfläche angreift, aber damit kannst du verhindern, dass ein Angreifer einfach die PHP-Datei aus der Javascriptfunktion automatisiert missbraucht, da ihm die Codes nicht geläufig sind.
    Es verhindert auch, dass ein unbedarfter User auf einer gefälschten Website irgendwelche Aktionen in der Opferanwendung tätigt.

    In der update.php selbst musst du natürlich immer prüfen, ob der Benutzer der die Aktion ausführt, diese auch ausführen darf. Mach dir Gedanken, wie deine Seite ohne Javascript aussehen würde, um Angriffe erfolgreich zu verhindern. Javascript machts nichts anderes als die Funktionen aufzurufen ohne die Seite neu zu laden. Wenn du die update.php entsprechend abgesichert hast ist es egal, ob ein Benutzer die Seite per Browser, per Bot, per Javascript oder per iOS App aufruft. Die Sicherung findet ja nicht auf dem Client Device sondern auf dem Server statt.
  6. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Hallo mlrecords, auch an dich ein danke für die schnelle Antwort,
    habe ich das jetzt richtig verstanden, dass ich einen zufällige Wert beim Login erstellen soll, den ich in der SESSION und in meiner MySQL Datenbank abspeichere und der nur für diese eine Sitzung, also bis zum nächsten logout, und nur für diesen einen Benutzer gültig ist?
    mfG THWBM
  7. Das wäre deine Session-Variable.

    Was ich meine sind aber Tokens. Du sendest zu jeder Anfrage an das Script ein Auth-Token mit. Dieses Auth Token musst du bei der Initialisierung (dem Erstellen) der Seite natürlich schon in den clientseitigen HTML-Quelltext einfügen. Wird das Token nun per JS an deine PHP-Datei geschickt machst du es da ungültig. So verhinderst du automatisierten Zugriff auf deine Funktionen.
  8. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Wie genau meinst du das denn jetzt? Ich kann dir nicht so ganz folgen, was sind denn jetzt "Auth-Token"? Das ist doch so eine art Schlüssel, oder? Ich hab mal gegooglet, aber nicht wirklich was brauchbares gefunden.
  9. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Du denkst dir am Server einen zufälligen String aus. Den speicherst du in deiner Session und hängst ihn auch bei deinem Link an.

    Wenn die update.php aufgerufen wird führt sie die Aktion nur dann aus, wenn der mitgeschickte Token mit dem in der Session zusammenströmt. Danach erstellst du einem neuen Token...

    Ein einfacher Link auf deine Seite kann also keine Aktion mehr ausführen.

    Beitrag zuletzt geändert: 3.10.2012 7:02:44 von hackyourlife
  10. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Hallo hackyourlife,
    ich glaube, dass ich dich entweder falsch verstanden habe oder ich einen Denkfehler gemacht habe. Wenn ich den Zufälligen String in die Session schreibe und diesen String dann auf dem Server nach einmaliger Beutzung entwerte, muss ich doch die Seite neu laden, damit ich den neuen String laden kann, oder? Ich möchte es aber ohne ein neuladen der Seite machen. Der rest leuchtet mir ja ein, aber der Link geht ja auf eine # (
    <a href="#">
    ) und ruft somit keine neue Seite auf.
    MFG THWBM
  11. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Du musst die Seite nicht neu laden um an den neuen String zu kommen, dafür hast du doch AJAX. Bis jetzt schickst du nur eine Anfrage an den Server, verwirfst aber die Antwort. Wenn du mit PHP den String auf dieser Seite ausgibst (update.php) bekommst du ihn direkt in deinem AJAX-Request zurück…

    Ich hab das hier vor einiger Zeit schon einmal erklärt, eventuell hilft dir das weiter: *klick*
  12. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Habe ich das jetzt richtig verstanden? Ich ergänze den Link so:
    <a onclick="datenbankupdate('?ID=I1&Sicherheitscode=XYZ')" href="#">//XYZ ist jetzt mal der zufällige String den ich aus der Session geladen habe
      Datenbank updaten
    </a>

    Dann frage ich in der Update.php ab, ob die Variabel "Sicherheitscode" den gleichen Wert enthält wie den, den ich in der MySQL Datenbank abgespeichert habe. So weit müsste das funktionieren, aber wenn ich für die nächste Aktion dann widerum einen anderen Code benutze, dann muss ich den ja nicht nur in der Datenbank, sondern auch in der Session ändern. Hab ich das so richtig verstanden oder nicht?
    MFG THWBM
  13. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Dann mal eine fertige Lösung, aber du solltest sie dir genau ansehen damit du sie auch verstehst.

    auth.php:
    <?php
    
    session_start();
    
    function generateRandomString($length) {
    	$alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    	$alphabet .= strtolower($alphabet) . '0123456789';
    	$string = '';
    	for($i = 0; $i < $length; $i++)
    		$string .= $alphabet[rand(0, strlen($alphabet))];
    	return $string;
    }
    
    function generateAuthToken() {
    	$token = generateRandomString(32);
    	$_SESSION['token'] = $token;
    	return $token;
    }
    
    function validateAuthToken($token) {
    	return $_SESSION['token'] == $token;
    }
    
    function hasAuthToken() {
    	return isset($_SESSION['token']);
    }
    
    ?>


    update.php:
    <?php
    
    include('auth.php');
    
    header('content-type: text/plain');
    $token = $_GET['token'];
    
    // im Fehlerfall einen neuen Token erstellen
    if($token == 'ERR') {
    	echo(generateAuthToken());
    	exit();
    }
    
    // gibt es überhaupt einen Auth-Token?
    if(!hasAuthToken())
    	die('ERR');
    
    // stimmt der Auth-Token?
    if(validateAuthToken($token)) {
    	// neuen Auth-Token erstellen
    	$token = generateAuthToken();
    	echo($token);
    
    	// mach deine Aktion
    	$id = $_GET['ID'];
    	// hier kannst du die DB updaten
    
    	exit();
    } else {
    	die('ERR');
    }
    
    ?>

    index.php:
    <?php
    
    include('auth.php');
    
    // Auth-Token zum 1. Mal erstellen
    $token = generateAuthToken();
    
    ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    	<head>
    		<title>Sicherheit mit AJAX</title>
    		<script type="text/javascript"><!--
    			var authtoken = '<?php echo($token); ?>'; // hier wird der Auth-Token gespeichert
    
    			function createXMLHttpRequest() {
    				if(window.XMLHttpRequest) {
    					// code for IE7+, Firefox, Chrome, Opera, Safari
    					return new XMLHttpRequest();
    					} else {
    					// code for IE6, IE5
    					return new ActiveXObject("Microsoft.XMLHTTP");
    				}
    			}
    
    			function datenbankupdate(data) {
    				var request = createXMLHttpRequest();
    				request.open('GET', 'update.php' + data, false);
    				request.send(); // Anfrage senden
    
    				// speicher den neuen Auth-Token
    				authtoken = request.responseText;
    				if(authtoken == 'ERR')
    					alert('Es trat ein Fehler auf. Session abgelaufen?\nVersuch es erneut!');
    			}
    		// --></script>
    	</head>
    	<body>
    		<p><a onclick="datenbankupdate('?ID=123&amp;token=' + authtoken)" href="#">Datenbank updaten</a></p>
    	</body>
    </html>


    Funktionsweise habe ich schon erklärt, MySQL braucht es hier nicht ;-)
  14. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    Wow, danke! Ich glaube damit kann ich was anfangen. Ich habe nur noch ein Problem:
    Warum dieses
    $string .= $alphabet[rand(0, strlen($alphabet))];
    in der auth.php in Zeile 10? Warum nicht einfach
    $string .= mt_rand(0, 62);
    ? Zumal ich bei der von dir vorgeschlagenen Variante manchmal so ganz spontan diesen Fehler hier bekomme:
    Notice: Uninitialized string offset: 62 in ...\auth.php on line 10
    . Warum? Mache ich etwas falsch?
    MFG THWBM
  15. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Wie du diesen String erstellst ist völlig egal… er sollte nur irgendwelche unsinnigen Zahlen und Buchstaben haben.

    thwbm schrieb:
    Warum dieses
    $string .= $alphabet[rand(0, strlen($alphabet))];
    in der auth.php in Zeile 10? Warum nicht einfach
    $string .= mt_rand(0, 62);
    ?
    Hat den Grund, dass mt_rand nur Zahlen zurückgibt und mit dieser Variante alle in
    $alphabet
    enthaltenen Zeichen für den String verwendet werden.

    Zum "Fehler": das ist, weil ich unglücklicherweise auf meinem Server Fehlermeldungen deaktiviert habe, und deshalb ist mir das nicht aufgefallen. Um das zu beheben musst du einfach ein
    -1
    anhängen, also so:
    $string .= $alphabet[rand(0, strlen($alphabet) - 1)];

    Du machst also nichts falsch ;-)

    Beitrag zuletzt geändert: 3.10.2012 20:18:08 von hackyourlife
  16. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    hackyourlife schrieb:
    Hat den Grund, dass mt_rand nur Zahlen zurückgibt und mit dieser Variante alle in
    $alphabet
    enthaltenen Zeichen für den String verwendet werden.

    Aber strlen gibt doch nur die Anzahl der Zeichen zurück, also A-Z + a-z + 1-9 = 62. Deshalb habe ich auch die Zahlen 0 und 62 bei dem Zufallsgenerator verwendet. Stimmt mein Gedankengang oder liege ich da falsch?
    MFG THWBM
  17. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    thwbm schrieb:
    hackyourlife schrieb:
    Hat den Grund, dass mt_rand nur Zahlen zurückgibt und mit dieser Variante alle in
    $alphabet
    enthaltenen Zeichen für den String verwendet werden.

    Aber strlen gibt doch nur die Anzahl der Zeichen zurück, also A-Z + a-z + 1-9 = 62. Deshalb habe ich auch die Zahlen 0 und 62 bei dem Zufallsgenerator verwendet. Stimmt mein Gedankengang oder liege ich da falsch?
    Mit diesem Gedankengang bist du so lange richtig, wie folgender Code dabei herauskommt:
    $string .= $alphabet[rand(0, 62 - 1)];
    Und das enspricht
    $string .= $alphabet[rand(0, 61)];
    Grund:
    rand()
    (oder
    mt_rand()
    ) erwartet als Parameter den kleinsten und den größten Wert. Da ein Array-Index aber die Werte 0 - (Arraylänge - 1) haben kann braucht es das -1, da
    strlen()
    die Anzahl der Elemente zurückgibt.
  18. Autor dieses Themas

    thwbm

    thwbm hat kostenlosen Webspace.

    hackyourlife schrieb:
    Grund:
    rand()
    (oder
    mt_rand()
    ) erwartet als Parameter den kleinsten und den größten Wert.

    Ja, deswegen frage ich mich ja, warum ich mir einen String nehmen soll, der immer 62 Zeichen hat, dann die länge ermittele und von der Länge dann 1 Abziehen soll und ich nicht einfach die Zahl 61 nehmen kann. Bedeutet diese Zeile:
    $string .= $alphabet[rand(0, 62 - 1)];

    jetzt etwa, dass er sich ein zufälliges Zeichen aus dem String $alphabet nehmen soll, wobei das Zeichen das erste Zeichen, aber auch das 62ste oder auch eins dazwischen sein kann? Wenn ja, hatte ich bisher einen Verständnisfehler.
    MFG THWBM
  19. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    thwbm schrieb:
    Bedeutet diese Zeile:
    $string .= $alphabet[rand(0, 62 - 1)];

    jetzt etwa, dass er sich ein zufälliges Zeichen aus dem String $alphabet nehmen soll, wobei das Zeichen das erste Zeichen, aber auch das 62ste oder auch eins dazwischen sein kann?
    Ja, genau das bedeutet es ;-)
  20. h**s

    hi,

    auch mit session und authcode bist du nicht auf der sicheren seite... schließlich sind beide vor einer aktion im browser verfügbar - es ist also kein problem den sessioncode und auch fortlaufend zurückgegebene authcodes für automatisierte anfragen zu benutzen/missbrauchen.

    ich denke die einzig wahre sache wäre wirklich bei jedem aufruf serverseitig zu prüfen ob die aktion auch erlaubt ist (z.b. beim kaufen: ist der gegenstand verfügbar ? hat der user genug geld ? etc...)
  21. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    hcms schrieb:
    auch mit session und authcode bist du nicht auf der sicheren seite... schließlich sind beide vor einer aktion im browser verfügbar - es ist also kein problem den sessioncode und auch fortlaufend zurückgegebene authcodes für automatisierte anfragen zu benutzen/missbrauchen.
    Hast du das Szenario verstanden? Es geht darum, dass der User eingeloggt ist und auf eine dritte Seite surft, die versucht die DB (des "Spieles") zu manipulieren…

    Und wie kommt durch den Auth-Code die Sicherheit?

    Ohne Auth-Code: Der Benuzter loggt sich ein und bekommt eine Session. Wenn er nun eingeloggt ist und auf einer anderen Seite einem Link folgt der irgend eine Aktion in der DB ausführt wird diese Aktion auch ausgeführt, da der User ja auf der echten Seite eingeloggt ist.

    Mit Auth-Code: Der Benutzer ist eingeloggt. Die "böse" Seite will ihn ebenfalls dazu bringen eine Aktion in der DB auszuführen, was aber nicht möglich ist, da die Angreiferseite den Auth-Code nicht kennt und ihn auch nicht erfragen kann, da sie die Session ebenfalls nicht hat. Warum braucht dann die Seite im 1. Beispiel die Session nicht? Weil der Link alleine reicht (da er immer gleich ist) und der Browser die Session von der echten Seite kennt.

    hcms schrieb:
    ich denke die einzig wahre sache wäre wirklich bei jedem aufruf serverseitig zu prüfen ob die aktion auch erlaubt ist (z.b. beim kaufen: ist der gegenstand verfügbar ? hat der user genug geld ? etc...)
    Was aber das hier besprochene Angriffsszenario nicht verhindert. Natürlich muss es dieses System ebenfalls geben, denn sonst kann der User selbst cheaten! Beides schützt aber nicht vor einem Bot, falls du das meinst…
  22. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!