Seien Sie am 30. April dabei: Vorstellung von Parasoft C/C++test CT für kontinuierliche Tests und Compliance-Exzellenz | Registrierung

So verhindern Sie SQL Injection

Kopfschuss von Arthur Hicken, Evangelist bei Parasoft
4. August 2020
10 min lesen

SQL-Injection kann die Robustheit und die Sicherheitsebenen Ihrer Software beeinträchtigen, wenn sie nicht frühzeitig erkannt und gestoppt wird. Lesen Sie weiter, um zu erfahren, wie sich SQL-Injection auf Ihre Software auswirken kann, und entdecken Sie unseren Ansatz zur Verwaltung der SQL-Injection.

Die SQL (Strukturierte Abfragesprache) Injection ist eine bekannte, wenn nicht eine der bekanntesten Software-Schwachstellen und Sicherheitslücken. Trotz seines guten Rufs bleibt die Verhinderung der SQL-Injection eine der größten Sicherheitslücken Angriffe nehmen weiter zu.

Suchen von SQL-Injektionen

Injection-Schwachstellen (von denen SQL-Injections eine Variante sind) sind laut OWASP Top 10. SQL-Injektionen sind die Nummer sechs auf der CWE-Top 25. Andere Beispiele für die gleichen Arten von Sicherheitslücken sind:

  • Befehlsinjektion (CWE-77)
  • OS-Befehlsinjektion (CWE-78)
  • Hibernate-Injektion (CWE-564)
  • Injektion der Ausdruckssprache (CWE-917)

Alle diese Schwachstellen haben ein gemeinsames Attribut. Sie werden mit Daten von außerhalb des Systems, Benutzer- oder Dateieingaben oder was auch immer in potenziell gefährlichen Funktionen ausgenutzt.

Kontinuierliches Testen für DevOps: Entwicklung über die einfache Automatisierung hinaus

Glücklicherweise können SQL-Injektionen von Tools sowohl statisch als auch dynamisch erkannt werden. Sie können jedoch nie sicher sein, dass Sie sie alle gefangen haben. Das Verhindern von SQL-Injektionen ist auch der Schlüssel zur Reduzierung der Häufigkeit und der Auswirkungen dieser Sicherheitsanfälligkeiten. Ein ausgereifter DevSecOps-Prozess, der die Erkennung und Verhinderung von Schwachstellen umfasst, kann diese Arten von Schwachstellen erkennen und verhindern, dass sie jemals in ein freigegebenes Produkt gelangen.

Was ist SQL?

SQL ist eine domänenspezifische Sprache für die Verwaltung relationaler Datenbanken. Relationale Datenbanken präsentieren Daten als Sammlung von Tabellen in Zeilen und Spalten. Jede Zeile hat einen Schlüssel, der die Beziehung zu anderen Tabellen bereitstellt. Hier ist ein Beispiel für die Tabelle "Benutzer":

[Tabelle “1” nicht gefunden /]

SQL ist die Sprache der Wahl zum Verwalten, Abfragen und Bearbeiten von Daten in einer Beziehungsdatenbank. Es definiert die Tabellen und Beziehungen bei der Datenbankerstellung. Für die meisten alltäglichen Anwendungen verwenden Entwickler SQL für „CRUD“ - zum Erstellen, Lesen, Aktualisieren und Löschen von Daten.

Warum ist SQL ausnutzbar?

Allgemeine Programmiersprachen unterstützen SQL nicht. Der Zugriff auf Datenbankbefehle erfolgt über eine vom Datenbankanbieter bereitgestellte API. In vielen Fällen werden SQL-Befehle als Zeichenfolgen gesendet, die von der API interpretiert und auf die Datenbank angewendet werden. Hier sind einige einfache SQL-Abfragen:

Eine typische SQL-Abfrage hat die folgende Form:

Wählen Sie (etwas) aus (irgendwo) (optionale Bedingung)

Anhand der obigen Tabellen als Beispiel zum Abrufen der E-Mail aus der Zeile, in der der Nachname "Smith" lautet, wird die folgende SQL-Anweisung verwendet:

Wählen Sie eine E-Mail vom Benutzer aus, bei der Nachname = 'Smith'.

Die Ausgabe wäre wie folgt:

Smith1234@mail.com John.smith@mail.net Smith1234@mail.com

Das Abrufen von Eingaben von Benutzern mit einem Webformular (siehe unten) ist ein häufiger Anwendungsfall in Webanwendungen. Die Daten, die die Benutzer beispielsweise in das Feld „Name“ eingeben, werden verwendet, um SQL-Abfragen basierend auf den empfangenen Eingaben zu erstellen. Betrachten Sie das folgende einfache Webformular:

Einfaches Webformular

Die Software verarbeitet das Formular und weist die Werte Variablen wie folgt zu:

String formName = request.getParameter (Name);

Die als "Name" eingegebene Zeichenfolge wird verwendet, um die Abfrage unter Verwendung dieser Benutzereingabe zusammenzustellen:

String myQuery = "Nachricht vom Benutzer auswählen, wobei email = '" + formName + "';"

Verwenden dieser konstruierten Abfrage:

Wählen Sie eine Nachricht vom Benutzer aus, bei der email = 'Smith1234@mail.com';

Die Ausgabe davon (unter Verwendung der obigen Tabelle als Beispiel) ist wie folgt:

Hallo wie geht's dir

Hoffentlich ist es leicht zu sehen, wie das alles schief gehen kann. Aufgrund der Verwendung von Benutzereingaben direkt in der Zeichenfolge kann jemand, der die SQL-Syntax versteht, diese leicht bearbeiten, um die SQL-Abfrage zu generieren. Betrachten Sie das folgende Beispiel:

Mit dem oben genannten Formular gibt jemand "Smith1234@mail.com" oder "1" = "1" in das E-Mail-Feld ein.

Mit demselben Code wird die folgende SQL-Abfragezeichenfolge zusammengestellt:

Wählen Sie eine Nachricht vom Benutzer aus, bei der email = 'Smith1234@mail.com' oder '1' = '1';

Das Hinzufügen von etwas Unschädlichem wie "oder 1 = 1" ändert die Logik der Abfrage und führt möglicherweise zu Datenlecks, indem alle Zeilen in der Tabelle mit dem Namen "Benutzer" zurückgegeben werden. In diesem Fall werden Ihnen Nachrichten für jeden Benutzer in der Tabelle angezeigt. Ein ernstes Datenschutzproblem und in einigen Gerichtsbarkeiten oder Kontexten auch ein potenzielles rechtliches Problem, wie z. B. GDPR, HIPAA oder CCPA.

Die obige Abfrage endet mit der folgenden unbeabsichtigten Ausgabe:

Hallo Passwort 1234 Wie geht es dir? Sag es niemandem Wassup

So funktioniert eine SQL-Injection

Der Grundgedanke einer SQL-Injection (und anderer Arten von Injection-Schwachstellen) ist die Verwendung ungeprüfter Daten von außerhalb der Anwendung, z. B. Benutzereingabetext, in einer SQL-Abfragezeichenfolge. Die Beschreibung für KWE 89: "Unsachgemäße Neutralisierung spezieller Elemente, die in einem SQL-Befehl verwendet werden ('SQL Injection')" definiert dies genauer:

„Ohne ausreichende Entfernung oder Anführungszeichen der SQL-Syntax in vom Benutzer steuerbaren Eingaben kann die generierte SQL-Abfrage dazu führen, dass diese Eingaben als SQL anstelle von normalen Benutzerdaten interpretiert werden. Dies kann verwendet werden, um die Abfragelogik zu ändern, um Sicherheitsüberprüfungen zu umgehen, oder um zusätzliche Anweisungen einzufügen, die die Back-End-Datenbank ändern, möglicherweise einschließlich der Ausführung von Systembefehlen. “

Der gleiche Eintrag in der CWE-Datenbank (CWE 89) bietet ein weiteres einfaches Beispiel für diesen Angriff. Angenommen, die Anwendung führt eine Abfrage im Namen des Benutzers "wiley" durch und der Benutzer erstellt die Eingabe so, dass sie SQL-Anweisungen enthält, zum Beispiel:

Name'; DELETE FROM items; - -

Wenn diese Anwendung keine Gültigkeitsprüfung für diese Eingabe durchführt, erstellt sie eine Abfrage wie folgt:

SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name'; DELETE FROM items; - '

Wenn dieser Angriff erfolgreich ist, werden alle Daten in Tabellenelementen gelöscht, was die Datenbank verwüstet. Jeder gültige SQL-Befehl könnte möglicherweise auf diese Weise ausgeführt werden. Dies ist ein Beispiel für einen Schreib- / Änderungsangriff, bei dem die Datenbank beschädigt oder unerwünschte Informationen eingefügt werden sollen. Das vorherige Beispiel ("oder 1 = 1") ist ein Leseangriff, bei dem die Absicht ein Datenverlust ist.

Viele Implementierungen von Datenbankservern akzeptieren das Semikolon als Befehlstrennzeichen, wodurch solche SQL-Injektionen so gefährlich werden können. Das nachfolgende "-" signalisiert, dass der Rest des Textes ein Kommentar ist, wodurch der SQL-Interpreter gezwungen wird, das nachfolgende Anführungszeichen zu ignorieren, was andernfalls einen Syntaxfehler verursachen würde. Es gibt mehrere Möglichkeiten, die zusammengestellte Abfragezeichenfolge auszutricksen. Manchmal auf eine Weise, die sich Entwickler nie vorgestellt haben.

Schutzmaßnahmen gegen SQL-Injektionen

Es gibt verschiedene Abhilfemaßnahmen, die Entwickler implementieren sollten. In erster Linie sollte die Sicherheitslage alle Daten berücksichtigen, die von außerhalb der Anwendung stammen und nicht vertrauenswürdig sind. Im Folgenden sind typische Strategien zur Schadensbegrenzung aufgeführt:

  • Verwenden Sie vorbereitete Anweisungen mit parametrisierten Abfragen.
  • Verwenden Sie gespeicherte Prozeduren.
  • Überprüfung der Whitelist-Eingabe.
  • Entfliehen Sie allen bereitgestellten Eingaben.

Diese werden im OWASP näher beschrieben Spickzettel für SQL-Injektionen.

Testen auf SQL-Injektionen

Ein typischer Sicherheitsansatz besteht darin, verschiedene Arten von Sicherheitstests im Rahmen regulärer QS-Vorgänge durchzuführen, wenn die integrierte Software ausgeführt wird. Leider versuchen Funktionstests nicht, Exploits in Benutzereingabefelder einzufügen, da die meisten Tester nicht als schlechte Schauspieler denken.

Abgesehen von der Tatsache, dass sie traditionell nicht die Zeit oder die Richtung haben, dies zu tun. Es ist auch schwierig, manuell auf Schwachstellen vom Injektionstyp zu testen, da so viele verschiedene Kombinationen von Eingaben ausprobiert werden müssen. Hier kommt das Fuzzing oder Fuzz-Testen ins Spiel. Es werden zufällige, unerwartete und ungültige Daten als Eingaben für die zu testende Anwendung erstellt. Fuzz-Tests sind Teil von Penetrationstests, da das Ziel darin besteht, Sicherheitslücken über die exponierten Schnittstellen aufzudecken.

Penetrationstests

Penetrationstests (und damit auch Fuzz-Tests) sind von Vorteil, da sie Sicherheitsprobleme erkennen können, die sich durch den Prozess geschlichen haben, und erhebliche Sicherheitsprobleme aufdecken können. Wie bei allen dynamischen Tests hängt es jedoch von der Menge der Test-, Code- und API-Abdeckung ab, alle möglichen Permutationen und Kombinationen vollständig zu testen. Penetrationstests hängen von der Gründlichkeit der Funktionstests ab, die normalerweise auf der Ebene der Benutzeroberfläche durchgeführt werden. Aus diesem Grund ist es wichtig, Ihre Penetrationstestbemühungen mit API-Tests und SAST zu unterstützen, um sicherzustellen, dass Sie gründlich sind.

API-Tests

API-Tests helfen dabei, Funktions- und Sicherheitstests nach links zu verschieben, indem die Abhängigkeit von spröden und zeitaufwändigen UI-Tests beseitigt wird. In der API-Schicht befindet sich ein Großteil der Anwendungsfunktionalität, und das Testen ist widerstandsfähiger gegenüber Änderungen auf dieser Ebene und einfacher zu automatisieren und zu warten.

Penetrationstests auf API-Ebene

Penetrationstests auf API-Ebene, um SQL-Injektionen verfügbar zu machen, sind mit Tools wie möglich Parasoft SOAtest Wenn automatisierte Fuzz-Tests aus vorhandenen Funktionstests erstellt werden, wird die Geschäftslogik der Anwendung angewendet. Parasoft SOAtest integriert sich in Burp Suite Das ist ein bekanntes Penetrationstest-Tool.

Bei der Ausführung von Funktionstestszenarien mit Parasoft SOAtest werden im Test definierte API-Aufrufe zusammen mit dem Anforderungs- und Antwortverkehr erfasst. Das Burp Suite-Analysetool leitet bei jedem Test die Verkehrsdaten an eine separate laufende Instanz der Burp Suite-Anwendung weiter, die anhand der in den Verkehrsdaten beobachteten API-Parameter anhand ihrer eigenen Heuristiken Penetrationstests für die API durchführt.

Das Burp Suite-Analysetool nimmt dann alle von Burp Suite gefundenen Fehler und meldet sie als Fehler in SOAtest, die mit dem Test verknüpft sind, der auf die API zugegriffen hat. Parasoft SOAtest-Ergebnisse werden im Berichts- und Analyse-Dashboard von Parasoft gemeldet. Für zusätzliche Berichtsfunktionen.

Weitere Informationen zu dieser Integration finden Sie in unserer previous post bei Penetrationstests. Weitere Informationen von Portswigger zur Verwendung von Burp für SQL-Injektionen finden Sie unter Schauen Sie sich ihren Beitrag an. Nachfolgend finden Sie eine Darstellung der Funktionsweise dieser Integration in Burp:

Verhindern Sie SQL-Injektionen mit Burp und Parasoft DTP

Die Integration dieser Art von Penetrationstests in Ihren CI / CD-Prozess ist ein wichtiger Bestandteil des Schutzes vor SQL-Injektionen und anderen Arten von Sicherheitslücken.

Penetration und Fuzzing sind sicherlich ein wichtiger Prozess und in DevSecOps von entscheidender Bedeutung. Es wirft jedoch Fragen auf.

  • Was passiert, wenn beim Testen Sicherheitslücken erkannt werden?
  • Was passiert, wenn ein Softwareteam feststellt, dass ein Großteil seiner Benutzereingabeverarbeitung unsicher ist?
  • Es muss sicherlich repariert werden, aber zu welchem ​​Preis?

Das Auffinden schwerwiegender Sicherheitsprobleme in diesem späten Entwicklungsstadium verursacht schwerwiegende Kosten und Verzögerungen. Prävention und Erkennung sind der Schlüssel, um Sicherheitsmaßnahmen weiter nach links zu verlagern, wo sie billiger und einfacher zu beheben sind.

Verschieben Sie die Erkennung und Eliminierung von SQL-Injektionen weiter nach links

Die Übernahme eines DevSecOps-Ansatzes für die Softwareentwicklung bedeutet die Integration von Sicherheit in alle Aspekte der DevOps-Pipeline. So wie Teams Qualitätsprozesse wie Codeanalyse und Unit-Tests so früh wie möglich im SDLC gilt dasselbe für die Sicherheit.

SQL-Injektionen könnten der Vergangenheit angehören, wenn Teams diesen Ansatz allgemeiner anwenden. Die Zunahme der Angriffe bedeutet, dass dies noch nicht geschieht. Lassen Sie uns unabhängig davon einen Ansatz skizzieren, um SQL-Injektionen so früh wie möglich zu verhindern.

Das Finden und Beheben potenzieller SQL-Injections (und anderer Injection-Schwachstellen) zahlt sich im Vergleich zum Patchen (und Entschuldigen!) Einer freigegebenen Anwendung aus. Ein einziger bedeutender Vorfall kann Kosten Unternehmen 200,000 USD oder mehr. Viele Vorfälle ereignen sich bei kleinen Unternehmen. Ein einzelner Angriff kann ernsthafte finanzielle Belastungen verursachen, ganz zu schweigen von potenziellen regulatorischen Problemen in Bezug auf die Offenlegung von Verstößen und den Schutz personenbezogener Daten.

Der unten beschriebene Ansatz zum Erkennen und Verhindern basiert auf der Verlagerung der Abschwächung von SQL-Injektionen nach links in die frühesten Entwicklungsstadien und deren Verstärkung durch Erkennung durch statische Code-Analyse.

So erkennen Sie SQL-Injections

Das Erkennen von SQL-Injektionen basiert auf statischen Analysen, um diese Arten von Schwachstellen im Quellcode zu finden. Die Erkennung erfolgt auf dem Desktop des Entwicklers und im Build-System. Es kann vorhandenen Code, Legacy-Code und Code von Drittanbietern enthalten.

Durch die kontinuierliche Erkennung von Sicherheitsproblemen wird sichergestellt, dass alle Probleme gefunden werden, die:

  • Entwickler in der IDE verpasst.
  • Bestehen Sie in Code, der älter ist als Ihr neuer Ansatz zum Erkennen und Verhindern.
Kontinuierliche Integration und kontinuierliche Bereitstellung für eingebettete Systeme

Der empfohlene Ansatz ist ein Trust-But-Verify-Modell. Die Sicherheitsanalyse erfolgt auf IDE-Ebene, wo Entwickler anhand der erhaltenen Berichte Entscheidungen in Echtzeit treffen. Überprüfen Sie als Nächstes auf Build-Ebene. Im Idealfall besteht das Ziel auf Build-Ebene nicht darin, Schwachstellen zu finden. Es soll überprüft werden, ob das System sauber ist.

Betrachten Sie als Beispiel die Demo-Anwendung von Parasoft: Parabank. In der Datei StockDataInserter.java in com.parasoft.parabank.dao.jdbc.internal befindet sich eine potenzielle SQL-Injection:

… Final String sql = sb.toString (); rows = (nextId - lastId) / JdbcSequenceDao.OFFSET; totalRows + = Zeilen; getJdbcTemplate (). update (sql); …

Der Bericht, der zum Zeitpunkt der Erstellung von erstellt wurde Parasoft Jtest ist das Folgende:

Suchen von SQL-Injektionen: Parasoft Jtest Report

Im Detail ist die folgende Warnung:

Aufruf einer gefährlichen Methode StockDataInserter.java (96): getJdbcTemplate (). Update (sql); *** Beschmutzte Daten: SQL

Mit einem Traceback zu einem vorherigen Punkt, an dem die mit der Quelle belasteten Daten (deaktivierte, nicht validierte Eingabe von außerhalb der Anwendung) gefunden werden:

Tainting-Punkt StockDataInserter.java (47): Rückgabe getJdbcTemplate (). Query (SQL, neuer ResultSetExtractor  > () {*** Beschmutzte Daten: getJdbcTemplate (). Query (SQL, neuer ResultSetExtractor

Im laufenden Kampf gegen SQL-Injektionen müssen Entwickler diese Warnungen ernst nehmen. Die Verwendung nicht validierter Daten in SQL-Abfragen ist ein ernstes Risiko. Auch wenn eine bestimmte Warnung in der aktuellen Form möglicherweise kein Problem darstellt, kann dieses spätere Refactoring diese Sicherheitsanfälligkeiten aufdecken. Überprüfen Sie alle in Abfragezeichenfolgen verwendeten Daten!

Entwickler sollten alle Daten von außerhalb einer Anwendung validieren, um sicherzustellen, dass sie dem erwarteten Format und Inhalt entsprechen. Die Umstellung auf die Philosophie „Immer validieren“ und ein Prozess, der sich eher auf sichere Codierung als auf Sicherheitstests stützt, erhöht die Anwendungssicherheit erheblich. Beginnen Sie mit dem Härten des Codes, um zu verhindern, dass SQL-Injektionen überhaupt ausgeführt werden.

Wann und wie verhindert man SQL Injection?

Die ideale Zeit und der ideale Ort, um SQL-Injektionen zu verhindern, sind, wenn Entwickler Code in ihre IDE schreiben. Teams, die sichere Codierungsstandards wie SEI CERT C für C und C ++ und OWASP Top 10 für Java und .NET oder CWE Top 25 anwenden, verfügen alle über Richtlinien, die vor nicht validierten Eingaben in SQL-Abfragen warnen.

Das Ausführen einer statischen Analyse für neu erstellten Code ist schnell und einfach und einfach in den CI / CD-Prozess zu integrieren. Es wird empfohlen, zu diesem Zeitpunkt alle Sicherheitswarnungen und unsicheren Codierungspraktiken zu untersuchen, um zu verhindern, dass dieser Code jemals in den Build aufgenommen wird.

Verwenden Sie die statische Code-Analyse, um SQL-Injektionen zu verhindern

Ein ebenso wichtiger Teil der Erkennung schlechter Codierungspraktiken ist die Nützlichkeit der Berichte. Es ist wichtig, die Grundursache für Verstöße gegen statische Analysen zu verstehen, um sie schnell und effizient beheben zu können. Hier finden Sie kommerzielle Tools wie Parasofts C / C ++ - Test, dotTEST und Test scheinen.

Die automatisierten Testtools von Parasoft bieten vollständige Spuren für Warnungen, veranschaulichen diese in der IDE und sammeln kontinuierlich Build- und andere Informationen. Diese gesammelten Daten bieten neben Testergebnissen und Metriken einen umfassenden Überblick über die Einhaltung des Codierungsstandards des Teams. Es zeigt auch den allgemeinen Qualitäts- und Sicherheitsstatus.

Die Berichte enthalten die Risikomodelle, die Teil der von OWASP, CERT und CWE bereitgestellten Informationen sind. Auf diese Weise verstehen Entwickler besser, welche Auswirkungen die vom Tool gemeldeten potenziellen Schwachstellen haben und welche dieser Schwachstellen priorisiert werden müssen. Alle auf IDE-Ebene generierten Daten korrelieren mit den oben beschriebenen nachgelagerten Aktivitäten.

Zusammenfassung

Die berüchtigte SQL-Injection-Schwachstelle plagt weiterhin Webanwendungen. Trotz des Wissens darüber, wie es funktioniert und genutzt werden kann, bleibt es weit verbreitet. Siehe die IoT-Hall of Shame für aktuelle Beispiele.

Wir schlagen einen Ansatz zum Verhindern und Erkennen vor, um aktive Sicherheitstests zu ergänzen. Dieser Ansatz verhindert, dass SQL-Injections so früh wie möglich in den SDLC eingefügt werden - bevor in den Code geschrieben wird. Das Verhindern von SQL-Injektionen in der IDE und das Erkennen von SQL-Injections in der CI / CD-Pipeline ist der Schlüssel zum Weiterleiten aus Ihrer Software. Zuletzt finden und beheben Sie diese Fehler während des Testens mithilfe von Penetrationstesttechniken.

Der Kampf gegen SQL-Injektionen (sowie andere verdorbene Daten-Exploits) geht weiter. Intelligente Teams können das Blatt mit den richtigen Prozessen, Tools und Automatisierungen in ihren vorhandenen Workflows wenden.

Der Geschäftswert sicherer Software