Guten Tag, liebe Leser. Mein Name ist Victor Burov, ich bin Entwickler bei ISPsystem. Im letzten Beitrag habe ich über das
Tool zum Erstellen von Autotests gesprochen . Heute werde ich meine Erfahrungen bei der Automatisierung von Sicherheitstests teilen.

Zunächst wurden Schwachstellen in Produkten von einem separaten Mitarbeiter durchsucht. Manuelle Tests nahmen viel Zeit in Anspruch und garantierten nicht, dass alle Schwachstellen gefunden wurden. Nachdem wir die Grundgesetze des Testens ermittelt hatten, kamen wir zu dem Schluss, dass es automatisiert werden kann. Dann haben wir uns entschlossen, ein Dienstprogramm zu schreiben, das dem Tester das Leben erleichtert, ihm Zeit spart und es Ihnen ermöglicht, die Produkte nach jeder Änderung zu überprüfen. Da der Tester Lida hieß, haben wir die neue Anwendung zu ihren Ehren benannt. Im Allgemeinen ist es in unserem Unternehmen zur Tradition geworden, Testwerkzeuge mit den Namen von Testern zu bezeichnen.
Nach der Analyse der Dienstprogramme zur Suche nach Sicherheitslücken kam ich zu dem Schluss, dass alle die aufzurufenden Funktionen und die verwendeten Parameter angeben müssen. Wir haben uns erneut entschlossen, die einheitliche Schnittstelle zu nutzen und die Anforderungen für Lida zu formulieren.
Startvoraussetzungen:
- Funktionslisten automatisch erstellen.
- Optionen für die automatische Vervollständigung.
- API-Anfragen stellen.
- Analyse der Datenausgabe nach Ausführung von Funktionen.
- Suchen Sie nach Schwachstellen in Daten.
- Erstellung von Berichten.
- Flexible Einstellungen.
All dies zu realisieren war nicht einfach.
Implementierung
Formulare und Listen umgehen
Um Schwachstellen in einer Funktion zu finden, muss diese ausgeführt werden, indem die erforderlichen Parameter übergeben werden. Unsere Schnittstelle basiert auf Listen und Formularen, sodass Sie die Datenerfassung automatisieren können, indem Sie XML-Dokumente verarbeiten, die die Struktur der Schnittstellenelemente beschreiben.
Ich beschloss, den Crawl über das Hauptmenü zu starten und rekursiv in alle verschachtelten Listen zu gehen. "Lida" öffnet die Liste der ersten Ebene. In der Regel verfügt es über mehrere Schaltflächen, die einige Funktionen aufrufen.
Wenn die Schaltfläche das Formular öffnet, ist das Ergebnis des Aufrufs ein XML-Dokument mit Knoten, die Informationen zu den Feldern enthalten: Name, Validator, Bereich gültiger Werte. Basierend auf diesen Informationen werden Feldwerte generiert. Beispielsweise wird eine Nummer für int generiert. Wenn kein Validator vorhanden ist, wird eine zufällige Zeichenfolge generiert. Nach dem Ausfüllen aller Felder des Formulars wird eine Anfrage gesendet.
Wenn es sich bei der Funktion um eine Liste handelt, wird sie geöffnet und die mit den Schaltflächen verknüpften Funktionen werden für ihre Elemente aufgerufen.
Beim Überprüfen von Listen tritt ein Problem auf: Alle Listen müssen über eine Reihe von Datensätzen verfügen, die sicherstellen, dass alle Schaltflächen in der Liste anklickbar sind.
SQL-Injection-Suche
Die SQL-Injection ist wahrscheinlich eines der häufigsten Probleme für Anwendungen, einschließlich unserer. Viele Funktionsaufrufe generieren verschiedene DBMS-Abfragen. Ein Fehler tritt auf, wenn Parameter, die von außen kommen, "wie sie sind" in den Anforderungshauptteil eingesetzt werden. Die Folgen solcher Fehler können traurig sein: vom unbefugten Empfang von Daten bis zum Löschen von Tabellen.
Um die Suche nach SQL-Injektionen zu starten, habe ich die Ausgabe aller SQL-Abfragen in einer Datei organisiert. Nachdem die Funktion ausgeführt wurde, sucht die Anwendung in den resultierenden SQL-Abfragen nach den Werten der übergebenen Parameter.
Sie können das Protokoll des SQL Servers selbst verwenden. In unserem Fall gibt es jedoch nur eine Methode zum Ausführen von Abfragen, und das Hinzufügen von Protokollierung war nicht schwierig. Dank dessen wissen wir genau, welche Herausforderung diese oder jene Anfrage ausgelöst hat.Wenn der Wert des übergebenen Parameters gefunden wird, übergibt das Dienstprogramm einen Wert mit einem einfachen Anführungszeichen an diesen Parameter. Wenn das Anführungszeichen in derselben Reihenfolge gefunden wird, wird der Parameter nicht maskiert - wir haben einen Platz für die SQL-Injection gefunden.
Systemaufrufanalyse
Ein ähnliches Problem tritt auf, wenn wir Systemaufrufe tätigen. Ich entschied mich, sie mit Strace zu suchen und wählte die optimalen Startparameter dafür aus. Beispiel für den Start von ISPmanager:
strace -f -s 1024 -e trace=file,process bin/core ispmgr
Neben SQL-Injections führt Lida eine Funktion aus und analysiert die Strace-Ausgabe, um festzustellen, ob die Werte der Parameter
open, unlink, rmdir, chmod chown, chflags, mknod, mkfifo, fcntl, symlink, link, execve, mkdir enthalten sind .
Wenn der Parameter gefunden wird, übergibt das Dienstprogramm einen Wert an ihn, der beispielsweise einen Pfad mit einem Übergang zum obigen Verzeichnis enthält. Wenn es so wird, wie es ist, wird eine potenzielle Sicherheitslücke gefunden.
Die Analyse der Execve-Funktion hat sich als sehr nützlich erwiesen. Hier können Sie bestimmen, in welchen Funktionsargumenten ausführbare Dateien nicht maskiert werden sollen. Dieser Fehler ist sehr teuer, da Sie dadurch durch einfaches Ändern des Kennworts Root-Zugriff auf den Server erhalten können.
Wenn Benutzer eine Sicherheitslücke in unseren Produkten finden, zahlt das Unternehmen eine Geldprämie, deren Höhe von der Kategorie der Sicherheitslücke abhängt. Dieser Ansatz kann billiger sein als die eigene Suche nach Fehlern (der Tester findet den Fehler möglicherweise nicht und erhält ein Gehalt).
Ein weiterer interessanter Test: Überprüfen der Reihenfolge des Aufrufs der stat-Funktionen und anderer. Oft wird der Zugriff zuerst durch stat und dann durch einige unsichere Aktionen überprüft, wodurch die Möglichkeit einer Substitution besteht. Dies haben wir jedoch nicht automatisiert.Überprüfen des Zugriffs auf Fremdkörper
Wir überprüfen den Zugriff auf Fremdkörper unter dem Benutzer auf die Entitäten eines anderen Benutzers und Administrators. In diesem Modus überprüfen wir die Fähigkeit, die Listen der Elemente eines fremden Benutzers zu lesen, zu ändern und anzuzeigen.
Lida umgeht alle Funktionen, die im Namen des Eigentümers oder Administrators verfügbar sind, und merkt sich deren Elemente. Dann ruft es die gleichen Funktionen mit Elementen unter einem anderen Benutzer auf. Im Idealfall sollte die Antwort ein Fehler wie "Zugriff" oder "Verpasst" sein. Wenn ein solcher Fehler nicht empfangen wird, ist es sehr wahrscheinlich, dass Sie die Daten eines anderen Benutzers lesen können.
In einigen Fällen bedeutet das Fehlen eines Fehlers nicht, dass Sie direkt auf die Objekte anderer Benutzer zugreifen können. Zu Beginn solcher Funktionen fügen wir eine Elementberechtigungsprüfung hinzu. Dies überprüft nicht nur die Sicherheit, sondern auch die Richtigkeit der Serverantworten.
API-Validierung
Die Validierung unserer API ist ein zusätzlicher Bonus für die Überprüfung von Funktionen auf Schwachstellen. Bei der Analyse von Berichten über die Arbeit von Lida haben wir gelernt, die richtigen Fehlertypen zurückzugeben, und unsere API komfortabler und logischer gestaltet. Infolgedessen haben wir wie beim Kassettenrekorder nicht nur eine Sicherheitsüberprüfung erhalten, sondern auch unsere API erneut auf „Konsistenz“ überprüft.
Schwierigkeiten
False Positives
Das Dienstprogramm kann mit allen unseren Produkten arbeiten und überprüft daher viele verschiedene Funktionen. Grundsätzlich wurden bei der Überprüfung des Zugriffs auf Fremdkörper falsch positive Ergebnisse angezeigt. Dies liegt an den Merkmalen der Tasten und Funktionen.
False Positives waren Lidas größtes Problem. Es schien, dass es vollständig debuggt war, aber bei der Überprüfung auf verschiedenen Panels traten neue Fehlalarme auf. Infolgedessen gab es mehrere Stufen ihrer Korrektur.
Entitätserstellung
Die meisten Aktionen im Bedienfeld werden für eine beliebige Entität (Domänenname, Datenbank usw.) ausgeführt. Um eine maximale Automatisierung zu erreichen, musste Lida diese Entitäten automatisch erstellen. In der Praxis erwies sich dies jedoch als schwierig umzusetzen. Manchmal wird die Validierung im Code durchgeführt, sodass es nicht immer möglich ist, einen Parameterwert automatisch zu ersetzen. Der zweite Grund sind abhängige Einheiten. Um beispielsweise ein Postfach zu erstellen, müssen Sie eine E-Mail-Domäne erstellen.
Deshalb haben wir uns entschieden, nicht für die vollständige Automatisierung zu kämpfen. Vor dem Start erstellt der Tester Entitäten manuell und erstellt eine Momentaufnahme des Computers, da Entitäten nach der Überprüfung geändert werden. Auf diese Weise können Sie die Überprüfung einer Gruppe von Funktionen nicht überspringen, wenn eine Entität nicht erfolgreich erstellt wurde.
Destruktive Funktionen aufrufen
Fast jede Liste verfügt über Funktionen zum Löschen oder Deaktivieren einer Entität. Wenn Sie sie nacheinander ausführen, wird die Entität gelöscht, bevor andere Funktionen ausgeführt werden. Ich definiere solche Funktionen und führe nach anderen aus. Zusätzlich wurde ein Schlüssel hinzugefügt, der die Ausführung solcher Funktionen verhindert.
Einige Funktionen starten den Server neu. Sie müssen verfolgt und zur Liste der Ignorierten hinzugefügt werden.
Aufgrund der Art der Betriebslogik starten einige Funktionen das Panel neu. Während der Sicherheitstests wird das Panel gestartet, ohne SQL-Abfragen oder Strace zu verfolgen. Eine weitere Überprüfung ist bedeutungslos. Sie müssen dies verfolgen und das Panel im Trace-Modus neu starten.
Abhängige Parameter prüfen
In Formularen gibt es Felder zur Texteingabe, Kontrollkästchen und Dropdown-Listen, von deren Werten die Verfügbarkeit von Werten anderer Felder abhängt. Jeder Wert des abhängigen Feldes kann einen separaten Codeabschnitt haben, daher die Teile, wenn sie möglicherweise nicht überprüft werden.
Um dieses Problem zu lösen, habe ich Algorithmen zum Analysieren abhängiger Felder und zum Überprüfen aller Kombinationen abhängiger Steuerelemente hinzugefügt.
Überprüfen von Funktionen, die in der Benutzeroberfläche nicht verfügbar sind
Servicefunktionen stehen für den Übergang nicht zur Verfügung, können jedoch Schwachstellen enthalten. Um sie zu identifizieren und zu überprüfen, haben wir eine spezielle Funktion, die eine Liste aller registrierten Funktionen zurückgibt. Wir vergleichen diese Liste mit der Liste der getesteten Funktionen. Es gibt keine Metadaten für Dienstprogrammfunktionen, daher ist es unmöglich, die darin verarbeiteten Parameter zu überprüfen. Um solche Funktionen irgendwie zu überprüfen, übergebe ich ihnen unsere Standardparameter
elid, plid und andere.
Fazit
Wir haben Lida in jeden Nachtaufbau in Jenkins aufgenommen. Basierend auf den Ergebnissen seiner Arbeit wird ein Verifizierungsbericht erstellt, in dem Informationen über die darin enthaltene verdächtige Funktion mit allen Parametern angezeigt werden.
Die vom Entwickler geschlossene Aufgabe wird nun nicht nur vom Tester, sondern auch von Lida geprüft. Der Tester verarbeitet den empfangenen Bericht: Kopiert die Parameter der verdächtigen Funktion in den Browser und analysiert das Verhalten und das Protokollfenster. Wenn die Sicherheitsanfälligkeit bestätigt wird, wird der Fehler beim Entwickler protokolliert.