it-swarm.com.de

So senden Sie sicher AJAX Anfragen mit PHP und jQuery

Das Problem

Seit einiger Zeit experimentiere ich also mit verschiedenen AJAX Ansätzen beim Senden von Daten an einen Server, der verarbeitet und in einer MySQL-Datenbank gespeichert wird. 

Die Seite, die die AJAX -Anforderung auf api.php trifft, verwendet die vorbereiteten PDO-Anweisungen von PHP zum Speichern der Daten. Daher sind MySQL-Injektionen kein Problem, und die Kennwörter oder Daten, die verschlüsselt werden müssen, werden auch von api.php verarbeitet, das nicht angegeben ist. Was ich hier frage. Meine Frage bezieht sich mehr darauf, wie sichergestellt werden kann, dass die Daten sicher sind, wenn sie vom Client zum Server übertragen werden.

Die Ansätze

Ich habe derzeit (für das Anmeldebeispiel, das ich unten aufgeführt habe):

  • SSL Cert/HTTPS, das in der Domäne ausgeführt wird.
  • Bestimmte AJAX - Anforderungen (offensichtlich nicht dieses Anmeldeanforderungsbeispiel, da keine Sitzung vorhanden ist) funktionieren nur, wenn die PHP -Sitzung auf der gesamten Site gültig ist (in diesem Beispiel für login.php und api.php verwendet). .
  • Ratenbegrenzung für api.php beim Zugriff auf Funktionen.
  • PHP PDO-Anweisungen für die Interaktion mit der Datenbank in api.php.
  • Verschlüsselt sensible Daten in api.php (für die Frage nicht relevant).

Die Fragen

Zum Schluss sind meine Fragen:

  1. Ist dieser Ansatz zur Verwendung von asynchronen HTTP (Ajax) -Anfragen sicher genug, um Daten zu verwenden, anstatt nur Daten an eine PHP -Seite zu senden und weiterzuleiten? (Dadurch wird die Benutzererfahrung verbessert).
  2. Wie kann ich überprüfen, ob die Daten, die mein Benutzer sendet, nicht manipuliert wurden?
  3. Mache ich vernünftigerweise genug, um die Daten meines Benutzers zu schützen, wenn nicht, was kann ich sonst tun?

Das Beispiel

Ich verstehe, dass jeder unterschiedliche Ansätze für den Umgang mit den Daten ihrer Website und den Transport dieser Daten hat. Ich verstehe auch, dass Sie, egal was Sie tun, niemals zu 100% geschützt sein können, da es Schwachstellen und Wege in Ihrem System gibt, die Sie nicht berücksichtigen können. Ich bin auf der Suche nach Rückmeldungen/Verbesserungen bezüglich meines generellen Ansatzes beim sicheren Senden von Daten und nicht nach Kritik am spezifischen Code, da dies nur ein Beispiel ist. Aber konstruktive Antworten sind willkommen. Vielen Dank, dass Sie sich die Zeit zum Lesen/Antworten genommen haben.

function loginUser() {
    var process = "loginUser";
    var data = $("form").serializeArray();
    data[1].value = SHA512(data[1].value); // sha then encrypt on api.php page 
    data = JSON.stringify(data);

    $("#loginButton").html('<i class="fa fa-spinner fa-Pulse fa-lg fa-fw"></i> Login');
    $.ajax({
        type: "POST",
        url: "api.php",
        data: {"process": process, "data": data},
        success: function(data) {
            if (data.response.state == "success") {
                // if api.php returns success, redirect to homepage
            } else {
                // if api.php returns failure, display error
            }  
        },
        error: function(jqXHR, textStatus, errorThrown, data) {
            // error handling
        },
        dataType: "json"
    });
}
24
LukeXF

1. Überprüfen Sie den Origin-Header

Als von OWASP angegeben ist dies nicht genug, wird jedoch empfohlen:

Es ist zwar trivial, jeden Header von Ihrem eigenen Browser aus zu fälschen. Dies ist jedoch im Allgemeinen bei CSRF-Angriffen nicht möglich, außer durch eine XSS-Sicherheitsanfälligkeit. Aus diesem Grund ist das Überprüfen von Kopfzeilen ein vernünftiger erster Schritt in Ihrer CSRF-Verteidigung. Da sie jedoch nicht immer vorhanden sind, wird sie im Allgemeinen nicht als ausreichende Verteidigung für sich betrachtet.

Und von Mozilla :

Der Origin-Header wird als hilfreich bei JSON-Datendiebstahl und CSRF-Angriffen betrachtet. Die von Origin bereitgestellten Informationen - ein paar kontextabhängige Anforderungserstellungsinformationen - sollten Web-Servern Hinweise auf die Vertrauenswürdigkeit von Anforderungen geben. [...]

Die Überprüfung des HTTP_Origin-Headers könnte folgendermaßen geschrieben werden:

header('Content-Type: application/json');

if (isset($_SERVER['HTTP_Origin'])) {
    $address = 'http://' . $_SERVER['SERVER_NAME'];
    if (strpos($address, $_SERVER['HTTP_Origin']) !== 0) {
        exit(json_encode([
            'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_Origin']
        ]));
    }
} else {
    exit(json_encode(['error' => 'No Origin header']));
}

1. (bis) Überprüfen Sie den REFERER-Header

Wieder aus OWASP :

Wenn der Origin-Header nicht vorhanden ist, überprüfen Sie, ob der Hostname im Referer-Header mit dem Origin der Site übereinstimmt. Die Überprüfung des Referers ist eine häufig verwendete Methode, um CSRF auf eingebetteten Netzwerkgeräten zu verhindern, da für jeden Benutzer kein Status erforderlich ist. Diese CSRF-Minderungsmethode wird auch häufig bei nicht authentifizierten Anforderungen verwendet. [...]

Die Überprüfung von HTTP_REFERER ist auch in PHP mit $_SERVER['HTTP_REFERER'] recht einfach. Sie können den obigen Code einfach aktualisieren.


BE CAREFUL mit der Prüfung, die immer wirklich genau sein muss: Keine Prüfung nur example.com oder api.example.com, aber die vollständige HTTPS: //) EXAMPLE.COM. Warum ? Sie könnten diese Prüfung mit einem Origin wie api.example.com.hacker.com fälschen.


2. CSRF-Token generieren

Ein gut erklärtes spezifische Antwort auf PHP wurde dort gegeben) , kurz:

  1. Generiere das Token:

    session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    
  2. Fügen Sie es in Ihren generierten Ansichten über eine Meta (wie Github) hinzu:

    <meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
    
  3. Richten Sie jQuery-Ajax-Aufrufe ein, um dieses Token aufzunehmen:

    $.ajaxSetup({
        headers : {
            'CsrfToken': $('meta[name="csrf-token"]').attr('content')
        }
    });
    
  4. Überprüfen Sie serverseitig Ihre AJAX -Anfragen:

    session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    
    header('Content-Type: application/json');
    
    $headers = Apache_request_headers();
    if (isset($headers['CsrfToken'])) {
        if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) {
            exit(json_encode(['error' => 'Wrong CSRF token.']));
        }
    } else {
        exit(json_encode(['error' => 'No CSRF token.']));
    }
    

Die meisten PHP - Frameworks verfügen über eine eigene CSRF-Implementierung, die mehr oder weniger auf demselben Prinzip basiert.


3. Desinfizieren Benutzereingabe überprüfen.

Sie müssen immer filter espace input und validieren Sie diese .


4. Schützen Sie Ihren Server


5. Niemals einer Benutzereingabe trauen

Wie @ blue112 sagte, es ist eines der elementarsten Sicherheitsgrundsätze .

enter image description here

50
Ivan Gabriele

Kurze Antwort: Sie können Ihre Kundenseite nicht schützen.

Lange Antwort:

  • Die Verwendung von AJAX ist genauso sicher wie das Buchen von Daten beispielsweise mit einem Formular.
  • Die Verwendung von HTTPS verhindert, dass Man-in-the-Middle Ihre Benutzerdaten sieht, sodass die vom Benutzer gesendeten tatsächlichen Daten sicher sind.

Sie können nichts tun, um den Browser zu beweisen, dass es tatsächlich Ihr Javascript-Code ist, der auf der Clientseite ausgeführt wird ... Dann ist die naheliegendste Maßnahme die einfachste: NIE VERTRAUEN SIE USER INPUT.

Dies bedeutet, dass Sie wie zu Beginn Ihre Serverseite mithilfe von Sitzung, Ratenbegrenzung, Datenvalidierung, fail2ban (Verbot einer Client-IP nach einer bestimmten Anzahl von Fehlern), Protokollüberwachung ... gesichert haben.

1
blue112

der beste Weg ist immer noch die serverseitige Sicherung. Wenn ich ein angemeldeter Benutzer auf der Site wäre, wäre ich auch in der Lage, das csrf-Token auf meinem Meta-Tag zu überprüfen und ein Skript an den Server zu fälschen. Die sichere Wette ist also die serverseitige Validierung