In einigen kürzlich erschienenen Artikeln habe ich dargelegt, wie Sie als Entwickler:in durch die Verwendung von New Relic Funktionen Ihre Sicherheitskompetenzen erweitern können. Ich habe mich auch eingehend damit befasst, wie versteckte Sicherheitsrisiken von Open-Source-Softwarebibliotheken gemindert werden können. Beide Blogs konzentrierten sich auf Drittanbietercode, und wie dieser die Sicherheit Ihrer Softwareanwendungen beeinträchtigen kann. In diesem Artikel befasse ich mich mit der Sicherheit Ihres eigenen benutzerdefinierten Codes, also des Codes, den Sie selbst schreiben.

Generell gibt es mehrere Methoden, mit denen Sie die Sicherheit Ihres Erstanbietercodes gewährleisten können. Ein gängiger Ansatz besteht darin, statische Code-Analysetools zu verwenden, die Ihren Quellcode vor der Bereitstellung in verschiedenen Umgebungen wie der Testphase, Qualitätssicherung und Produktion scannen. Diese Vorgehensweise ist sinnvoll, da sie die Aufnahme hartcodierter Secrets in Ihr Repository oder Ihre Software-Builds verhindert. Allerdings bieten solche Techniken nur Einblick in die statischen Aspekte Ihrer Anwendung.

Um dieser Einschränkung zu begegnen, verlässt sich die Branche häufig auf dynamische Anwendungssicherheitstools, die Black-Box-Tests durchführen, indem sie Ihre Anwendung aus einer externen Perspektive untersuchen. Obwohl dieser Ansatz eine zusätzliche Perspektive bietet, zeigt er ebenfalls nur einen Aspekt der gesamten Sicherheitslage auf. Der Knackpunkt ist, dass keine dieser Methoden einen umfassenden Überblick bietet.

Das Interactive Application Security Testing (IAST) von New Relic ist genau darauf ausgelegt, dieses Problem anzugehen. Mit IAST können Sie Ihre Observability optimieren, da die Tools von New Relic bereits von innen heraus detaillierte Einblicke in die dynamischen Aspekte Ihrer Anwendung bieten. Beim Application Performance Monitoring (APM) wird der Code beobachtet, während er auf den Systemen ausgeführt wird. Das bedeutet, dass wir nicht nur Performance und Fehler sehen, sondern auch, welche Codeversion für jede Instanz des Dienstes bereitgestellt wurde und welche Methoden tatsächlich ausgelöst werden – basierend auf der Echtzeitaktivität in der Anwendung selbst.

Bei der Beobachtung Ihrer Dienste werden Bedenken hinsichtlich der Anwendungssicherheit, sowohl aus Erst- als auch aus Drittquellen, immer wichtiger. New Relic IAST spielt in diesem Zusammenhang eine Schlüsselrolle, da es Schwachstellen in Ihren Anwendungen schnell erkennt. Es liefert schlüssige Indizien für Exploits und deren genaue Positionen in Ihrem Code. Darüber hinaus bietet das Tool umsetzbare und wiederholbare Testverfahren und Abhilfemaßnahmen, die es Ihnen ermöglichen, Sicherheitsprobleme in Vorproduktions- oder Entwicklungsumgebungen effizient anzugehen, bevor sie zur Gefahr werden können. Ein Beispiel dafür, was unter „umsetzbar“ und „wiederholbar“ zu verstehen ist: Für jeden Sicherheitstest gibt es einen zugehörigen Curl-Befehl (oder eine andere Form eines Testskripts), sodass Sie den Test bei Codekorrekturen wiederholt durchführen können. Anschließend kann dasselbe Testskript verwendet werden, um zu überprüfen, ob das Problem wirklich behoben ist, ohne den gesamten Test noch einmal ausführen zu müssen.

Als ersten Schritt hin zu nachweisbarer Sicherheit sorgt New Relic IAST für einen echten Shift-Left-Ansatz in der Softwaresicherheit, indem es DevOps und Sicherheitsteams ermöglicht, in enger Zusammenarbeit CI/CD-Pipelines für Continuous Integration und Continuous Deployment zu beschleunigen. So können Unternehmen Innovation fördern und Ihre Anwendungen schon früh im Dev-Lifecycle schützen.

Den Schwerpunkt auf ausnutzbare Schwachstellen zu setzen, hat noch einen Vorteil, denn herkömmlichen Anwendungssicherheitstools fehlt oft der Kontext, was zu einer Alert-Schwemme führen kann. Die rasche Erkennung dringender Sicherheitsrisiken wird so erschwert, ebenso wie die Verifizierung von Sicherheitsverbesserungen. New Relic IAST verringert die Anzahl falsch-positiver Alerts, die bei vielen anderen Lösungen ein Problem darstellt, und liefert einen Proof-of-Exploit.

Sehen wir uns nun an, wie New Relic IAST in der Praxis funktioniert.

Bitte beachten Sie: Bevor ich Ihnen zeige, wie Sie New Relic IAST verwenden können, möchte ich auf einen wichtigen Aspekt hinweisen. New Relic IAST simuliert eine Reihe realer Angriffe innerhalb Ihrer Anwendung. Das bedeutet, dass Testdaten verwendet werden, um ausnutzbare Schwachstellen zu simulieren und zu testen. Aus diesem Grund sollte New Relic IAST nur in Vorproduktionsumgebungen verwendet werden.

New Relic Language Agents

Die neuesten New Relic APM Agents beinhalten jetzt das IAST-Toolset. Wir alle wissen, wie einfach es ist, APM Agents zu einer App hinzuzufügen, um Fehler und Performance-Probleme zu ermitteln. Sehen Sie sich dieses intuitive Beispiel für eine .NET-Umgebung an. Jetzt können wir Ihren benutzerdefinierten Code ohne zusätzlichen Aufwand auch auf die häufigsten Schwachstellen gemäß den OWASP Top 10 testen, z. B. auf Injection-Angriffe.  Meiner Meinung nach ist dies ein unglaublicher Vorteil von New Relic IAST, den viele Stakeholder schätzen werden:

  • Das IT-Team, weil es keinen weiteren Agent bereitstellen muss.
  • Sicherheitsteams, denn dadurch werden Dev-Teams selbst zu Multiplikatoren der Sicherheit.
  • Sie als Entwickler:in, weil es bereits Teil Ihrer Toolkette ist, die Sie bereits verwenden.

Diese Funktion ist sehr einfach zu implementieren. In meinem Beispiel verwende ich die OWASP Juice Shop-Anwendung erneut als Demoumgebung.

Juice Shop ist mit Node.js erstellt und daher füge ich meiner Anwendung den neuesten New Relic Node.js-Agent hinzu (IAST wurde in Version v10.3.0 hinzugefügt).

Wir führen den folgenden Befehl entsprechend der üblichen Vorgehensweise in unserem Repository aus

npm install newrelic

Dadurch wird die New Relic Agent-Bibliothek in unserer Anwendung installiert. Der einfachste Weg, den Agent zu konfigurieren, ist die Definition der folgenden Umgebungsvariablen:

NEW_RELIC_APP_NAME=juice-shop-mysql
NEW_RELIC_LICENSE_KEY=<your New Relic license key>

Sie können nun die restlichen Abhängigkeiten von Juice Shop mit npm install installieren und die Anwendung mit npm start ausführen. Nach kurzer Zeit werden die Daten in Ihrem New Relic Konto in der gewohnten kuratierten Umgebung für APM angezeigt.

Ohne weitere Konfiguration erfasst der Agent alle in Ihrer Anwendung verwendeten Bibliotheken und sucht nach bekannten Schwachstellen. Diese Daten werden im Abschnitt „Vulnerability Management“ Ihres Dienstes in New Relic veröffentlicht.

Aktivieren Sie New Relic IAST

Nachdem der Agent nun betriebsbereit ist und bereits Schwachstellen für Drittanbieter-Bibliotheken meldet, fahren wir mit der Aktivierung der IAST-Funktionen fort.

Ich stoppe die Anwendung und füge zwei zusätzliche Umgebungsvariablen hinzu:

NEW_RELIC_SECURITY_ENABLED=true
NEW_RELIC_SECURITY_AGENT_ENABLED=true

Die erste Umgebungsvariable bestimmt, ob die Sicherheitsdaten an New Relic gesendet werden oder nicht. Wenn dies deaktiviert ist und NEW_RELIC_SECURITY_AGENT_ENABLED wahr ist, wird das Sicherheitsmodul ausgeführt, aber es werden keine Daten gesendet. Mit der zweiten Option können Sie alle Sicherheitsfunktionen allgemein aktivieren oder deaktivieren.

Nachdem wir dies eingerichtet haben, müssen wir nichts weiter konfigurieren. Den Rest erledigt der Agent für uns, sobald die Anwendung erneut ausgeführt wird.

Simulation realer Angriffe

Da die Anwendung nun wieder läuft (durch erneutes Ausführen von npm start ), können wir unsere regulären Unit-Tests ausführen. Im Juice Shop-Repository befinden sich alle Unit-Tests im Ordner test. Beispielsweise können Sie die API-Tests ausführen, indem Sie npm run test:api ausführen. Allein durch das Auslösen dieser Tests identifiziert der Agent den Kontext der Anfrage; d. h. eine Transaktion im New Relic Kontext, einschließlich aller Details zu Parametern, Payload usw.

Unser Juice Shop beinhaltet beispielsweise eine API zur Anmeldung bei der Anwendung. Dieser Endpunkt empfängt z. B. die Anmeldedaten zur Authentifizierung der Benutzer:innen.

Jetzt versuchen wir, uns mit einem vorhandenen Benutzer-Login bei der Anwendung anzumelden.

Nach kurzer Zeit werden Sie feststellen, dass unser Agent in Ihrer Anwendung aktiv wird. Wenn der Agent ein Problem erkennt, fügt er eine Schwachstelle zum Abschnitt „New Relic Vulnerability Management“ hinzu. Der große Unterschied besteht darin, dass dies nur dann geschieht, wenn die Schwachstelle tatsächlich ausnutzbar ist.

Hier ist ein Beispiel.

Ausnutzbare Schwachstellen werden in der Spalte Exploitable durch ein Ausrufezeichen gekennzeichnet. Das bedeutet, dass wir nicht nur ein Problem gefunden haben, sondern auch einen Proof-of-Exploit dafür identifiziert haben. Ein weiterer wichtiger Aspekt bei der Analyse der Schwachstellen ist die Priorisierung dieser Schwachstellenliste nach Schweregrad.

Klicken Sie auf das Problem SQL Injection, um weitere Informationen dazu zu erhalten und zu sehen, wie New Relic den Proof-of-Exploit oder Nachweis der Ausnutzbarkeit erbringt. Hier finden Benutzer:innen eine detaillierte Beschreibung der Sicherheitslücke und spezifischer Vorkommnisse dieses Problems in Ihrem Erstanbietercode.

Wenn Sie auf eine der SQL Injection-Instanzen klicken, erhalten Sie weitere Informationen über die Position in Ihrem Quellcode, und wie Sie das Problem beheben können.

Behebung einer ausnutzbaren Sicherheitslücke

Eine der Hauptfunktionen von New Relic IAST ist der von New Relic bereitgestellte Wiederholungstest. Im Abschnitt Test auf dem Bildschirm finden Sie ein Testskript, mit dem Sie die Ausnutzbarkeit nachweisen können. In unserem Fall führen wir dieses Skript aus, um zu beweisen, dass SQL Injection tatsächlich ein echtes und ausnutzbares Problem in Juice Shop ist.

Jetzt öffnen wir ein Terminal und führen den folgenden Befehl aus, den wir aus der New Relic UI kopieren. Bitte beachten Sie: Ich habe die vollständige URL in der ersten Zeile des Skripts hinzugefügt. Zusätzlich habe ich den data-raw-Parameter leicht angepasst.

curl --location --request POST 'https://wxmqzkpgeu.us-east-1.awsapprunner.com/rest/user/login' \
--header 'x-forwarded-proto:https' \
--header 'user-agent:Mozilla/5.0 (Macintosh;Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67;' \
--header 'accept:application/json, text/plain, */*' \
--header 'sec-ch-ua-platform:"macOS"' \
--header 'sec-ch-ua-mobile:?0' \
--header 'sec-fetch-site:same-origin' \
--header 'accept-encoding:gzip, deflate, br' \
--header 'accept-language:de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6;' \
--header 'host:wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'cookie:language=en;welcomebanner_status=dismiss;cookieconsent_status=dismiss;' \
--header 'origin:https://wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'x-envoy-expected-rq-timeout-ms:120000' \
--header 'content-type:application/json' \
--header 'sec-fetch-dest:empty' \
--header 'x-request-id:dfc1b83b-5e24-4cb6-877b-20913a9cd54f' \
--header 'sec-ch-ua:"Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114";' \
--header 'sec-fetch-mode:cors' \
--header 'x-forwarded-for:79.252.203.104' \
--header 'referer:https://wxmqzkpgeu.us-east-1.awsapprunner.com/' \
--header 'x-envoy-external-address:79.252.203.104' \
--data-raw '{"email": "1'"'"' OR TRUE; #","password":"12345"}'

Nachdem dieses Skript ausgeführt wurde, werden Sie feststellen, dass wir einige JSON-Daten mit Informationen vom Juice Shop-Admin-Benutzer zurückerhalten. Das ist natürlich nicht das, was die Anwendung bieten sollte, und beweist, dass tatsächlich ein kritisches Problem und damit eine Schwachstelle vorliegt.

Die von New Relic IAST gemeldete Schwachstellenposition zeigt uns, dass eines der SQL Injection-Probleme in „/rest/user/login“ zu finden ist.

Sehen wir uns den Quellcode der Anwendung an und öffnen die Datei „server.ts“. (im Stammverzeichnis des Repositorys). Im Bereich um Zeile 543 sehen Sie, welche Methode tatsächlich aufgerufen wird, wenn jemand auf den Endpunkt „/rest/user/login“ zugreift. Die Methode „login()“ wird ausgeführt und diese ist in „/routes/login.ts“ zu finden. Als Entwickler:in kann ich sehen, wie die SQL-Abfrage verkettet wird, indem die Benutzereingabe direkt in die SQL-Anweisung eingefügt wird (Zeile 36).

models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: UserModel, plain: true })

Dies zählt definitiv nicht zu den Best Practices und Entwickler:innen sollten es vermeiden, solche SQL-Abfragen zu erstellen.

Idealerweise würden Sie parametrisierte Abfragen verwenden. Im „sequelize“-Framework wird dies als replacements oder Ersetzungen bezeichnet. Idealerweise sollten wir also Parameter in der Abfrage selbst verwenden und sie mithilfe des Ersetzungskonzepts durch den Inhalt ersetzen. Der aktualisierte Code sollte etwa so aussehen:

models.sequelize.query(`SELECT * FROM Users WHERE email = :email AND password = :password AND deletedAt IS NULL`,
      {
        model: UserModel,
        plain: true,
        replacements: {
          email: req.body.email || '',
          password: security.hash(req.body.password || '')
        }
      })

Jetzt beheben wir dieses Codeproblem und stellen die Anwendung erneut bereit. Da nun die neue Version unserer App läuft und Daten an New Relic gehen, können wir unser Test-Curl-Skript erneut ausführen.

Danach erhalten wir nicht mehr das gleiche Ergebnis wie zuvor (also die Anmeldeinformationen des/der Juice Shop-Admin-Benutzer:in). Wir erhalten stattdessen die Meldung, dass wir eine ungültige E-Mail-Adresse oder ein ungültiges Passwort angegeben haben. Dies ist tatsächlich das, was wir erwarten, und beweist, dass unser Bugfix im Erstanbieter-Quellcode den Fehler tatsächlich behoben hat.

Wenn wir nun zurück zu unserer New Relic Benutzeroberfläche wechseln und in der Anwendung zum Abschnitt Vulnerability Management navigieren, werden Sie feststellen, dass die beiden ausnutzbaren Schwachstellen noch immer angezeigt werden. Allerdings sehen Sie auch, dass SQL Injection zuletzt vor ca. vier Stunden erkannt wurde, das Problem Reflected XSS jedoch immer noch besteht, da es nach dem Deployment erneut gemeldet wurde.

Fazit

Was ich Ihnen in diesem Beispiel gezeigt habe, ist der vollständige Ablauf eines interaktiven Anwendungssicherheitsscans. Ihre Anwendung wird untersucht und Tests werden ausgeführt, um ausnutzbare Schwachstellen zu finden.

Dabei haben wir nicht nur ein Problem identifiziert, sondern auch bestimmte Instanzen mit Testskripten erhalten, die wir wiederholt ausführen konnten, um tatsächlich zu beweisen, dass die identifizierten Probleme tatsächlich ausnutzbar sind. Nachdem wir das Problem in unserem Erstanbietercode behoben hatten, erstellten wir eine neue Version unserer Anwendung und stellten sie bereit. Diesmal konnten die Tests unseres New Relic IAST Agent für diesen Bereich unserer Anwendung nicht erfolgreich ausgeführt werden. Ich konnte die erfolgreiche Fehlerbehebung nachweisen, indem ich dasselbe Testskript ausführte und die Bestätigung erhielt, dass dies in unserer Anwendung kein Problem mehr darstellt.