Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edan

Hey Habr!

Ing karya kita, perusahaan kita kerep banget ngurusi macem-macem alat analisis kode statis (SAST). Metu saka kothak kabeh padha kerja rata-rata. Mesthine, kabeh gumantung marang proyek lan teknologi sing digunakake ing kana, uga kepiye teknologi kasebut dilindhungi dening aturan analisis. Mratelakake panemume, salah sawijining kritéria sing paling penting nalika milih alat SAST yaiku kemampuan kanggo ngatur kanthi spesifik aplikasi sampeyan, yaiku nulis lan ngganti aturan analisis utawa, sing luwih asring diarani, Custom Queries.

Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edan

Paling asring kita nggunakake Checkmarx - penganalisa kode sing menarik lan kuat. Ing artikel iki aku bakal ngomong babagan pengalaman nulis aturan analisis kasebut.

Daftar Isi

entri

Kanggo miwiti, aku pengin menehi rekomendasi salah sawijining sawetara artikel ing basa Rusia babagan fitur nulis pitakon kanggo Checkmarx. Iki diterbitake ing Habré ing pungkasan taun 2019 kanthi judhul: "Halo, Checkmarx!" Kepiye carane nulis pitakon Checkmarx SAST lan golek kerentanan sing apik.

Nliti kanthi rinci babagan carane nulis pitakon pisanan ing CxQL (Checkmarx Query Language) kanggo sawetara aplikasi tes lan nuduhake prinsip dhasar babagan aturan analisis.

Aku ora bakal mbaleni apa sing diterangake ing, sanajan sawetara prapatan isih bakal ana. Ing artikelku, aku bakal nyoba ngumpulake jinis "koleksi resep", dhaptar solusi kanggo masalah tartamtu sing aku temoni sajrone kerja karo Checkmarx. Aku kudu rak otakku liwat akeh masalah iki. Kadhangkala ora ana informasi sing cukup ing dokumentasi, lan kadhangkala uga angel ngerti carane nindakake apa sing dibutuhake. Muga-muga pengalaman lan bengi sing ora bisa turu ora muspra, lan "koleksi resep-resep Custom Queries" iki bakal ngirit sawetara jam utawa sawetara sel saraf. Dadi, ayo miwiti!

Informasi umum babagan aturan

Pisanan, ayo ndeleng sawetara konsep dhasar lan proses nggarap aturan, supaya luwih ngerti apa sing bakal kelakon sabanjure. Lan uga amarga dokumentasi ora ngomong apa-apa bab iki utawa banget nyebar metu ing struktur, kang ora trep banget.

  1. Aturan kasebut ditrapake sajrone mindhai gumantung saka prasetel sing dipilih nalika wiwitan (sakumpulan aturan aktif). Sampeyan bisa nggawe prasetel nomer tanpa wates, lan carane nggawe struktur kasebut gumantung saka spesifik proses sampeyan. Sampeyan bisa klompok miturut basa utawa milih prasetel kanggo saben proyek. Jumlah aturan aktif mengaruhi kacepetan lan akurasi mindhai.

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanNyetel prasetel ing antarmuka Checkmarx

  2. Aturan kasebut diowahi ing alat khusus sing diarani CxAuditor. Iki minangka aplikasi desktop sing nyambung menyang server sing nganggo Checkmarx. Alat iki duwe rong mode operasi: aturan nyunting lan nganalisa asil scan sing wis ditindakake.

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanAntarmuka CxAudit

  3. Aturan ing Checkmarx dipérang miturut basa, yaiku, saben basa nduweni pitakonan dhewe-dhewe. Ana uga sawetara aturan umum sing ditrapake preduli saka basa, iki sing diarani pitakon dhasar. Umume, pitakon dhasar kalebu nggoleki informasi sing digunakake aturan liyane.

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanPamisahan aturan miturut basa

  4. Aturan yaiku "Executable" lan "Non-Executable" (Dieksekusi lan Ora Dieksekusi). Ora cukup jeneng sing bener, ing mratelakake panemume, nanging apa iku. Ing ngisor iki yaiku asil saka nglakokake aturan "Executable" bakal ditampilake ing asil scan ing UI, lan aturan "Non-Executable" mung perlu kanggo nggunakake asil ing panjalukan liyane (intine, mung fungsi).

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanNemtokake jinis aturan nalika nggawe

  5. Sampeyan bisa nggawe aturan anyar utawa nambah / nulis ulang sing wis ana. Kanggo nulis ulang aturan, sampeyan kudu nemokake ing wit, klik-tengen lan pilih "Nganti" saka menu gulung mudhun. Penting kanggo elinga ing kene yen aturan anyar ora kalebu ing prasetel lan ora aktif. Kanggo miwiti nggunakake, sampeyan kudu ngaktifake ing menu "Preset Manager" ing instrumen. Aturan sing ditulis maneh tetep setelan, yaiku, yen aturan kasebut aktif, aturan kasebut bakal tetep lan bakal ditrapake langsung.

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanConto aturan anyar ing antarmuka Preset Manager

  6. Sajrone eksekusi, "wit" panjaluk dibangun, sing gumantung saka apa. Aturan sing ngumpulake informasi dieksekusi pisanan, lan sing nggunakake kaloro. Asil eksekusi di-cache, dadi yen bisa nggunakake asil saka aturan sing wis ana, luwih becik ditindakake, iki bakal nyuda wektu pemindaian.

  7. Aturan bisa ditrapake ing tingkat sing beda:

  • Kanggo kabeh sistem - bakal digunakake kanggo mindhai proyek apa wae

  • Ing tingkat tim (Tim) - mung bakal digunakake kanggo mindhai proyek ing tim sing dipilih.

  • Ing tingkat proyek - Bakal diterapake ing proyek tartamtu

    Kepiye carane nulis aturan kanggo Checkmarx lan ora dadi edanNemtokake level ing ngendi aturan bakal diterapake

"Kamus" kanggo pamula

Lan aku bakal miwiti karo sawetara bab sing nyebabake kula pitakonan, lan aku uga bakal nuduhake sawetara Techniques sing Ngartekno bakal menakake urip.

Operasi karo dhaptar

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

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

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

Kabeh barang sing ditemokake

Ing basa sing dipindai, sampeyan bisa entuk dhaptar kabeh unsur sing wis diidentifikasi dening Checkmarx (string, fungsi, kelas, metode, lsp). Iki sawetara spasi obyek sing bisa diakses liwat All. Yaiku, kanggo nggoleki obyek kanthi jeneng tartamtu searchMe, sampeyan bisa nggoleki, contone, kanthi jeneng ing kabeh obyek sing ditemokake:

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

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

Nanging, yen sampeyan kudu nggoleki ing basa liya sing sakperangan alesan ora klebu ing scan (contone, groovy ing project Android), sampeyan bisa nggedhekake spasi obyek liwat variabel:

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

Fungsi kanggo analisis Aliran

Fungsi-fungsi kasebut digunakake ing pirang-pirang aturan lan ing ngisor iki minangka lembar ngapusi babagan apa tegese:

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

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

Njupuk jeneng file / path

Ana sawetara atribut sing bisa dipikolehi saka asil pitakon (jeneng file sing entri ditemokake, senar, lsp.), nanging dokumentasi ora ngandhani carane entuk lan nggunakake. Dadi, kanggo nindakake iki, sampeyan kudu ngakses properti LinePragma lan obyek sing dibutuhake bakal ana ing njero:

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

Iku worth mbudidaya sing FileName ngandhut bener path kanggo file, awit kita digunakake cara GetFirstGraph.

Hasil eksekusi

Ana variabel khusus ing CxQL result, sing ngasilake asil eksekusi aturan sing ditulis. Diwiwiti langsung lan sampeyan bisa nulis asil penengah, ngganti lan nyaring nalika sampeyan kerja. Nanging, yen ora ana tugas kanggo variabel utawa fungsi iki ing aturan kasebut return- asil eksekusi bakal tansah nul.

Pitakonan ing ngisor iki ora bakal ngasilake apa-apa marang kita minangka asil saka eksekusi lan bakal tansah kosong:

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

Nanging, sawise menehi asil eksekusi menyang asil variabel sihir, kita bakal weruh apa telpon iki bali menyang kita:

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

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

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

Nggunakake asil saka aturan liyane

Aturan ing Checkmarx bisa diarani analog karo fungsi ing basa pamrograman biasa. Nalika nulis aturan, sampeyan bisa uga nggunakake asil pitakon liyane. Contone, ora perlu nelusuri kabeh cara telpon ing kode saben wektu, mung nelpon aturan sing dikarepake:

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

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

Pendekatan iki ngidini sampeyan nyepetake kode lan nyuda wektu eksekusi aturan.

Solusi masalah

logging

Nalika nggarap alat kasebut, kadhangkala ora bisa langsung nulis pitakon sing dikarepake lan sampeyan kudu nyoba, nyoba macem-macem opsi. Kanggo kasus kaya mengkono, alat kasebut nyedhiyakake logging, sing diarani kaya ing ngisor iki:

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

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

Nanging kudu eling yen metode iki mung ditampa minangka input senar, supaya ora bisa nampilake dhaptar lengkap unsur sing ditemokake minangka asil saka operasi pisanan. Opsi kapindho, sing digunakake kanggo debugging, yaiku nemtokake variabel sihir saka wektu kanggo wektu result asil saka pitakonan lan ndeleng apa mengkono. Pendekatan iki ora trep banget; sampeyan kudu mesthekake yen ora ana overrides utawa operasi karo iki ing kode sawise result utawa mung komentar kode ing ngisor iki. Utawa sampeyan bisa, kaya aku, lali mbusak sawetara telpon saka aturan siap-digawe lan wonder apa ora bisa.

Cara sing luwih trep yaiku nelpon metode kasebut return karo parameter sing dibutuhake. Ing kasus iki, eksekusi aturan bakal rampung lan kita bakal bisa ndeleng apa sing kedadeyan minangka asil saka apa sing kita tulis:

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

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

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

Masalah mlebu

Ana kahanan nalika sampeyan ora bisa ngakses alat CxAudit (sing digunakake kanggo nulis aturan). Ana akeh alasan kanggo iki, kalebu kacilakan, nganyari Windows dadakan, BSOD lan kahanan sing ora dikarepake liyane sing ora bisa dikontrol. Ing kasus iki, kadhangkala ana sesi sing durung rampung ing database, sing ngalangi sampeyan ora mlebu maneh. Kanggo ndandani, sampeyan kudu mbukak sawetara pitakon:

Kanggo Checkmarx sadurunge 8.6:

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

Kanggo Checkmarx sawise 8.6:

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

Aturan nulis

Saiki kita menyang bagean paling menarik. Nalika sampeyan miwiti nulis aturan ing CxQL, apa sing asring kurang dokumentasi minangka sawetara conto urip kanggo ngrampungake masalah tartamtu lan njlèntrèhaké proses operasi query ing umum.

Aku bakal nyoba kanggo nggawe urip luwih gampang kanggo wong-wong sing wiwit nyilem menyang basa pitakonan lan menehi sawetara conto nggunakake Custom Queries kanggo ngatasi masalah tartamtu. Sawetara iku cukup umum lan bisa digunakake ing perusahaan sampeyan kanthi praktis tanpa owah-owahan, liyane luwih spesifik, nanging uga bisa digunakake kanthi ngganti kode sing cocog karo spesifik aplikasi sampeyan.

Dadi, ing ngisor iki masalah sing paling sering kita alami:

Tugas: Ana sawetara Aliran ing asil nglakokaké aturan lan salah siji saka wong-wong mau nesting liyane, sampeyan kudu ninggalake salah siji saka wong-wong mau.

solusi: Pancen, kadhangkala Checkmarx nuduhake sawetara aliran data sing bisa tumpang tindih lan dadi versi singkat saka liyane. Ana cara khusus kanggo kasus kasebut NgurangiFlow. Gumantung ing parameter, bakal milih Aliran paling cendhak utawa paling dawa:

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

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

Tugas: Nggedhekake dhaptar data sensitif sing ditanggepi alat kasebut

solusi: Checkmarx duwe aturan dhasar, asile digunakake dening akeh pitakon liyane. Kanthi nambah sawetara aturan kasebut kanthi data khusus kanggo aplikasi sampeyan, sampeyan bisa langsung nambah asil pindai. Ing ngisor iki conto aturan kanggo miwiti:

General_privacy_violation_list

Ayo nambah sawetara variabel sing digunakake ing aplikasi kita kanggo nyimpen informasi sensitif:

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

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

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

Tugas: Nggedhekake dhaptar variabel kanthi tembung sandhi

solusi: Aku nyaranake langsung menehi perhatian marang aturan dhasar kanggo nemtokake sandhi ing kode lan nambahake dhaptar jeneng variabel sing umum digunakake ing perusahaan sampeyan.

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

Tugas: Tambah kerangka kerja sing ora didhukung dening Checkmarx

solusi: Kabeh pitakon ing Checkmarx dipérang miturut basa, dadi sampeyan kudu nambah aturan kanggo saben basa. Ing ngisor iki sawetara conto aturan kasebut.

Yen perpustakaan digunakake sing nglengkapi utawa ngganti fungsi standar, bisa gampang ditambahake menyang aturan dhasar. Banjur saben wong sing nggunakake bakal langsung sinau babagan introduksi anyar. Contone, perpustakaan kanggo mlebu ing Android yaiku Timber lan Loggi. Ing paket dhasar, ora ana aturan kanggo ngenali telpon non-sistem, dadi yen sandhi utawa pengenal sesi mlebu log, kita ora bakal ngerti. Ayo nyoba nambah definisi metode kasebut menyang aturan Checkmarx.

Tuladha kode tes sing nggunakake perpustakaan Timber kanggo logging:

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

Lan ing ngisor iki minangka conto panjalukan kanggo Checkmarx, sing bakal ngidini sampeyan nambah definisi nelpon metode Timber minangka titik metu kanggo data saka aplikasi:

GolekAndroidOutputs

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

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

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

Lan sampeyan uga bisa nambah aturan tetanggan, nanging iki langsung ana hubungane karo mlebu ing Android:

GolekAndroidLog_Outputs

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

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

Uga, yen aplikasi Android nggunakake WorkManager kanggo karya asinkron, luwih becik menehi informasi tambahan marang Checkmarx babagan iki kanthi nambahake cara kanggo njupuk data saka tugas kasebut. getInputData:

GolekAndroidRead

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

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

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

Tugas: Nggoleki data sensitif ing plist kanggo proyek iOS

solusi: iOS asring nggunakake file khusus karo extension .plist kanggo nyimpen macem-macem variabel lan nilai. Nyimpen sandhi, token, kunci lan data sensitif liyane ing file kasebut ora dianjurake, amarga bisa diekstrak saka piranti tanpa masalah.

File Plist duwe fitur sing ora ketok, nanging penting kanggo Checkmarx. Ayo nulis aturan sing bakal nelusuri data sing kita butuhake lan ngandhani yen tembung sandhi utawa token kasebut ing endi wae.

Conto file kasebut, sing ngemot token kanggo komunikasi karo layanan 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>

Lan aturan kanggo Checkmarx, sing duwe sawetara nuansa sing kudu digatekake nalika nulis:

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

Tugas: Nggoleki Informasi ing XML

solusi: Checkmarx nduweni fungsi sing trep banget kanggo nggarap XML lan nggoleki nilai, tag, atribut lan liya-liyane. Nanging, sayangé, ana kesalahan ing dokumentasi amarga ora ana conto siji. Senadyan kasunyatan manawa cacat iki wis diilangi ing versi dokumentasi paling anyar, ati-ati yen sampeyan nggunakake versi dokumen sadurunge.

Iki minangka conto sing salah saka dokumentasi:

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

Minangka asil saka nyoba eksekusi, kita bakal nampa kesalahan sing All ora ana cara kasebut ... Lan iki bener, amarga ana ruang obyek khusus sing kapisah kanggo nggunakake fungsi kanggo nggarap XML - cxXPath. Iki minangka pitakon sing bener kanggo nemokake setelan ing Android sing ngidini panggunaan lalu lintas HTTP:

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

Ayo katon luwih rinci, amarga sintaks kanggo kabeh fungsi padha, sawise sampeyan ngerti siji, sampeyan mung kudu milih sing sampeyan butuhake. Dadi, sequentially miturut paramèter:

  • "*.xml"- topeng file sing bakal digoleki

  • 8 - id basa sing ditrapake aturan kasebut

  • "cleartextTrafficPermitted"- jeneng atribut ing xml

  • "true" - Nilai saka atribut iki

  • false - nggunakake ekspresi reguler nalika nggoleki

  • true - tegese telusuran bakal ditindakake kanthi ora nggatekake kasus, yaiku, ora sensitif huruf cilik

Contone, kita nggunakake aturan sing ngenali salah, saka sudut pandang keamanan, setelan sambungan jaringan ing Android sing ngidini komunikasi karo server liwat protokol HTTP. Conto setelan sing ngemot atribut cleartextTrafficPermitted kanthi teges 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>

Tugas: Matesi asil miturut jeneng berkas/path

solusi: Ing salah sawijining proyek gedhe sing ana gandhengane karo pangembangan aplikasi seluler kanggo Android, kita nemokake positip palsu saka aturan sing nemtokake setelan obfuscation. Kasunyatan iku aturan metu saka kothak nggoleki ing file build.gradle setelan tanggung jawab kanggo aplikasi aturan obfuscation kanggo versi release saka aplikasi.

Nanging ing proyek gedhe kadhangkala ana file anak build.gradle, sing nuduhake perpustakaan sing kalebu ing proyek kasebut. Keanehan kasebut yaiku sanajan file kasebut ora nuduhake kabutuhan obfuscation, setelan file perakitan induk bakal ditrapake sajrone kompilasi.

Mangkono, tugas iku kanggo Cut mati pemicu ing file anak sing kagungane perpustakaan. Padha bisa dikenali dening ngarsane saka baris apply 'com.android.library'.

Tuladha kode saka file build.gradle, sing nemtokake kabutuhan obfuscation:

apply plugin: 'com.android.application'

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

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

dependencies {
  ...
}

Tuladha file build.gradle kanggo perpustakaan sing kalebu ing proyek sing ora duwe setelan iki:

apply plugin: 'android-library'

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

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

Lan aturan kanggo 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);
		}
	}
}

Pendekatan iki bisa uga cukup universal lan migunani ora mung kanggo aplikasi Android, nanging uga kanggo kasus liyane nalika sampeyan kudu nemtokake manawa asil kasebut kalebu file tartamtu.

Tugas: Tambah dhukungan kanggo perpustakaan pihak katelu yen sintaks ora didhukung kanthi lengkap

solusi: Jumlah macem-macem kerangka kerja sing digunakake ing proses nulis kode mung ora ana ing grafik. Mesthine, Checkmarx ora tansah ngerti babagan eksistensi, lan tugas kita yaiku ngajar supaya ngerti yen metode tartamtu kalebu khusus kanggo kerangka iki. Kadhangkala iki rumit amarga kasunyatane framework nggunakake jeneng fungsi sing umum banget lan ora bisa nemtokake hubungan telpon tartamtu menyang perpustakaan tartamtu.

Kangelan yaiku sintaks perpustakaan kasebut ora mesthi diakoni kanthi bener lan sampeyan kudu nyoba supaya ora entuk akeh positip palsu. Ana sawetara opsi kanggo nambah akurasi mindhai lan ngatasi masalah:

  • Opsi pisanan, kita ngerti manawa perpustakaan digunakake ing proyek tartamtu lan bisa ngetrapake aturan kasebut ing tingkat tim. Nanging yen tim mutusake kanggo njupuk pendekatan sing beda utawa nggunakake sawetara perpustakaan sing jeneng fungsi tumpang tindih, kita bisa entuk gambaran sing ora nyenengake babagan akeh positip palsu.

  • Pilihan kapindho yaiku kanggo nggoleki file sing perpustakaan wis diimpor kanthi jelas. Kanthi pendekatan iki, kita bisa yakin manawa perpustakaan sing kita butuhake pancen digunakake ing file iki.

  • Lan pilihan katelu yaiku nggunakake loro pendekatan ing ndhuwur bebarengan.

Minangka conto, ayo goleki perpustakaan sing kondhang ing bunderan sempit lunyu kanggo basa pemrograman Scala, yaiku, fungsi Penyambungan Nilai Literal. Umumé, kanggo ngirim parameter menyang query SQL, sampeyan kudu nggunakake operator $, kang substitutes data menyang query SQL preformed. Tegese, iku analog langsung saka Prepared Statement ing Jawa. Nanging, yen sampeyan kudu nggawe pitakon SQL kanthi dinamis, umpamane, yen sampeyan kudu menehi jeneng tabel, sampeyan bisa nggunakake operator. #$, sing bakal langsung ngganti data menyang query (meh kaya string concatenation).

Kode sampel:

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

Checkmarx durung ngerti carane ndeteksi panggunaan Nilai Literal Splicing lan nglewati operator #$, mula ayo sinau kanggo ngenali injeksi SQL potensial lan nyorot panggonan sing bener ing kode kasebut:

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

Tugas: Telusuri fungsi sing rawan digunakake ing perpustakaan Open-Source

solusi: Akeh perusahaan nggunakake alat ngawasi Open-Source (praktik OSA) kanggo ndeteksi panggunaan versi perpustakaan sing rawan ing aplikasi sing dikembangake. Kadhangkala ora bisa nganyari perpustakaan kasebut menyang versi sing aman. Ing sawetara kasus ana watesan fungsi, ing liyane ora ana versi aman. Ing kasus iki, kombinasi praktik SAST lan OSA bakal mbantu nemtokake manawa fungsi sing nyebabake eksploitasi kerentanan ora digunakake ing kode kasebut.

Nanging kadhangkala, utamane nalika nimbang JavaScript, iki bisa uga ora dadi tugas sing ora pati penting. Ing ngisor iki minangka solusi, mbok menawa ora becik, nanging bisa digunakake, nggunakake conto kerentanan ing komponen kasebut. lodash ing metode template и *set.

Conto tes kode sing bisa rawan ing file 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!'

Lan nalika nyambung langsung ing 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>

Kita nggoleki kabeh cara sing rawan, sing didaftar ing kerentanan:

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

Tugas: Nggoleki sertifikat sing dipasang ing aplikasi kasebut

solusi: Ora umum kanggo aplikasi, utamane seluler, nggunakake sertifikat utawa kunci kanggo ngakses macem-macem server utawa verifikasi SSL-Pinning. Saka perspektif keamanan, nyimpen barang kasebut ing kode dudu praktik paling apik. Ayo nyoba nulis aturan sing bakal nelusuri file sing padha ing repositori:

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

Tugas: Nemokake token sing dikompromi ing aplikasi kasebut

solusi: Asring perlu kanggo mbatalake token sing dikompromi utawa informasi penting liyane sing ana ing kode kasebut. Mesthi, nyimpen ing kode sumber ora apik, nanging kahanan beda-beda. Thanks kanggo pitakon CxQL, nemokake perkara kaya iki cukup gampang:

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

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

kesimpulan

Muga-muga artikel iki bisa migunani kanggo wong-wong sing miwiti kenalan karo alat Checkmarx. Mungkin wong-wong sing wis suwe nulis aturane dhewe uga bakal nemokake sing migunani ing pandhuan iki.

Sayange, saiki ana kekurangan sumber daya ing ngendi ide-ide anyar bisa ditemokake sajrone pangembangan aturan kanggo Checkmarx. Mulane kita digawe repositori ing Github, ngendi kita bakal ngirim karya kita supaya saben wong sing nggunakake CxQL bisa nemokake soko migunani ing, lan uga duwe kesempatan kanggo nuduhake karya karo masyarakat. Repositori ing proses ngisi lan nyusun konten, mula kontributor ditampa!

Matur suwun!

Source: www.habr.com

Add a comment