হে হাবর!
আমাদের কাজে, আমাদের কোম্পানি প্রায়শই বিভিন্ন স্ট্যাটিক কোড অ্যানালাইসিস টুল (SAST) ব্যবহার করে থাকে। ডিফল্টভাবে, এগুলোর পারফরম্যান্স মাঝারি মানের হয়। অবশ্যই, সবকিছু নির্ভর করে প্রজেক্ট এবং ব্যবহৃত প্রযুক্তির উপর, সেইসাথে অ্যানালাইসিস রুলগুলো দ্বারা এই প্রযুক্তিগুলো কতটা ভালোভাবে কভার করা হয়েছে তার উপর। আমার মতে, একটি SAST টুল বেছে নেওয়ার ক্ষেত্রে সবচেয়ে গুরুত্বপূর্ণ মানদণ্ডগুলোর মধ্যে একটি হলো আপনার অ্যাপ্লিকেশনের নির্দিষ্টতা অনুযায়ী এটিকে কাস্টমাইজ করার ক্ষমতা, বিশেষ করে অ্যানালাইসিস রুল লেখা এবং পরিবর্তন করার ক্ষমতা, বা যা সাধারণত কাস্টম কোয়েরি নামে পরিচিত।

আমরা প্রায়শই চেকমার্ক্স (Checkmarx) ব্যবহার করি, যা একটি অত্যন্ত আকর্ষণীয় ও শক্তিশালী কোড অ্যানালাইজার। এই আর্টিকেলে আমি এর জন্য অ্যানালাইসিস রুল লেখার অভিজ্ঞতা শেয়ার করব।
বিষয়বস্তু সূচি
প্রবেশ
প্রথমত, আমি চেকমার্ক্স-এর জন্য কোয়েরি লেখার খুঁটিনাটি বিষয়ে রুশ ভাষায় লেখা অল্প কয়েকটি প্রবন্ধের মধ্যে একটির সুপারিশ করতে চাই। এটি ২০১৯ সালের শেষে হাবর-এ এই শিরোনামে প্রকাশিত হয়েছিল: .
একটি টেস্ট অ্যাপ্লিকেশনের জন্য CxQL (চেকমার্ক্স কোয়েরি ল্যাঙ্গুয়েজ)-এ কীভাবে আপনার প্রথম কোয়েরিগুলো লিখতে হয়, তা এখানে বিস্তারিতভাবে আলোচনা করা হয়েছে এবং অ্যানালাইসিস রুলগুলো কীভাবে কাজ করে তার মৌলিক নীতিগুলো দেখানো হয়েছে।
সেখানে বর্ণিত সবকিছু আমি পুনরাবৃত্তি করব না, যদিও কিছু মিল থেকেই যাবে। এই আর্টিকেলে, আমি একটি "রেসিপি সংকলন" তৈরি করার চেষ্টা করব, যা হলো চেকমার্ক্স (Checkmarx) নিয়ে কাজ করার সময় আমার সম্মুখীন হওয়া নির্দিষ্ট কিছু সমস্যার সমাধানের একটি তালিকা। এই কাজগুলোর অনেকগুলোর জন্যই যথেষ্ট চিন্তাভাবনার প্রয়োজন হয়েছিল। কখনও কখনও ডকুমেন্টেশন অপর্যাপ্ত ছিল, আবার কখনও যা করার প্রয়োজন ছিল তা কীভাবে করতে হবে, তা বোঝাই কঠিন ছিল। আমি আশা করি আমার অভিজ্ঞতা এবং বিনিদ্র রাতগুলো বৃথা যাবে না, এবং এই "কাস্টম কোয়েরি রেসিপি সংকলন" আপনার কয়েক ঘণ্টা বা মানসিক চাপ বাঁচাবে। তাহলে, চলুন শুরু করা যাক!
নিয়মাবলী সম্পর্কে সাধারণ তথ্য
এরপরে কী ঘটতে চলেছে তা আরও ভালোভাবে বোঝার জন্য, চলুন কিছু মৌলিক ধারণা এবং নিয়ম নিয়ে কাজ করার প্রক্রিয়া দিয়ে শুরু করা যাক। এর আরেকটি কারণ হলো, ডকুমেন্টেশনে এই বিষয়গুলো বিস্তারিতভাবে আলোচনা করা হয়নি অথবা সেগুলো খুব অগোছালোভাবে ছড়িয়ে ছিটিয়ে আছে, যা খুব একটা সুবিধাজনক নয়।
শুরুতে নির্বাচিত প্রিসেট (সক্রিয় নিয়মগুলোর সেট)-এর উপর ভিত্তি করে স্ক্যানিংয়ের সময় নিয়মগুলো প্রয়োগ করা হয়। আপনি সীমাহীন সংখ্যক প্রিসেট তৈরি করতে পারেন, এবং সেগুলোর বিন্যাস আপনার কর্মপ্রবাহের নির্দিষ্টতার উপর নির্ভর করে। আপনি সেগুলোকে ভাষা অনুযায়ী গ্রুপ করতে পারেন অথবা প্রতিটি প্রজেক্টে প্রিসেট বরাদ্দ করতে পারেন। সক্রিয় নিয়মের সংখ্যা স্ক্যানিংয়ের গতি এবং নির্ভুলতাকে প্রভাবিত করে।
চেকমার্ক্স ইন্টারফেসে একটি প্রিসেট সেট আপ করাCxAuditor নামক একটি বিশেষ টুলে নিয়মগুলো সম্পাদনা করা হয়। এই ডেস্কটপ অ্যাপ্লিকেশনটি Checkmarx চালিত সার্ভারের সাথে সংযুক্ত হয়। এই টুলটির দুটি মোড রয়েছে: নিয়ম সম্পাদনা করা এবং বিদ্যমান কোনো স্ক্যানের ফলাফল বিশ্লেষণ করা।
CxAudit ইন্টারফেসচেকমার্ক্স নিয়মগুলো ভাষা অনুযায়ী বিভক্ত, অর্থাৎ প্রতিটি ভাষার নিজস্ব কোয়েরি সেট রয়েছে। এছাড়াও কিছু সাধারণ নিয়ম আছে যা ভাষা নির্বিশেষে প্রযোজ্য—এগুলোকে বেস কোয়েরি বলা হয়। বেশিরভাগ বেস কোয়েরি এমন তথ্য অনুসন্ধান করে যা অন্যান্য নিয়ম দ্বারা ব্যবহৃত হয়।
ভাষার দ্বারা নিয়মের পৃথকীকরণরুলগুলোকে 'এক্সিকিউটেবল' এবং 'নন-এক্সিকিউটেবল' হিসেবে শ্রেণীবদ্ধ করা হয়। আমার মতে, এটি পুরোপুরি সঠিক পরিভাষা নয়, কিন্তু বিষয়টা এমনই। এর মূল ধারণাটি হলো, 'এক্সিকিউটেবল' রুলগুলোর ফলাফল UI-এর স্ক্যান রেজাল্টে প্রদর্শিত হবে, অন্যদিকে 'নন-এক্সিকিউটেবল' রুলগুলোর ফলাফল শুধুমাত্র অন্যান্য কোয়েরিতে ব্যবহারের জন্যই প্রয়োজন হয় (মূলত, এগুলো এক ধরনের ফাংশন মাত্র)।
তৈরি করার সময় নিয়মের ধরণ নির্ধারণ করাআপনি নতুন নিয়ম তৈরি করতে পারেন অথবা বিদ্যমান নিয়মগুলো পরিপূরণ বা ওভাররাইট করতে পারেন। কোনো নিয়ম ওভাররাইড করতে, ট্রি-তে সেটি খুঁজুন, সেটির উপর রাইট-ক্লিক করুন এবং ড্রপ-ডাউন মেনু থেকে 'ওভাররাইড' নির্বাচন করুন। এটা মনে রাখা গুরুত্বপূর্ণ যে, নতুন নিয়মগুলো প্রাথমিকভাবে প্রিসেট-এ অন্তর্ভুক্ত থাকে না এবং সক্রিয়ও থাকে না। এগুলো ব্যবহার শুরু করতে, আপনাকে টুলের 'প্রিসেট ম্যানেজার' মেনু থেকে এগুলো সক্রিয় করতে হবে। ওভাররাইড করা নিয়মগুলো তাদের সেটিংস ধরে রাখে, অর্থাৎ যদি কোনো নিয়ম সক্রিয় থাকে, তবে সেটি সক্রিয়ই থাকবে এবং সাথে সাথে প্রয়োগ হয়ে যাবে।
প্রিসেট ম্যানেজার ইন্টারফেসে একটি নতুন নিয়মের উদাহরণএক্সিকিউশনের সময়, কোয়েরিগুলোর একটি 'ট্রি' তৈরি করা হয়, যা নির্ধারণ করে কোন নিয়মটি কার উপর নির্ভরশীল। যে নিয়মগুলো তথ্য সংগ্রহ করে, সেগুলো প্রথমে এক্সিকিউট করা হয়, এবং এরপরে সেই তথ্য ব্যবহারকারী নিয়মগুলো এক্সিকিউট হয়। ফলাফলগুলো ক্যাশ করা থাকে, তাই যদি কোনো বিদ্যমান নিয়মের ফলাফল ব্যবহার করা সম্ভব হয়, তবে তা করাই শ্রেয়; এতে স্ক্যান টাইম কমে আসবে।
নিয়মগুলো বিভিন্ন স্তরে প্রয়োগ করা যেতে পারে:
সিস্টেম-ব্যাপী - যেকোনো প্রজেক্টের যেকোনো স্ক্যানের জন্য ব্যবহৃত হবে।
টিম পর্যায়ে - এটি শুধুমাত্র নির্বাচিত টিমের স্ক্যানিং প্রোজেক্টগুলোর ক্ষেত্রে প্রযোজ্য হবে।
প্রকল্প স্তর - একটি নির্দিষ্ট প্রকল্পে প্রযোজ্য হবে
কোন স্তরে নিয়মটি প্রযোজ্য হবে তা নির্ধারণ করা
শিক্ষানবিসদের জন্য "অভিধান"
আমি এমন কিছু বিষয় দিয়ে শুরু করব যা আমার মনে প্রশ্ন জাগিয়েছিল, এবং আমি আপনাদের এমন কিছু কৌশলও দেখাব যা জীবনকে আরও অনেক সহজ করে তুলবে।
তালিকা কার্যক্রম
- вычитание одного из другого (list2 - list1)
* пересечение списков (list1 * list2)
+ сложение списков (list1 + list2)
& (логическое И) - объединяет списки по совпадению (list1 & list2), аналогично пересечению (list1 * list2)
| (логическое ИЛИ) - объединяет списки по широкому поиску (list1 | list2)
Со списками не работает: ^ && || % / প্রাপ্ত সমস্ত উপাদান
স্ক্যান করা ভাষার মধ্যে, আপনি চেকমার্ক্স দ্বারা সংজ্ঞায়িত একেবারে সমস্ত উপাদানের (স্ট্রিং, ফাংশন, ক্লাস, মেথড, ইত্যাদি) একটি তালিকা পেতে পারেন। এটি এক ধরণের অবজেক্ট স্পেস যা এর মাধ্যমে অ্যাক্সেস করা যায়। Allঅর্থাৎ, একটি নির্দিষ্ট নাম দিয়ে কোনো বস্তু অনুসন্ধান করা। searchMeউদাহরণস্বরূপ, আপনি নাম দিয়ে খুঁজে পাওয়া সমস্ত বস্তু অনুসন্ধান করতে পারেন:
// Такой запрос выдаст все элементы
result = All;
// Такой запрос выдаст все элементы, в имени которых присутствует “searchMe“
result = All.FindByName("searchMe");কিন্তু, যদি আপনাকে অন্য কোনো ভাষায় অনুসন্ধান করতে হয় যা কোনো কারণে স্ক্যানে অন্তর্ভুক্ত ছিল না (উদাহরণস্বরূপ, একটি প্রকল্পের জন্য গ্রুভি)। 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");কিন্তু, এক্সিকিউশনের ফলাফলটি 'result' ম্যাজিক ভেরিয়েবলে অ্যাসাইন করার পর, আমরা দেখব এই কলটি আমাদের কী রিটার্ন করে:
// Находим элементы foo
CxList libraries = All.FindByName("foo");
// Выводим, как результат выполнения правила
result = libraries
// Или еще короче
result = All.FindByName("foo");অন্যান্য নিয়মের ফলাফল ব্যবহার করে
চেকমার্ক্স-এর নিয়মগুলো একটি সাধারণ প্রোগ্রামিং ভাষার ফাংশনের অনুরূপ। একটি নিয়ম লেখার সময়, আপনি সহজেই অন্যান্য কোয়েরির ফলাফল ব্যবহার করতে পারেন। উদাহরণস্বরূপ, আপনার কোডের প্রতিটি মেথড কল খোঁজার কোনো প্রয়োজন নেই; কেবল কাঙ্ক্ষিত নিয়মটি কল করুন:
// Получаем результат выполнения другого правила
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 কোয়েরি এক্সিকিউশনের ফলাফল দেখুন এবং কী ঘটে তা পর্যবেক্ষণ করুন। এই পদ্ধতিটি খুব একটা সুবিধাজনক নয়; আপনাকে নিশ্চিত করতে হবে যে এর পরে কোডে 'this' দিয়ে কোনো ওভাররাইড বা অপারেশন করা হয়নি। result অথবা সহজভাবে নিচের কোডটি কমেন্ট আউট করে দিন। কিংবা, আমার মতো, আপনিও হয়তো তৈরি হয়ে যাওয়া রুলটি থেকে এই কলগুলোর কয়েকটি সরাতে ভুলে যেতে পারেন এবং অবাক হতে পারেন যে কেন কিছুই কাজ করছে না।
আরও সুবিধাজনক উপায় হলো পদ্ধতিটিকে কল করা। return প্রয়োজনীয় প্যারামিটার সহ। এক্ষেত্রে, রুলটির এক্সিকিউশন শেষ হবে এবং আমরা আমাদের কোডের ফলাফল দেখতে পাব:
// Находим что-то
CxList toLog = All.FindByShortName("log");
// Выводим результат выполнения
return toLog
//Все, что написано дальше не будет выполнено
result = All.DataInfluencedBy(toLog)লগইনে সমস্যা
মাঝে মাঝে এমন হয় যে আপনি CxAudit টুলটি (যা রুল লেখার জন্য ব্যবহৃত হয়) অ্যাক্সেস করতে পারেন না। এটি বিভিন্ন কারণে হতে পারে, যেমন—ক্র্যাশ, অপ্রত্যাশিত আপডেট বা অন্য কিছু। Windowsবিএসওডি (BSOD), এবং আমাদের নিয়ন্ত্রণের বাইরে থাকা অন্যান্য অপ্রত্যাশিত পরিস্থিতি। এই ধরনের ক্ষেত্রে, ডাটাবেসে একটি অসমাপ্ত সেশন থেকে যেতে পারে, যা পুনরায় প্রবেশে বাধা দেয়। এটি ঠিক করার জন্য, আপনাকে কয়েকটি কোয়েরি চালাতে হবে:
চেকমার্ক্স ৮.৬ পর্যন্ত:
// Проверяем, что есть залогиненые пользователи, выполнив запрос в БД
SELECT COUNT(*) FROM [CxDB].[dbo].LoggedinUser WHERE [ClientType] = 6;
// Если что-то есть, а на самом деле даже если и нет, попробовать выполнить запрос
DELETE FROM [CxDB].[dbo].LoggedinUser WHERE [ClientType] = 6;
৮.৬-এর পরে চেকমার্ক্সের জন্য:
// Проверяем, что есть залогиненые пользователи, выполнив запрос в БД
SELECT COUNT(*) FROM LoggedinUser WHERE (ClientType = 'Audit');
// Если что-то есть, а на самом деле даже если и нет, попробовать выполнить запрос
DELETE FROM [CxDB].[dbo].LoggedinUser WHERE (ClientType = 'Audit');লেখার নিয়ম
এখন আমরা সবচেয়ে আকর্ষণীয় অংশে পৌঁছেছি। যখন আপনি CxQL-এ নিয়ম লেখা শুরু করেন, তখন প্রায়শই ডকুমেন্টেশনের চেয়ে নির্দিষ্ট সমস্যা সমাধানের বাস্তব-জগতের উদাহরণ এবং সামগ্রিক কোয়েরি প্রক্রিয়ার বর্ণনার অভাব বেশি দেখা যায়।
যারা কোয়েরি ল্যাঙ্গুয়েজ নিয়ে সবেমাত্র কাজ শুরু করছেন, তাদের জন্য কাস্টম কোয়েরি ব্যবহার করে নির্দিষ্ট সমস্যার সমাধানের কয়েকটি উদাহরণ দিয়ে আমি বিষয়টি কিছুটা সহজ করার চেষ্টা করব। এগুলোর মধ্যে কয়েকটি বেশ সাধারণ এবং সামান্য বা কোনো পরিবর্তন ছাড়াই আপনার প্রতিষ্ঠানে প্রয়োগ করা যেতে পারে, আবার অন্যগুলো আরও সুনির্দিষ্ট, কিন্তু আপনার অ্যাপ্লিকেশনের বিশেষ প্রয়োজন অনুসারে কিছু কাস্টমাইজেশন করে সেগুলোও ব্যবহার করা সম্ভব।
সুতরাং, এই কাজগুলোই আমরা সবচেয়ে বেশি সম্মুখীন হয়েছি:
উদ্দেশ্য: নিয়মের ফলাফলে একাধিক ফ্লো রয়েছে এবং সেগুলোর মধ্যে একটি অন্যটির নেস্টিং। এগুলোর মধ্যে একটি অবশ্যই রেখে দিতে হবে।
সমাধান: প্রকৃতপক্ষে, কখনও কখনও চেকমার্ক্স একাধিক ডেটা ফ্লো প্রদর্শন করে, যেগুলো একে অপরের সাথে ওভারল্যাপ করতে পারে বা অন্যগুলোর সংক্ষিপ্ত সংস্করণ হতে পারে। এই ধরনের ক্ষেত্রের জন্য একটি বিশেষ পদ্ধতি রয়েছে। রিডিউসফ্লো। প্যারামিটারের উপর নির্ভর করে এটি সবচেয়ে ছোট বা দীর্ঘতম ফ্লো নির্বাচন করবে:
// Оставить только длинные Flow
result = result.ReduceFlow(CxList.ReduceFlowType.ReduceSmallFlow);
// Оставить только короткие Flow
result = result.ReduceFlow(CxList.ReduceFlowType.ReduceBigFlow);উদ্দেশ্য: সংবেদনশীল তথ্যের তালিকাটি প্রসারিত করুন, যেগুলোতে টুলটি সাড়া দেয়।
সমাধান: চেকমার্ক্সে কিছু মৌলিক নিয়ম অন্তর্ভুক্ত রয়েছে, যেগুলোর ফলাফল অন্যান্য অনেক কোয়েরিতে ব্যবহৃত হয়। আপনার অ্যাপ্লিকেশনের জন্য নির্দিষ্ট ডেটা দিয়ে এই নিয়মগুলোর কয়েকটিকে পরিপূরক করে, আপনি স্ক্যানের ফলাফল তাৎক্ষণিকভাবে উন্নত করতে পারেন। আপনাকে শুরু করার জন্য নিচে একটি উদাহরণ নিয়ম দেওয়া হলো:
সাধারণ_গোপনীয়তা_লঙ্ঘন_তালিকা
চলুন আমাদের অ্যাপ্লিকেশনে সংবেদনশীল তথ্য সংরক্ষণের জন্য ব্যবহৃত কয়েকটি ভেরিয়েবল যোগ করি:
// Получаем результат выполнения базового правила
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);
}
}উদ্দেশ্য: ব্যবহৃত ফ্রেমওয়ার্কগুলো যোগ করুন যা চেকমার্ক্স দ্বারা সমর্থিত নয়।
সমাধান: চেকমার্ক্স-এর সমস্ত কোয়েরি ভাষা অনুযায়ী বিভক্ত, তাই প্রতিটি ভাষার জন্য নিয়মগুলো আপডেট করতে হয়। নিচে এই ধরনের কিছু নিয়মের উদাহরণ দেওয়া হলো।
যদি আপনি এমন লাইব্রেরি ব্যবহার করেন যা প্রচলিত কার্যকারিতার পরিপূরক বা বিকল্প, তবে সেগুলোকে সহজেই মূল নিয়মে যোগ করা যেতে পারে। তাহলে যারা এটি ব্যবহার করবে, তারা সবাই নতুন ইনপুটটি সম্পর্কে সঙ্গে সঙ্গে জানতে পারবে। উদাহরণস্বরূপ, লাইব্রেরি লগিং করা। Android টিম্বার এবং লগি। ডিফল্ট ডিস্ট্রিবিউশনে নন-সিস্টেম কল শনাক্ত করার কোনো নিয়ম নেই, তাই যদি কোনো পাসওয়ার্ড বা সেশন আইডি লগ হয়ে যায়, আমরা তা জানতে পারব না। আমরা চেকমার্ক্স নিয়মে এই ধরনের মেথড শনাক্ত করার ব্যবস্থা যোগ করার চেষ্টা করব।
লগিংয়ের জন্য টিম্বার লাইব্রেরি ব্যবহার করে এমন একটি টেস্ট কোডের উদাহরণ:
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");
}
}এখানে চেকমার্ক্স-এর জন্য একটি অনুরোধের উদাহরণ দেওয়া হলো, যা আপনাকে অ্যাপ্লিকেশন থেকে ডেটার প্রস্থান বিন্দু হিসাবে টিম্বার মেথড কল করার জন্য একটি সংজ্ঞা যোগ করার সুযোগ দেবে:
আবিষ্কারAndroidআউটপুট
// Получаем результат выполнения базового правила
result = base.Find_Android_Outputs();
// Дополняем вызовами, которые приходят из библиотеки Timber
CxList timber = All.FindByExactMemberAccess("Timber.*") +
All.FindByShortName("Timber").GetMembersOfTarget();
// Добавляем к конечному результату
result.Add(timber);এবং আপনি একটি পার্শ্ববর্তী নিয়মও যোগ করতে পারেন, তবে সেটি যেন সরাসরি লগ ইন করার সাথে সম্পর্কিত হয়। Android:
আবিষ্কারAndroidলগ_আউটপুট
// Получаем результат выполнения базового правила
result = base.Find_Android_Log_Outputs();
// Дополняем вызовами, которые приходят из библиотеки Timber
result.Add(
All.FindByExactMemberAccess("Timber.*") +
All.FindByShortName("Timber").GetMembersOfTarget()
);এছাড়াও, যদি মধ্যে Androidঅ্যাপ্লিকেশনগুলিতে ব্যবহৃত হয় অ্যাসিঙ্ক্রোনাস কাজের ক্ষেত্রে, টাস্ক থেকে ডেটা নেওয়ার জন্য একটি মেথড যোগ করে চেকমার্ক্সকে এই বিষয়ে অতিরিক্তভাবে জানানো একটি ভালো উপায় হবে। getInputData:
আবিষ্কারAndroidপড়া
// Получаем результат выполнения базового правила
result = base.Find_Android_Read();
// Дополняем вызовом функции getInputData, которая используется в WorkManager
CxList getInputData = All.FindByShortName("getInputData");
// Добавляем к конечному результату
result.Add(getInputData.GetMembersOfTarget());উদ্দেশ্য: iOS প্রোজেক্টের plist ফাইল থেকে সংবেদনশীল ডেটা খুঁজে বের করা
সমাধান: 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>এবং চেকমার্ক্সের জন্য একটি নিয়ম, যার কয়েকটি সূক্ষ্ম দিক রয়েছে যা লেখার সময় বিবেচনায় রাখা উচিত:
// Используем результат выполнения правила по поиску файлов 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-এ তথ্য অনুসন্ধান
সমাধান: চেকমার্ক্স-এ এক্সএমএল (XML) নিয়ে কাজ করার এবং ভ্যালু, ট্যাগ, অ্যাট্রিবিউট ও আরও অনেক কিছু খোঁজার জন্য খুবই সুবিধাজনক ফাংশন রয়েছে। তবে, দুর্ভাগ্যবশত, ডকুমেন্টেশনে একটি ত্রুটি রয়েছে যার কারণে কোনো উদাহরণই কাজ করে না। যদিও ডকুমেন্টেশনের সর্বশেষ সংস্করণে এই সমস্যাটি সমাধান করা হয়েছে, তবুও ডকুমেন্টেশনের পূর্ববর্তী সংস্করণগুলো ব্যবহার করার সময় অনুগ্রহ করে সতর্ক থাকবেন।
ডকুমেন্টেশন থেকে নেওয়া একটি ভুল উদাহরণ নিচে দেওয়া হলো:
// Код работать не будет
result = All.FindXmlAttributesByNameAndValue("*.app", 8, “id”, "error- section", false, true);এটি কার্যকর করার চেষ্টা করার ফলে আমরা একটি ত্রুটি পাব যে All এরকম কোনো পদ্ধতি নেই... এবং এটি সত্যি, কারণ XML নিয়ে কাজ করার জন্য ফাংশন ব্যবহারের একটি বিশেষ, আলাদা অবজেক্ট স্পেস রয়েছে - cxXPathসেটিংটি খুঁজে বের করার জন্য সঠিক কোয়েরিটি দেখতে এইরকম। AndroidHTTP ট্র্যাফিক ব্যবহারের অনুমতি দিয়ে:
// Правильный вариант с использованием 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'
...
}এবং চেকমার্ক্সের নিয়ম:
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 অ্যাপ্লিকেশনগুলির জন্য তো বটেই, সেইসাথে অন্যান্য ক্ষেত্রেও যখন কোনো নির্দিষ্ট ফাইলের সাথে ফলাফলের সম্পর্ক নির্ধারণ করা প্রয়োজন হয়।
উদ্দেশ্য: সিনট্যাক্সটি সম্পূর্ণরূপে সমর্থিত না হলে একটি থার্ড-পার্টি লাইব্রেরির জন্য সমর্থন যোগ করুন।
সমাধান: কোডিং-এ ব্যবহৃত বিভিন্ন ফ্রেমওয়ার্কের সংখ্যা রীতিমতো বিস্ময়কর। স্বাভাবিকভাবেই, চেকমার্ক্স সবসময় এগুলোর অস্তিত্ব সম্পর্কে অবগত থাকে না, এবং আমাদের কাজ হলো একে শেখানো যে নির্দিষ্ট কিছু মেথড একটি বিশেষ ফ্রেমওয়ার্কের অন্তর্গত। এই বিষয়টি কখনও কখনও আরও জটিল হয়ে ওঠে, কারণ ফ্রেমওয়ার্কগুলো বহুল ব্যবহৃত ফাংশনের নাম ব্যবহার করে, যার ফলে কোনো একটি নির্দিষ্ট কল কোন লাইব্রেরির অন্তর্গত তা স্পষ্টভাবে শনাক্ত করা কঠিন হয়ে পড়ে।
অসুবিধাটি হলো এই যে, এই ধরনের লাইব্রেরির সিনট্যাক্স সবসময় সঠিকভাবে শনাক্ত করা যায় না, যার ফলে প্রচুর ভুল শনাক্তকরণ এড়ানোর জন্য পরীক্ষা-নিরীক্ষার প্রয়োজন হয়। স্ক্যানিংয়ের নির্ভুলতা বাড়াতে এবং সমস্যাটি সমাধান করতে বেশ কিছু উপায় রয়েছে:
প্রথম বিকল্পে, আমরা নিশ্চিতভাবে জানি যে একটি লাইব্রেরি একটি নির্দিষ্ট প্রকল্পে ব্যবহৃত হচ্ছে এবং দলীয় পর্যায়ে একটি নিয়ম প্রয়োগ করতে পারি। তবে, যদি দলটি ভিন্ন কোনো পন্থা অবলম্বন করার সিদ্ধান্ত নেয় অথবা একই ধরনের ফাংশনের নামযুক্ত একাধিক লাইব্রেরি ব্যবহার করে, তাহলে আমরা অসংখ্য ভুল ফলাফলের এক বেশ অপ্রীতিকর চিত্রের সম্মুখীন হতে পারি।
দ্বিতীয় উপায়টি হলো এমন ফাইল খোঁজা, যেগুলোতে লাইব্রেরিটি স্পষ্টভাবে ইম্পোর্ট করা আছে। এই পদ্ধতির মাধ্যমে আমরা নিশ্চিত হতে পারি যে ফাইলটি আমাদের প্রয়োজনীয় লাইব্রেরিটিই ব্যবহার করছে।
আর তৃতীয় বিকল্পটি হলো উপরের দুটি পদ্ধতি একসাথে ব্যবহার করা।
উদাহরণস্বরূপ, আসুন এমন একটি লাইব্রেরির দিকে নজর দেওয়া যাক যা সীমিত মহলে সুপরিচিত। স্ক্যালা প্রোগ্রামিং ভাষার জন্য, অর্থাৎ, ফাংশনাল সাধারণত, একটি SQL কোয়েরিতে প্যারামিটার পাস করার জন্য, আপনাকে অপারেটরটি ব্যবহার করতে হবে। $যা আগে থেকে তৈরি করা একটি SQL কোয়েরিতে ডেটা প্রবেশ করায়। অন্য কথায়, এটি মূলত জাভার Prepared Statement-এর একটি সরাসরি প্রতিরূপ। তবে, যদি আপনার ডাইনামিকভাবে একটি SQL কোয়েরি তৈরি করার প্রয়োজন হয়, উদাহরণস্বরূপ, যদি আপনার টেবিলের নাম পাস করার প্রয়োজন হয়, তাহলে আপনি অপারেটরটি ব্যবহার করতে পারেন। #$যা সরাসরি কোয়েরিতে ডেটা প্রবেশ করাবে (কার্যত স্ট্রিং সংযুক্ত করার মতো)।
কোড উদাহরণ:
// В общем случае - значения, контролируемые пользователем
val table = "coffees"
sql"select * from #$table where name = $name".as[Coffee].headOptionচেকমার্ক্স এখনও স্প্লাইসিং লিটারাল ভ্যালু-এর ব্যবহার শনাক্ত করতে সক্ষম নয় এবং অপারেটরগুলো এড়িয়ে যায়। #$সুতরাং, চলুন এটিকে সম্ভাব্য 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 পদ্ধতির একটি সমন্বয় সাহায্য করতে পারে, যা নিশ্চিত করে যে কোডে এমন কোনো ফাংশন ব্যবহার করা হচ্ছে না যা দুর্বলতার সুযোগ নিতে পারে।
কিন্তু কখনও কখনও, বিশেষ করে জাভাস্ক্রিপ্টের ক্ষেত্রে, এটি একটি বেশ কঠিন কাজ হতে পারে। নিচে একটি সমাধান দেওয়া হলো, যা হয়তো আদর্শ নয়, কিন্তু একটি কম্পোনেন্ট ভালনারেবিলিটির উদাহরণ ব্যবহার করে এটি কার্যকর। 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 পিনিং যাচাই করতে সার্টিফিকেট বা কী ব্যবহার করে। নিরাপত্তার দৃষ্টিকোণ থেকে, কোডের মধ্যে এই ধরনের জিনিস সংরক্ষণ করা সর্বোত্তম অনুশীলন নয়। চলুন এমন একটি নিয়ম লেখার চেষ্টা করি যা রিপোজিটরিতে এই ধরনের ফাইলগুলো অনুসন্ধান করবে:
// Найдем все сертификаты по маске файла
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");উপসংহার
আমি আশা করি, যারা চেকমার্ক্স নিয়ে সবেমাত্র কাজ শুরু করছেন, তাদের জন্য এই নিবন্ধটি সহায়ক হবে। সম্ভবত যারা বেশ কিছুদিন ধরে নিজেদের নিয়ম তৈরি করছেন, তারাও এই নির্দেশিকাটিতে কিছু দরকারি জিনিস খুঁজে পাবেন।
দুর্ভাগ্যবশত, চেকমার্ক্সের জন্য নিয়মকানুন তৈরি করার সময় নতুন ধারণার উৎস হিসেবে বর্তমানে যথেষ্ট উপকরণের অভাব রয়েছে। এই কারণেই আমরা তৈরি করেছি এখানে আমরা আমাদের কাজ শেয়ার করব, যাতে CxQL ব্যবহারকারী প্রত্যেকেই কিছু দরকারি জিনিস খুঁজে পান এবং আমাদের কাজ কমিউনিটির সাথে শেয়ার করার সুযোগ পান। রিপোজিটরিটি এখনও আপডেট এবং কাঠামোবদ্ধ করা হচ্ছে, তাই অবদানকারীদের স্বাগত জানানো হচ্ছে!
আপনার মনোযোগের জন্য আপনাকে ধন্যবাদ!
উত্স: www.habr.com

চেকমার্ক্স ইন্টারফেসে একটি প্রিসেট সেট আপ করা
CxAudit ইন্টারফেস
ভাষার দ্বারা নিয়মের পৃথকীকরণ
তৈরি করার সময় নিয়মের ধরণ নির্ধারণ করা
প্রিসেট ম্যানেজার ইন্টারফেসে একটি নতুন নিয়মের উদাহরণ
কোন স্তরে নিয়মটি প্রযোজ্য হবে তা নির্ধারণ করা