it-swarm.com.de

Verhindern gespeicherte Prozeduren die SQL-Injection?

Stimmt es, dass gespeicherte Prozeduren SQL-Injection-Angriffe auf PostgreSQL-Datenbanken verhindern? Ich habe ein wenig recherchiert und festgestellt, dass SQL Server, Oracle und MySQL nicht gegen SQL-Injection sicher sind, selbst wenn wir nur gespeicherte Prozeduren verwenden. Dieses Problem besteht jedoch nicht in PostgreSQL.

Verhindert die Implementierung gespeicherter Prozeduren im PostgreSQL-Kern SQL-Injection-Angriffe oder ist es etwas anderes? Oder ist PostgreSQL auch anfällig für SQL-Injection, selbst wenn wir nur gespeicherte Prozeduren verwenden? Wenn ja, zeigen Sie mir bitte ein Beispiel (z. B. Buch, Website, Papier usw.).

84
Am1rr3zA

Nein, gespeicherte Prozeduren verhindern die SQL-Injection nicht. Hier ist ein aktuelles Beispiel (aus einer internen App, die jemand dort erstellt hat, wo ich arbeite) einer gespeicherten Prozedur, die leider eine SQL-Injection zulässt:

Dieser SQL Server-Code:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO

ungefähr gleichbedeutend mit Postgres:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;

Die Idee des Entwicklers war es, ein vielseitiges Suchverfahren zu erstellen. Das Ergebnis ist jedoch, dass die WHERE-Klausel alles enthalten kann, was der Benutzer möchte, sodass ein Besuch von kleine Bobby-Tabellen möglich ist.

Ob Sie SQL-Anweisungen oder gespeicherte Prozeduren verwenden, spielt keine Rolle. Entscheidend ist, ob Ihr SQL Parameter oder verkettete Zeichenfolgen verwendet. Parameter verhindern die SQL-Injection. verkettete Zeichenfolgen ermöglichen die SQL-Injection.

71
Kyralessa

SQL-Injection-Angriffe sind solche, bei denen nicht vertrauenswürdige Eingaben direkt an Abfragen angehängt werden, sodass der Benutzer beliebigen Code effektiv ausführen kann, wie in diesem kanonischen XKCD-Comic. dargestellt

So bekommen wir die Situation:

 userInput = getFromHTML # "Robert ') Tabellenschüler löschen; -" 
 
 Query = "Wählen Sie * aus Schülern aus, bei denen studentName =" + userInput 

Gespeicherte Prozeduren sind im Allgemeinen eine gute Verteidigung gegen SQL-Injection-Angriffe , da die eingehenden Parameter niemals analysiert werden.

In einer gespeicherten Prozedur sehen in den meisten DBs (und Programmen nicht zu vergessen, dass vorkompilierte Abfragen als gespeicherte Prozeduren gelten) wie folgt aus:

 
 
 Gespeicherte Prozedur foo erstellen (
 Wählen Sie * aus den Schülern aus, bei denen studentName =: 1 
); 
 

Wenn das Programm dann Zugriff wünscht, ruft es foo(userInput) auf und ruft das Ergebnis glücklich ab.

Eine gespeicherte Prozedur ist keine magische Verteidigung gegen SQL-Injection, da die Leute durchaus in der Lage sind, schlechte gespeicherte Prozeduren zu schreiben. Vorkompilierte Abfragen, ob in der Datenbank oder im Programm gespeichert, sind jedoch viel schwieriger, Sicherheitslücken in zu öffnen, wenn Sie verstehen, wie SQL-Injection funktioniert.

Sie können mehr über SQL-Injection lesen:

46

Ja, bis zu einem gewissen Grad.
Gespeicherte Prozeduren allein verhindern SQL Injection nicht.

Lassen Sie mich zunächst über --- Injection aus OWASP zitieren

Ein SQL-Injection-Angriff besteht aus dem Einfügen oder "Injection" einer SQL-Abfrage über die Eingabedaten vom Client in die Anwendung. Ein erfolgreicher SQL-Injection-Exploit kann vertrauliche Daten aus der Datenbank lesen, Datenbankdaten ändern (Einfügen/Aktualisieren/Löschen), Verwaltungsvorgänge für die Datenbank ausführen (z. B. das DBMS herunterfahren) und den Inhalt einer bestimmten Datei in der DBMS-Datei wiederherstellen System und in einigen Fällen Befehle an das Betriebssystem ausgeben. SQL-Injection-Angriffe sind eine Art von Injection-Attacken, bei denen SQL-Befehle in die Eingabe auf Datenebene injiziert werden, um die Ausführung vordefinierter SQL-Befehle zu bewirken.

Sie müssen Benutzereingaben bereinigen und SQL-Anweisungen nicht verketten, selbst wenn Sie eine gespeicherte Prozedur verwenden.

Jeff Attwood erklärte die Konsequenzen der Verkettung von SQL in " Gib mir parametrisiertes SQL oder gib mir den Tod "

Das Folgende ist der interessante Cartoon, der mir einfällt, wenn ich SQL Injection höre alt text Ich denke du hast den Punkt verstanden :-)

Werfen Sie einen Blick auf SQL Injection Prevention Cheat Sheet , Präventionsmethoden werden übersichtlich erklärt ...

29
CoderHawk

Die Verkettung von Zeichenfolgen ist die Ursache für SQL Injection. Dies wird durch Parametrisierung vermieden.

Gespeicherte Prozeduren bieten eine zusätzliche Sicherheitsebene, indem sie beim Verketten eine ungültige Syntax erzwingen. Sie sind jedoch nicht "sicherer", wenn Sie beispielsweise dynamisches SQL verwenden.

Ihr obiger Code wird also durch Verkettung dieser Zeichenfolgen verursacht

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

Dies ergibt eine ungültige Syntax, zum Glück

Parametrisierung würde es geben

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'

Das heisst

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

Im obigen Code erhalten Sie keine Zeilen, da ich davon ausgehe, dass Sie keinen Benutzer x' AND 1=(SELECT COUNT(*) FROM Client); -- haben

Wenn der gespeicherte Prozess so aussah (unter Verwendung von verkettetem dynamischem SQL ), ermöglicht Ihr parametrisierter Aufruf des gespeicherten Prozesses weiterhin SQL Injection

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....

Wie gezeigt, ist die Verkettung von Zeichenfolgen der Hauptfeind für die SQL-Injection

Gespeicherte Prozeduren fügen zwar Kapselung, Transaktionsbehandlung, reduzierte Berechtigungen usw. hinzu, können jedoch weiterhin für die SQL-Injection missbraucht werden.

Weitere Informationen zu Parametrisierung finden Sie unter Stapelüberlauf

12
gbn

"SQL-Injection-Angriffe treten auf, wenn Benutzereingabe Falsch codiert ist. In der Regel handelt es sich bei der Benutzereingabe um einige Daten, die der Benutzer mit seiner Abfrage sendet, d. H. Werte in $_GET, $_POST, $_COOKIE, $_REQUEST, oder $_SERVER Arrays. Benutzereingaben können jedoch auch aus einer Vielzahl anderer Quellen stammen, z. B. aus Sockets, Remote-Websites, Dateien usw. Daher sollten Sie wirklich alles außer Konstanten behandeln. -) (mögen 'foobar') als Benutzereingabe . "

Ich habe mich in letzter Zeit gründlich mit diesem Thema befasst und möchte mit anderen recht interessantes Material teilen, um diesen Beitrag vollständiger und lehrreicher für alle zu machen.



Von YouTube


Aus Wikipedia


Von OWASP


Von PHP Manual


Von Microsoft und Oracle


Stapelüberlauf


SQL Injection Scanner

10
Ilia Rostovtsev

Gespeicherte Prozeduren verhindern die SQL-Injection nicht auf magische Weise, aber sie erleichtern das Verhindern erheblich. Sie müssen lediglich Folgendes tun (Beispiel Postgres):

CREATE OR REPLACE FUNCTION my_func (
  IN in_user_id INT 
)
[snip]
  SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]

Das ist es! Das Problem tritt nur auf, wenn eine Abfrage über eine Zeichenfolgenverkettung (d. H. Dynamisches SQL) erstellt wird, und selbst in diesen Fällen können Sie möglicherweise eine Bindung herstellen! (Abhängig von der Datenbank.)

So vermeiden Sie SQL-Injection in Ihrer dynamischen Abfrage:

Schritt 1) ​​Fragen Sie sich, ob Sie wirklich eine dynamische Abfrage benötigen. Wenn Sie Zeichenfolgen zusammenkleben, um die Eingabe festzulegen, machen Sie es wahrscheinlich falsch. (Es gibt Ausnahmen von dieser Regel. Eine Ausnahme ist das Melden von Abfragen in einigen Datenbanken. Möglicherweise treten Leistungsprobleme auf, wenn Sie nicht zwingen, bei jeder Ausführung eine neue Abfrage zu kompilieren. Untersuchen Sie dieses Problem jedoch, bevor Sie darauf eingehen. )

Schritt 2) Suchen Sie nach der richtigen Methode zum Festlegen der Variablen für Ihr bestimmtes RDBMS. Mit Oracle können Sie beispielsweise Folgendes tun (aus den Dokumenten zitieren):

sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
           || v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!

Hier verketten Sie die Eingabe immer noch nicht. Sie sind sicher verbindlich! Hurra!

Wenn Ihre Datenbank so etwas wie das oben Genannte nicht unterstützt (hoffentlich ist keiner von ihnen immer noch so schlecht, aber ich wäre nicht überrascht) - oder wenn Sie Ihre Eingabe wirklich verketten müssen (wie im "manchmal" Fall, in dem Abfragen als gemeldet werden Ich habe oben angedeutet), dann müssen Sie eine ordnungsgemäße Fluchtfunktion verwenden. Schreib es nicht selbst. Zum Beispiel bietet postgres die Funktion quote_literal (). Also würdest du rennen:

sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);

Auf diese Weise speichert quote_literal Ihren Hintern durch, wenn in_name etwas Falsches wie '[snip] oder 1 = 1' ist (der Teil "oder 1 = 1" bedeutet, dass alle Zeilen ausgewählt werden, damit der Benutzer die Gehälter sehen kann, die er nicht sehen sollte!) Erstellen der resultierenden Zeichenfolge:

SELECT salary FROM employees WHERE name = '[snip] or 1=1'

Es werden keine Ergebnisse gefunden (es sei denn, Sie haben Mitarbeiter mit wirklich seltsamen Namen.)

Das ist der Kern davon! Lassen Sie mich jetzt einen Link zu einem klassischen Beitrag von Oracle-Guru Tom Kyte zum Thema SQL Injection hinterlassen, um den Punkt nach Hause zu bringen: Linky

2
MWDB