Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginn

Hey Habr!

An eiser Aarbecht beschäftegt eis Firma ganz dacks verschidde statesch Code Analyse Tools (SAST). Aus der Këscht schaffen se all duerchschnëttlech. Natierlech hänkt alles vum Projet of an den Technologien, déi an deem benotzt ginn, wéi och wéi gutt dës Technologien duerch d'Regele vun der Analyse ofgedeckt sinn. Menger Meenung no ass ee vun de wichtegste Critèren bei der Auswiel vun engem SAST-Tool d'Fäegkeet et un d'Spezifizitéiten vun Ären Uwendungen ze personaliséieren, nämlech Analyseregelen ze schreiwen an z'änneren oder, wéi se méi dacks genannt ginn, Custom Queries.

Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginn

Mir benotzen meeschtens Checkmarx - e ganz interessanten a mächtege Code Analyser. An dësem Artikel wäert ech iwwer meng Erfahrung schwätzen Analyse Regele fir et ze schreiwen.

Inhaltsverzeechnes

Element

Fir unzefänken, géif ech gär ee vun de puer Artikelen op Russesch iwwer d'Features vum Schreiwen vun Ufroen fir Checkmarx recommandéieren. Et gouf um Habré Enn 2019 ënner dem Titel publizéiert: "Moien, Checkmarx!" Wéi schreift ech eng Checkmarx SAST Ufro a fanne cool Schwachstelle.

Et ënnersicht am Detail wéi déi éischt Ufroen an CxQL (Checkmarx Query Language) fir eng Testapplikatioun ze schreiwen a weist d'Basisprinzipien wéi d'Analyseregele funktionnéieren.

Ech widderhuelen net, wat dra beschriwwe gëtt, obwuel e puer Kräizungen nach ëmmer präsent sinn. A mengem Artikel probéieren ech eng Zort "Rezeptsammlung" ze kompiléieren, eng Lëscht vu Léisunge fir spezifesch Probleemer, déi ech während menger Aarbecht mat Checkmarx begéint hunn. Ech hat meng Gehir iwwer vill vun dëse Problemer ze Rack. Heiansdo war et net genuch Informatioun an der Dokumentatioun, an heiansdo war et souguer schwéier ze verstoen, wéi ee maache wat néideg ass. Ech hoffen, datt meng Erfahrung a schloflos Nuechten net vergeblech sinn, an dës "Sammlung vu Custom Queries Rezepter" spuert Iech e puer Stonnen oder e puer Nervenzellen. Also, loosst eis ufänken!

Allgemeng Informatiounen iwwert d'Regelen

Als éischt kucke mer e puer grondleeënd Konzepter an de Prozess fir mat de Regelen ze schaffen, fir e bessert Verständnis vu wat duerno geschitt. An och well d'Dokumentatioun näischt iwwer dëst seet oder ganz an der Struktur verbreet ass, wat net ganz bequem ass.

  1. D'Regele gi wärend dem Scannen ugewannt ofhängeg vun der Preset déi um Start gewielt gouf (eng Rei vun aktive Regelen). Dir kënnt eng onlimitéiert Zuel vu Presets erstellen, a genau wéi Dir se strukturéiert hänkt vun de Spezifizitéiten vun Ärem Prozess of. Dir kënnt se no Sprooch gruppéieren oder Presets fir all Projet auswielen. D'Zuel vun den aktive Regelen beaflosst d'Geschwindegkeet an d'Genauegkeet vum Scannen.

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnPreset an der Checkmarx Interface opsetzen

  2. D'Regele ginn an engem speziellen Tool mam Numm CxAuditor geännert. Dëst ass eng Desktop-Applikatioun déi mat engem Server mat Checkmarx verbënnt. Dëst Tool huet zwee Operatiounsmodi: Reegelen z'änneren an d'Resultater vun engem scho gemaache Scan analyséieren.

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnCxAudit Interface

  3. Regelen am Checkmarx sinn duerch Sprooch ënnerdeelt, dat ass, all Sprooch huet seng eege Formatioun vun Ufroen. Et ginn och e puer allgemeng Reegelen, déi onofhängeg vun der Sprooch gëllen, dat sinn déi sougenannte Basisufroen. Fir de gréissten Deel, Basis Ufroen involvéiert d'Sich no Informatioun déi aner Reegele benotzen.

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnRegele vun der Sprooch deelen

  4. Regele sinn "Ausféierbar" an "Net ausféierbar" (ausgefouert an net ausgefouert). Net ganz de richtegen Numm, menger Meenung no, awer dat ass wat et ass. Déi ënnescht Linn ass datt d'Resultat vun der Ausféierung vun "Executable" Reegelen an de Scannerresultater an der UI ugewise ginn, an "Net-Executable" Reegele sinn nëmme gebraucht fir hir Resultater an aner Ufroen ze benotzen (tatsächlech si se just eng Funktioun) ).

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnBestëmmung vun der Regel Typ wann schafen

  5. Dir kënnt nei Reegelen erstellen oder existéierend ergänzen / nei schreiwen. Fir eng Regel ëmzeschreiwen, musst Dir se am Bam fannen, klickt mat riets a wielt "Iwwerschreiden" aus dem Dropdown-Menü. Et ass wichteg hei ze erënneren datt déi nei Regelen am Ufank net an de Presets abegraff sinn an net aktiv sinn. Fir se ze benotzen, musst Dir se am Menü "Preset Manager" am Instrument aktivéieren. Neigeschriwwe Regelen behalen hir Astellungen, dat heescht, wann d'Regel aktiv war, bleift se sou a gëtt direkt applizéiert.

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnBeispill vun enger neier Regel am Preset Manager Interface

  6. Während der Ausféierung gëtt e "Bam" vun Ufroen gebaut, wat hänkt dovun of. D'Regele, déi Informatioun sammelen, ginn als éischt ausgefouert, an déi, déi se als zweet benotzen. D'Ausféierungsresultat gëtt cache, also wann et méiglech ass d'Resultater vun enger existéierender Regel ze benotzen, ass et besser dat ze maachen, dëst wäert d'Scannenzäit reduzéieren.

  7. Regele kënnen op verschidden Niveauen applizéiert ginn:

  • Fir de ganze System - gëtt fir all Scannen vun all Projet benotzt

  • Um Teamniveau (Team) - gëtt nëmme benotzt fir Projeten am ausgewielten Team ze scannen.

  • Um Projet Niveau - Wäert an engem spezifesche Projet applizéiert ginn

    Wéi schreiwen ech Regele fir Checkmarx ouni verréckt ze ginnBestëmmung vum Niveau op deem d'Regel applizéiert gëtt

"Wörterbuch" fir Ufänger

An ech fänken mat e puer Saachen un, déi mir Froen gestallt hunn, an ech wäert och eng Rei vun Techniken weisen, déi d'Liewen wesentlech vereinfachen.

Operatiounen mat Lëschten

- вычитание одного из другого (list2 - list1)
* пересечение списков (list1 * list2)
+ сложение списков (list1 + list2)

& (логическое И) - объединяет списки по совпадению (list1 & list2), аналогично пересечению (list1 * list2)
| (логическое ИЛИ) - объединяет списки по широкому поиску (list1 | list2)

Со списками не работает:  ^  &&  ||  %  / 

All fonnt Elementer

An der gescannter Sprooch kënnt Dir eng Lëscht vun absolut all Elementer kréien, déi Checkmarx identifizéiert huet (Strings, Funktiounen, Klassen, Methoden, etc.). Dëst ass e Raum vun Objeten déi duerch zougänglech sinn All. Dat ass, fir en Objet mat engem spezifeschen Numm ze sichen searchMe, Dir kënnt zum Beispill mam Numm iwwer all fonnt Objete sichen:

// Такой запрос выдаст все элементы
result = All;

// Такой запрос выдаст все элементы, в имени которых присутствует “searchMe“
result = All.FindByName("searchMe");

Awer wann Dir an enger anerer Sprooch sicht, déi aus irgendege Grënn net am Scan abegraff war (zum Beispill, groovy an engem Android Projet), kënnt Dir eisen Objektraum duerch eng Variabel ausbauen:

result = AllMembers.All.FindByName("searchMe");

Fonctiounen fir Flow Analyse

Dës Funktiounen ginn a ville Reegele benotzt an hei ass e klenge Cheatsheet vun deem wat se bedeiten:

// Какие данные second влияют на first.
// Другими словами - ТО (second) что влияет на  МЕНЯ (first).
result = first.DataInfluencedBy(second);

// Какие данные first влияют на second.
// Другими словами - Я (first) влияю на ТО (second).
result = first.DataInfluencingOn(second);

Gitt Dateinumm / Wee

Et gi verschidde Attributer déi aus de Resultater vun enger Ufro kritt kënne ginn (den Numm vun der Datei an där d'Entrée fonnt gouf, String, etc.), awer d'Dokumentatioun seet net wéi se se kréien a benotzen. Also, fir dëst ze maachen, musst Dir Zougang zu der LinePragma Eegeschafte kréien an d'Objeten déi mir brauchen wäerten dobannen lokaliséiert sinn:

// Для примера найдем все методы
CxList methods = Find_Methods();

// В методах найдем по имени метод scope
CxList scope = methods.FindByName("scope");

// Таким образом можо получить путь к файлу
string current_filename = scope.GetFirstGraph().LinePragma.FileName;

// А вот таким - строку, где нашлось срабатывание
int current_line = scope.GetFirstGraph().LinePragma.Line;

// Эти параметры можно использовать по разному
// Например получить все объекты в файле
CxList inFile = All.FindByFileName(current_filename);

// Или найти что происходит в конкретной строке
CxList inLine = inFile.FindByPosition(current_line);

Et ass derwäert dat am Kapp ze halen FileName enthält tatsächlech de Wee op d'Datei, well mir d'Method benotzt hunn GetFirstGraph.

Ausféierung Resultat

Et gëtt eng speziell Variabel bannent CxQL result, déi d'Resultat vun der Ausféierung vun Ärer schrëftlecher Regel zréckginn. Et gëtt direkt initialiséiert an Dir kënnt Tëscheresultater dran schreiwen, se änneren a verfeineren wéi Dir schafft. Awer, wann et keng Uerderung fir dës Variabel oder Funktioun bannent der Regel gëtt return- d'Ausféierungsresultat wäert ëmmer null sinn.

Déi folgend Ufro gëtt eis näischt zréck als Resultat vun der Ausféierung a wäert ëmmer eidel sinn:

// Находим элементы foo
CxList libraries = All.FindByName("foo");

Awer, nodeems d'Ausféierungsresultat dem magesche Variabel Resultat zougewisen ass, wäerte mir gesinn wat dësen Uruff un eis zréckkënnt:

// Находим элементы foo
CxList libraries = All.FindByName("foo");

// Выводим, как результат выполнения правила
result = libraries

// Или еще короче
result = All.FindByName("foo");

Benotzen d'Resultater vun anere Regelen

Regelen am Checkmarx kënnen analog zu Funktiounen an enger regulärer Programméiersprooch genannt ginn. Wann Dir eng Regel schreift, kënnt Dir gutt d'Resultater vun anere Ufroen benotzen. Zum Beispill, et ass net néideg fir all Method Appellen am Code all Kéier ze sichen, rufft just déi gewënscht Regel un:

// Получаем результат выполнения другого правила
CxList methods = Find_Methods();

// Ищем внутри метод foo. 
// Второй параметр false означает, что ищем без чувствительности к регистру
result = methods.FindByShortName("foo", false);

Dës Approche erlaabt Iech de Code ze verkierzen an d'Regel Ausféierungszäit wesentlech ze reduzéieren.

Léisung vu Probleemer

Logged

Wann Dir mam Tool schafft, ass et heiansdo net méiglech direkt déi gewënschte Ufro ze schreiwen an Dir musst experimentéieren, verschidde Méiglechkeeten probéieren. Fir esou e Fall gëtt de Tool Logbuch, wat wéi follegt genannt gëtt:

// Находим что-то
CxList toLog = All.FindByShortName("log");

// Формируем строку и отправляем в лог
cxLog.WriteDebugMessage (“number of DOM elements =” + All.Count);

Awer et ass derwäert ze erënneren datt dës Method nëmmen als Input akzeptéiert String, also ass et net méiglech eng komplett Lëscht vun fonnt Elementer als Resultat vun der éischter Operatioun ze weisen. Déi zweet Optioun, déi fir Debugging benotzt gëtt, ass eng magesch Variabel vun Zäit zu Zäit ze ginn result d'Resultat vun der Ufro a kuckt wat geschitt. Dës Approche ass net ganz bequem; Dir musst sécher sinn datt et keng Iwwerschreiden oder Operatioune mat dësem am Code sinn result oder kommentéiert einfach de Code hei drënner. Oder Dir kënnt, wéi ech, vergiessen, e puer esou Uriff aus enger fäerdeger Regel ze läschen a froen Iech firwat näischt funktionnéiert.

E méi praktesche Wee ass d'Method ze nennen return mat dem erfuerderleche Parameter. An dësem Fall wäert d'Ausféierung vun der Regel ophalen a mir kënne gesinn wat geschitt ass als Resultat vun deem wat mir geschriwwen hunn:

// Находим что-то
CxList toLog = All.FindByShortName("log");

// Выводим результат выполнения
return toLog

//Все, что написано дальше не будет выполнено
result = All.DataInfluencedBy(toLog)

Login Problem

Et gi Situatiounen, wann Dir net Zougang zum CxAudit-Tool hutt (dee benotzt gëtt fir Regelen ze schreiwen). Et kënne vill Grënn dofir sinn, dorënner Crashen, plötzlech Windows Updates, BSOD an aner onerwaart Situatiounen déi iwwer eis Kontroll sinn. An dësem Fall gëtt et heiansdo eng onfäerdeg Sessioun an der Datebank, déi Iech verhënnert datt Dir Iech erëm aloggen. Fir et ze fixéieren, musst Dir e puer Ufroen ausféieren:

Fir Checkmarx virum 8.6:

// Проверяем, что есть залогиненые пользователи, выполнив запрос в БД
SELECT COUNT(*) FROM [CxDB].[dbo].LoggedinUser WHERE [ClientType] = 6;
 
// Если что-то есть, а на самом деле даже если и нет, попробовать выполнить запрос
DELETE FROM [CxDB].[dbo].LoggedinUser WHERE [ClientType] = 6;

Fir Checkmarx no 8.6:

// Проверяем, что есть залогиненые пользователи, выполнив запрос в БД
SELECT COUNT(*) FROM LoggedinUser WHERE (ClientType = 'Audit');
 
// Если что-то есть, а на самом деле даже если и нет, попробовать выполнить запрос
DELETE FROM [CxDB].[dbo].LoggedinUser WHERE (ClientType = 'Audit');

Schreiwen Regelen

Elo komme mer zum interessantsten Deel. Wann Dir ufänkt Reegelen an CxQL ze schreiwen, wat Dir dacks feelt ass net sou vill Dokumentatioun wéi e puer lieweg Beispiller fir verschidde Probleemer ze léisen an de Prozess ze beschreiwen wéi Ufroen am Allgemengen funktionnéieren.

Ech wäert probéieren d'Liewen e bësse méi einfach ze maachen fir déi, déi ufänken an d'Ufrosprooch ze tauchen an e puer Beispiller ze ginn fir Custom Queries ze benotzen fir verschidde Probleemer ze léisen. E puer vun hinnen sinn zimlech allgemeng a kënne praktesch ouni Ännerungen an Ärer Firma benotzt ginn, anerer si méi spezifesch, awer si kënnen och benotzt ginn andeems Dir de Code ännert fir de Spezifizitéiten vun Ären Uwendungen ze passen.

Also, hei sinn d'Problemer déi mir am meeschte begéint hunn:

Eng Aufgab: Et gi verschidde Flows an de Resultater vun der Ausféierung vun der Regel an ee vun hinnen ass en Nesting vun engem aneren, Dir musst ee vun hinnen verloossen.

Léisung: Tatsächlech weist Checkmarx heiansdo verschidden Datefloss déi iwwerlappe kënnen an eng verkierzte Versioun vun aneren sinn. Et gëtt eng speziell Method fir esou Fäll Flow reduzéieren. Ofhängeg vum Parameter wäert et de kürzeste oder längste Flow auswielen:

// Оставить только длинные Flow
result = result.ReduceFlow(CxList.ReduceFlowType.ReduceSmallFlow);

// Оставить только короткие Flow
result = result.ReduceFlow(CxList.ReduceFlowType.ReduceBigFlow);

Eng Aufgab: Erweidert d'Lëscht vu sensiblen Donnéeën op déi den Tool reagéiert

Léisung: Checkmarx huet Basisregelen, d'Resultater vun deenen gi vu villen anere Ufroe benotzt. Andeems Dir e puer vun dëse Reegele mat Daten spezifesch fir Är Uwendung ergänzt, kënnt Dir Är Scanresultater direkt verbesseren. Drënner ass eng Beispill Regel fir Iech unzefänken:

General_privacy_violation_list

Loosst eis e puer Variabelen addéieren déi an eiser Applikatioun benotzt gi fir sensibel Informatioun ze späicheren:

// Получаем результат выполнения базового правила
result = base.General_privacy_violation_list();

// Ищем элементы, которые попадают под простые регулярные выражения. Можно дополнить характерными для вас паттернами.
CxList personalList = All.FindByShortNames(new List<string> {
	"*securityToken*", "*sessionId*"}, false);

// Добавляем к конечному результату
result.Add(personalList);

Eng Aufgab: Erweidert d'Lëscht vu Variabelen mat Passwierder

Léisung: Ech géif recommandéieren direkt op d'Basisregel opmierksam ze maachen fir Passwierder am Code ze definéieren an eng Lëscht mat variabelen Nimm ze addéieren déi allgemeng an Ärer Firma benotzt ginn.

Password_privacy_violation_list

CxList allStrings = All.FindByType("String"); 
allStrings.Add(All.FindByType(typeof(StringLiteral))); 
allStrings.Add(Find_UnknownReference());
allStrings.Add(All.FindByType(typeof (Declarator)));
allStrings.Add(All.FindByType(typeof (MemberAccess)));
allStrings.Add(All.FindByType(typeof(EnumMemberDecl))); 
allStrings.Add(Find_Methods().FindByShortName("get*"));

// Дополняем дефолтный список переменных
List < string > pswdIncludeList = new List<string>{"*password*", "*psw", "psw*", "pwd*", "*pwd", "*authKey*", "pass*", "cipher*", "*cipher", "pass", "adgangskode", "benutzerkennwort", "chiffre", "clave", "codewort", "contrasena", "contrasenya", "geheimcode", "geslo", "heslo", "jelszo", "kennwort", "losenord", "losung", "losungswort", "lozinka", "modpas", "motdepasse", "parol", "parola", "parole", "pasahitza", "pasfhocal", "passe", "passord", "passwort", "pasvorto", "paswoord", "salasana", "schluessel", "schluesselwort", "senha", "sifre", "wachtwoord", "wagwoord", "watchword", "zugangswort", "PAROLACHIAVE", "PAROLA CHIAVE", "PAROLECHIAVI", "PAROLE CHIAVI", "paroladordine", "verschluesselt", "sisma",
                "pincode",
								"pin"};
								
List < string > pswdExcludeList = new List<string>{"*pass", "*passable*", "*passage*", "*passenger*", "*passer*", "*passing*", "*passion*", "*passive*", "*passover*", "*passport*", "*passed*", "*compass*", "*bypass*", "pass-through", "passthru", "passthrough", "passbytes", "passcount", "passratio"};

CxList tempResult = allStrings.FindByShortNames(pswdIncludeList, false);
CxList toRemove = tempResult.FindByShortNames(pswdExcludeList, false);
tempResult -= toRemove;
tempResult.Add(allStrings.FindByShortName("pass", false));

foreach (CxList r in tempResult)
{
	CSharpGraph g = r.data.GetByIndex(0) as CSharpGraph;
	if(g != null && g.ShortName != null && g.ShortName.Length < 50)
	{
		result.Add(r);
	}
}

Eng Aufgab: Füügt benotzte Kaderen un déi net vun Checkmarx ënnerstëtzt ginn

Léisung: All Ufroen am Checkmarx sinn no Sprooch gedeelt, also musst Dir Regele fir all Sprooch addéieren. Drënner sinn e puer Beispiller vun esou Regelen.

Wann Bibliothéike benotzt ginn, déi d'Standardfunktionalitéit ergänzen oder ersetzen, kënne se einfach un d'Basisregel bäigefüügt ginn. Da léiert jiddereen, deen et benotzt, direkt iwwer déi nei Aféierung. Als Beispill, Bibliothéike fir aloggen op Android sinn Timber a Loggi. Am Basispaket gi keng Regele fir d'Identifikatioun vun Net-System Uriff, also wann e Passwuert oder Sessiounsidentifizéierer an de Logbuch kënnt, wësse mer net doriwwer. Loosst eis probéieren Definitioune vun esou Methoden un d'Checkmarx Regelen ze addéieren.

Testcode Beispill dat d'Timberbibliothéik benotzt fir ze protokolléieren:

package com.death.timberdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import timber.log.Timber;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Timber.e("Error Message");
        Timber.d("Debug Message");

        Timber.tag("Some Different tag").e("And error message");
    }
}

An hei ass e Beispill vun enger Demande fir Checkmarx, déi Iech erlaabt eng Definitioun vun Timber Methoden ze nennen als Ausgangspunkt fir Daten aus der Applikatioun ze addéieren:

FindAndroidOutputs

// Получаем результат выполнения базового правила
result = base.Find_Android_Outputs();

// Дополняем вызовами, которые приходят из библиотеки Timber
CxList timber = All.FindByExactMemberAccess("Timber.*") +
    All.FindByShortName("Timber").GetMembersOfTarget();

// Добавляем к конечному результату
result.Add(timber);

An Dir kënnt och un d'Nopeschregel addéieren, awer dëst bezitt sech direkt op d'Aloggen op Android:

FindAndroidLog_Outputs

// Получаем результат выполнения базового правила
result = base.Find_Android_Log_Outputs();

// Дополняем вызовами, которые приходят из библиотеки Timber
result.Add(
  All.FindByExactMemberAccess("Timber.*") +
  All.FindByShortName("Timber").GetMembersOfTarget()
);

Och, wann Android Uwendungen benotzen Aarbecht Manager fir asynchron Aarbecht ass et eng gutt Iddi fir Checkmarx zousätzlech doriwwer z'informéieren andeems Dir eng Method bäidréit fir Daten aus der Aufgab ze kréien getInputData:

Fannt AndroidRead

// Получаем результат выполнения базового правила
result = base.Find_Android_Read();

// Дополняем вызовом функции getInputData, которая используется в WorkManager
CxList getInputData = All.FindByShortName("getInputData");

// Добавляем к конечному результату
result.Add(getInputData.GetMembersOfTarget());

Eng Aufgab: Sich no sensiblen Donnéeën am Plist fir iOS Projeten

Léisung: iOS benotzt dacks speziell Dateien mat der .plist Extensioun fir verschidde Variabelen a Wäerter ze späicheren. Passwierder, Tokens, Schlësselen an aner sensibel Donnéeën an dëse Fichieren ze späicheren ass net recommandéiert, well se ouni Probleemer aus dem Apparat extrahéiert kënne ginn.

Plist Dateien hunn Features déi net mat bloussem Auge offensichtlech sinn, awer fir Checkmarx wichteg sinn. Loosst eis eng Regel schreiwen déi no den Donnéeën sicht déi mir brauchen an eis soen ob Passwierder oder Token iergendwou ernimmt ginn.

E Beispill vun esou enger Datei, déi en Token fir Kommunikatioun mam Backend Service enthält:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>DeviceDictionary</key>
	<dict>
		<key>phone</key>
		<string>iPhone 6s</string>
	</dict>
	<key>privatekey</key>
	<string>MIICXAIBAAKBgQCqGKukO1De7zhZj6+</string>
</dict>
</plist>

An eng Regel fir Checkmarx, déi e puer Nuancen huet, déi beim Schreiwen berücksichtegt ginn:

// Используем результат выполнения правила по поиску файлов plist, чтобы уменьшить время работы правила и 
CxList plist = Find_Plist_Elements();

// Инициализируем новую переменную
CxList dictionarySettings = All.NewCxList();

// Теперь добавим поиск всех интересующих нас значений. В дальнейшем можно расширять этот список.
// Для поиска значений, как ни странно, используется FindByMemberAccess - поиск обращений к методам. Второй параметр внутри функции, false, означает, что поиск нечувствителен к регистру
dictionarySettings.Add(plist.FindByMemberAccess("privatekey", false));
dictionarySettings.Add(plist.FindByMemberAccess("privatetoken", false));

// Для корректного поиска из-за особенностей структуры plist - нужно искать по типу "If statement"
CxList ifStatements = plist.FindByType(typeof(IfStmt));

// Добавляем в результат, перед этим получив родительский узел - для правильного отображения
result = dictionarySettings.FindByFathers(ifStatements);

Eng Aufgab: Fannt Informatiounen am XML

Léisung: Checkmarx huet ganz praktesch Funktiounen fir mat XML ze schaffen an no Wäerter, Tags, Attributer a méi ze sichen. Awer leider gouf et e Feeler an der Dokumentatioun wéinst deem net een eenzegt Beispill funktionnéiert. Trotz der Tatsaach, datt dësen Defekt an der leschter Versioun vun der Dokumentatioun eliminéiert gouf, sollt Dir virsiichteg sinn wann Dir fréier Versioune vun Dokumenter benotzt.

Hei ass e falscht Beispill aus der Dokumentatioun:

// Код работать не будет
result = All.FindXmlAttributesByNameAndValue("*.app", 8, “id”, "error- section", false, true);

Als Resultat vun der Ausféierung Versuch, wäerte mir e Feeler kréien, datt All et gëtt keng sou eng Method ... An dat ass wouer, well et gëtt e speziellen, getrennten Objektraum fir Funktiounen ze benotzen fir mat XML ze schaffen - cxXPath. Dëst ass wéi déi richteg Ufro ausgesäit fir eng Astellung an Android ze fannen déi d'Benotzung vum HTTP-Traffic erlaabt:

// Правильный вариант с использованием cxXPath
result = cxXPath.FindXmlAttributesByNameAndValue("*.xml", 8, "cleartextTrafficPermitted", "true", false, true);

Loosst eis et e bësse méi detailléiert kucken, well d'Syntax fir all Funktiounen ähnlech ass, nodeems Dir eng erausfonnt hutt, da musst Dir just deen wielen deen Dir braucht. Also, sequentiell no de Parameteren:

  • "*.xml"- Mask vu Dateien fir ze sichen

  • 8 - ID vun der Sprooch fir déi d'Regel applizéiert gëtt

  • "cleartextTrafficPermitted"- Attribut Numm an xml

  • "true" - de Wäert vun dësem Attribut

  • false - Benotzung vum reguläre Ausdrock beim Sichen

  • true - heescht datt d'Sich duerchgefouert gëtt andeems de Fall ignoréiert, dat heescht, case-onsensitiv

Als Beispill hu mir eng Regel benotzt déi falsch, aus Sécherheetssiicht, Netzwierkverbindungsastellungen an Android identifizéiert, déi d'Kommunikatioun mam Server iwwer den HTTP-Protokoll erlaben. Beispill vun engem Astellung mat engem Attribut cleartextTrafficPermitted mat Bedeitung true:

<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">example.com</domain>
        <trust-anchors>
            <certificates src="@raw/my_ca"/>
        </trust-anchors>
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">secure.example.com</domain>
        </domain-config>
    </domain-config>
</network-security-config>

Eng Aufgab: Limitéiert Resultater duerch Dateinumm / Wee

Léisung: An engem vun de grousse Projeten am Zesummenhang mat der Entwécklung vun enger mobiler Applikatioun fir Android, hu mir falsch Positiver vun der Regel begéint, déi d'Obfuscatiounsstellung bestëmmt. D'Tatsaach ass datt d'Regel aus der Këscht an der Datei sicht build.gradle e Kader verantwortlech fir d'Verduebungsregele fir d'Verëffentlechungsversioun vun der Applikatioun z'applizéieren.

Awer a grousse Projeten ginn et heiansdo Kannerdateien build.gradle, déi op d'Bibliothéike bezéien, déi am Projet abegraff sinn. D'Besonderheet ass datt och wann dës Dateien net de Besoin fir Verdueblung uginn, d'Astellunge vun der Elterenversammlungsdatei ginn während der Kompiléierung applizéiert.

Also ass d'Aufgab Ausléiser an Kannerdateien ofzeschneiden déi zu Bibliothéike gehéieren. Si kënnen duerch d'Präsenz vun der Linn identifizéiert ginn apply 'com.android.library'.

Beispill Code aus Fichier build.gradle, wat de Besoin fir Verdueblung bestëmmt:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        ...
    }

    buildTypes {
        release {
            minifyEnabled true
            ...
        }
    }
}

dependencies {
  ...
}

Fichier Beispill build.gradle fir eng Bibliothéik am Projet abegraff déi dës Astellung net huet:

apply plugin: 'android-library'

dependencies {
  compile 'com.android.support:support-v4:18.0.+'
}

android {
  compileSdkVersion 14
  buildToolsVersion '17.0.0'
  ...
}

An d'Regel fir Checkmarx:

ProGuardObfuscationNotInUse

// Поиск метода release среди всех методов в Gradle файлах
CxList releaseMethod = Find_Gradle_Method("release");

// Все объекты из файлов build.gradle
CxList gradleBuildObjects = Find_Gradle_Build_Objects();

// Поиск того, что находится внутри метода "release" среди всех объектов из файлов build.gradle
CxList methodInvokesUnderRelease = gradleBuildObjects.FindByType(typeof(MethodInvokeExpr)).GetByAncs(releaseMethod);

// Ищем внутри gradle-файлов строку "com.android.library" - это значит, что данный файл относится к библиотеке и его необходимо исключить из правила
CxList android_library = gradleBuildObjects.FindByName("com.android.library");

// Инициализация пустого массива
List<string> libraries_path = new List<string> {};

// Проходим через все найденные "дочерние" файлы
foreach(CxList library in android_library)
{
    // Получаем путь к каждому файлу
	string file_name_library = library.GetFirstGraph().LinePragma.FileName;
    
    // Добавляем его в наш массив
	libraries_path.Add(file_name_library);
}

// Ищем все вызовы включения обфускации в релизных настройках
CxList minifyEnabled = methodInvokesUnderRelease.FindByShortName("minifyEnabled");

// Получаем параметры этих вызовов
CxList minifyValue = gradleBuildObjects.GetParameters(minifyEnabled, 0);

// Ищем среди них включенные
CxList minifyValueTrue = minifyValue.FindByShortName("true");

// Немного магии, если не нашли стандартным способом :D
if (minifyValueTrue.Count == 0) {
	minifyValue = minifyValue.FindByAbstractValue(abstractValue => abstractValue is TrueAbstractValue);
} else {
    // А если всё-таки нашли, то предыдущий результат и оставляем
	minifyValue = minifyValueTrue;	
}

// Если не нашлось таких методов
if (minifyValue.Count == 0)
{
    // Для более корректного отображения места срабатывания в файле ищем или buildTypes или android
	CxList tempResult = All.NewCxList();
	CxList buildTypes = Find_Gradle_Method("buildTypes");
	if (buildTypes.Count > 0) {
		tempResult = buildTypes;
	} else {
		tempResult = Find_Gradle_Method("android");
	}
	
	// Для каждого из найденных мест срабатывания проходим и определяем, дочерний или основной файлы сборки
	foreach(CxList res in tempResult)
	{
        // Определяем, в каком файле был найден buildType или android методы
		string file_name_result = res.GetFirstGraph().LinePragma.FileName;
        
        // Если такого файла нет в нашем списке "дочерних" файлов - значит это основной файл и его можно добавить в результат
		if (libraries_path.Contains(file_name_result) == false){
			result.Add(res);
		}
	}
}

Dës Approche kann zimmlech universell an nëtzlech sinn net nëmme fir Android Uwendungen, awer och fir aner Fäll wou Dir musst bestëmmen ob e Resultat zu enger spezifescher Datei gehéiert.

Eng Aufgab: Füügt Ënnerstëtzung fir eng Drëtt Partei Bibliothéik wann d'Syntax net voll ënnerstëtzt gëtt

Léisung: D'Zuel vu verschiddene Kaderen déi am Prozess vum Code schreiwen benotzt ginn ass einfach aus den Charts. Natierlech weess Checkmarx net ëmmer iwwer hir Existenz, an eis Aufgab ass et ze léieren ze verstoen datt verschidde Methoden speziell zu dësem Kader gehéieren. Heiansdo ass dëst komplizéiert duerch d'Tatsaach datt Kaderen Funktiounsnimm benotzen déi ganz heefeg sinn an et ass onméiglech d'Relatioun vun engem bestëmmten Uruff zu enger spezifescher Bibliothéik eendeiteg ze bestëmmen.

D'Schwieregkeet ass datt d'Syntax vun esou Bibliothéiken net ëmmer richteg unerkannt gëtt an Dir musst experimentéieren fir ze vermeiden datt eng grouss Zuel vu falschen Positiver kritt. Et gi verschidde Méiglechkeeten fir d'Scannengenauegkeet ze verbesseren an de Problem ze léisen:

  • Déi éischt Optioun, mir wëssen sécher datt d'Bibliothéik an engem spezifesche Projet benotzt gëtt a kann d'Regel um Teamniveau uwenden. Awer wann d'Team decidéiert eng aner Approche ze huelen oder verschidde Bibliothéike benotzt, an deenen d'Funktiounsnimm iwwerlappen, kënne mir en net ganz agreabelt Bild vu ville falsche Positiver kréien

  • Déi zweet Optioun ass fir Dateien ze sichen an deenen d'Bibliothéik kloer importéiert ass. Mat dëser Approche kënne mir sécher sinn datt d'Bibliothéik déi mir brauchen genau an dësem Fichier benotzt gëtt.

  • An déi drëtt Optioun ass déi zwee uewe genannte Approche zesummen ze benotzen.

Als Beispill kucke mer eng Bibliothéik déi am schmuele Krees bekannt ass glat fir d'Scala Programméiersprooch, nämlech d'Funktionalitéit Splicing Literal Wäerter. Am Allgemengen, fir Parameteren un eng SQL Ufro ze passéieren, musst Dir den Bedreiwer benotzen $, déi Daten an eng preforméiert SQL Ufro ersetzt. Dat ass, tatsächlech, et ass en direkten Analog vu Prepared Statement op Java. Awer wann Dir dynamesch eng SQL Ufro muss konstruéieren, zum Beispill, wann Dir Tabellennimm passéiere musst, kënnt Dir den Bedreiwer benotzen #$, déi d'Donnéeën direkt an d'Ufro ersetzen (bal wéi Stringkoncatenatioun).

Beispill Code:

// В общем случае - значения, контролируемые пользователем
val table = "coffees"
sql"select * from #$table where name = $name".as[Coffee].headOption

Checkmarx weess nach net wéi d'Benotzung vu Splicing Literal Values ​​​​entdecken a spréngt Bedreiwer #$, Also loosst eis probéieren et ze léieren fir potenziell SQL Injektiounen z'identifizéieren an déi richteg Plazen am Code ze markéieren:

// Находим все импорты
CxList imports = All.FindByType(typeof(Import));

// Ищем по имени, есть ли в импортах slick
CxList slick = imports.FindByShortName("slick");

// Некоторый флаг, определяющий, что импорт библиотеки в коде присутствует
// Для более точного определения - можно применить подход с именем файла
bool not_empty_list = false;
foreach (CxList r in slick)
{
    // Если встретили импорт, считаем, что slick используется
	not_empty_list = true;
}

if (not_empty_list) {
    // Ищем вызовы, в которые передается SQL-строка
	CxList sql = All.FindByShortName("sql");
	sql.Add(All.FindByShortName("sqlu"));
	
	// Определяем данные, которые попадают в эти вызовы
	CxList data_sql = All.DataInfluencingOn(sql);
	
	// Так как синтакис не поддерживается, можно применить подход с регулярными выражениями
	// RegExp стоит использовать крайне осторожно и не применять его на большом количестве данных, так как это может сильно повлиять на производительность
	CxList find_possible_inj = data_sql.FindByRegex(@"#$", true, true, true);

    // Избавляемся от лишних срабатываний, если они есть и выводим в результат
	result = find_possible_inj.FindByType(typeof(BinaryExpr));
}

Eng Aufgab: Sich no benotzt vulnerabel Funktiounen an Open-Source Bibliothéiken

Léisung: Vill Firmen benotzen Open-Source Iwwerwachungstools (OSA Praxis) fir d'Benotzung vu vulnerabel Versioune vu Bibliothéiken an entwéckelten Uwendungen z'entdecken. Heiansdo ass et net méiglech sou eng Bibliothéik op eng sécher Versioun ze aktualiséieren. A verschiddene Fäll sinn et funktionell Aschränkungen, an anerer gëtt et guer keng sécher Versioun. An dësem Fall hëlleft eng Kombinatioun vu SAST an OSA Praktiken ze bestëmmen datt d'Funktiounen, déi zur Ausbeutung vun der Schwachstelle féieren, net am Code benotzt ginn.

Awer heiansdo, besonnesch wann Dir JavaScript berécksiichtegt, ass dëst vläicht net eng komplett trivial Aufgab. Drënner ass eng Léisung, vläicht net ideal, awer trotzdem funktionnéiert, andeems Dir d'Beispill vu Schwachstelle benotzt an der Komponent lodash an Methoden template и *set.

Beispiller vun Test potenziell vulnerabel Code an enger JS Datei:

/**
 * Template example
 */

'use strict';
var _ = require("./node_modules/lodash.js");


// Use the "interpolate" delimiter to create a compiled template.
var compiled = _.template('hello <%= js %>!');
console.log(compiled({ 'js': 'lodash' }));
// => 'hello lodash!'

// Use the internal `print` function in "evaluate" delimiters.

var compiled = _.template('<% print("hello " + js); %>!');
console.log(compiled({ 'js': 'lodash' }));
// => 'hello lodash!'

A wann Dir direkt an HTML verbënnt:

<!DOCTYPE html>
<html>
<head>
    <title>Lodash Tutorial</title>
    <script src="./node_modules/lodash.js"></script>
    <script type="text/javascript">
  // Lodash chunking array
        nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];

        let c1 = _.template('<% print("hello " + js); %>!');
        console.log(c1);

        let c2 = _.template('<% print("hello " + js); %>!');
        console.log(c2);
    </script>
</head>
<body></body>
</html>

Mir sichen no all eis vulnérabel Methoden, déi a Schwachstelle opgelëscht sinn:

// Ищем все строки: в которых встречается строка lodash (предполагаем, что это объявление импорта библиотеки
CxList lodash_strings = Find_String_Literal().FindByShortName("*lodash*");

// Ищем все данные: которые взаимодействуют с этими строками
CxList data_on_lodash = All.InfluencedBy(lodash_strings);


// Задаем список уязвимых методов
List<string> vulnerable_methods = new List<string> {"template", "*set"};

// Ищем все наши уязвимые методы, которые перечисленны в уязвимостях и отфильтровываем их только там, где они вызывались
CxList vulnerableMethods = All.FindByShortNames(vulnerable_methods).FindByType(typeof(MethodInvokeExpr));

//Находим все данные: которые взаимодействуют с данными методами
CxList vulnFlow = All.InfluencedBy(vulnerableMethods);

// Если есть пересечение по этим данным - кладем в результат
result = vulnFlow * data_on_lodash;

// Формируем список путей по которым мы уже прошли, чтобы фильтровать в дальнейшем дубли
List<string> lodash_result_path = new List<string> {};

foreach(CxList lodash_result in result)
{
    // Очередной раз получаем пути к файлам
	string file_name = lodash_result.GetFirstGraph().LinePragma.FileName;
	lodash_result_path.Add(file_name);
}

// Дальше идет часть относящаяся к html файлам, так как в них мы не можем проследить откуда именно идет вызов
// Формируем массив путей файлов, чтобы быть уверенными, что срабатывания уязвимых методов были именно в тех файлах, в которых объявлен lodash
List<string> lodash_path = new List<string> {};
foreach(CxList string_lodash in lodash_strings)
{
	string file_name = string_lodash.GetFirstGraph().LinePragma.FileName;
	lodash_path.Add(file_name);
}

// Перебираем все уязвимые методы и убеждаемся, что они вызваны в тех же файлах, что и объявление/включение lodash
foreach(CxList method in vulnerableMethods)
{
	string file_name_method = method.GetFirstGraph().LinePragma.FileName;
	if (lodash_path.Contains(file_name_method) == true && lodash_result_path.Contains(file_name_method) == false){
		result.Add(method);
	}
}

// Убираем все UknownReferences и оставляем самый "длинный" из путей, если такие встречаются
result = result.ReduceFlow(CxList.ReduceFlowType.ReduceSmallFlow) - result.FindByType(typeof(UnknownReference));

Eng Aufgab: Sich no Certificaten, déi an der Applikatioun agebonne sinn

Léisung: Et ass net ongewéinlech fir Uwendungen, besonnesch mobil, Zertifikater oder Schlësselen ze benotzen fir Zougang zu verschiddene Serveren ze benotzen oder SSL-Pinning z'iwwerpréiwen. Aus enger Sécherheetsperspektiv, sou Saachen am Code ze späicheren ass net déi bescht Praxis. Loosst eis probéieren eng Regel ze schreiwen déi no ähnlechen Dateien am Repository sichen:

// Найдем все сертификаты по маске файла
CxList find_certs = All.FindByShortNames(new List<string> {"*.der", "*.cer", "*.pem", "*.key"}, false);

// Проверим, где в приложении они используются
CxList data_used_certs = All.DataInfluencedBy(find_certs);

// И для мобильных приложений - можем поискать методы, где вызывается чтение сертификатов
// Для других платформ и приложений могут быть различные методы
CxList methods = All.FindByMemberAccess("*.getAssets");

// Пересечение множеств даст нам результат по использованию локальных сертификатов в приложении
result = methods * data_used_certs;

Eng Aufgab: Fannt kompromittéiert Tokens an der Applikatioun

Léisung: Et ass dacks néideg kompromittéiert Tokens oder aner wichteg Informatioun zréckzezéien déi am Code präsent ass. Natierlech ass se am Quellcode ze späicheren net eng gutt Iddi, awer d'Situatioun variéieren. Dank CxQL Ufroen, Saache wéi dëst ze fannen ass ganz einfach:

// Получаем все строки, которые содержатся в коде
CxList strings = base.Find_Strings();

// Ищем среди всех строк нужное нам значение. В примере токен в виде строки "qwerty12345"
result = strings.FindByShortName("qwerty12345");

Konklusioun

Ech hoffen, datt dësen Artikel nëtzlech ass fir déi, déi hir Bekanntschaft mam Checkmarx-Tool ufänken. Vläicht déi, déi hir eege Regele fir eng laang Zäit geschriwwen hunn, fannen och eppes nëtzlech an dësem Guide.

Leider feelt et momentan un eng Ressource wou bei der Entwécklung vu Regele fir Checkmarx nei Iddie gesammelt kënne ginn. Dofir hu mir geschaf Repository op Github, wou mir eis Aarbecht posten, fir datt jiddereen, deen CxQL benotzt, eppes Nëtzleches dran fënnt, an och d'Méiglechkeet huet hir Aarbecht mat der Gemeinschaft ze deelen. De Repository ass amgaang Inhalter auszefëllen an ze strukturéieren, sou datt d'Bäiträg wëllkomm sinn!

Merci fir Är Opmierksamkeet!

Source: will.com

Setzt e Commentaire