Cumu scrive regule per Checkmarx senza impazzisce

Ehi Habr!

In u nostru travagliu, a nostra cumpagnia assai spessu tratta di vari strumenti di analisi di codice staticu (SAST). Fora di a scatula tutti travaglianu in media. Di sicuru, tuttu dipende di u prugettu è di e tecnulugii utilizati in questu, è ancu di quantu queste tecnulugia sò cuparti da e regule di analisi. In u mo parè, unu di i criterii più impurtanti quandu sceglite un strumentu SAST hè a capacità di persunalizà à e specifiche di e vostre applicazioni, vale à dì, scrive è cambià e regule di analisi o, cum'è più spessu chjamati, Custom Queries.

Cumu scrive regule per Checkmarx senza impazzisce

U più spessu usemu Checkmarx - un analizzatore di codice assai interessante è putente. In questu articulu, parraraghju di a mo sperienza di scrive regule di analisi per questu.

Indice di cuntenutu

Plus

Per principià, mi piacerebbe ricumandemu unu di i pochi articuli in russu nantu à e caratteristiche di e dumande di scrittura per Checkmarx. Hè statu publicatu annantu à Habré à a fine di u 2019 sottu u titulu: "Salutu, Checkmarx!" Cumu scrive una query Checkmarx SAST è truvà vulnerabilità interessanti.

Esamina in dettagliu cumu scrive e prime dumande in CxQL (Checkmarx Query Language) per qualchì applicazione di teste è mostra i principii basi di cumu funziona e regule di analisi.

Ùn ripeteraghju micca ciò chì hè descrittu in questu, ancu s'è certi intersezioni seranu sempre presenti. In u mo articulu, pruvaraghju à cumpilà un tipu di "raccolta di ricette", una lista di suluzioni à prublemi specifichi chì aghju scontru durante u mo travagliu cù Checkmarx. Aviu avutu à scaccià u mo cervellu annantu à parechji di sti prublemi. Certe volte ùn ci era micca abbastanza infurmazione in a ducumentazione, è qualchì volta era ancu difficiule di capisce cumu fà ciò chì era necessariu. Spergu chì a mo sperienza è e notti insonne ùn saranu micca in vanu, è sta "raccolta di ricette Custom Queries" vi risparmià uni pochi d'ore o un paru di cellule nervose. Allora, cuminciamu !

Informazione generale nantu à e regule

Prima, fighjemu uni pochi di cuncetti basi è u prucessu di travaglià cù e regule, per capisce megliu ciò chì succede dopu. È ancu perchè a documentazione ùn dice nunda di questu o hè assai spargugliatu in a struttura, chì ùn hè micca assai còmuda.

  1. E regule sò applicate durante a scansione secondu u preset sceltu à u principiu (un settore di regule attive). Pudete creà un numeru illimitatu di presets, è esattamente cumu a struttura di elli dipende da e specifiche di u vostru prucessu. Pudete raggruppà per lingua o selezziunate presets per ogni prughjettu. U numeru di regule attive afecta a rapidità è a precisione di scanning.

    Cumu scrive regule per Checkmarx senza impazzisceConfigurazione di Preset in l'interfaccia Checkmarx

  2. I reguli sò editati in un strumentu speciale chjamatu CxAuditor. Questa hè una applicazione desktop chì si cunnetta à un servitore chì esegue Checkmarx. Stu strumentu hà dui modi di funziunamentu: edizione di regule è analizà i risultati di una scansione digià realizata.

    Cumu scrive regule per Checkmarx senza impazzisceInterfaccia CxAudit

  3. I reguli in Checkmarx sò divisi per lingua, vale à dì, ogni lingua hà u so propiu settore di dumande. Ci hè ancu alcune regule generale chì s'applicanu indipendente di a lingua, queste sò e chjamate dumande basiche. Per a maiò parte, e dumande basi implicanu a ricerca di l'infurmazioni chì altre regule utilizanu.

    Cumu scrive regule per Checkmarx senza impazzisceDividendu e regule per lingua

  4. E regule sò "Eseguibili" è "Non-Eseguibili" (Eseguitu è ​​micca Eseguitu). Ùn hè micca u nome currettu, in my opinion, ma hè ciò chì hè. U fondu hè chì u risultatu di eseguisce e regule "Executable" serà mostratu in i risultati di scanning in l'UI, è e regule "Non-Executable" sò necessarii solu per utilizà i so risultati in altre dumande (in fatti, sò solu una funzione. ).

    Cumu scrive regule per Checkmarx senza impazzisceDeterminà u tipu di regula quandu crea

  5. Pudete creà novi règule o supplementà / scrive e esistenti. Per riscrive una regula, avete bisognu di truvà in l'arbulu, cliccate right-click è selezziunate "Override" da u menù drop-down. Hè impurtante di ricurdà quì chì e novi regule ùn sò micca inizialmente incluse in i presets è ùn sò micca attivi. Per principià cù elli, avete bisognu di attivà in u menù "Manager Preset" in u strumentu. I reguli riscritti conservanu i so paràmetri, vale à dì, se a regula era attiva, ferma cusì è serà applicata immediatamente.

    Cumu scrive regule per Checkmarx senza impazzisceEsempiu di una nova regula in l'interfaccia di Preset Manager

  6. Durante l'esekzione, un "arbre" di dumande hè custruitu, chì dipende di ciò chì. E regule chì cullighjanu l'infurmazioni sò eseguite prima, è quelli chì l'utilizanu secondu. U risultatu di l'esekzione hè in cache, perchè s'ellu hè pussibule di utilizà i risultati di una regula esistente, allora hè megliu per fà, questu riduce u tempu di scanning.

  7. E regule ponu esse applicate à diversi livelli:

  • Per tuttu u sistema - serà utilizatu per ogni scanning di qualsiasi prughjettu

  • À u livellu di a squadra (Team) - serà solu utilizatu per scansà i prughjetti in a squadra scelta.

  • À u livellu di u prughjettu - Sarà applicatu in un prughjettu specificu

    Cumu scrive regule per Checkmarx senza impazzisceDeterminà u livellu à quale a regula serà applicata

"Dizziunariu" per i principianti

E cumminciaraghju cù uni pochi di cose chì m'hà causatu dumande, è vi mustrarà ancu una quantità di tecniche chì simplificà significativamente a vita.

Operazioni cù listi

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

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

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

Tutti l'articuli truvati

Dentru a lingua scanned, pudete ottene una lista di assolutamente tutti l'elementi chì Checkmarx hà identificatu (strings, funzioni, classi, metudi, etc.). Questu hè un spaziu di oggetti chì ponu accede à traversu All. Questu hè, per circà un oggettu cù un nome specificu searchMe, pudete cercà, per esempiu, per nome in tutti l'uggetti truvati:

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

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

Ma, sè avete bisognu di circà in una altra lingua chì per una certa ragione ùn era micca inclusa in a scansione (per esempiu, groovy in un prughjettu Android), pudete espansione u nostru spaziu di l'ughjettu attraversu una variabile:

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

Funzioni per l'analisi di flussu

Queste funzioni sò aduprate in parechje regule è quì hè una piccula scheda di ciò chì significanu:

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

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

Ottene u nome di u schedariu / percorso

Ci hè parechje attributi chì ponu esse ottenuti da i risultati di una dumanda (u nome di u schedariu in u quale l'entrata hè stata trovata, stringa, etc.), ma a documentazione ùn dice micca cumu uttene è aduprà. Dunque, per fà questu, avete bisognu di accede à a pruprietà LinePragma è l'uggetti chì avemu bisognu seranu situati in questu:

// Для примера найдем все методы
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);

Vale a pena tene in mente chì FileName cuntene veramente u percorsu à u schedariu, postu chì avemu usatu u metudu GetFirstGraph.

Risultu di l'esecuzione

Ci hè una variabile speciale in CxQL result, chì torna u risultatu di eseguisce a vostra regula scritta. Hè inizializatu immediatamente è pudete scrive risultati intermedi in questu, cambiendu è raffinendu mentre travagliate. Ma, se ùn ci hè micca assignazione à sta variabile o funzione in a regula return- u risultatu di l'esekzione serà sempre zero.

A seguente dumanda ùn ci restituverà nunda in u risultatu di l'esekzione è serà sempre viota:

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

Ma, dopu avè assignatu u risultatu di l'esekzione à u risultatu variabile magicu, vedemu ciò chì sta chjama torna à noi:

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

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

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

Utilizà i risultati di altre regule

E regule in Checkmarx ponu esse chjamatu analogu à e funzioni in una lingua di prugrammazione regulare. Quandu scrivite una regula, pudete bè aduprà i risultati di altre dumande. Per esempiu, ùn ci hè bisognu di cercà tutte e chjama di metudu in u codice ogni volta, solu chjamate a regula desiderata:

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

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

Stu approcciu vi permette di accurtà u codice è di riduce significativamente u tempu d'esekzione di a regula.

Risoluzione di prublemi

Logging

Quandu u travagliu cù l'uttellu, qualchì volta ùn hè micca pussibule di scrive immediatamente a dumanda desiderata è avete da sperimentà, pruvate diverse opzioni. Per un tali casu, u strumentu furnisce logging, chì hè chjamatu cusì:

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

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

Ma vale a pena ricurdà chì stu metudu accetta solu cum'è input stringa, cusì ùn serà micca pussibule di vede una lista cumpleta di elementi truvati in u risultatu di a prima operazione. A seconda opzione, chì hè utilizata per debugging, hè di assignà à una variabile magica da u tempu à u tempu result u risultatu di a dumanda è vede ciò chì succede. Stu approcciu ùn hè micca assai cunvene; vi tocca à esse sicuru chì ùn ci hè micca overrides o operazioni cù questu in u codice dopu. result o simpricimenti cumentu u codice sottu. O pudete, cum'è mè, scurdate di caccià parechje tali chjamate da una regula pronta è dumandassi perchè nunda ùn funziona.

Una manera più còmuda hè di chjamà u metudu return cù u paràmetru necessariu. In questu casu, l'esekzione di a regula finirà è pudemu vede ciò chì hè accadutu cum'è u risultatu di ciò chì avemu scrittu:

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

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

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

Prublemu di login

Ci sò situazioni quandu ùn pudete micca accede à l'uttellu CxAudit (chì hè utilizatu per scrive regule). Ci ponu esse parechje ragioni per questu, cumprese crashes, aghjurnamenti improvvisi di Windows, BSOD è altre situazioni impreviste chì sò fora di u nostru cuntrollu. In questu casu, qualchì volta ci hè una sessione infinita in a basa di dati, chì impedisce di login in novu. Per riparà, avete bisognu di eseguisce parechje dumande:

Per Checkmarx prima di 8.6:

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

Per Checkmarx dopu à 8.6:

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

Reguli di scrittura

Avà ghjunghjemu à a parte più interessante. Quandu avete principiatu à scrive regule in CxQL, ciò chì spessu manca ùn hè micca tantu documentazione cum'è alcuni esempi viventi di risolve certi prublemi è di descrizzione di u prucessu di cumu si travaglia in generale.

Pruvaraghju di fà a vita un pocu più faciule per quelli chì cumincianu à immerse in a lingua di quistione è dà parechji esempi di usu di Custom Queries per risolve certi prublemi. Certi di elli sò abbastanza generale è ponu esse aduprati in a vostra cumpagnia praticamente senza cambiamenti, altri sò più specifichi, ma ponu ancu esse utilizati cambiendu u codice per adattà à e specifiche di e vostre applicazioni.

Dunque, quì sò i prublemi chì avemu scontru più spessu:

Un compitu: Ci hè parechje Flussi in i risultati di eseguisce a regula è unu di elli hè un nidificazione di l'altru, duvete lascià unu di elli.

suluzione: In verità, qualchì volta Checkmarx mostra parechji flussi di dati chì ponu sovrappone è esse una versione accurtata di l'altri. Ci hè un metudu speciale per tali casi Riduce u flussu. Sicondu u paràmetru, selezziunà u flussu più cortu o più longu:

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

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

Un compitu: Espandi a lista di dati sensittivi à quale u strumentu reagisce

suluzione: Checkmarx hà reguli basi, i risultati di quale sò usati da parechje altre dumande. Supplimentendu alcune di queste regule cù dati specifichi per a vostra applicazione, pudete immediatamente migliurà i risultati di scansione. Quì sottu hè un esempiu di regula per avè principiatu:

Lista_di_violazione_di_privacy_generale

Aghjunghjemu parechje variàbili chì sò usati in a nostra applicazione per almacenà infurmazione sensitiva:

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

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

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

Un compitu: Espandi a lista di variàbili cù password

suluzione: Avissi ricumandemu prestu attentu à a regula basica per definisce e password in codice è aghjunghjendu una lista di nomi di variàbili chì sò comunmente usati in a vostra cumpagnia.

Lista_di_violazione_privacy_password

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);
	}
}

Un compitu: Aghjunghjite frameworks usati chì ùn sò micca supportati da Checkmarx

suluzione: Tutte e dumande in Checkmarx sò divise per lingua, cusì avete bisognu di aghjunghje regule per ogni lingua. Quì sottu sò qualchi esempi di tali règuli.

Se i biblioteche sò aduprate chì cumplementanu o rimpiazzanu a funziunalità standard, ponu esse facilmente aghjuntu à a regula basica. Allora tutti quelli chì l'utilizanu amparanu immediatamente nantu à e novi introduzioni. Per esempiu, biblioteche per logging in Android sò Timber è Loggi. In u pacchettu di basa, ùn ci sò micca regule per identificà e chjama non-sistema, cusì se una password o identificatore di sessione entra in u logu, ùn sapemu micca. Pruvemu di aghjunghje definizioni di tali metudi à e regule Checkmarx.

Esempiu di codice di prova chì usa a biblioteca Timber per u logu:

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");
    }
}

È quì hè un esempiu di una dumanda per Checkmarx, chì vi permetterà di aghjunghje una definizione di chjamà i metudi di Timber cum'è un puntu di uscita per i dati da l'applicazione:

FindAndroidOutputs

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

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

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

È pudete ancu aghjunghje à a regula vicina, ma questu hè direttamente in relazione cù u logu in Android:

FindAndroidLog_Outputs

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

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

Inoltre, se l'applicazioni Android usanu WorkManager per u travagliu asincronu, hè una bona idea di informà in più à Checkmarx nantu à questu aghjustendu un metudu per uttene dati da u compitu. getInputData:

FindAndroidRead

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

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

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

Un compitu: A ricerca di dati sensibili in plist per i prughjetti iOS

suluzione: iOS spessu usa schedarii speciali cù l'estensione .plist per almacenà diverse variàbili è valori. U almacenamentu di password, tokens, chjavi è altri dati sensibili in questi schedari ùn hè micca cunsigliatu, postu chì ponu esse estratti da u dispusitivu senza prublemi.

I schedarii Plist anu caratteristiche chì ùn sò micca evidenti à l'occhiu nudu, ma sò impurtanti per Checkmarx. Scrivemu una regula chì cercarà e dati chì avemu bisognu è ci dicenu se password o tokens sò citati in qualchì locu.

Un esempiu di tali file, chì cuntene un token per a cumunicazione cù u serviziu backend:

<?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>

È una regula per Checkmarx, chì hà parechje sfumature chì deve esse cunsideratu quandu scrive:

// Используем результат выполнения правила по поиску файлов 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);

Un compitu: Truvà infurmazione in XML

suluzione: Checkmarx hà funzioni assai convenienti per travaglià cù XML è cercà valori, tags, attributi è più. Ma, sfurtunatamenti, ci hè statu un errore in a ducumentazione per via di quale ùn hè micca un solu esempiu. Malgradu u fattu chì stu difettu hè statu eliminatu in l'ultima versione di a ducumentazione, fate cura s'è vo aduprate versioni precedenti di documenti.

Eccu un esempiu incorrectu da a documentazione:

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

In u risultatu di u tentativu di esicuzzioni, riceveremu un errore chì All ùn ci hè micca un tali metudu ... È questu hè veru, postu chì ci hè un spaziu d'ughjettu speciale è separatu per aduprà funzioni per travaglià cù XML - cxXPath. Questu hè ciò chì pare a dumanda curretta per truvà un paràmetru in Android chì permette l'usu di u trafficu HTTP:

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

Fighjemu in un pocu più di dettu, postu chì a sintassi per tutte e funzioni hè simile, dopu avè capitu unu, allora basta à selezziunate quellu chì avete bisognu. Allora, sequentially secondu i paràmetri:

  • "*.xml"- maschera di i schedari da circà

  • 8 - id di a lingua per a quale a regula hè applicata

  • "cleartextTrafficPermitted"- nome attributu in xml

  • "true" - u valore di stu attributu

  • false - l'usu di l'espressione regulare in a ricerca

  • true - significa chì a ricerca serà realizata ignorendu u casu, vale à dì, insensibile à u casu

Per esempiu, avemu usatu una regula chì identifica incorrecte, da un puntu di vista di sicurità, paràmetri di cunnessione di rete in Android chì permettenu a cumunicazione cù u servitore per via di u protocolu HTTP. Esempiu di un paràmetru chì cuntene un attributu cleartextTrafficPermitted cun significatu 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>

Un compitu: Limite i risultati per nome di file / percorsu

suluzione: In unu di i grandi prughjetti ligati à u sviluppu di una applicazione mobile per Android, avemu scontru falsi pusitivi di a regula chì determina u paràmetru di offuscazione. U fattu hè chì a regula fora di a casella cerca in u schedariu build.gradle un paràmetru rispunsevule per applicà e regule di offuscazione per a versione di liberazione di l'applicazione.

Ma in i grandi prughjetti qualchì volta ci sò schedarii di i zitelli build.gradle, chì riferenu à e biblioteche incluse in u prugettu. A peculiarità hè chì ancu s'è questi schedari ùn indicanu micca a necessità di l'obfuscazione, i paràmetri di u schedariu di l'assemblea parenti seranu applicati durante a compilazione.

Cusì, u compitu hè di cut off triggers in i schedarii di i zitelli chì appartenenu à e biblioteche. Puderanu esse identificati da a presenza di a linea apply 'com.android.library'.

Esempiu di codice da u schedariu build.gradle, chì determina a necessità di offuscazione:

apply plugin: 'com.android.application'

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

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

dependencies {
  ...
}

File d'esempiu build.gradle per una biblioteca inclusa in u prugettu chì ùn hà micca sta paràmetra:

apply plugin: 'android-library'

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

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

È a regula per 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);
		}
	}
}

Stu approcciu pò esse abbastanza universale è utile micca solu per l'applicazioni Android, ma ancu per altri casi quandu avete bisognu di stabilisce se un risultatu appartene à un schedariu specificu.

Un compitu: Aghjunghjite u supportu per una biblioteca di terzu se a sintassi ùn hè micca cumplettamente supportata

suluzione: U numeru di diversi frameworks chì sò usati in u prucessu di scrittura di codice hè solu fora di i charts. Di sicuru, Checkmarx ùn sapi micca sempre di a so esistenza, è u nostru compitu hè di insignà à capisce chì certi metudi appartenenu specificamente à stu quadru. A volte questu hè cumplicatu da u fattu chì i frameworks utilizanu nomi di funzioni chì sò assai cumuni è hè impussibile di determinà senza ambiguità a relazione di una chjamata particulari à una biblioteca specifica.

A difficultà hè chì a sintassi di tali biblioteche ùn hè micca sempre ricunnisciuta currettamente è avete da sperimentà per evità di ottene un gran numaru di falsi pusitivi. Ci hè parechje opzioni per migliurà a precisione di scanning è risolve u prublema:

  • A prima opzione, sapemu di sicuru chì a biblioteca hè aduprata in un prughjettu specificu è pò applicà a regula à u livellu di a squadra. Ma se u squadra decide di piglià un accostu diversu o usa parechje biblioteche in quale i nomi di funzioni si sovrapponenu, pudemu avè una stampa micca assai piacevule di numerosi falsi pusitivi.

  • A seconda opzione hè di circà i schedari in quale a biblioteca hè chjaramente impurtata. Cù stu approcciu, pudemu esse sicuru chì a biblioteca chì avemu bisognu hè usata esattamente in stu schedariu.

  • È a terza opzione hè di utilizà i dui approcci sopra inseme.

Per esempiu, fighjemu una biblioteca ben cunnisciuta in i circles stretti sciaccatu per a lingua di prugrammazione Scala, vale à dì, a funziunalità Splicing Literal Values. In generale, per passà i paràmetri à una query SQL, duvete aduprà l'operatore $, chì sustituisci dati in una dumanda SQL preformata. Hè, in fattu, hè un analogu direttu di Prepared Statement in Java. Ma, sè avete bisognu di custruisce dinamicamente una dumanda SQL, per esempiu, se avete bisognu di passà i nomi di tavule, pudete aduprà l'operatore. #$, chì sustituverà direttamente i dati in a dumanda (quasi cum'è a concatenazione di stringa).

Codice di mostra:

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

Checkmarx ùn sapi ancu cumu detectà l'usu di Splicing Literal Values ​​è salta l'operatori #$, allora pruvemu à insignà à identificà potenziale injections SQL è mette in risaltu i posti ghjusti in u codice:

// Находим все импорты
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));
}

Un compitu: Ricerca di funzioni vulnerabili usate in biblioteche Open-Source

suluzione: Parechje cumpagnie utilizanu strumenti di surviglianza Open-Source (pratica OSA) per detectà l'usu di versioni vulnerabili di biblioteche in applicazioni sviluppate. A volte ùn hè micca pussibule di aghjurnà una tale biblioteca à una versione sicura. In certi casi, ci sò limitazioni funziunali, in altri ùn ci hè micca una versione sicura. In questu casu, una cumminazione di pratiche SAST è OSA aiutanu à determinà chì e funzioni chì portanu à a sfruttamentu di a vulnerabilità ùn sò micca utilizati in u codice.

Ma qualchì volta, soprattuttu quandu si cunsiderà JavaScript, questu pò esse micca un compitu cumplitamenti triviale. A sottu hè una suluzione, forse micca ideale, ma ancu di travagliu, usendu l'esempiu di vulnerabili in u cumpunente lodash in metudi template и *set.

Esempii di teste di codice potenzialmente vulnerabile in un schedariu JS:

/**
 * 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!'

È quandu cunnette direttamente in html:

<!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>

Cerchemu tutti i nostri metudi vulnerabili, chì sò listati in vulnerabilità:

// Ищем все строки: в которых встречается строка 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));

Un compitu: Ricerca di certificati incrustati in l'applicazione

suluzione: Ùn hè pocu cumu per l'applicazioni, in particulare i mobili, per utilizà certificati o chjave per accede à diversi servitori o verificate SSL-Pinning. Da una perspettiva di sicurità, almacenà tali cose in codice ùn hè micca a megliu pratica. Pruvemu di scrive una regula chì cercarà file simili in u repository:

// Найдем все сертификаты по маске файла
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;

Un compitu: Truvà tokens compromessi in l'applicazione

suluzione: Hè spessu necessariu di revocà tokens cumprumessi o altre infurmazione impurtante chì hè presente in u codice. Di sicuru, guardà elli in u codice fonte ùn hè micca una bona idea, ma e situazioni varienu. Grazie à e dumande CxQL, truvà cose cum'è questu hè abbastanza faciule:

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

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

cunchiusioni

Spergu chì questu articulu serà utile à quelli chì principianu a so cunniscenza cù u strumentu Checkmarx. Forsi quelli chì anu scrittu e so regule per un bellu pezzu truveranu ancu qualcosa d'utile in sta guida.

Sfurtunatamente, ci hè attualmente una mancanza di una risorsa induve l'idee novi puderanu esse raccolte durante u sviluppu di e regule per Checkmarx. Hè per quessa chì avemu creatu repository nantu à Github, induve puderemu u nostru travagliu per chì tutti quelli chì utilizanu CxQL ponu truvà qualcosa d'utile in questu, è ancu avè l'uppurtunità di sparte u so travagliu cù a cumunità. U repositariu hè in u prucessu di riempimentu è di strutturazione di u cuntenutu, cusì i cuntributori sò benvenuti!

Ti ringraziu per a vostra attenzione!

Source: www.habr.com

Add a comment