
Hallo habr
In dem Artikel möchte ich über unsere Erfahrungen bei der Erstellung meiner Abfragen in Checkmarx SAST sprechen.
Wenn Sie sich zum ersten Mal mit diesem Analysegerät vertraut machen, haben Sie möglicherweise den Eindruck, dass es nicht nur nach schwachen Verschlüsselungs- / Hashing-Algorithmen und einer Menge falsch positiver Ergebnisse sucht, sondern auch nichts anderes zurückgibt. Aber wenn es richtig konfiguriert ist, ist es ein sehr leistungsfähiges Tool, das nach schweren Fehlern suchen kann.
Wir werden die Feinheiten der Checkmarx SAST-Abfragesprache verstehen und 2 Abfragen schreiben, um nach SQL-Injections und Insecure Direct Object References zu suchen.
Eintrag
Nach langem Suchen nach Anleitungen oder Artikeln zu Checkmarx wurde mir klar, dass es neben der offiziellen Dokumentation nicht genügend nützliche Informationen gab. Und die offizielle Dokumentation besagt nicht, dass alles sehr klar und verständlich wird. Zum Beispiel konnte ich keine Best Practices finden, wie man Überschreibungsabfragen richtig organisiert, wie man Abfragen "für Dummies" schreibt usw. Ja, es gibt eine Dokumentation zu den CMx Query Language-Funktionen, aber hier ist, wie man diese Funktionen in einer einzigen Abfrage kombiniert. Die Dokumentation ist nicht geschrieben.
Vielleicht ist das Fehlen von Artikeln und Anleitungen aus der Checkmarx-Community mit den hohen Kosten des Tools und demzufolge einem kleinen Publikum verbunden. Oder vielleicht kümmern sich nur wenige Leute um die Feinabstimmung und verwenden die Lösung wie sie ist.
Meiner Erfahrung nach wird SAST eher zur Erfüllung von Formalitäten im Zusammenhang mit verschiedenen Kundenanforderungen verwendet, als zur Suche nach echten Fehlern. Infolgedessen haben wir bestenfalls eine relativ kleine Anzahl von „Schwachstellen“, die fast automatisch als „nicht ausnutzbar“ bezeichnet werden (da dies in 99,9% der Fälle der Fall ist).
Es sollte beachtet werden, dass Checkmarx selbst versucht, ihre Abfragen zu aktualisieren, damit sie sofort das beste Ergebnis liefern. CMx Query Language-Abfragen sind jedoch auf den „allgemeinen Fall“ zugeschnitten. Die anfängliche Suche nach Tokens basiert auf dem Namen. CMx SAST geht beispielsweise davon aus, dass alle Abfragen an die Datenbank folgendermaßen aussehen: * createQuery * oder * createSQLQuery *. Wenn jedoch die interne Entwicklung für die Arbeit mit der Datenbank verwendet wird und die Methode zum Abfragen der Datenbank anders aufgerufen wird, z. B. * driveMyQuery *, werden alle SQL-Methoden übersprungen. Beispielsweise verwendet unser Kunde benutzerdefiniertes ORM für SQL DB. In diesem Fall haben CMx-Abfragen alle SQL-Injections übersprungen.
Abkürzungen und Definitionen
CMx - Checkmarx SAST.
CMxQL - Checkmarx SAST-Abfragesprache
Token - Ein String mit einem bestimmten Wert ist das Ergebnis der Arbeit des lexikalischen Analysators (auch Tokenisierung genannt).
Anwendung testen
Um einen Artikel zu schreiben, skizzierte ich Java-Code, eine kleine Testanwendung. Dieser Code ist eine ungefähre Kopie eines kleinen Teils des realen Systems. Obwohl sich der Code der Testanwendung im Allgemeinen von keinem anderen HTTP-Backend-Code stark unterscheidet. Wichtige Abschnitte des Testanwendungscodes werden in den Screenshots angezeigt.
Die Testanwendung hat folgenden Aufbau
WebRouter- Klasse zur Verarbeitung eingehender HTTP-Anfragen, 4 Methoden zur Verarbeitung von URLs:
- / getTransaction - akzeptiert die Transaktions- ID bei der Eingabe und gibt die Informationen dazu zurück, nimmt sie als Zeichenfolge und übergibt sie an getTransactionInfo (transactionId) => getTransactionInfo (transactoinId ).
- / getSecureTransaction - akzeptiert die Transaktions- ID als Eingabe und gibt die Informationen dazu zurück. id nimmt sie als Zeichenfolge und übergibt sie Fall, dass die Injektion nicht ausgenutzt wird);
- / getSettings - akzeptiert die Benutzer- ID und die Postfach- ID als Eingabe - und gibt die Postfacheinstellungen aus. Überprüft nicht, ob die Mailbox-ID dem Benutzer gehört.
- / getSecureSettings - akzeptiert auch die Benutzer- ID und die Postfach- ID für die Eingabe und zeigt die Postfacheinstellungen an. ABER prüft, ob die Mailbox-ID dem Benutzer gehört.
CMx: Allgemeine Informationen und grundlegende Definitionen
Bevor Sie mit der Entwicklung von Abfragen beginnen
Die Entwicklung von Abfragen erfolgt in einem separaten Programm CxAuditor. In CxAuditor müssen Sie den gesamten Code scannen (lokales Projekt erstellen), für das wir Abfragen schreiben. Danach können Sie neue Abfragen schreiben und ausführen. Bei einer großen Codebasis kann das primäre Scannen Stunden dauern und Gigabyte an Speicher beanspruchen. Danach wird jede Anfrage nicht schnell genug ausgeführt. Dies ist für die Entwicklung völlig ungeeignet.
Aus diesem Grund können Sie eine kleine Menge von Dateien aus dem Projekt entnehmen, idealerweise mit einem Fehler, der im Code vor dem Typ gefunden wurde, unter dem die Anforderung geschrieben wird (oder den Fehler manuell dort abgelegt), und nur diese Dateien durchsuchen. Es ist nicht erforderlich, die Dateistruktur des Projekts einzuhalten. Das heißt, wenn Sie über Java-Paket A und B verfügen und die Klassen in Paket B die Klassen und Methoden von Paket A verwenden, können Sie all dies in ein einziges Verzeichnis packen, und CMx wird die Beziehungen und Aufrufketten zwischen Dateien immer noch richtig (gut oder fast) verstehen immer korrekt, obwohl Fehler kaum mit der Dateistruktur des Projekts zusammenhängen).
Grundlegende Definitionen
Cxlist
Der Hauptdatentyp in CMx. Das Ergebnis fast aller CMxQL-Funktionen ist
CxList . Dies sind viele Elemente mit bestimmten Eigenschaften. Die Eigenschaften, die für die Entwicklung am nützlichsten sind, werden unten betrachtet.
Ergebnis
CMxQL hat ein eingebautes variables
Ergebnis . Die Menge, die die
Ergebnisvariable enthält, wird nach Ausführung der gesamten Abfrage als Ergebnis angezeigt.
Das heißt, die letzte Operation einer Abfrage sollte das Zeichenfolgenergebnis
= WHATEVER sein , zum Beispiel:
result = All.FindByName("anyname");
Flow- und Code-Element
Die meisten CMxQL-Funktionen werden nach dem Typ der zurückgegebenen Werte in zwei Funktionen unterteilt, die "Codeelemente" zurückgeben und die Flow zurückgeben. In beiden Fällen ist das Ergebnis eine
CxList . Der Inhalt unterscheidet sich jedoch geringfügig für Flow- und Code-Elemente.
- Codeelement - Token - zum Beispiel eine Variable, ein Methodenaufruf, eine Zuweisung usw .;
- Flow - die Beziehung zwischen den gegebenen Token.
Alle und "Unter" Alle
Jede CMxQL-Funktion kann entweder für die Gruppe "
Alle" (sie enthält alle Token des gesamten gescannten Codes, wir haben bereits ein Beispiel mit
Ergebnis gesehen ) oder für die
Gruppe "CxList" ausgeführt werden , die wiederum als Ergebnis einiger Operationen in der Abfrage abgerufen wurde, beispielsweise der Abfrage:
CxList newList = CxList.New();
erstellt eine leere Menge, die wir dann mit der
Add () -Methode mit Elementen füllen und dann bereits nach den Elementen der neuen Menge suchen können:
CxList newFind = newList.FindByName("narrowedScope");
Eigenschaften der gefundenen Gegenstände
Jedes Element der CxList-Gruppe verfügt über mehrere Eigenschaften. Bei der Analyse der Ergebnisse zum Schreiben von Abfragen sind die folgenden am nützlichsten:
- SourceFile - der Name der Datei, die dieses Element enthält;
- Source Line - Zeilennummer mit Token;
- Quellenname - Der Name des Tokens. Entspricht dem Token, d. H. Wenn die Variable var1 heißt, ist der Quellenname = var1;
- Quelltyp - Der Typ des Tokens. Wenn es sich beispielsweise um eine Zeichenfolge handelt, ist dies StringLiteral, wenn die Methode aufgerufen wird, MethodInvokeExpr und viele andere.
- Zieldatei
- Ziellinie;
- Zielname;
- Zieltyp.
Quelle und Ziel unterscheiden sich, wenn die Elemente der Ergebnismenge Flow sind, und umgekehrt, wenn das Ergebnis Codeelemente sind.
Erstellen Sie Abfragen
Alle CMxQL-Funktionen können in verschiedene Typen unterteilt werden. Hier kann man meiner Meinung nach den Hauptnachteil der CMxQL-Dokumentation bemerken, alle Funktionen im Dock werden einfach in alphabetischer Reihenfolge beschrieben, während es viel bequemer wäre, sie nach der Funktionalität und nur dann alphabetisch zu strukturieren.
- Suchfunktionen - fast alle CMxQL-Funktionen mit den Namen FindBy * und GetBy * ;
- Die Funktionen von Operationen auf Mengen sind Addition, Subtraktion, Schnittmenge, Iteration über Elemente usw.
- Analysefunktionen - Dies sind im Grunde * InfluencedBy * * InfluencingOn * -Funktionen.
Das Grundprinzip von Abfragen ist die Abwechslung dieser Arten von Funktionen. Zunächst wählen wir mithilfe der Suchfunktionen nur die Token aus, die uns aufgrund bestimmter Eigenschaften interessieren. Mit Operationen auf Mengen können wir verschiedene Mengen mit verschiedenen Token-Eigenschaften zu einer kombinieren oder umgekehrt die andere von einer subtrahieren. Anschließend erstellen wir mithilfe der Analysefunktionen den Code Flow und versuchen zu verstehen, ob die potenziellen Schwachstellen von den Parametern an den Einstiegspunkten abhängen.
Die Wahl des Ortes, von dem aus die Suche gestartet werden soll, und im Allgemeinen der gesamte Suchpfad, hängt vom spezifischen Code ab, genauer gesagt sogar vom „Text“. In einigen Fällen ist es bequem, vom Einstiegspunkt aus nach Benutzerabfragen zu suchen, in einigen Fällen ist es bequemer, vom „Ende“ oder sogar von der Mitte aus zu beginnen. Es hängt alles vom spezifischen Code ab und Sie müssen jedes Repository einzeln ansprechen.
Beispiel: SQL-Injection durchsuchen
Suchplan, in Klammern habe ich den Namen der Mengen angegeben (Variablen in der Abfrage):
- Ausnahmen definieren - Token, die sofort aus dem Suchbereich entfernt werden können ( exclusionList );
- Bestimmen Sie den Ort der Desinfektion / Sicherheitskontrollen ( Desinfektion );
- Finde alle Low-Level-Stellen mit Abfrageausführung in der Datenbank ( runSuperSecureSQLQuery );
- Finde alle Parameter der aufgerufenen Methoden runSuperSecureSQLQuery ( runSSSQParams );
- Suchen von Einstiegspunkten (übergeordnete Methoden und deren Parameter) für die Orte der Abfrageausführung in der Datenbank ( entryPointsParameters );
- Ermitteln Sie die Abhängigkeiten von runSSSQParams- Parametern von entryPoints , während nur die Stellen angezeigt werden , an denen keine Bereinigung der Eingabebereinigung erfolgt .
Als Ergebnis erhalten wir Low-Level-Methoden mit SQL-Abfragen, bei denen die Parameter der SQL-Abfrage:
- hängen von den Parametern der Methode ab;
- Parameter werden als Zeichenfolgen akzeptiert.
- Parameter werden mit der Anforderung verknüpft.
Wir werden nicht prüfen, ob wir diese Parameter kontrollieren können Wir glauben, dass es einen Mechanismus zum Zuordnen von Variablen zu einer Abfrage gibt und dass Zahlen in einen numerischen Typ umgewandelt werden. Die Verkettung von Zeichenfolgen wird immer als gefährlich angesehen. Auch wenn die Leitung derzeit nicht kontrolliert wird, wird sie möglicherweise in der neuen Version angezeigt.
SQLi: Schritt 1. Ausnahmen definieren
In Ausnahmefällen müssen Sie die Klassen oder Dateien hinzufügen, deren Tokennamen mit den gesuchten übereinstimmen können, weil Diese Token führen zu ungültigen Einträgen.
Eine Methode für den Zugriff auf eine Datenbank heißt beispielsweise
runSuperSecureSQLquery . Wir gehen davon aus, dass die
darin enthaltene Methode
runSuperSecureSQLquery sicher implementiert ist. Und unsere Aufgabe ist es, Orte zu finden, an denen es nicht sicher ist, die Methode selbst anzuwenden. Bei der SQL-Injection sind Orte der Verkettung von benutzergesteuerten Parametern keine sicheren Orte. Und sichere Orte für die Zuordnung von Parametern in die ORM-Struktur oder zum Beispiel für numerische Parameter, dies ist eine Umwandlung in den entsprechenden Typ. Wir müssen nicht den gesamten Code scannen, der "tiefer" liegt als
runSuperSecureSQLquery . Das heißt, es ist besser, ihn auszuschließen, um unnötige Fundstellen zu vermeiden.
Um nach solchen Ausnahmen zu suchen, ist es zweckmäßig, die CMxQL-Funktionen zu verwenden:
- FindByFileName () - Findet die Menge aller Token in einer bestimmten Datei.
- GetByClass () - Findet die Menge aller Token in der Klasse mit dem angegebenen Namen.
Bei einer
Testanwendung ist dies die
Session- Klasse, die die Implementierung der
runSuperSecureSQLquery- Methode enthält.
Ein Beispiel für eine Anforderung zum Ausschließen von Code in der
Session- Klasse (die
GetByClass () -Methode überprüft, welche der an die Eingabe übergebenen Token einen CMx-Typ von
ClassDecl aufweisen und viele Token dieser Klasse ausgeben).
CxList exclusionList = All.GetByClass(All.FindByName("*Session*")); result = exclusionList;
Eine andere Möglichkeit besteht darin, Code in die gesamte
Session.java- Datei zu werfen:
CxList exclusionList = All.FindByFileName("*Session.java"); result = exclusionList;
Das Sternchen vor dem Namen ist wichtig, da der Dateiname den gesamten Pfad enthält.
Jetzt haben wir viele Token, die in den nächsten Schritten vom Suchbereich abgezogen werden können.
Das Ergebnis der Suche nach Tokens in der
Session- Klasse:

SQLi: Schritt 2. Bestimmen der Desinfektionsorte
Die Testanwendung enthält 2 API-Methoden (siehe kurze Beschreibung der Testanwendung). Der Unterschied zwischen den beiden API-Methoden besteht darin, dass
getTransactionInfo () den transactionId-Parameter in der SQL-Abfrage verkettet und
getTransactionInfoSecured () zuerst transactionId in Long
konvertiert und dann als Zeichenfolge übergibt. Sicherheitslücke (Parameterverkettung) ist in beide Methoden eingebettet. Dank dem Casting auf Long in
getTransactionInfoSecured () ist die letzte Methode jedoch nicht anfällig für Injection, da beim Versuch, eine Injection (String) zu übergeben, eine Java-Ausnahme auftritt.
In diesem Beispiel betrachten wir die Besetzung von Long als Sanitärstandort. So finden Sie diese Token:
CxList sanitization = All.FindByName("*Long*"); result = sanitization;
Beispielergebnis:

Das Ergebnis enthielt Token mit den YP-Methoden
Long und
getValueAsLong , die
den Wert intern
in den Typ
Long konvertieren . Sie müssen das Ergebnis sorgfältig prüfen, um sicherzustellen, dass keine zusätzlichen Informationen vorhanden sind.
SQLi: Schritt 3. Finden Sie alle Low-Level-Stellen mit Abfrageausführung in der Datenbank
Die folgende Abfrage findet alle Orte mit dem runSuperSecureSQLQuery-Token (mit dem auf die Datenbank zugegriffen wird):
result = All.FindByName("*runSuperSecureSQLQuery*")
Suchergebnis nach Tokenname runSuperSecureSQLQuery:

Außerdem werden für Stellen, an denen diese Methode aufgerufen wird (
Abrechnungsklasse ), nur Methodenaufruftoken (Typ
MethodInvokeExpr ) und für die Methodendeklarationsstelle (
Sitzungsklasse ) auch alle Token - Variablen gefunden.
Wir filtern nur die Methodenaufruftoken heraus:
CxList runSuperSecureSQLQuery = All.FindByName("*runSuperSecureSQLQuery*").FindByType(typeof(MethodInvokeExpr)); result = runSuperSecureSQLQuery;
Ergebnis:

Als Ergebnis erhielten wir 7 Stellen, davon 4 die erforderlichen Aufrufe der
runSuperSecureSQLQuery () -Methode (
Billing- und
User- Klassen). 2 - ruft die interne Methode runSuperSecureSQLQuery () in der
Session- Klasse auf, und eine weitere Methode ist die
add- Methode, bei der es sich eher um eine CMxQL-Suche handelt. Sagen wir einfach, dass ich nicht damit gerechnet habe, dass es in der Liste enthalten ist =) Die Token in der
Session- Klasse, wie wir in Schritt 1 herausgefunden haben, sind für uns nicht interessant, deshalb werden wir sie einfach vom Ergebnis abziehen:
CxList runSuperSecureSQLQuery = All.FindByName("*runSuperSecureSQLQuery*").FindByType(typeof(MethodInvokeExpr)); result = runSuperSecureSQLQuery - exclusionList;
Wir erhalten eine gültige Liste der Aufrufe der gewünschten Methode:

Beachten Sie die Funktionen
FindByType () und
typeof () in der vorherigen Abfrage. Wenn wir nach CMx-Typ suchen möchten, dh nach der
CxList- Eigenschaft „Source Type“ - dann verwenden wir
typeof (Source Type) . Wenn wir eine Suche nach Datentyp durchführen möchten, müssen wir den Parameter nur als Zeichenfolge übergeben. Zum Beispiel:
result = All.FindByType("String");
findet alle Java-Token mit dem Typ String.
SQLi: Schritt 4. Suchen Sie alle Parameter der runSuperSecureSQLQuery-Methode
Zur Suche nach Methodenparametern wird die CMxQL-Funktion
GetParameters () verwendet :
CxList runSSSQParams = All.GetParameters(runSuperSecureSQLQuery); result = runSSSQParams;
Ergebnis:

SQLi: Schritt 5. Suchen Sie Einstiegspunkte für Abfrageausführungsorte in der Datenbank
Dazu erhalten wir zuerst die Namen der übergeordneten Methoden, in denen sich die Aufrufe der
runSuperSecureSQLQuery- Datenbank befinden, und dann deren Parameter. Um nach übergeordneten Token zu suchen, wird die CMxQL-Funktion
GetAncOfType () verwendet :
CxList entryPoints = runSuperSecureSQLQuery.GetAncOfType(typeof(MethodDecl)); result = entryPoints;
Geben Sie in dieser Abfrage für die Gruppe runSuperSecureSQLQuery alle übergeordneten Token des Typs MethodDecl zurück. Dies ist die vorherige Methode im Aufrufstapel:

Zur Suche nach Methodenparametern verwenden wir auch
GetParameters () :
CxList entryPointsParameters = All.GetParameters(entryPoints).FindByType("String");
Die Abfrage gibt die Parameter einer Teilmenge von
entryPoints mit dem Java-Typ String zurück:

SQLi: Schritt 6. Ermitteln Sie die Abhängigkeiten der runSSSQParams-Parameter von entryPointsParameters, während nur an den Stellen keine Eingabe für die Bereinigung erfolgt
In diesem Schritt verwenden wir die Analysefunktionen. Die folgenden Funktionen werden verwendet, um den Flow-Code zu analysieren:
- Beeinflusst durch ()
- InfluencedByAndNotSanitized ()
- InfluencingOn ()
- InfluencingOnAndNotSanitized ()
- NotInfluencedBy ()
- NotInfluencingOn ()
So ermitteln Sie den
Ablauf von
runSSSQParams- Anforderungsparametern in Abhängigkeit von den Parametern der übergeordneten Methode
entryPointsParameters und schließen
Bereinigungstoken aus:
CxList dataInflOnTable = runSSSQParams.InfluencedByAndNotSanitized(entryPointsParameters, sanitization);
Ich bin mir jedoch nicht sicher, ob die
* AndNotSanitized- Funktionen etwas Magie
bewirken , und es sieht eher so aus, als würde die Methode die bereinigte Menge einfach von ihrem Ergebnis subtrahieren. Das heißt, wenn Sie tun:
CxList dataInflOnTable = runSSSQParams.InfluencedBy(entryPointsParameters) - sanitization;
es stellt sich das gleiche heraus. Obwohl ich vielleicht einfach keine Option gefunden habe, wenn es immer noch Unterschiede gibt.
Das Ergebnis der Abfrage ergibt einen korrekt aufgebauten Flow:

Got Flow mit potenzieller SQL-Injection. Wie aus dem Screenshot hervorgeht, hat Checkmarx 3 Flow zurückgegeben. Der Ablauf im Screenshot ist der kürzeste. Er beginnt und endet in einer Datei und einer Methode. Der nächste Flow geht bereits in die Session-Klasse. Achten Sie auf Quelle / Ziel. Und die letzte ist eine andere Methode in der Session-Klasse. Der Ablauf in der
Sitzung sieht folgendermaßen aus:

Um einen Flow auszuwählen, wird die
ReduceFlow- Methode
(CxList.ReduceFlowType flowType) verwendet , wobei flowType Folgendes sein kann:
- CxList.ReduceFlowType.ReduceBigFlow - Wählen Sie den kürzesten Flow aus
- CxList.ReduceFlowType.ReduceSmallFlow - Wählen Sie den längsten Flow aus
SQLi: Letzte Abfrage zum Auffinden der SQL-Injection
Beispiel 2: Suchen nach unsicheren direkten Objektreferenzen
In dieser Anfrage werden wir nach allen Stellen suchen, an denen mit Objekten gearbeitet wird, ohne den Eigentümer des Objekts zu überprüfen. In diesem Fall können unterschiedliche Namen von HTTP-Parametern für mailboxid verwendet werden (wir gehen davon aus, dass dies Legacy ist), und die Überprüfung selbst kann in verschiedenen Phasen erfolgen: irgendwo direkt am HTTP-Eintrags-API-Punkt, irgendwo vor der Anforderung an die Datenbank und manchmal in Zwischenmethoden.
Plan suchen
- Ausnahmen definieren ( exclusionList );
- Stellen für Berechtigungsprüfungen identifizieren ( idorSanitizer );
- Einstiegspunkte suchen - Orte für die primäre Verarbeitung von HTTP-Anforderungen ( webRemoteMethods );
- Nur nach Einstiegspunkt-Token, um den Extraktionsort des HTTP-Parameters mailboxid ( mailboxidInit ) zu ermitteln.
- Suchen Sie alle Aufrufe von webRemoteMethods an Middleware-Methoden und Parameter dieser Aufrufe ( middlewareMethods ).
- Finden Sie Middleware-Methoden, die von mailboxid ( apiPotentialIDOR ) abhängen.
- Suchen Sie alle Stellen, an denen Middleware-Methoden definiert sind ( middlewareDecl ).
- Gehen Sie alle apiPotentialIDOR durch und wählen Sie nur die MiddlewareDecl aus, in denen keine Überprüfung des Besitzers des Mailboxid- Objekts erfolgt.
IDOR: Schritt 1. Ausnahmen identifizieren
In diesem Fall schließen Sie alle Token in einer bestimmten Datei aus:
CxList exclusionList = All.FindByFileName("*WebMethodContext.java"); result = exclusionList;
WebMethodContext.java enthält eine Implementierung von Methoden wie
getMailboxId und
getUserId sowie die Zeichenfolge "mailboxid". Da der Name der Token mit dem übereinstimmt, den wir für die Suche nach Sicherheitslücken benötigen, gibt diese Datei falsche Ergebnisse aus.
IDOR: Schritt 2. Suchen Sie die Berechtigungsprüfungen
In der Testanwendung wird mit der
validateMailbox () -Methode bestimmt, ob das angeforderte Objekt dem Benutzer gehört:
CxList idorSanitizer = All.FindByName("*validateMailbox*"); result = idorSanitizer;
Ergebnis:

IDOR: Schritt 3. Suchen Sie Einstiegspunkte für benutzerdefinierte HTTP-API-Anforderungen
HTTP-Request-Handler sind mit einer speziellen Anmerkung versehen, die das Auffinden erleichtert. In meinem Fall ist dies "WebRemote", die CMxQL-Funktion
FindByCustomAttribute () wird verwendet, um nach Anmerkungen zu suchen. Für
FindByCustomAttribute () gibt die Suchfunktion des übergeordneten Tokens
GetAncOfType () die Methode unter der Anmerkung zurück:
CxList webRemoteMethods = All.FindByCustomAttribute("WebRemote") .GetAncOfType(typeof(MethodDecl)); result = webRemoteMethods;
Anforderungsergebnis:

IDOR: Schritt 4. Verwenden Sie nur Einstiegspunkt-Token, um die HTTP-Extraktionspositionen für den Parameter mailboxid zu ermitteln
So finden Sie Token, die sich auf die Verarbeitung des HTTP-Parameters mailboxid beziehen:
CxList getMailboxId = All.FindByName("\"mailboxId\"") + All.FindByName("\"mid\"") + All.FindByName("\"boxid\""); result = getMailboxId;
Wir haben 3 Sets mit 3 verschiedenen Zeilen hinzugefügt, weil Der Legende nach kann der Name des HTTP-Parameters in verschiedenen Teilen des Systems unterschiedlich sein.
Die Abfrage findet alle Stellen, an denen
mailboxid / mid / boxid als Zeichenfolge geschrieben ist (in doppelten Anführungszeichen). Aber diese Abfrage wird eine Menge Funde zurückgeben, tk. Eine solche Zeichenfolge befindet sich nicht nur an Stellen, an denen HTTP-Parameter extrahiert werden. Wenn wir mit diesem Set weiterarbeiten, werden wir eine große Anzahl falscher Funde erhalten.
Aus diesem
Grund suchen wir nur nach Token für Einstiegspunkte (
webRemoteMethods ). Um alle untergeordneten Token zu finden, wird die CMBQL-Funktion
GetByAncs () verwendet :
result = All.GetByAncs(webRemoteMethods);
Die Anforderung gibt alle Token zurück, die zu als
WebRemote gekennzeichneten Methoden
gehören . Bereits jetzt können wir die Token der Methoden filtern, bei denen der Eigentümer des Objekts überprüft wird. Daher schreiben wir die vorherige Abfrage neu, um nach
untergeordneten Token zu
suchen ,
sodass nur die
untergeordneten Token der
WebRemote- Methoden
ausgewählt werden, bei denen keine Sicherheitsüberprüfung für den Eigentümer des Objekts erfolgt. Verwenden Sie dazu eine Schleife mit der Bedingung:
Jetzt können wir mithilfe der HTTP-
Mailbox-ID- Parameter eine genauere Auswahl
treffen :
CxList getMailboxHTTPParams = entry_point_tokens.FindByName("\"mailboxid\"") + entry_point_tokens.FindByName("\"mid\"") + entry_point_tokens.FindByName("\"boxid\""); result = getMailboxHTTPParams;
Uns interessieren jedoch nicht die Stellen, an denen die HTTP-Parameter abgerufen werden, sondern die Variablen, denen letztendlich die Werte der HTTP-Parameter zugewiesen werden. Da es zuverlässiger ist, Flow genau nach Variablen zu suchen.
Die CMxQL-Funktion
FindByInitialization () findet die Stellen der Variableninitialisierung für die angegebenen Token:
CxList mailboxidInit = entry_point_tokens.FindByInitialization(getMailboxHTTPParams); result = mailboxidInit;
Ergebnis:

IDOR: Schritt 5. Alle Aufrufe von webRemoteMethods an Middleware-Methoden und -Parameter dieser Aufrufe suchen
Mit Middleware meine ich Code, der tiefer geht als die Verarbeitungsmethoden von HTTP-API-Anforderungen, dh tiefer als die Einstiegspunkte von Benutzeranforderungen. Für den obigen Screenshot sind dies beispielsweise Methoden der
User- Klasse, Aufrufe von
user.getSettings () und
user.getSecureSettings () :
CxList middlewareMethods = All.FindByShortName("user").GetRightmostMember(); CxList middlewareMethodsParams = entry_point_tokens.GetParameters(middlewareMethods); result = middlewareMethodsParams;
Zuerst wählen wir alle Token mit dem Namen user aus, und dann
wählen wir mit
GetRightmostMember () die
Aufruftoken für Middleware aus.
GetRightmostMember () in der Kette der Methodenaufrufe gibt das am weitesten rechts stehende zurück. Dann leiten wir die Parameter der gefundenen Methode mit
GetParameters () ab .
Ergebnis:

IDOR: Schritt 6. Suchen Sie nach Middleware-Methoden, die von der Mailbox-ID abhängen
Die Durchflussanalyse verwendet die
Methoden * InfluencedBy * und
* InfluncingOn * . Der Unterschied zwischen ihnen ist durch den Namen klar.
Zum Beispiel:
All.InfluencedBy(getMailboxHTTPParams)
Durchläuft die Gruppe Alle und findet alle Token, die von
getMailboxHTTPParams abhängen.
Das gleiche kann auf andere Weise geschrieben werden:
getMailboxHTTPParams.InfluencingOn(All)
So suchen Sie nach Token, die von
mailboxidInit abhängig
sind :
CxList apiPotentialIDOR = entry_point_tokens.InfluencedByAndNotSanitized(mailboxidInit, idorSanitizer); result = apiPotentialIDOR;
Ergebnis:

IDOR: Schritt 7. Finden Sie alle Stellen, an denen Sie Middleware-Methoden definieren können
Lassen Sie uns die Definitionen aller Zwischenmethoden finden, die an Stellen verwendet werden können, an denen Benutzeranforderungen verarbeitet werden. Dazu heben wir ihre gemeinsame Eigenschaft hervor. In all diesen Methoden wird beispielsweise ein
Request () -Objekt erstellt. Das Erstellen eines Objekts ist vom CMx-Typ
ObjectCreateExpr :
CxList requests = (All - exclusionList).FindByType(typeof(ObjectCreateExpr)).FindByName("*Request*"); CxList middlewareDecl = requests.GetAncOfType(typeof(MethodDecl)); result = middlewareDecl;
(All - exclusionList) - Sie können diese Subtraktion von Mengen durchführen und dann die gewünschte CMxQL-Funktion aus dem Ergebnis aufrufen.
Requests enthält jetzt alle Token mit dem Namen
Request und dem Typ, der der Erstellung des Objekts entspricht.
Als nächstes finden wir mit dem bekannten
GetAncOfType () das übergeordnete Token vom Typ
MethodDecl .
Ergebnis:

IDOR: Schritt 8. Durchlaufen Sie alle apiPotentialIDOR und wählen Sie nur die MiddlewareDecl aus, in denen keine Überprüfung des Besitzers des Mailboxid-Objekts erfolgt
Im letzten Teil der Anforderung bestimmen wir, welche der Middleware-Methoden direkt von den Einstiegspunktmethoden aufgerufen werden, und überprüfen nicht, wem die
Mailbox-ID gehört. Kombinieren Sie dann Flow für eine bequemere Analyse der Ergebnisse.
Neue Funktionen, die wir noch nicht genutzt haben:
GetCxListByPath () - Diese Funktion wird benötigt, um den Flow zu durchlaufen. Wenn sie NICHT verwendet wird, komprimiert CMx den Flow im Code-Element (im ersten Flow-Knoten).
Verketten * () - Eine Reihe von Funktionen, die zum Kombinieren mehrerer Flows zu einem Flow erforderlich sind
FindByParameters () -
Findet eine Methode anhand eines bestimmten Parameter-Tokens
GetName () -
Gibt eine Zeichenfolge mit dem Tokennamen zurück. Befindet sich mehr als ein Element in CxList, wird die erste zurückgegeben. Die Methode wird nur verwendet, wenn Elemente einer Menge durchlaufen werden.
Der letzte Teil der Anfrage:
Ergebnis:
CocatenatePath , . Code Element Flow
IDOR: IDOR
Fazit
Checkmarx , . , , , .. Flow ( ). , , «» .
false positive, :
- , ( ).
- , ( ). , «Privacy Violation», , , Web UI. , .. UI . TLS XSS .
- - , (, ). , XXE , , - , .
- false positive, , CMxQL FindBy/GetBy. , ( SQL).
- false positives, , , , , CMx, . , LDAP , . c LDAP- , , .
how-to «hello world» , Checkmarx.