Web-Anwendungen und -Services stellen heute zentrale Bausteine vieler Dienste dar. Insbesondere die strategische Ausrichtung vieler Unternehmen in die Cloud unterstreicht die kritische Bedeutung von Web-Anwendungen und -Services – egal ob browserbasiert oder in Form von API’s.
Umso bedeutsamer ist das Thema „Sicherheit“ in der Web-Umgebung. Denn der durch die Cloud gewonnene strategische Vorteil des „zentralen“ Services hat auch seine Schattenseiten. So ist z.B. allgemein anerkannt dass jedes System nur so sicher ist wie seine schwächste Komponente. Einmal kompromittiert sind sämtliche Daten und Dienste abhanden gekommen und gestört bzw. nicht mehr verfügbar.
Die gute Nachricht jedoch: auch wenn Mittel und Werkzeuge von Angreifern sich ändern, die Methoden bleiben die selben: Social Engineering, Einschleusen von Schadcode (Injections), fehlende oder unzureichende Zugriffskontrolle sind einige von diesen.
In dieser Blogserie möchten wir uns tiefergehend mit den verschiedenen Bereichen der IT Security beschäftigen. In insgesamt neun Blogposts möchten wir tiefergehend auf verschiedene Szenarien eingehen, mögliche Schutzmechanismen präsentieren und diese – wenn möglich – durch praktische Beispiele demonstrieren. Nach Blogpost #9 werden wir diese Serie und weitere Tipps und Tricks als PDF zur Verfügung stellen. Sie können sich unter dem nachfolgenden Formular zum Newsletter anmelden, um das PDF zu erhalten:
[newsletters_subscribe form=3]
Arten von Injection Attacken
„Cross-Site-Scripting“ (XSS) und „SQL-Injection“ (SQLi) sind die am weitverbreitetesten Injection Attacken. Darüber hinaus existieren noch weitere, wie z.B. ganz allgemein Code Injection, Email-Header Injection, LDAP Injection oder Command Injection auf Betriebssystem-Ebene. Nachfolgend wollen wir auf einige von diesen eingehen:
EDIT 25.09.2023: Dieser Beitrag ist auch auf YouTube verfügbar
Cross-Site-Scripting (XSS)
Cross-Site-Scripting ist Angriff, bei dem externer Code in den legitimen Code der Website eingeschleust wird. Der Angreifer kann den infizierten Code an den Benutzer senden, da der Browser ihn als vertrauenswürdig einstuft. Dieser Angriff erfolgt meist an den Stellen, an denen der Benutzer Daten eingeben und übermitteln kann. Der Angriff kann – je nach Art und Szenario – auf Cookies, Sitzungen, Datenbestand und andere (sensible) Informationen über den Browser zugreifen. Das folgende Beispiel zeigt ein XSS-anfälligen Quellcode:
Die folgende URL enthält JavaScript-Code – genauer einen alert-Befehl in dem HTML-Tag „script“:
http://example.com/search/?search=<script>alert('test')</script>
@app.route("/search")
def doSearch():
search = request.args.get("search")
print search
die Methode „doSearch“ filtert die Benutzereingabe nicht und gibt sie an den Browser weiter. Der Browser wiederum erkennt den Code als valides HTML (da eingebettet in script-Tags) und führt den alert-Befehl aus.
Ein böswilliger Angreifer könnte auf diese Art allerlei Angriffe ausführen – z.B. Cookie- oder Session-Daten klauen, sensible Informationen im Browser (z.B. Banking) kopieren und an einen entfernten Server schicken oder – in einem aufwendigeren Szenario – den Browser für eigene Zwecke ausnutzen (z.B. Crypto-Mining).
XSS-Angriffe sind einfach durch HTML-Escaping abzuwehren, werden sehr oft einfach vergessen. Bei dem Escaping werden Sonderzeichen wie eckige Klammern oder Hochkomma durch ihre ASCII-Zeichen bzw. HTML-Codes ersetzt.
Alle gängigen Programmiersprachen und Frameworks für das Web bieten Boardmittel für HTML-Escaping.
SQL-Injection (SQLi)
SQLi ist relativ ähnlich zu XSS. Der Kerngedanke ist derselbe: über nicht vorhandene oder zu schwache Schutzmechanismen wird versucht, Fremd- bzw. Schadcode einzuschleusen.
Nehmen wir das Beispiel von oben:
URL: http://example.com/search/?search=“foobar;DROP TABLE SEARCHES;“
@app.route("/search")
def doSearch():
search = request.args.get("search")
b.query("SELECT * FROM searches WHERE title = " + search)
Wie schon bei XSS wird in diesem Beispiel die Benutzereingabe ungefiltert als Abfrage an die Datenbank weitergegeben. Das ausgeführte SQL-Statement ist wie folgt:
SELECT * FROM searches WHERE title = foobar; DROP TABLE SEARCHES;
Dieser String würde also zwei Befehle ausführen: einen SELECT und ein DROP TABLE.
SQLi ist ebenfalls relativ einfach durch Prepared Statements zu verhindern. Alle gängigen Programmiersprachen und Frameworks bieten Prepared Statements an.
E-Mail-Injection
E-Mail-Injection ist eine spezielle Form von Header-Injection bzw. CLRF-Injection. Bei CLRF-Injection geht es darum, eingeschleuste Carriage Return Zeichen (\n
und \r
bzw. ASCII 13 und ASCII 10) weitere Header in das Protokoll (z.B. SMTP, HTTP, etc) einzuschleusen. Möglich wird dies, weil Header in dem Format <Name>:<Wert>
durch CR-Zeichen getrennt werden.
Zusätzliche Header können z.B. zusätzliche Empfänger, Reply-To-Adressen oder eigene Header sein. Das Beispiel von oben noch einmal erweitert um einen E-Mail-Versand:
URL: http://example.com/send_mail/?receiver="valid_receiver@example.com, malicous_receiver@example.com"
@app.route("/send_mail")
def doSendMail():
receiver_email = request.args.get("receiver")
context = ssl.create_default_context()
with smtplib.SMTP("smtp.example.com", 587) as server:
server.starttls(context=context)
server.login("me@example.com", "topsecret")
server.sendmail("me@example.com", receiver_email, "Hello World")
Im Unterschied zu den vorhergehenden Injection-Beispielen werden hier Daten anstelle Code injected. Die Auswirkungen sind aber dieselben: das auszuführende Programm zeigt ein abweichendes Verhalten auf als beabsichtigt.
E-Mail-Injection- oder allgemein Header-Injection-Angriffe können im Gegensatz zu den vorhergehenden Beispielen nicht durch Escaping verhindert werden.
Stattdessen muss auf striktes Whitelisting gesetzt werden – dies gilt sowohl für die Werte als auch für die zu setzenden Header. Im Idealfall kann der Benutzer nicht direkt bestimmen welche Header gesetzt werden sollen. Einen detaillierten Blogpost zu E-Mail-Injection hatten wir bereits im vergangen Jahr geteilt.
Es existieren noch viele weitere Injection-Angriffe, z.B. Command-Injection auf Betriebssystem-Ebene oder LDAP-Injection. Allen Injection-Angriffen liegt das einschleusen von Code und/oder Daten zugrunde, die nicht gefiltert oder escaped werden. Bei Command-Injections wird z.B. ein Shell-Befehl von einem Programm (z.B. Python) aufgerufen, ohne vorherige Validierung – sowohl für die Befehle selbst als auch für mögliche Options und Arguments. Ähnliches gilt auch für LDAP-Injections, bei dem Benutzerberechtigungen und/oder -privilegien verändert/gelöscht werden können, wenn die Befehle nicht vorher validiert oder gefiltert werden.
Injection-Angriffe durch Security Audits verhindern
Viele Anwendungen entwickeln im Laufe der Zeit sehr viele Features und nicht immer wird jeder Aspekt vollumfänglich bedacht – so auch die IT-Sicherheit. Wir verstehen, dass dies in der Natur des Software-Engineerings liegt.
Wir bieten Ihnen vollumfänglichen Source-Code Audit zum Absichern Ihrer Anwendung gegen u.a. Injections und weiteren sicherheitsrelevanten Aspekten. Durch automatisierte und manuelle Prozesse helfen wir Ihnen, Ihre sensiblen und geschäftskritischen Informationen zu schützen und die geltenden Gesetze einzuhalten.
Unsere automatisierten Tests beinhalten u.a. Penetrationtests, toolbasierte Codeanalyse und -dokumentation. Darauf aufbauend analysieren wir den Source-Coden persönlich, versuchen die Architektur zu verstehen und mögliche Probleme bzw. Vorschläge in dem Zusammenhang zu identifizieren bzw. unterbreiten.
Kontaktieren Sie uns heute noch für ein unverbindliches Erstgespräch. Wir freuen uns darauf!