جدول محتوا
پیشگفتار
فازینگ (Fuzzing) روشی برای شناسایی باگ و آسیبپذیریهای موجود در نرمافزارها و سیستمعاملها است. به عبارت دیگر کارشناس امنیت در فازینگ تلاش میکند تا با ارسال تعداد زیادی از ورودیهای غیر معتبر و غیر پیشبینی شده به یک برنامه، پاسخ آن برنامه را ارزیابی کرده و رفتارهای نا متعارف یا Crash نرمافزار در برابر ورودیهای خاص را شناسایی کند. با این روش میتوان آسیبپذیریها و مشکلات موجود در هر نرمافزار را شناسایی کرد. این آسیبپذیریها در امنسازی نرمافزار و سیستمعامل، نوشتن اکسپلویت برای آن یا گزارش در پلتفرمهای باگبانتی جهت دریافت جایزه کاربرد دارد (بسته به هدفی که متخصص از اجرای فازینگ داشته است). ابزارهای زیادی برای شناسایی آسیبپذیریهای شناخته شده در کدهای برنامهنویسی یا سامانهها وجود دارد اما فازینگ این قابلیت را به ما میدهد تا آسیبپذیریهایی را شکار کنیم که تا پیش از این ناشناخته بودند. هکرهای کلاه سیاه از این روش برای شناسایی آسیبپذیریهای جدید و توسعهی اکسپلویتهای Zero-Day برای آنها بهره میبرند. در طرف مقابل شرکتها و سازمانهای تلاش میکنند تا با اجرای انواع فازینگ در سامانههای خود، آسیبپذیریهای موجود را پیش از مهاجمین شناسایی و برطرف کنند. فازینگ را میتوان برای فایلها و سامانههای مختلفی مانند موارد زیر اجرا کرد:- کامپایلرها
- مفسرها
- برنامههای وب
- انواع فایلها مثل PNG ، JSON، YML و غیره
libFuzzer چیست؟
libFuzzer در حقیقت کتابخانهای (Library) است که برای فاز کردن کتابخانههای متنباز (Open Source) دیگر کاربرد دارد. این کتابخانه توسط Clang برای کامپایلر زبان C توسعه داده شده است. آسیبپذیریهای مهم بسیاری در دنیا با استفاده از همینlibFuzzer کشف و برطرف شدهاند. به عنوان مثال میتوان به مورد زیر اشاره کرد:https://llvm.org/docs/LibFuzzer.html#trophies
libFuzzer از سیستمعاملهای ویندوز، مک، لینوکس و اندروید پشتیبانی میکند. در این مقاله ابتدا میخواهم شیوهی استفاده از libFuzzer را به صورت خلاصه و کاربردی به شما آموزش دهم بهگونهای که بتوانید برنامههای خود یا سازمانتان را با فازینگ تست کنید. در انتهای مقاله نیز یک مثال کاربردی استفاده از libFuzzer را شرح خواهم داد.![](https://ravinacademy.com/wp-content/uploads/2020/12/کد-برنامههای-متن-باز-با-استفاده-از-LibFuzzer-cta.jpeg)
آشنایی با ClusterFuzz
شرکت گوگل پروژهای برای فازینگ کتابخانههای متنباز شروع کرده که ClusterFuzz نام دارد. این پروژه بر روی بسترGoogleCloud اجرا میشود و از libFuzzer تحت عنوان OSS-Fuzz برای فازینگ کتابخانهها بهره میبرد. معماری OSS-Fuzz در شکل زیر نمایش داده شده است.![](https://ravinacademy.com/wp-content/uploads/2020/12/q.png)
https://github.com/google/oss-fuzz/tree/master/projects
شیوهی نصب و استفاده از libFuzzer
در اولین گام از نصب libFuzzer در سیستمعامل لینوکس نیاز است تا کامپایلر Clang/Clang++ را با استفاده از دستور زیر نصب کنیم:$ apt-get install clang/clang++
در گام دوم باید کتابخانهی Sanitizer را با دستور زیر نصب کنیم (در دورهی مبانی اکسپلویتنویسی لینوکس، مثالهای کاربری متعددی در خصوص این کتابخانه را با هم کار خواهیم کرد):$ apt-get install libasan
Sanitizer در واقع راهکاری برای کشف خطاهای حافظه (Memory Error Detector) است که خود به چند نوع به شرح زیر تقسیم میشود:- AddressSanitizer (ASAN)
- MemorySanitizer (MSAN)
- ThreadSanitizer (TSAN)
- LeakSanitizer
- UndefinedBehaviorSanitizer (UBSAN)
$ ./build.sh
ar: `u' modifier ignored since `D' is the default (see `U')
ar: creating libFuzzer.a
اگر خروجی مشابه بالا دریافت کردید به این معنا است که libFuzzer به درستی و به صورت Static Library کامپایل شده است.چگونه با استفاده از libFuzzer یک فازر بنویسیم؟
در این بخش یک فازر ساده با استفاده از libFuzzer نوشته و با استفاده از آن، تلاش میکنیم آسیبپذیر بودن یک برنامهی نمونه با ورودیهای مختلف را بررسی کنیم. اگر فایل first_fuzzer.cc را بخوانید، یک متد فازینگ در خطی مشابه زیر مشاهده خواهید کرد:extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
return 0;
}
LLVMFuzzerTestOneInput در واقع یک متد فازینگ است که دو ورودی دریافت میکند. البته در اینجا که قصد فازینگ یک API را داریم، باید توجه کنیم که نوع ورودی ما مشابه با نوع ورودی همان API یا متد باشد. برای مثال کد زیر را در نظر بگیرید.char func_api(const char *in, int size) {
...
}
int LLVMFuzzerTestOneInput(const char *Data, long long Size) {
func_api(Data, Size);
return 0;
}
با استفاده از دستورات زیر میتوان این فازر را کامپایل کرد:$ clang++ -g -std=c++11 -fsanitize=address,fuzzer -fsanitize-coverage=trace-pc-guard first_fuzzer.cc Fuzzer/libFuzzer.a -o first_fuzzer
دستور -fsanitize=address,fuzzer به صورت اتوماتیک برنامهی ما را با کتابخانهی libFuzzer لینک (Link) میکند. همچنین دقت داشته باشید هنگامی که متد VulnerableFunction1(data, size) را فراخوانی می کنیم، هیچ Argument ورودی دریافت نمیکند. درنتیجه خود کتابخانهی libFuzzer ورودی تستی برای متد VulnerableFunction1 را تولید خواهد کرد. سپس با استفاده از دستور زیر برنامهی کامپایل شده را اجرا میکنیم:$ git clone https://github.com/Ravin-Academy/OSS-LibFuzzer.git
$ ./first_fuzzer
نمونهی خروجی اجرای این فاز در شکل زیر نمایش داده شده است.![](https://ravinacademy.com/wp-content/uploads/2020/12/o.png)
https://github.com/CloudAvid/PParam
در گام بعد مثالهایی از این برنامه را در آدرس زیر مطالعه و بررسی کردم:https://github.com/CloudAvid/PParam/tree/master/examples
سپس دو مثال از این برنامه را انتخاب و در پروژهی خودم در پوشهی به نام fuzz در آدرس زیر قرار دادم:https://github.com/raminfp/fuzz-libpparam/tree/master/fuzz
در شکل زیر یک برنامه که در پوشهی مثال وجود دارد نمایش داده شده است. همانگونه که مشاهده میکنید یک متد به نام main در آن وجود دارد.![](https://ravinacademy.com/wp-content/uploads/2020/12/p.png)
![](https://ravinacademy.com/wp-content/uploads/2020/12/y.png)
$ clang++ -g -std=c++11 -fsanitize=address,fuzzer -fsanitize-coverage=trace-pc-guard nic.cpp Fuzzer/libFuzzer.a -o nic
سپس برنامه کامپایل شده را اجرا میکنیم.$ ./nic
در خروجی اجرایی این برنامه که در شکل زیر نمایش داده شده است میبینیم که یک crash رخ داده است.![](https://ravinacademy.com/wp-content/uploads/2020/12/u.png)
https://github.com/CloudAvid/PParam/issues/9
CVE ثبت شده برای این آسیبپذیری نیز از لینک زیر قابل مشاهده است:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28723
ارتباط با نویسندهی مقاله «رامین فرجپور»:![](https://ravinacademy.com/wp-content/uploads/2020/12/کد-برنامههای-متن-باز-با-استفاده-از-LibFuzzer-cta.jpeg)