Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibe

Hey Habr!

Di xebata me de, pargîdaniya me pir caran bi amûrên analîzkirina koda statîk ên cihêreng (SAST) re mijûl dibe. Ji qutîkê ew hemî navîn dixebitin. Bê guman, ew hemî bi proje û teknolojiyên ku di wê de têne bikar anîn ve girêdayî ye, û hem jî ev teknolojiyên çiqas bi qaîdeyên analîzê ve têne vegirtin. Bi dîtina min, yek ji pîvanên herî girîng dema hilbijartina amûrek SAST-ê ev e ku meriv wê li gorî taybetmendiyên serîlêdanên xwe xweş bike, ango, nivîsandin û guheztina qaîdeyên analîzê an, wekî ku pir caran jê re tê gotin, Pirsên Xweser.

Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibe

Em pir caran Checkmarx bikar tînin - analîzek kodê pir balkêş û hêzdar. Di vê gotarê de ez ê qala ezmûna xwe ya nivîsandina qaîdeyên analîzê ji bo wê bikim.

Table of Contents

entry

Ji bo destpêkê, ez dixwazim yek ji çend gotarên bi rûsî li ser taybetmendiyên nivîsandina pirsên ji bo Checkmarx pêşniyar bikim. Ew di dawiya sala 2019-an de li ser Habré di bin sernavê de hate weşandin: "Silav, Checkmarx!" Meriv çawa pirsek Checkmarx SAST binivîse û qelsiyên xweş bibîne.

Ew bi hûrgulî lêkolîn dike ka meriv çawa pirsên yekem di CxQL (Zimanê Query Checkmarx) de ji bo hin serlêdana ceribandinê dinivîse û prensîbên bingehîn ên ka qaîdeyên analîzê çawa dixebitin destnîşan dike.

Ez ê tiştê ku tê de tê ravekirin dubare nekim, her çend hin navber hîn jî hebin. Di gotara xwe de ez ê hewl bidim ku celebek "kolek reçeteyan", navnîşek çareseriyên ji bo pirsgirêkên taybetî yên ku ez di dema xebata xwe ya bi Checkmarx de pê re rû bi rû bûm, berhev bikim. Ez neçar bûm ku mêjiyê xwe li ser gelek ji van pirsgirêkan rakim. Carinan di belgeyan de agahdarî têr nedibû, carinan jî zehmet bû ku meriv fêm bike ka meriv çawa hewce dike. Ez hêvî dikim ku serpêhatiya min û şevên bêxew dê vala nebin, û ev "berhevkirina reçeteyên Lêpirsînên Xweser" dê we çend demjimêr an çend hucreyên nervê xilas bike. Ji ber vê yekê, em dest pê bikin!

Agahiyên giştî li ser qaîdeyên

Pêşî, bila em li çend têgehên bingehîn û pêvajoya xebata bi qaîdeyan binerin, ji bo ku em çêtir fam bikin ka dê paşê çi bibe. Û di heman demê de ji ber ku belge li ser vê yekê tiştek nabêjin an jî di strukturê de pir belav e, ku ne pir hêsan e.

  1. Rêgez di dema şopandinê de li gorî pêşdibistanê ku di destpêkê de hatî hilbijartin (komek rêzikên çalak) têne sepandin. Hûn dikarin hejmareke bêsînor ji pêşdebiran biafirînin, û tam ka meriv çawa wan ava dike bi taybetmendiyên pêvajoya we ve girêdayî ye. Hûn dikarin wan li gorî ziman kom bikin an ji bo her projeyek pêşdibistanê hilbijêrin. Hejmara qaîdeyên çalak bandorê li lez û rastbûna şopandinê dike.

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeSazkirina Pêşînsaziyê di navbera Checkmarx de

  2. Rêgez di amûrek taybetî ya bi navê CxAuditor de têne guherandin. Ev serîlêdanek sermaseyê ye ku bi serverek Checkmarx-ê ve girêdayî ye. Vê amûrê du awayên xebitandinê hene: guheztina qaîdeyên û analîzkirina encamên lêgerînek berê hatî çêkirin.

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeNavrûya CxAudit

  3. Rêgezên di Checkmarx de ji hêla ziman ve têne dabeş kirin, ango, her zimanek komek pirsên xwe hene. Di heman demê de hin qaîdeyên gelemperî hene ku bêyî ferqê ziman têne bikar anîn, ev bi navê pirsên bingehîn in. Bi piranî, pirsên bingehîn lêgerîna agahdariya ku qaîdeyên din bikar tînin vedihewîne.

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeDabeşkirina qaîdeyan li gorî ziman

  4. Rêgez "Cirandî" û "Ne-Pêkhatî" ne (Dervekirin û Ne Kirin). Bi dîtina min ne navekî rast e, lê ew ew e. Rêzeya jêrîn ev e ku encama bicîhkirina qaîdeyên "Derkêşbar" dê di encamên şopandinê de di UI-yê de were xuyang kirin, û qaîdeyên "Ne-Karker" tenê hewce ne ku encamên wan di daxwazên din de bikar bînin (di eslê xwe de, tenê fonksiyonek).

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeDi dema afirandinê de celebê qaîdeyê diyar dike

  5. Hûn dikarin qaîdeyên nû biafirînin an yên heyî zêde bikin / ji nû ve binivîsin. Ji bo ku hûn qaîdeyek ji nû ve binivîsin, hûn hewce ne ku wê di darê de bibînin, rast-klîk bikin û ji pêşeka daketî "Override" hilbijêrin. Girîng e ku li vir ji bîr mekin ku qaîdeyên nû di destpêkê de ne di nav pêşdebiran de ne û ne çalak in. Ji bo ku hûn dest bi karanîna wan bikin, hûn hewce ne ku wan di menuya "Rêveberê Pêşkêşkirî" ya amûrê de çalak bikin. Rêzikên ji nû ve hatine nivîsandin mîhengên xwe diparêzin, ango heke qaîdeyek çalak bû, ew ê wusa bimîne û dê tavilê were sepandin.

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeMînaka qaîdeyek nû di navbera Rêvebirê Pêşîn de

  6. Di dema darvekirinê de, "darek" daxwazan tê çêkirin, ku bi çi ve girêdayî ye. Qaîdeyên ku agahdarî berhev dikin yekem têne darve kirin, û yên ku wan bikar tînin duyemîn têne bicîh kirin. Encama darvekirinê cached e, ji ber vê yekê heke gengaz e ku meriv encamên qaîdeyek heyî bikar bîne, wê hingê çêtir e ku meriv wiya bike, ev ê dema şopandinê kêm bike.

  7. Qanûn dikarin di astên cûda de bêne sepandin:

  • Ji bo tevahiya pergalê - dê ji bo her şopandina her projeyê were bikar anîn

  • Di asta tîmê de - dê tenê ji bo şopandina projeyên di tîmê hilbijartî de were bikar anîn.

  • Di asta projeyê de - Dê di projeyek taybetî de were sepandin

    Meriv çawa qaîdeyên ji bo Checkmarx dinivîse bêyî ku dîn bibeTesbîtkirina asta ku wê qayde were sepandin

"Ferheng" ji bo destpêk

Û ez ê bi çend tiştên ku bûne sedema pirsa min dest pê bikim, û ez ê çend teknîkên ku dê jiyanê bi girîngî hêsan bikin jî nîşan bidim.

Operasyonên bi lîsteyan

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

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

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

Hemû tiştên hatine dîtin

Di hundurê zimanê şelandî de, hûn dikarin navnîşek bêkêmasî hemî hêmanên ku Checkmarx destnîşan kiriye (rêz, fonksiyon, çîn, rêbaz, hwd.) bistînin. Ev hinek cîhê tiştan e ku meriv dikare bi navgîniyê ve were gihîştin All. Ango lêgerîna tiştekî bi navekî taybet e searchMe, hûn dikarin, wek nimûne, bi navî li hemî tiştên ku hatine dîtin bigerin:

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

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

Lê, heke hûn hewce ne ku li zimanek din bigere ku ji ber hin sedeman di şansê de nehatibû girtin (mînak, groovy di projeyek Android-ê de), hûn dikarin cîhê meya me bi guhêrbarek berfireh bikin:

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

Fonksiyonên ji bo analîza Flow

Van fonksiyonan di gelek qaîdeyan de têne bikar anîn û li vir pelek piçûk a xapandinê ya wateya wan heye:

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

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

Navê pelê / rêyê digirin

Gelek taybetmendî hene ku dikarin ji encamên pirsekê werin wergirtin (navê pelê ku tê de tê de hate dîtin, rêzik, hwd.), lê di belgeyê de nayê gotin ka meriv çawa wan digire û bikar tîne. Ji ber vê yekê, ji bo ku hûn vê yekê bikin, hûn hewce ne ku xwe bigihînin taybetmendiya LinePragma û tiştên ku em hewce ne dê di hundurê wê de bin:

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

Hêjayî bîrxistinê ye ku FileName di rastiyê de riya pelê vedihewîne, ji ber ku me rêbaz bikar anî GetFirstGraph.

Encama darvekirinê

Di hundurê CxQL de guhêrbarek taybetî heye result, ku encama pêkanîna qaîdeya weya nivîskî vedigerîne. Ew tavilê dest pê dike û hûn dikarin encamên navîn tê de binivîsin, dema ku hûn dixebitin wan biguhezînin û paqij bikin. Lê, heke di hundurê qaîdeyê de peywira vê guhêrbar an fonksiyonê tune be return- Encama darvekirinê dê her dem sifir be.

Pirsa jêrîn dê di encama darvekirinê de tiştek ji me re venegerîne û dê her gav vala bimîne:

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

Lê, piştî ku encama darvekirinê li encama guhêrbar a sêrbaz veqetand, em ê bibînin ka ev bang li me çi vedigere:

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

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

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

Bikaranîna encamên qaîdeyên din

Rêgezên di Checkmarx de dikare wekî fonksiyonên di zimanek bernamesaziya birêkûpêk de were gotin. Dema ku qaîdeyek dinivîsin, hûn dikarin encamên pirsên din bikar bînin. Mînakî, ne hewce ye ku her carê li hemî bangên rêbazê di kodê de bigerin, tenê qaîdeya xwestinê bang bikin:

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

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

Ev nêzîkatî dihêle hûn kodê kurt bikin û wextê pêkanîna qaîdeyê bi girîngî kêm bikin.

Areseriya pirsgirêkan

Logging

Dema ku bi amûrê re dixebitin, carinan ne gengaz e ku hûn tavilê pirsa xwestinê binivîsin û divê hûn ceribandin, vebijarkên cihêreng biceribînin. Ji bo rewşek wusa, amûr têketinê peyda dike, ku bi vî rengî tê gotin:

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

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

Lê hêja ye ku ji bîr mekin ku ev rêbaz tenê wekî têketinê qebûl dike ben, ji ber vê yekê dê ne gengaz be ku di encama operasyona yekem de navnîşek bêkêmasî ya hêmanên hatine dîtin nîşan bide. Vebijarka duyemîn, ku ji bo xeletkirinê tê bikar anîn, ew e ku dem bi dem guhêrbarek sêrbaz were veqetandin result encama lêpirsînê û bibînin ka çi diqewime. Ev nêzîkatî ne pir rehet e; hûn hewce ne ku pê ewle bin ku di kodê de piştî vê yekê tu serûber an operasyon tune ne result an jî bi tenê koda jêrîn şîrove bikin. An jî hûn dikarin, mîna min, ji bîr bikin ku çend bangên weha ji qaîdeyek amade derxînin û meraq bikin ka çima tiştek naxebite.

Rêyek hêsantir ev e ku meriv rêbazê bang bike return bi parametreya pêwîst. Di vê rewşê de, cîbicîkirina hukmê dê biqede û em ê karibin bibînin ka di encama tiştê ku me nivîsî de çi qewimî:

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

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

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

Pirsgirêka têketinê

Rewş hene ku hûn nekarin bigihîjin amûra CxAudit (ku ji bo nivîsandina qaîdeyan tê bikar anîn). Dibe ku gelek sedemên vê yekê hebin, di nav de têkçûn, nûvekirinên ji nişka ve Windows, BSOD û rewşên din ên nediyar ên ku li derveyî kontrola me ne. Di vê rewşê de, carinan di databasê de danişînek neqediya ye, ku rê li ber we digire ku hûn dîsa têkevinê. Ji bo rastkirina wê, hûn hewce ne ku çend pirsan bimeşînin:

Ji bo Checkmarx berî 8.6:

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

Ji bo Checkmarx piştî 8.6:

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

Rêgezên nivîsandinê

Niha em diçin beşa herî balkêş. Gava ku hûn dest bi nivîsandina qaîdeyan di CxQL de dikin, tiştê ku hûn pir caran kêmasiya we dikin ne ewqas belgekirin e ku hin mînakên zindî yên çareserkirina hin pirsgirêkan û danasîna pêvajoya xebata lêpirsînê bi gelemperî ne.

Ez ê hewl bidim ku jiyanê hinekî hêsantir bikim ji bo wan kesên ku dest bi lêdana zimanê pirsê dikin û çend nimûneyên karanîna Pirsên Xweser ji bo çareserkirina hin pirsgirêkan bidim. Hin ji wan pir gelemperî ne û dikarin di pargîdaniya we de bi pratîkî bêyî guhertin werin bikar anîn, yên din taybetîtir in, lê ew dikarin bi guheztina kodê jî bikar bînin da ku li gorî taybetmendiyên serîlêdanên we bin.

Ji ber vê yekê, li vir pirsgirêkên ku em pir caran rastî wan hatine:

Karekî: Di encamên pêkanîna qaîdeyê de çend Herik hene û yek ji wan hêlîna yekê ye, divê hûn yek ji wan bihêlin.

çareseriya: Bi rastî, carinan Checkmarx çend herikîna daneyan nîşan dide ku dibe ku hevûdu bibin û guhertoyek kurtkirî ya yên din bin. Ji bo rewşên weha rêbazek taybetî heye ReduceFlow. Bi parametreyê ve girêdayî, ew ê herikîna herî kurt an dirêj hilbijêrin:

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

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

Karekî: Navnîşa daneyên hesas ên ku amûr bertek nîşanî wan dide berfireh bikin

çareseriya: Checkmarx qaîdeyên bingehîn hene, encamên ku ji hêla gelek pirsên din ve têne bikar anîn. Bi lêzêdekirina hin ji van qaîdeyan bi daneyên taybetî yên serîlêdana we re, hûn dikarin tavilê encamên şopandina xwe baştir bikin. Li jêr qaîdeyek mînakek heye ku hûn dest pê bikin:

General_privacy_violation_list

Ka em çend guherbarên ku di serlêdana me de têne bikar anîn zêde bikin da ku agahdariya hesas hilînin:

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

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

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

Karekî: Navnîşa guherbaran bi şîfreyan berfireh bike

çareseriya: Ez ê tavilê pêşniyar bikim ku hûn bala xwe bidin qaîdeya bingehîn ji bo destnîşankirina şîfreyên di kodê de û navnîşek navên guhêrbar ên ku bi gelemperî di pargîdaniya we de têne bikar anîn lê zêde bikin.

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

Karekî: Çarçoveyên bikar anîn ên ku ji hêla Checkmarx ve nayê piştgirî kirin zêde bikin

çareseriya: Hemî lêpirsînên li Checkmarx ji hêla ziman ve têne dabeş kirin, ji ber vê yekê hûn hewce ne ku ji bo her zimanî qaîdeyan zêde bikin. Li jêr çend mînakên qaîdeyên weha hene.

Ger pirtûkxaneyên ku fonksiyonên standard temam dikin an şûna wan digirin, têne bikar anîn, ew dikarin bi hêsanî li qaîdeya bingehîn werin zêdekirin. Wê hingê her kesê ku wê bikar tîne dê tavilê li ser danasîna nû fêr bibe. Wekî mînak, pirtûkxaneyên ji bo têketina Android-ê Timber û Loggi ne. Di pakêta bingehîn de, ji bo naskirina bangên ne-pergalê rêgez tune, ji ber vê yekê heke şîfreyek an nasnavek danişînê têkeve têketinê, em ê pê nizanin. Ka em hewl bidin ku pênaseyên van rêbazan li qaîdeyên Checkmarx zêde bikin.

Mînaka koda testê ya ku ji bo têketinê pirtûkxaneya Timber bikar tîne:

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

Va ye mînakek daxwazek ji bo Checkmarx, ku dê dihêle hûn pênaseyek bangkirina rêbazên Timber wekî xalek derketinê ji bo daneyên ji serîlêdanê zêde bikin:

FindAndroidOutputs

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

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

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

Û hûn dikarin qaîdeya cîran jî lê zêde bikin, lê ev yek rasterast bi têketina Android-ê ve girêdayî ye:

FindAndroidLog_Outputs

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

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

Di heman demê de, heke serîlêdanên Android-ê bikar bînin WorkManager ji bo xebata asynchronous, ramanek baş e ku hûn li ser vê yekê jî Checkmarx agahdar bikin û rêbazek ji bo wergirtina daneyan ji peywirê zêde bikin. getInputData:

FindAndroidRead

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

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

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

Karekî: Ji bo projeyên iOS-ê di plistê de li daneyên hesas digere

çareseriya: iOS gelek caran pelên taybet ên bi dirêjkirina .plist bikar tîne da ku guhêrbar û nirxan cihêreng hilîne. Di van pelan de hilanîna şîfre, nîşanok, kilîtan û daneyên din ên hesas nayê pêşniyar kirin, ji ber ku ew dikarin bêyî pirsgirêk ji cîhazê werin derxistin.

Pelên Plist xwedan taybetmendiyên ku bi çavê rût ne diyar in, lê ji Checkmarx re girîng in. Werin em qaîdeyek binivîsin ku dê li daneyên ku em hewce ne bigerin û ji me re vebêjin ka şîfre an nîşanek li cîhek hatine behs kirin.

Mînakek pelek wusa, ku nîşanek ji bo danûstendina bi karûbarê paşîn re vedihewîne:

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

Û qaîdeyek ji bo Checkmarx, ku çend nuans hene ku divê di dema nivîsandinê de bêne hesibandin:

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

Karekî: Agahdariyê di XML de bibînin

çareseriya: Checkmarx ji bo xebata bi XML û lêgerîna nirx, nîşan, taybetmendî û hêj bêtir fonksiyonên pir hêsan hene. Lê, mixabin, di belgeyê de xeletiyek hebû ku ji ber vê yekê yek mînakek kar nake. Digel vê yekê ku ev kêmasî di guhertoya herî dawî ya belgeyê de ji holê rabûye, heke hûn guhertoyên berê yên belgeyan bikar bînin baldar bin.

Li vir mînakek xelet ji belgeyê ye:

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

Di encama hewldana darvekirinê de, em ê xeletiyek werbigirin All Rêbazek wusa tune... Û ev rast e, ji ber ku cîhek taybetî, cihê cihê heye ku fonksiyonên ji bo xebata bi XML-ê re bikar bîne - cxXPath. Ji bo dîtina mîhengek li Android-ê ku destûrê dide karanîna seyrûsefera HTTP-ê, pirsa rast ev e:

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

Ka em hinekî hûrgulî lê binihêrin, ji ber ku hevoksaziya hemî fonksiyonan mîna hev e, piştî ku we yek fêhm kir, wê hingê hûn tenê hewce ne ku ya ku hûn hewce ne hilbijêrin. Ji ber vê yekê, bi rêz li gorî pîvanan:

  • "*.xml"- maskeya pelên ku werin lêgerîn

  • 8 - Nasnameya zimanê ku qayde lê tê sepandin

  • "cleartextTrafficPermitted"- navê taybetmendiyê di xml de

  • "true" - nirxa vê taybetmendiyê

  • false - dema lêgerînê de peyva birêkûpêk bikar bînin

  • true - tê wê wateyê ku lêgerîn dê bi paşguhkirina dozê, ango nehesasiya dozê were kirin

Mînakî, me qaîdeyek bikar anî ku ji hêla ewlehiyê ve, mîhengên pêwendiya torê ya di Android-ê de xelet nas dike ku rê dide danûstendina bi serverê re bi protokola HTTP re. Mînakek mîhengek ku taybetmendiyek tê de heye cleartextTrafficPermitted bi wate 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>

Karekî: Encamên bi navê pelê / riya sînor bikin

çareseriya: Di yek ji wan projeyên mezin ên ku bi pêşkeftina serîlêdana desta ya ji bo Android-ê ve girêdayî ye, me bi pozîtîfên derewîn ên qaîdeya ku mîhengê mêtingeriyê destnîşan dike re rû bi rû hat. Rastî ev e ku qaîdeya derveyî qutiyê di pelê de digere build.gradle mîhengek berpirsiyar e ku ji bo guhertoya serbestberdana serîlêdanê sepandina qaîdeyên tevlihevkirinê ye.

Lê di projeyên mezin de carinan pelên zarokan hene build.gradle, ku behsa pirtûkxaneyên ku di projeyê de hene. Taybetmendî ev e ku her çend van pelan hewcedariya nezelalbûnê nîşan nedin jî, dê mîhengên pelê civîna dêûbav di dema berhevkirinê de werin sepandin.

Ji ber vê yekê, peywir ev e ku di pelên zarokan ên ku aîdê pirtûkxaneyan de ne, teşqeleyan qut bikin. Ew dikarin bi hebûna rêzê têne naskirin apply 'com.android.library'.

Nimûneya kodê ji pelê build.gradle, ku hewcedariya obfuscasyonê diyar dike:

apply plugin: 'com.android.application'

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

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

dependencies {
  ...
}

Mînak pelê build.gradle ji bo pirtûkxaneyek ku di projeyê de heye ku ev mîheng nîne:

apply plugin: 'android-library'

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

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

Û qaîdeya ji bo 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);
		}
	}
}

Ev nêzîkatî ne tenê ji bo serîlêdanên Android-ê, lê di heman demê de ji bo rewşên din jî dema ku hûn hewce ne ku diyar bikin ka encamek ji pelek taybetî re ye, dikare pir gerdûnî û kêrhatî be.

Karekî: Heger hevoksazî bi tevahî nayê piştgirî kirin, piştgirî ji bo pirtûkxaneyek partiya sêyemîn zêde bikin

çareseriya: Hejmara çarçoveyên cihêreng ên ku di pêvajoya nivîsandina kodê de têne bikar anîn tenê ji nexşeyan dûr e. Bê guman, Checkmarx her gav bi hebûna wan nizane, û peywira me ew e ku em wê fêr bikin ku fêm bike ku hin rêbaz bi taybetî ji vê çarçoveyê re girêdayî ne. Carinan ev ji ber vê yekê tevlihev dibe ku çarçove navên fonksiyonê yên ku pir gelemperî ne bikar tînin û ne gengaz e ku meriv pêwendiya bangek taybetî bi pirtûkxaneyek taybetî re bi rengek zelal diyar bike.

Zehmetî ev e ku hevoksaziya pirtûkxaneyên weha her gav rast nayê nas kirin û hûn neçar in ku ceribandinê bikin da ku hûn hejmareke mezin ji erênîyên derewîn negirin. Gelek vebijark hene ku rastbûna şopandinê baştir bikin û pirsgirêkê çareser bikin:

  • Vebijarka yekem, em bi guman dizanin ku pirtûkxane di projeyek taybetî de tê bikar anîn û dikare di asta tîmê de qaîdeyê bicîh bîne. Lê heke tîmê biryar bide ku nêzîkatiyek cûda bigire an çend pirtûkxaneyên ku navên fonksiyonan li hev dikin bikar bîne, em dikarin wêneyek ne pir xweş a gelek erênîyên derewîn bistînin.

  • Vebijarka duyemîn lêgerîna pelên ku tê de pirtûkxane bi zelalî tê veguheztin e. Bi vê nêzîkatiyê, em dikarin pê bawer bin ku pirtûkxaneya ku em hewce ne tam di vê pelê de tê bikar anîn.

  • Û vebijarka sêyemîn ev e ku meriv her du nêzîkatiyên jorîn bi hev re bikar bîne.

Weke mînak, ka em li pirtûkxaneyek ku di nav derdorên teng de tê zanîn binerin qelişîn ji bo zimanê bernamenûsê Scala, bi navê, fonksiyonê Bihevxistina Nirxên Literal. Bi gelemperî, ji bo ku hûn pîvanan ji pirsek SQL re derbas bikin, divê hûn operator bikar bînin $, ku daneyan dixe nav pirsek SQL ya pêşwextkirî. Ango, bi rastî, ew analogek rasterast a Daxuyaniya Amadekirî ya Java-yê ye. Lê, heke hûn hewce ne ku bi dînamîkî pirsek SQL ava bikin, mînakî, heke hûn hewce ne ku navên tabloyê derbas bikin, hûn dikarin operatorê bikar bînin. #$, ya ku dê rasterast daneyê bixe şûna pirsê (hema hema mîna hevgirtina rêzê).

Nimûne kod:

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

Checkmarx hîn nizane ka meriv çawa karanîna Nirxên Wêjeyî yên Splicing tespît dike û operatoran dişoxilîne #$, ji ber vê yekê em hewl bidin ku wê hîn bikin ku derziyên potansiyel ên SQL nas bike û cihên rast di kodê de ronî bike:

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

Karekî: Di pirtûkxaneyên Çavkaniya Vekirî de li fonksiyonên xeternak ên bikar anîn bigerin

çareseriya: Gelek pargîdan amûrên çavdêriya Çavkaniya Vekirî (pratîka OSA) bikar tînin da ku karanîna guhertoyên xedar ên pirtûkxaneyan di serîlêdanên pêşkeftî de tespît bikin. Carinan ne gengaz e ku pirtûkxaneyek wusa bi guhertoyek ewledar nûve bike. Di hin rewşan de tixûbên fonksiyonel hene, di hinên din de qet guhertoyek ewledar tune. Di vê rewşê de, tevlihevkirina pratîkên SAST û OSA dê ji bo destnîşankirina fonksiyonên ku rê li ber îstismarkirina qelsbûnê vedigirin di kodê de neyên bikar anîn.

Lê carinan, nemaze dema ku JavaScript-ê dihesibînin, dibe ku ev ne karekî bêkêmasî be. Li jêr çareseriyek heye, belkî ne îdeal e, lê dîsa jî dixebite, bi karanîna mînaka qelsbûnên di beşê de lodash di rêbazên template и *set.

Nimûneyên ceribandina koda potansiyel xeternak di pelek JS de:

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

Û dema ku rasterast bi html ve girêdayî ye:

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

Em li hemî rêbazên xwe yên xedar digerin, ku di qelsiyan de têne navnîş kirin:

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

Karekî: Li sertîfîkayên ku di serîlêdanê de cih digirin digerin

çareseriya: Ne asayî ye ku serîlêdan, nemaze yên mobîl, sertîfîka an mifteyan bikar bînin da ku bigihîjin serverên cihêreng an verastkirina SSL-Pinning. Ji perspektîfek ewlehiyê, hilanîna tiştên weha di kodê de ne pratîka çêtirîn e. Ka em hewl bidin ku qaîdeyek binivîsin ku dê pelên wekhev di depoyê de bigerin:

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

Karekî: Di serîlêdanê de nîşaneyên lihevhatî bibînin

çareseriya: Bi gelemperî pêdivî ye ku tokenên lihevhatî an agahdariyên din ên girîng ên ku di kodê de hene betal bikin. Bê guman, hilanîna wan di hundurê koda çavkaniyê de ne ramanek baş e, lê rewş cûda dibin. Bi saya pirsên CxQL, dîtina tiştên bi vî rengî pir hêsan e:

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

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

encamê

Ez hêvî dikim ku ev gotar ji bo kesên ku dest bi nasîna xwe bi amûra Checkmarx dikin re kêrhatî be. Dibe ku yên ku demek dirêj rêzikên xwe dinivîsin jî dê di vê rêbernameyê de tiştek kêrhatî bibînin.

Mixabin, niha kêmasiyek çavkaniyek heye ku di dema pêşkeftina qaîdeyên ji bo Checkmarx de ramanên nû werin berhev kirin. Ji ber vê yekê me afirandin depoya li ser Github, ku em ê xebata xwe bişînin da ku her kesê ku CxQL bikar tîne bikaribe tê de tiştek bikêr bibîne, û her weha derfet hebe ku xebata xwe bi civakê re parve bike. Depo di pêvajoya dagirtin û birêkûpêkkirina naverokê de ye, ji ber vê yekê beşdar bi xêr hatin!

Ji bo baldariya te spas!

Source: www.habr.com

Add a comment