Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависед

Эй Ҳабр!

Дар кори мо, ширкати мо аксар вақт бо асбобҳои гуногуни таҳлили коди статикӣ (SAST) сарукор дорад. Хамаи онхо ба хисоби миёна кор мекунанд. Албатта, ҳамааш аз лоиҳа ва технологияҳои дар он истифодашаванда ва инчунин то чӣ андоза ин технологияҳо бо қоидаҳои таҳлил фаро гирифта шудаанд, вобаста аст. Ба андешаи ман, яке аз муҳимтарин меъёрҳо ҳангоми интихоби асбоби SAST ин қобилияти танзим кардани он ба хусусиятҳои замимаҳои шумо, яъне навиштан ва тағир додани қоидаҳои таҳлил ё тавре ки онҳоро бештар маъмулан дархостҳои фармоишӣ меноманд, мебошад.

Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависед

Мо аксар вақт Checkmarx-ро истифода мебарем - як таҳлилгари хеле ҷолиб ва пурқуввати код. Дар ин мақола ман дар бораи таҷрибаи худ дар навиштани қоидаҳои таҳлили он сӯҳбат хоҳам кард.

Мундариҷа

даромад

Барои оғоз, ман мехоҳам яке аз чанд мақоларо бо забони русӣ дар бораи хусусиятҳои навиштани дархостҳо барои Checkmarx тавсия диҳам. Он дар Ҳабре дар охири соли 2019 таҳти унвони: "Салом, Чекмаркс!" Чӣ тавр дархости Checkmarx SAST-ро нависед ва осебпазирии олиро пайдо кунед.

Он ба таври муфассал чӣ гуна навиштани дархостҳои аввалро дар CxQL (Checkmarx Query Language) барои баъзе барномаҳои санҷишӣ меомӯзад ва принсипҳои асосии кори қоидаҳои таҳлилро нишон медиҳад.

Ман он чизеро, ки дар он тасвир шудааст, такрор намекунам, гарчанде ки баъзе чорроҳаҳо ҳоло ҳам мавҷуданд. Дар мақолаи худ ман кӯшиш мекунам, ки як навъ "маҷмӯаи рецептҳо" -ро тартиб диҳам, ки рӯйхати ҳалли мушкилоти мушаххасеро, ки ман ҳангоми кор бо Checkmarx дучор шудаам, тартиб диҳам. Ман маҷбур шудам, ки майнаамро дар бораи бисёре аз ин мушкилот рафъ кунам. Баъзан дар хуччатхо маълу-моти кофй набуд ва баъзан фахмидани он ки чй тавр ичро кардани он чи талаб карда мешавад, хатто душвор буд. Умедворам, ки таҷриба ва шабҳои бехобии ман беҳуда нахоҳанд рафт ва ин "маҷмӯаи дастурҳои дархостҳои фармоишӣ" шуморо чанд соат ё якчанд ҳуҷайраҳои асаб сарфа мекунад. Пас, биёед оғоз кунем!

Маълумоти умумӣ дар бораи қоидаҳо

Аввалан, биёед якчанд мафҳумҳои асосӣ ва раванди кор бо қоидаҳоро дида бароем, то дарки беҳтари он чӣ рӯй хоҳад дод. Ва инчунин аз он сабаб, ки ҳуҷҷатҳо дар ин бора чизе намегӯянд ё дар сохтор хеле паҳн шудаанд, ки ин чандон қулай нест.

  1. Қоидаҳо ҳангоми сканкунӣ вобаста ба танзимоти пешакӣ интихобшуда дар оғоз истифода мешаванд (маҷмӯи қоидаҳои фаъол). Шумо метавонед шумораи номаҳдуди танзимоти пешакӣ эҷод кунед ва маҳз чӣ гуна сохтани онҳо аз хусусиятҳои раванди шумо вобаста аст. Шумо метавонед онҳоро аз рӯи забон гурӯҳбандӣ кунед ё барои ҳар як лоиҳа танзимоти пешакӣ интихоб кунед. Шумораи қоидаҳои фаъол ба суръат ва дақиқии сканкунӣ таъсир мерасонад.

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедНасб кардани Preset дар интерфейси Checkmarx

  2. Қоидаҳо дар асбоби махсус бо номи CxAuditor таҳрир карда мешаванд. Ин як барномаи мизи корӣ аст, ки ба сервере, ки Checkmarx кор мекунад, пайваст мешавад. Ин асбоб ду намуди кор дорад: қоидаҳои таҳрир ва таҳлили натиҷаҳои скан, ки аллакай анҷом дода шудааст.

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедИнтерфейси CxAudit

  3. Қоидаҳо дар Checkmarx аз рӯи забон тақсим мешаванд, яъне ҳар як забон маҷмӯи дархостҳои худро дорад. Инчунин баъзе қоидаҳои умумӣ мавҷуданд, ки новобаста аз забон татбиқ мешаванд, инҳо ба истилоҳ дархостҳои асосӣ мебошанд. Дар аксари мавридҳо, дархостҳои асосӣ ҷустуҷӯи маълумотеро дар бар мегиранд, ки қоидаҳои дигар истифода мебаранд.

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедТақсим кардани қоидаҳо аз рӯи забон

  4. Қоидаҳо "Иҷрошаванда" ва "Иҷрошаванда" мебошанд (Иҷрошаванда ва иҷро намешаванд). Ба назари ман, номи дуруст нест, аммо ин ҳамон аст. Хулоса ин аст, ки натиҷаи иҷрои қоидаҳои "Иҷрошаванда" дар натиҷаҳои скан дар UI намоиш дода мешавад ва қоидаҳои "Иҷронашаванда" танҳо барои истифодаи натиҷаҳои онҳо дар дархостҳои дигар (аслан, танҳо функсия) лозиманд.

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедМуайян кардани намуди қоида ҳангоми эҷод

  5. Шумо метавонед қоидаҳои нав эҷод кунед ё қоидаҳои мавҷударо илова кунед/аз нав нависед. Барои аз нав навиштани қоида, шумо бояд онро дар дарахт пайдо кунед, тугмаи рости мушро клик кунед ва аз менюи афтанда "Барқарор кардан" -ро интихоб кунед. Дар ин ҷо фаромӯш кардан муҳим аст, ки қоидаҳои нав дар аввал ба танзимоти пешакӣ дохил карда нашудаанд ва фаъол нестанд. Барои оғози истифодаи онҳо, шумо бояд онҳоро дар менюи "Менеҷери пешакӣ" дар асбоб фаъол созед. Қоидаҳои аз нав навишташуда танзимоти худро нигоҳ медоранд, яъне агар қоида фаъол бошад, он боқӣ мемонад ва фавран татбиқ карда мешавад.

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедНамунаи қоидаҳои нав дар интерфейси менеҷери пешакӣ

  6. Дар рафти ичро «дарахти» дархостхо сохта мешавад, ки аз чй вобаста аст. Қоидаҳое, ки маълумот ҷамъ мекунанд, аввал иҷро мешаванд ва онҳое, ки онро истифода мебаранд, дуюм. Натиҷаи иҷро кэш карда мешавад, бинобар ин, агар имкони истифодаи натиҷаҳои қоидаи мавҷуда бошад, беҳтар аст, ки ин корро кунед, ин вақти сканро кам мекунад.

  7. Қоидаҳо метавонанд дар сатҳҳои гуногун татбиқ карда шаванд:

  • Барои тамоми система - барои ҳама гуна сканкунии ягон лоиҳа истифода мешавад

  • Дар сатҳи даста (дастаи) - танҳо барои скан кардани лоиҳаҳо дар дастаи интихобшуда истифода мешавад.

  • Дар сатҳи лоиҳа - Дар як лоиҳаи мушаххас татбиқ карда мешавад

    Чӣ гуна қоидаҳоро барои Checkmarx бе девона шудан нависедМуайян кардани сатҳе, ки қоида дар он татбиқ мешавад

«Луғат» барои шурӯъкунандагон

Ва ман бо чанд чизҳое оғоз мекунам, ки боиси саволҳои ман шуданд ва ман инчунин як қатор усулҳоеро нишон медиҳам, ки ҳаётро ба таври назаррас содда мекунанд.

Амалиёт бо рӯйхатҳо

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

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

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

Ҳама ашёи ёфтшуда

Дар доираи забони сканшуда, шумо метавонед рӯйхати комилан ҳама унсурҳоеро, ки Checkmarx муайян кардааст (сатрҳо, функсияҳо, синфҳо, усулҳо ва ғайра) дастрас кунед. Ин баъзе фазои объектҳоест, ки тавассути онҳо дастрас шудан мумкин аст All. Яъне барои ҷустуҷӯи объект бо номи мушаххас searchMe, шумо метавонед, масалан, аз рӯи ном дар тамоми объектҳои ёфтшуда ҷустуҷӯ кунед:

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

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

Аммо, агар ба шумо лозим ояд, ки бо забони дигаре, ки бо ягон сабаб ба скан дохил карда нашудааст, ҷустуҷӯ кунед (масалан, groovy дар лоиҳаи Android), шумо метавонед фазои объекти моро тавассути як тағирёбанда васеъ кунед:

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

Функсияҳо барои таҳлили ҷараён

Ин функсияҳо дар бисёр қоидаҳо истифода мешаванд ва дар ин ҷо як варақаи фиреби онҳо чӣ маъно дорад:

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

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

Гирифтани номи файл/роҳ

Якчанд атрибутҳое мавҷуданд, ки аз натиҷаи дархост ба даст оварда мешаванд (номи файле, ки дар он сабт пайдо шудааст, сатр ва ғ.), аммо дар ҳуҷҷатҳо тарзи гирифтан ва истифода бурдани онҳо гуфта нашудааст. Ҳамин тавр, барои ин, шумо бояд ба моликияти LinePragma дастрасӣ пайдо кунед ва объектҳое, ки ба мо лозиманд, дар дохили он ҷойгир мешаванд:

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

Бояд дар назар дошт, ки FileName дар асл роҳи файлро дар бар мегирад, зеро мо ин усулро истифода мебарем GetFirstGraph.

Натиҷаи иҷроиш

Дар дохили CxQL як тағирёбандаи махсус мавҷуд аст result, ки натиҷаи иҷрои қоидаи хаттии шуморо бармегардонад. Он фавран оғоз карда мешавад ва шумо метавонед дар он натиҷаҳои мобайнӣ нависед, ҳангоми кор онҳоро тағир диҳед ва такмил диҳед. Аммо, агар дар дохили қоида ягон таъинот ба ин тағирёбанда ё функсия мавҷуд набошад return— натицаи ичро хамеша сифр мешавад.

Дархости зерин дар натиҷаи иҷро ба мо чизе барнамегардонад ва ҳамеша холӣ хоҳад буд:

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

Аммо, натиҷаи иҷроро ба натиҷаи тағирёбандаи ҷодугарӣ таъин карда, мо мебинем, ки ин занг ба мо чӣ бармегардад:

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

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

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

Истифодаи натиҷаҳои дигар қоидаҳо

Қоидаҳоро дар Checkmarx метавон шабеҳи функсияҳои забони барномасозии муқаррарӣ номид. Ҳангоми навиштани қоида, шумо метавонед аз натиҷаҳои дархостҳои дигар истифода баред. Масалан, ҳар дафъа барои ҷустуҷӯи ҳамаи зангҳои методӣ дар код лозим нест, танҳо ба қоидаи дилхоҳ занг занед:

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

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

Ин равиш ба шумо имкон медиҳад, ки кодро кӯтоҳ кунед ва вақти иҷрои қоидаҳоро хеле кам кунед.

Ҳалли мушкилот

Бақайдгирӣ

Ҳангоми кор бо асбоб баъзан дарҳол навиштани дархости дилхоҳ имконнопазир аст ва шумо бояд таҷриба карда, вариантҳои гуногунро санҷед. Барои чунин ҳолат, асбоб ба қайдгириро таъмин мекунад, ки чунин ном дорад:

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

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

Аммо бояд дар хотир дошт, ки ин усул танҳо ҳамчун вуруд қабул карда мешавад сатр, бинобар ин намоиш додани рӯйхати пурраи унсурҳои ёфтшуда дар натиҷаи амалиёти аввал имконнопазир хоҳад буд. Варианти дуюм, ки барои ислоҳкунӣ истифода мешавад, таъин кардани тағирёбандаи ҷодугарӣ аз вақт ба вақт аст result натиҷаи пурсиш ва бубинед, ки чӣ мешавад. Ин равиш чандон қулай нест; шумо бояд боварӣ ҳосил кунед, ки пас аз он дар код ҳеҷ гуна тағирот ё амалиёт бо ин вуҷуд надорад. result ё танҳо рамзи зерро шарҳ диҳед. Ё шумо метавонед, мисли ман, аз як қоидаи тайёр хориҷ кардани якчанд чунин зангҳоро фаромӯш кунед ва ҳайрон шавед, ки чаро ҳеҷ чиз кор намекунад.

Роҳи қулайтар даъват кардани усул аст return бо параметри зарурӣ. Дар ин сурат иљрои ќоида ба охир мерасад ва мо метавонем бубинем, ки дар натиљаи он чизе ки мо навишта будем, чї шуд:

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

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

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

Мушкилоти воридшавӣ

Ҳолатҳое вуҷуд доранд, ки шумо ба абзори CxAudit дастрасӣ пайдо карда наметавонед (ки барои навиштани қоидаҳо истифода мешавад). Ин метавонад сабабҳои зиёде дошта бошад, аз ҷумла садамаҳо, навсозии ногаҳонии Windows, BSOD ва дигар ҳолатҳои ғайричашмдошт, ки аз назорати мо берунанд. Дар ин ҳолат, баъзан дар базаи маълумот сеанси нотамом мавҷуд аст, ки ба шумо дубора ворид шуданро манъ мекунад. Барои ислоҳи он, шумо бояд якчанд дархостҳоро иҷро кунед:

Барои Checkmarx пеш аз 8.6:

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

Барои Checkmarx пас аз 8.6:

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

Қоидаҳои навиштан

Акнун мо ба қисми ҷолибтарин меравем. Вақте ки шумо ба навиштани қоидаҳо дар CxQL шурӯъ мекунед, он чизе, ки шумо аксар вақт намерасед, на он қадар ҳуҷҷатҳо, балки мисолҳои зиндаи ҳалли мушкилоти муайян ва тавсифи раванди кори дархостҳо дар маҷмӯъ.

Ман кӯшиш хоҳам кард, ки ҳаётро барои онҳое, ки ба забони пурсишҳо ғарқ мешаванд, каме осонтар гардонам ва якчанд мисолҳои истифодаи дархостҳои фармоиширо барои ҳалли мушкилоти муайян оварам. Баъзеи онҳо комилан умумӣ буда, онҳоро дар ширкати шумо амалан бидуни тағир истифода бурдан мумкин аст, дигарон мушаххастаранд, аммо онҳо инчунин метавонанд тавассути тағир додани код барои мувофиқ кардани хусусиятҳои замимаҳои шумо истифода шаванд.

Ҳамин тавр, инҳоянд мушкилоте, ки мо аксар вақт дучор меоем:

Вазифа: Дар натиҷаи иҷрои қоида якчанд ҷараён мавҷуд аст ва яке аз онҳо лона гузоштани дигаре аст, шумо бояд яке аз онҳоро тарк кунед.

ҳалли: Дарвоқеъ, баъзан Checkmarx якчанд ҷараёнҳои маълумотро нишон медиҳад, ки метавонанд ба ҳам мувофиқат кунанд ва версияи кӯтоҳшудаи дигарон бошанд. Барои чунин ҳолатҳо усули махсус вуҷуд дорад Reduce Flow. Вобаста аз параметр, он кӯтоҳтарин ё дарозтарин Ҷараёнро интихоб мекунад:

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

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

Вазифа: Рӯйхати маълумоти ҳассосро, ки асбоб ба онҳо вокуниш нишон медиҳад, васеъ кунед

ҳалли: Checkmarx дорои қоидаҳои асосӣ мебошад, ки натиҷаҳои онҳо аз ҷониби бисёр дархостҳои дигар истифода мешаванд. Бо илова кардани баъзе аз ин қоидаҳо, шумо метавонед фавран натиҷаҳои скании худро беҳтар созед. Дар зер як қоидаи намунавӣ барои оғоз кардани шумо оварда шудааст:

Рӯйхати_махфияти_вайронкунии_умумӣ

Биёед якчанд тағирёбандаҳоро илова кунем, ки дар барномаи мо барои нигоҳ доштани маълумоти ҳассос истифода мешаванд:

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

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

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

Вазифа: Рӯйхати тағирёбандаҳоро бо паролҳо васеъ кунед

ҳалли: Ман тавсия медиҳам, ки фавран ба қоидаҳои асосии муайян кардани паролҳо дар код диққат диҳед ва ба он рӯйхати номҳои тағирёбандаеро, ки дар ширкати шумо маъмулан истифода мешаванд, илова кунед.

Рӯйхати_парол_махфияти_вайрон кардани_парол

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

Вазифа: Илова кардани чаҳорчӯбаҳои истифодашуда, ки аз ҷониби Checkmarx дастгирӣ намешаванд

ҳалли: Ҳама дархостҳо дар Checkmarx аз рӯи забон тақсим мешаванд, бинобар ин шумо бояд қоидаҳоро барои ҳар як забон илова кунед. Дар зер баъзе мисолҳои чунин қоидаҳо оварда шудаанд.

Агар китобхонаҳое истифода шаванд, ки функсияҳои стандартиро пурра ё иваз мекунанд, онҳоро ба осонӣ ба қоидаи асосӣ илова кардан мумкин аст. Он гоҳ ҳар касе, ки онро истифода мебарад, фавран дар бораи муаррифии нав огоҳ хоҳад шуд. Мисол, китобхонаҳо барои ворид шудан ба Android Timber ва Loggi мебошанд. Дар бастаи асосӣ қоидаҳо барои муайян кардани зангҳои ғайрисистема вуҷуд надоранд, аз ин рӯ, агар парол ё идентификатори сессия ба гузориш ворид шавад, мо дар ин бора намедонем. Биёед кӯшиш кунем, ки таърифҳои чунин усулҳоро ба қоидаҳои Checkmarx илова кунем.

Намунаи коди санҷишӣ, ки китобхонаи Timber-ро барои сабткунӣ истифода мебарад:

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

Ва ин аст як мисоли дархост барои Checkmarx, ки ба шумо имкон медиҳад, ки таърифи даъват кардани усулҳои Timberро ҳамчун нуқтаи баромад барои маълумот аз барнома илова кунед:

FindAndroidOutputs

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

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

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

Ва шумо инчунин метавонед ба қоидаи ҳамсоя илова кунед, аммо ин бевосита ба воридшавӣ дар Android дахл дорад:

FindAndroidLog_Outputs

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

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

Инчунин, агар барномаҳои Android истифода баранд Менеҷери корӣ барои кори асинхронӣ, фикри хуб аст, ки ба Checkmarx дар ин бора тавассути илова кардани усули гирифтани маълумот аз супориш ба таври иловагӣ хабар диҳед. getInputData:

FindAndroidRead

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

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

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

Вазифа: Ҷустуҷӯи маълумоти ҳассос дар plist барои лоиҳаҳои iOS

ҳалли: iOS аксар вақт файлҳои махсусро бо васеъшавии .plist барои нигоҳ доштани тағирёбандаҳо ва арзишҳои гуногун истифода мебарад. Нигоҳ доштани паролҳо, нишонаҳо, калидҳо ва дигар маълумоти ҳассос дар ин файлҳо тавсия дода намешавад, зеро онҳо метавонанд аз дастгоҳ бе ягон мушкилот истихроҷ карда шаванд.

Файлҳои Plist дорои хусусиятҳое мебошанд, ки ба чашми бараҳна аён нестанд, аммо барои Checkmarx муҳиманд. Биёед қоидае нависем, ки маълумотеро, ки ба мо лозим аст, ҷустуҷӯ кунад ва ба мо бигӯяд, ки оё парол ё нишонаҳо дар ҷое зикр шудаанд.

Намунаи чунин файл, ки дорои аломати иртибот бо хидмати пуштибонӣ:

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

Ва қоида барои Checkmarx, ки якчанд нозукиҳо дорад, ки ҳангоми навиштан бояд ба назар гирифта шаванд:

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

Вазифа: Ҷустуҷӯи маълумот дар XML

ҳалли: Checkmarx дорои функсияҳои хеле қулай барои кор бо XML ва ҷустуҷӯи арзишҳо, тегҳо, атрибутҳо ва ғайра мебошад. Аммо, мутаассифона, дар ҳуҷҷатгузорӣ хатогӣ рух дод, ки аз он сабаб ягон мисол кор намекунад. Сарфи назар аз он, ки ин камбуди дар версияи охирини ҳуҷҷатҳо бартараф карда шудааст, агар шумо версияҳои қаблии ҳуҷҷатҳоро истифода баред, эҳтиёт шавед.

Ин аст як мисоли нодуруст аз ҳуҷҷатҳо:

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

Дар натиҷаи кӯшиши иҷро, мо хатогиеро мегирем, ки All чунин усул вуҷуд надорад... Ва ин дуруст аст, зеро фазои махсуси объекти алоҳида барои истифодаи функсияҳо барои кор бо XML мавҷуд аст - cxXPath. Ин аст дархости дуруст барои дарёфти танзимот дар Android, ки имкон медиҳад трафики HTTP истифода шавад:

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

Биёед онро каме муфассалтар дида бароем, зеро синтаксиси ҳамаи функсияҳо якхела аст, пас аз он ки шумо якеро муайян кардед, шумо танҳо онеро, ки ба шумо лозим аст, интихоб кардан лозим аст. Ҳамин тавр, пайдарпай аз рӯи параметрҳо:

  • "*.xml"— ниқоби файлҳои ҷустуҷӯшаванда

  • 8 — идентификатсияи забоне, ки барои он қоида татбиқ мешавад

  • "cleartextTrafficPermitted"— номи атрибут дар xml

  • "true" - арзиши ин сифат

  • false — ҳангоми ҷустуҷӯ истифода аз ифодаи муқаррарӣ

  • true — маънои онро дорад, ки ҷустуҷӯ бидуни сарфи назар кардани ҳарфҳо, яъне ба ҳарфи ҳарфҳо ҳассос анҷом дода мешавад

Ҳамчун мисол, мо қоидаеро истифода бурдем, ки аз нуқтаи назари амният нодуруст танзимоти пайвасти шабакаро дар Android муайян мекунад, ки иртибот бо сервер тавассути протоколи HTTP имкон медиҳад. Намунаи танзимоте, ки дорои атрибут аст cleartextTrafficPermitted бо маъно 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>

Вазифа: Маҳдуд кардани натиҷаҳо аз рӯи номи файл/роҳ

ҳалли: Дар яке аз лоиҳаҳои азими марбут ба таҳияи замимаи мобилӣ барои Android, мо бо мусбатҳои бардурӯғи қоидае дучор шудем, ки танзимоти печидаро муайян мекунад. Далели он аст, ки қоида берун аз қуттии ҷустуҷӯ дар файл build.gradle танзимот барои татбиқи қоидаҳои нофаҳмо барои версияи барориши барнома масъул аст.

Аммо дар лоиҳаҳои калон баъзан файлҳои кӯдакона мавҷуданд build.gradle, ки ба китобхонахои ба лоиха дохилшуда дахл доранд. Хусусият дар он аст, ки ҳатто агар ин файлҳо зарурати печидаро нишон надиҳанд, танзимоти файли ассамблеяи волидайн ҳангоми тартибдиҳӣ татбиқ карда мешаванд.

Ҳамин тариқ, вазифа аз он иборат аст, ки триггерҳо дар файлҳои кӯдакона, ки ба китобхонаҳо тааллуқ доранд, қатъ карда шаванд. Онҳоро бо мавҷудияти хати муайян кардан мумкин аст apply 'com.android.library'.

Намунаи код аз файл build.gradle, ки зарурати ифшоро муайян мекунад:

apply plugin: 'com.android.application'

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

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

dependencies {
  ...
}

Намунаи файл build.gradle барои китобхонае, ки ба лоиҳа дохил карда шудааст, ки ин танзимотро надорад:

apply plugin: 'android-library'

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

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

Ва қоида барои 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);
		}
	}
}

Ин равиш метавонад на танҳо барои барномаҳои Android, балки барои дигар ҳолатҳое, ки шумо бояд муайян кунед, ки оё натиҷа ба файли мушаххас тааллуқ дорад, хеле универсалӣ ва муфид аст.

Вазифа: Агар синтаксис пурра дастгирӣ нашавад, дастгирии китобхонаи сеюмро илова кунед

ҳалли: Шумораи чаҳорчӯбаҳои гуногун, ки дар раванди навиштани код истифода мешаванд, танҳо аз диаграммаҳо берунанд. Албатта, Чекмарк на ҳама вақт дар бораи мавҷудияти онҳо огоҳ аст ва вазифаи мо он аст, ки ба он фаҳмем, ки усулҳои муайян махсусан ба ин чаҳорчӯба тааллуқ доранд. Баъзан ин аз он сабаб мушкил мешавад, ки чаҳорчӯбаҳо номҳои функсияҳоро истифода мебаранд, ки хеле маъмуланд ва ба таври дақиқ муайян кардани робитаи занги мушаххас ба китобхонаи мушаххас ғайриимкон аст.

Мушкилот дар он аст, ки синтаксиси чунин китобхонаҳо на ҳама вақт дуруст эътироф карда мешавад ва шумо бояд озмоиш кунед, то шумораи зиёди мусбатҳои бардурӯғро пешгирӣ кунед. Якчанд вариантҳо барои беҳтар кардани дақиқии сканер ва ҳалли мушкилот мавҷуданд:

  • Варианти аввал, мо аниқ медонем, ки китобхона дар як лоиҳаи мушаххас истифода мешавад ва метавонад қоидаро дар сатҳи даста татбиқ кунад. Аммо агар даста тасмим гирад, ки равиши дигарро пеш гирад ё якчанд китобхонаҳоеро истифода барад, ки дар онҳо номҳои функсионалӣ ба ҳам мувофиқанд, мо метавонем тасвири на он қадар гуворо дар бораи шумораи зиёди мусбатҳои бардурӯғ ба даст орем.

  • Варианти дуюм ин ҷустуҷӯи файлҳое мебошад, ки дар онҳо китобхона ба таври равшан ворид карда шудааст. Бо ин равиш, мо метавонем итминон дошта бошем, ки китобхонае, ки ба мо лозим аст, маҳз дар ин файл истифода мешавад.

  • Ва варианти сеюм ин аст, ки ду равиши дар боло зикршударо якҷоя истифода баред.

Барои мисол китобхонаеро, ки дар доираи танг маълум аст, дида мебароем лағжонак барои забони барномасозии Scala, яъне функсия Ҷойгиркунии арзишҳои аслӣ. Умуман, барои интиқоли параметрҳо ба дархости SQL, шумо бояд операторро истифода баред $, ки маълумотро ба дархости пешакӣ сохташудаи SQL иваз мекунад. Яъне, дар асл, он як аналоги мустақими Изҳороти омодашуда дар Java аст. Аммо, агар ба шумо лозим аст, ки дархости SQL-ро ба таври динамикӣ созед, масалан, агар шумо номҳои ҷадвалро гузоред, шумо метавонед операторро истифода баред. #$, ки маълумотро мустақиман ба дархост иваз мекунад (қариб ба пайванди сатр).

Рамзи намунавӣ:

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

Checkmarx ҳанӯз намедонад, ки чӣ гуна истифодаи арзишҳои аслии Splicing ва операторҳоро гузаронад. #$, бинобар ин биёед кӯшиш кунем, ки онро омӯзем, то тазриқи эҳтимолии SQL-ро муайян кунад ва ҷойҳои дурустро дар код қайд кунад:

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

Вазифа: Ҷустуҷӯи функсияҳои осебпазири истифодашуда дар китобхонаҳои кушодаасос

ҳалли: Бисёре аз ширкатҳо барои ошкор кардани истифодаи версияҳои осебпазири китобхонаҳо дар замимаҳои таҳияшуда аз абзорҳои мониторинги кушодаасос (таҷрибаи OSA) истифода мебаранд. Баъзан навсозии чунин китобхона ба версияи бехатар имконнопазир аст. Дар баъзе ҳолатҳо маҳдудиятҳои функсионалӣ вуҷуд доранд, дар дигар ҳолатҳо версияи бехатар вуҷуд надорад. Дар ин ҳолат, маҷмӯи амалияҳои SAST ва OSA барои муайян кардани он, ки функсияҳое, ки ба истисмори осебпазирӣ оварда мерасонанд, дар код истифода намешаванд.

Аммо баъзан, махсусан ҳангоми баррасии JavaScript, ин метавонад кори комилан ночиз набошад. Дар зер як ҳалли, шояд идеалӣ нест, вале бо вуҷуди ин кор бо истифода аз мисоли осебпазирии ҷузъ. lodash дар усулхо template и *set.

Намунаҳои санҷиши коди эҳтимолан осебпазир дар файли 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!'

Ва ҳангоми пайвастшавӣ мустақиман дар 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>

Мо ҳама усулҳои осебпазири худро меҷӯем, ки дар осебпазирӣ номбар шудаанд:

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

Вазифа: Ҷустуҷӯи сертификатҳое, ки дар барнома ҷойгир шудаанд

ҳалли: Барои барномаҳо, бахусус барномаҳои мобилӣ, истифодаи сертификатҳо ё калидҳо барои дастрасӣ ба серверҳои гуногун ё тасдиқи SSL-Pinning маъмул нест. Аз нуқтаи назари амният, нигоҳ доштани чунин чизҳо дар код таҷрибаи беҳтарин нест. Биёед кӯшиш кунем, ки қоидае нависем, ки файлҳои шабеҳро дар анбор ҷустуҷӯ кунад:

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

Вазифа: Ҷустуҷӯи аломатҳои вайроншуда дар барнома

ҳалли: Аксар вақт лозим аст, ки токенҳои вайроншуда ё дигар маълумоти муҳимеро, ки дар код мавҷуданд, бекор кунед. Албатта, нигоҳ доштани онҳо дар дохили коди ибтидоӣ фикри хуб нест, аммо вазъиятҳо гуногунанд. Бо шарофати дархостҳои CxQL, ёфтани чизҳои ба ин монанд хеле осон аст:

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

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

хулоса

Умедворам, ки ин мақола барои онҳое, ки шиносоӣ бо асбоби Checkmarx оғоз мекунанд, муфид хоҳад буд. Шояд онҳое, ки муддати тӯлонӣ қоидаҳои худро навиштаанд, дар ин дастур чизи муфид пайдо кунанд.

Мутаассифона, дар айни замон захирае мавҷуд нест, ки дар он ғояҳои нав ҳангоми таҳияи қоидаҳо барои Checkmarx ба даст оварда шаванд. Барои ҳамин мо эҷод кардем анбор дар Github, ки мо кори худро дар он ҷо ҷойгир мекунем, то ҳар касе, ки CxQL-ро истифода мебарад, дар он чизи муфид пайдо кунад ва инчунин имкони мубодилаи кори худро бо ҷомеа дошта бошад. Анбор дар ҷараёни пур кардан ва сохторбандии мундариҷа аст, аз ин рӯ саҳмгузоронро хуш омадед!

Ташаккур барои таваҷҷӯҳатон!

Манбаъ: will.com

Илова Эзоҳ