[gelöst] SQL-Injection

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [gelöst] SQL-Injection

    Moin!

    Zur Zeit beschäftige ich mich wieder intensiv mit einigen Teilbereichen von (My)SQL, um mein Wissen bezüglich Sicherheit zu verbessern. Ich habe mir nämlich vorgenommen, mir die kleinen oder eventuell auch großen Sicherheitslücken meines (noch nicht online gestellten Projektes), die durch SQL-Injection entstehen können einmal genauer unter die Lupe zu nehmen. Man muss seine Feinde ja kennen, um ihnen vorbereitet gegenübertreten zu können.


    Alo hab ich mir ein kleines Script geschrieben, um die billigste aller SQL-Injections zu testen und auch einzelne andere Fälle mal zu beleuchten und durchzugehen.

    Wer mir helfen möchte, aber selbst testen will kann sich ganz schnell die benötigte Datenbank mit diesem SQL anlegen:


    Code:
    CREATE DATABASE IF NOT EXISTS sql_injection_check;
    
    USE sql_injection_check;
    
    CREATE TABLE IF NOT EXISTS users (
    id INT(6) unsigned auto_increment,
    username VARCHAR(24) NOT NULL DEFAULT '',
    password VARCHAR(40) NOT NULL DEFAULT '',
    privatedata VARCHAR(100) NOT NULL DEFAULT '',
    PRIMARY KEY(id));
    
    INSERT INTO users (username, password, privatedata) VALUES
    ('Someone', SHA1('abc'), 'Gestern ne Flasche Schnaps geklaut'),
    ('Someoneelse', SHA1('123'), 'Heute ordentlich die Putze vernascht');
    Mit diesem absichtlich primitiven Script habe ich mir das Testen vorgenommen:

    PHP-Code:
    <?php

        
    if (get_magic_quotes_gpc()) {
            
    $_POST array_map("stripslashes"$_POST);
            
    $_GET array_map("stripslashes"$_GET);
            
    $_COOKIE array_map("stripslashes"$_COOKIE);
        }


        if(!isset(
    $_POST['submit'])) {

    ?>

    <form action="hacking_test.php" method="post">
        <p>
            <label for="username">Username: </label>
            <input type="text" name="username" id="username" />
        </p>
        <p>
            <label for="password">Password: </label>
            <input type="password" name="password" id="password" />
        </p>
        <p>
            <input type="submit" name="submit" value="Submit" />
        </p>
    </form>


    <?php

        
    } else {

            if(isset(
    $_POST['username'], $_POST['password'])) {

                
    $username $_POST['username'];
                
    $password $_POST['password'];

                
    $link mysql_connect("localhost""root""")
                  OR die(
    "<p>Database connection could not be established.</p>\n");

                
    mysql_select_db("sql_injection_check"$link)
                  OR die(
    mysql_error("<p>Database could not be selected.</p>\n"));

                
    $sql "SELECT
                          COUNT(*) AS count
                        FROM
                          users
                        WHERE
                          username = '" 
    $username "'
                        AND
                          password = SHA1('" 
    $password "')";

                
    $result mysql_query($sql$link) OR die("<p>Bad query.</p>\n");

                while(
    $row mysql_fetch_assoc($result)) {

                    if(
    $row['count'] !== '0') {

                        echo 
    "<p>Welcome " $username ", you are logged in.</p>\n";

                    } else {

                        echo 
    "<p>Wrong password and/or username</p>\n";

                    }

                }

            }

        }

    ?>
    Um die magic_quotes_gpc kümmert sich die erste Abfrage, somit habe ich keine "störenden" Slashes in den $_POST-Variablen.

    Das Wichtigste ist ja nun der Query und wie die $_POST-Variablen behandelt oder eben nicht behandelt werden.


    Query:
    Code:
    SELECT
        COUNT(*) AS count
    FROM
        users
    WHERE
        username = '" . $username . "'
    AND
        password = SHA1('" . $password . "');
    Die billigste Methode ist jetzt wahrscheinlich, die Abfrage durch ein OR so zu zu relativieren, dass die "count" immer mindestens 1, also TRUE ist.

    Wenn ich jetzt in das Formular "bla" als Namen und "irgendwas' OR '1'='1" (ohne doppelte Anführungszeichen) eingebe, so sollte der Query doch zu:

    Code:
    SELECT
        COUNT(*) AS count
    FROM
        users
    WHERE
        username = 'bla'
    AND
        password = SHA1('irgendwas')
    OR 
        '1'='1';
    werden und folglich zumindest eine Zahl liefern, die höher ist als 0, womit wiederum die Abfrage im Script vernalassen müsste, dass: "Welcome bla, you are logged in." ausgegeben wird.

    Stutzig macht mich, dass ich, obschon ich versuche, mein eigenes Script zu "hacken", keinen Erfolg habe, wobei es andere auf anderen Seiten leider immer wieder ohne Probleme hinbekommen.

    Ohne ein Beispiel, wie man es denn wirklich nicht machen wollte, kann ich mir allerdings auch keine Gedanken zu einer Gegenmaßahem machen.

    Was mache ich also falsch, bzw richtig? ;-)
    Zuletzt geändert von Jester_Prince; 19.09.2009, 17:36.

    1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
    2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen


  • #2
    Hi,

    so kompliziert ist es gar nicht. Du musst nur beachten, dass alle Nutzereingaben, die in SQL Statements verwurstet werden, mit mysql_real_escape_string behandelt werden.

    Gruß,

    Amica
    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
    Super, danke!
    [/COLOR]

    Kommentar


    • #3
      mysql_real_escape_string()

      Kommentar


      • #4
        @AmicaNoctis: Danke für deine Antwort. Aber das beantwortet leider nicht meine Frage.

        @onemorenerd: Wie man mysql_real_escape_string() anwendet und wofür dies gut ist, weiß ich längst. Ein paar Seiten im Manual finde ich auch noch selbst. Da soll keine Kritik sein, aber manchamal frage ich mich, ob auch jeder Mod die Frage-posts liest, bevor er sie kommentarlos mit Links zu Seiten im PHP Manual bedenkt, die jeder wirklich PHP Lernwillige bereits auf Englisch und Deutsch gelesen hat. Aber nichts für ungut.


        Mein Versuch bezog sich auf das kontrollierte Testen von SQL-Injections in einem eigenen, möglichst unsicheren Script.

        Damit, dass das von mir gepostete Script unsicher ist, wird wohl jeder einverstanden sein, der sich mehr als zwei Wochen mit PHP/MySQL beschäftigt. Dennoch sehe ich nicht, dass die SQL-Injection (wie zum Beispiel auch auf der erlinkten Seite gezeigt) in meinem Script funktioniert.

        Ich möchte den Grund dafür erfahren. Das würde massiv zu meinem Verständnis der Materie beitragen, deswegen wäre ich Euch dankbar, wenn ihr mir diesbezüglich helfen könntet.
        Zuletzt geändert von Jester_Prince; 20.09.2009, 10:55.

        1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
        2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

        Kommentar


        • #5
          Debuggen. Lass die das SQL-Query ausgeben und probier es selber in der Datenbank aus.

          Warum schreibst du eigentlich Zahlenwerte in Hochkomma? Dann muss ja MySQL erst wieder den String in einen Zahlenwert konvertieren.

          Außerdem ist das COUNT(*) unnötig. Die Anzahl kann doch eh nur 0 oder 1 sein, oder? Wozu willst du dann MySQL unnötig die Tabelle durchsuchen und zählen lassen? Ist jetzt kein wirklich Fehler, aber es ist etwas unschön.
          Zuletzt geändert von h3ll; 20.09.2009, 10:38.

          Kommentar


          • #6
            Guten Morgen,

            du willst also ein konkretes Injection-Beispiel?:

            username: bla
            passwort: ') or ('1'='1

            Gruß,

            Amica
            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
            Super, danke!
            [/COLOR]

            Kommentar


            • #7
              Zitat von h3ll Beitrag anzeigen
              Debuggen. Lass die das SQL-Query ausgeben und probier es selber in der Datenbank aus.
              Das habe ich getan. Eigenartig fand ich einfach, dass:
              Code:
              SELECT
                  COUNT(*) AS count
              FROM
                  users
              WHERE
                  username = 'bla'
              AND
                  password = SHA1('irgendwas')
              OR 
                  '1'='1';
              zwar in phpMyAdmin funktionierte, aber nicht über mein Script.

              Zitat von h3ll Beitrag anzeigen
              Warum schreibst du eigentlich Zahlenwerte in Hochkomma? Dann muss ja MySQL erst wieder den String in einen Zahlenwert konvertieren.
              Stimmt, das sollte ich tatsächlich noch einmal überdenken. Danke für den Denkanstoß!

              Zitat von h3ll Beitrag anzeigen
              Außerdem ist das COUNT(*) unnötig. Die Anzahl kann doch eh nur 0 oder 1 sein, oder? Wozu willst du dann MySQL unnötig die Tabelle durchsuchen und zählen lassen? Ist jetzt kein wirklich Fehler, aber es ist etwas unschön.
              Da bin ich mir jetzt nicht ganz sicher, aber auch das werde ich austesten. Danke auch hierfür.

              1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
              2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

              Kommentar


              • #8
                Zitat von AmicaNoctis Beitrag anzeigen
                Guten Morgen,

                du willst also ein konkretes Injection-Beispiel?:

                username: bla
                passwort: ') or ('1'='1

                Gruß,

                Amica
                Nachtrag: Und Dir natürlich ebenfalls einen guten Morgen!

                Aha, danke! So funktioniert es tatsächlich. Nur frage ich mich, warum, denn Klammern habe ich doch gar nicht in meinem Query, und über phpMyAdmin funktioniert es doch auch. Das hilft mir jedenfalls erst einmal weiter, denn nun weiß ich wieder etwas besser, worauf ich achten muss.
                Zuletzt geändert von Jester_Prince; 20.09.2009, 10:57.

                1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
                2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

                Kommentar


                • #9
                  Zitat von Jester_Prince Beitrag anzeigen
                  zwar in phpMyAdmin funktionierte, aber nicht über mein Script.
                  Du hast es falsch eingesetzt, wegen der rechten Klammer von SHA1, siehe Beispiel

                  Zitat von Jester_Prince Beitrag anzeigen
                  Aha, danke! So funktioniert es tatsächlich. Nur frage ich mich, warum, denn Klammern habe ich doch gar nicht in meinem Query
                  Doch, hast du: die von SHA1

                  Zitat von Jester_Prince Beitrag anzeigen
                  nun weiß ich wieder etwas besser, worauf ich achten muss.
                  Eigentlich auf nichts außer mysql_real_escape_string, aber das sagte ich ja schon. Das alleine verhindert SQL Injections schon. Dass du das Prinzip verstehen willst, ist völlig OK, aber sonst gibt es eigentlich nichts zu beachten, solange du Nutzereingaben als literale Werte benutzt und nicht etwa als Tabellen- oder Spaltenreferenzen.
                  Zuletzt geändert von AmicaNoctis; 20.09.2009, 10:58.
                  [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                  Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                  Super, danke!
                  [/COLOR]

                  Kommentar


                  • #10
                    Jetzt habe ich meinen Fehler verstanden!

                    Wenn ich das Passwort ohne Verschlüsselung abgefragt hätte, dann hätte irgendwas' OR '1'='1 zum Erfolg geführt.

                    Da ich aber das Passwort als $passwort in SHA1(' ... ') einsetze, muss ich natürlich die erste Klammer wieder schließen, bevor ich etwas weiteres einfügen kann, ohne dass es ein Syntaxfehler ist oder die Eingabe tatsächlich verschlüsselt wird. Das gleiche gilt natürlich auch für die zweite Klammer.

                    Danke, Amica. Du hast mir den nötigen Denkanstoß zu einem weiteren Kapitel in Sachen Sicherheit gegeben.

                    1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
                    2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

                    Kommentar


                    • #11
                      SHA ist keine Verschlüsselung.

                      Kommentar


                      • #12
                        Zitat von h3ll Beitrag anzeigen
                        SHA ist keine Verschlüsselung.
                        Ich bitte vielmals um Entschuldigung, Asche auf mein Haupt, möge er mir nur verzeigen, dass ich Unwürdiger, den Secure Hash Algorithm in beinahe obszöner, doch zumindest vulgärer Art lediglich als "Verschlüsselung" bezeichnet habe. Natürlich hast du Recht, es ist nur eine kryptologische Hash-Funktion und keine Verschlüsselung...

                        Meine Güte, manche Leute übertreiben es wirklich mit der Besserwisserei.

                        1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
                        2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

                        Kommentar


                        • #13
                          Das wäre genauso, als würdest du in einem Backrezept Salz statt Zucker schreiben. Das ist ein gravierender Unterschied.

                          Kommentar


                          • #14
                            Zitat von Jester_Prince Beitrag anzeigen
                            Meine Güte, manche Leute übertreiben es wirklich mit der Besserwisserei.
                            Und manche mit der Genervtheit, die sie bei solchen Hinweisen an den Tag legen.


                            Wenn du hier schon einen Thread mit einer Fragestellung dieser Qualität aufmachst - dann bleib bitte wenigstens mal ein bisschen locker, wenn du Hinweise erhältst, an welchen Stellen es sich lohnen könnte, genauer zu differenzieren. Wenn sie schon was dich angeht keine Wirkung haben, dann sind vielleicht andere Mitleser trotzdem daran interessiert.
                            I don't believe in rebirth. Actually, I never did in my whole lives.

                            Kommentar


                            • #15
                              Zitat von h3ll Beitrag anzeigen
                              Das wäre genauso, als würdest du in einem Backrezept Salz statt Zucker schreiben. Das ist ein gravierender Unterschied.
                              Der Vergleich hinkt sehr stark und war auch für die Problemlösung nicht relevant.

                              1. Ja, ich habe die entsprechenden Einträge im Manual gelesen. Google habe ich auch benutzt. Das mache ich immer zuerst, wenn ich eine Frage habe, denn ich habe zu Glück das selbstständige Denken gelernt, sonst würde ich nicht fragen
                              2. Ja, ich besitze den erstzunehmenden Ehrgeiz, die Dinge, nach denen ich frage, auch zu begreifen und/oder begreifen zu lernen, sonst würde ich nicht fragen

                              Kommentar

                              Lädt...
                              X