فازینگ (Fuzzing) به عنوان یکی از پرکاربردترین تکنیکهای آزمون نرمافزار، با تولید تعداد زیادی ورودی آزمون (Test Input) میتواند طیف متنوعی از نقاط ضعف موجود در یک برنامه، از جمله باگهای نرمافزاری (Software Bugs) و آسیبپذیریها (Vulnerabilities) را شناسایی کند. به دلیل اثربخشی این روش، فازینگ به عنوان روشی ارزشمند برای کشف و شکار باگ (Bug Hunting) شناخته میشود. در این مقاله، ضمن ارائه مروری بر فازینگ که بر فرآیند کلی و دستهبندیهای آن متمرکز است، به بحثی مفصل درباره موانع کلیدی و برخی از فناوریهای پیشرفته و بهروز و وضعیت کنونی دانش و روشها (State-of-the-Art Technologies) میپردازیم که با هدف غلبه بر این موانع یا کاهش اثرات آنها ارائه شدهاند. علاوه بر این، تعدادی از ابزارهای فازینگ پرکاربرد را مورد بررسی و دستهبندی قرار میدهیم. هدف اصلی ما این است که درک بهتری از فازینگ و راهکارهای بالقوه برای بهبود روشهای فازینگ را در حوزه آزمون نرمافزار (Software Testing) و امنیت (Security) در اختیار ذینفعان قرار دهیم. همچنین، بهمنظور الهامبخشی به پژوهشهای آینده، برخی مسیرهای احتمالی و جهتگیریهای آتی پژوهش در زمینه فازینگ را پیشبینی و مطرح میکنیم.
واژههای کلیدی:
فازینگ، قابلیت اطمینان، امنیت، آزمون نرمافزار، مطالعه مروری.
۱. مقدمه
فازینگ (Fuzzing) که کوتاه شدهی عبارت آزمون فاز (Fuzz Testing) است، یک تکنیک آزمون خودکار میباشد که با استفاده از دادههای نامعتبر (Invalid Data) از جمله دادههای حاصل از فایلها، پروتکلهای شبکه، فراخوانیهای رابط برنامهنویسی کاربردی (Application Programming Interface یا API) و سایر اهداف به عنوان ورودی برنامه، تعداد زیادی از حالات مرزی (Boundary Cases) را پوشش میدهد تا از عدم وجود آسیبپذیریهای قابل بهرهبرداری (Exploitable Vulnerabilities) اطمینان حاصل شود [1]. فازینگ نخستین بار توسط Miller و همکاران [2] در سال ۱۹۸۸ مطرح شد و از آن زمان تاکنون، به روشی مؤثر، سریع و عملی برای شناسایی باگهای نرمافزاری تبدیل شده است [3– 5]. ایده اصلی فازینگ، تولید تعداد زیادی مورد آزمون (Test Case) و تغذیه برنامه هدف با این ورودیها، به این امید است که برخی از آنها بتوانند خطاهای نرمافزاری (Software Errors) را فعال کنند. خلاقانهترین بخش فازینگ، نحوه تولید موارد آزمون مناسب است و روشهای متداول امروزی در این زمینه شامل راهبردهای هدایت شده بر اساس پوشش (Coverage-Guided Strategies)، الگوریتمهای ژنتیک (Genetic Algorithms)، اجرای نمادین (Symbolic Execution)، تحلیل آلودگی (Taint Analysis) و سایر روشها میباشند.
بر اساس این روشها، تکنیکهای مدرن فازینگ از هوشمندی بالایی برای آشکارسازی باگهای پنهان برخوردارند. از این رو، فازینگ به عنوان یک روش آزمون منحصربهفرد که در آن موفقیت آزمون را میتوان بر اساس معیارهای معنادار کیفیت نرمافزار کمیسازی کرد، از جایگاه مهمی در دو بعد نظری و تجربی برخوردار است. فازینگ به عنوان معیاری برای مقایسه عمل میکند که سایر روشها باید در برابر آن ارزیابی شوند [6]. علاوه بر این، فازینگ بهتدریج به یک تکنیک ترکیبی (Synthesis Technique) تبدیل شده است که با ترکیب همافزایانه اطلاعات ایستا (Static) و پویا (Dynamic) مربوط به برنامه هدف، امکان تولید موارد آزمون بهتر و در نتیجه، شناسایی باگهای بیشتر را فراهم میکند [7].
فازینگ با ارسال مداوم موارد آزمون دارای ساختار نادرست (Malformed) یا نیمهمعتبر (Semi-Valid) به برنامه هدف، حملات را شبیهسازی میکند. به واسطه این ورودیهای نامتعارف، فازرها (Fuzzers) که از آنها با عنوان ابزارهای فازینگ (Fuzzing Tools) نیز یاد میشود، اغلب میتوانند آسیبپذیریهایی را شناسایی کنند که پیش از آن ناشناخته بودهاند [8 – 11]. این موضوع یکی از دلایل اصلی اهمیت فازینگ در آزمون نرمافزار (Software Testing) است.
بااینحال، عدم آگاهی از ساختار و رفتار برنامه (Blindness) در فرایند تولید موارد آزمون که میتواند به پوشش کد (Code Coverage) پایین منجر شود، مهمترین قیودی است که فازینگ همواره در تلاش برای غلبه بر آن بوده است. همانطور که پیشتر اشاره شد، روشهای مختلفی برای کاهش این مشکل به کار گرفته شدهاند و فازینگ در این زمینه پیشرفت چشمگیری داشته است. امروزه، فازینگ بهطور گسترده برای آزمون انواع مختلف نرمافزارها، از جمله کامپایلرها (Compilers)، برنامههای کاربردی (Applications)، پروتکلهای شبکه (Network Protocols)، هستهها (Kernels) و غیره، و همچنین در حوزههای کاربردی متعددی مورد استفاده قرار میگیرد؛ از جمله ارزیابی بازیابی از خطاهای نحوی (Syntax Error Recovery) [12] و مکانیابی خطا (Fault Localization) [13].
۱.۱ دلایل انجام پژوهش (Motivation)
دو دلیل اصلی ما را به نگارش این مطالعه مروری ترغیب کرده است: (۱) فازینگ به دلیل توانایی مؤثر آن در شناسایی باگها، در حوزههای امنیت و قابلیت اطمینان نرمافزار توجه روزافزونی را به خود جلب کرده است. بسیاری از شرکتهای حوزه فناوری اطلاعات، از جمله Google و Microsoft، در حال مطالعه تکنیکهای فازینگ و توسعه بیشتر ابزارهای فازینگ هستند؛ برای مثال، SAGE [14]، Syzkaller [15] و SunDew [16]، با هدف شناسایی باگها در برنامه هدف. (۲) طی چند سال گذشته، هیچ مطالعه مروری نظاممند درباره فازینگ ارائه نشده است. اگرچه برخی مقالات، مروری بر فازینگ ارائه کردهاند، این مطالعات معمولاً یا به مرور مقالات منتخب [1]، [17] پرداختهاند، یا مطالعات مروری درباره موضوعات خاصی در حوزه آزمون نرمافزار [18]،[19] ارائه دادهاند. ازاینرو، بر این باوریم که ارائه یک مطالعه مروری جامع برای جمعبندی جدیدترین روشها و دستاوردهای پژوهشی نوین در این حوزه ضروری است. بنابراین، هدف ما از نگارش این مقاله آن است که نه تنها پژوهشگران و افراد تازهوارد بتوانند درک کلی از فازینگ به دست آورند، بلکه متخصصان این حوزه نیز بتوانند مروری جامع و عمیق بر حوزه فازینگ داشته باشند.
۱.۲ ساختار مقاله (Outline)
ادامه این مقاله به شرح زیر سازماندهی شده است: بخش دوم به معرفی روششناسیِ مرورِ بهکاررفته در این پژوهش و همچنین ارائه خلاصهای مختصر و تحلیلی از برخی مقالات منتخب میپردازد. بخش سوم فرآیند کلی فازینگ را تشریح میکند. بخش چهارم به معرفی طبقهبندی روشهای فازینگ اختصاص دارد. بخش پنجم تکنیکهای پیشرفته فازینگ (fuzzing) را توصیف میکند. بخش ششم به معرفی چندین ابزار فازینگِ پرکاربرد میپردازد که بر اساس حوزههای کاربرد و دامنههای مسئله طبقهبندی شدهاند. در نتیجة این بررسی، شماری از چالشهای پژوهشی به عنوان مسیرهایی برای تحقیقات آتی در بخش هفتم شناسایی شدهاند. در نهایت، بخش هشتم به جمعبندی مقاله میپردازد.
۲. روش بررسی (REVIEW METHOD)
به منظور انجام یک مطالعه مروری جامع درباره فازینگ، از یک روش نظاممند و ساختاریافته بهره گرفتیم که با الهام از دستورالعملهای ارائه شده توسط Kitchenham [20] و Webster و Watson [21] تدوین شده است. در بخشهای بعدی، روشهای پژوهش، دادههای گردآوری شده و تحلیلهای انجام شده را به تفصیل تشریح خواهیم کرد.
۲.۱ پرسشهای پژوهشی (Research Questions)
هدف اصلی این مطالعه، پاسخگویی به پرسشهای پژوهشی زیر در زمینه «فازینگ» (fuzzing) است: پرسش پژوهشی اول (RQ1) که پاسخ آن در بخش پنجم ارائه میشود، به ما امکان میدهد تا دیدگاهی عمیق و جامع نسبت به فازینگ به دست آوریم و روند پیشرفت وضعیت کنونی دانش و روشها (State of the Art) در این حوزه را از زمان معرفی اولیه آن بررسی کنیم. پرسش پژوهشی دوم (RQ2) که در بخش ششم مورد بحث قرار میگیرد، با هدف ارائه بینشی درباره دامنه کاربرد فازینگ (Scope of Fuzzing) و میزان قابلیت بهکارگیری آن در حوزههای مختلف مطرح شده است. در نهایت، بر اساس پاسخهای بهدستآمده برای پرسشهای پیشین، انتظار داریم مسائل حل نشده و فرصتهای پژوهشی موجود را در پاسخ به پرسش پژوهشی سوم (RQ3) شناسایی کنیم؛ پاسخ این پرسش در بخش هفتم ارائه میشود.
۲.۲ معیارهای ورود و خروج (Inclusion and Exclusion Criteria)
ما متون موجود را بهدقت بررسی کردیم تا مقالات مرتبط با تمام جنبههای «فازینگ» (fuzzing) از جمله روشها، ابزارها، کاربردها در مسائل خاصِ آزمون، ارزیابیهای تجربی و مطالعات مروری را شناسایی کنیم. مقالاتی که توسط نویسندگان یکسان و با محتوای مشابه نوشته شده بودند، بهمنظور انجام تحلیلی دقیقتر، عمداً به عنوان آثار مجزا طبقهبندی و ارزیابی شدند. سپس، مقالاتی را که تفاوت عمدهای در نحوه ارائه نتایج نداشتند، در یک گروه قرار دادیم. ما مقالات را بر اساس معیارهای زیر کنار گذاشتیم:
- عدم ارتباط با حوزه علوم کامپیوتر؛
- عدم نگارش به زبان انگلیسی؛
- عدم انتشار توسط ناشر معتبر؛
- انتشار توسط ناشری معتبر اما با حجم کمتر از شش صفحه؛
- عدم دسترسی از طریق وب.
به عنوان مثال، با استفاده از رابط جستوجوی وبسایت Wiley InterScience و بهکارگیری کلیدواژههایی مانند fuzzing / fuzz testing / fuzzer، به ۳۲ مقاله دست یافتیم که بر اساس بررسی چکیده (Abstract) آنها، تنها هفت مورد از مرتبط با حوزه علوم کامپیوتر بودند.
۲.۳ منابع و راهبرد جستجو (Source Material and Search Strategy)
به منظور ارائه یک مطالعه مروری جامع که تمامی انتشارات مرتبط با فازینگ را پوشش دهد، ما مجموعهای از انتشارات حوزه فازینگ را جمعآوری کردیم.
جدول ۱. ناشران و تعداد مطالعات اولیه:
پایگاهی که شامل بیش از ۳۵۰ مقاله از ژانویه ۱۹۹۰ تا ژوئن ۲۰۱۷ است، طی سه مرحله گردآوری شد. نخست، ما در برخی از پایگاه آنلاین اصلی مانند (IEEE XPlore، ACM Digital Library، Springer Online Library، Wiley InterScience،USENIX و (Elsevier ScienceDirect Online Library جستجو کردیم و مقالاتی را که واژگان کلیدی «fuzz testing»، «fuzzing»، «fuzzer»،«testing » یا «swarm testing» در عنوان، چکیده یا کلمات کلیدی آنها وجود داشت، گردآوری نمودیم. دوم، از چکیده مقالات گردآوریشده برای حذف برخی از آنها بر اساس معیارهای انتخاب خود استفاده کردیم. در مواردی که تصمیمگیری بر اساس چکیده امکانپذیر نبود، متن کامل مقاله را مطالعه کردیم. این مرحله توسط دو نویسنده مختلف انجام شد. مجموعهمقالات کاندیدا به ۱۷۱ مورد که در حیطه پژوهش ما قرار داشتند، تقلیل یافت. از این مقالات با عنوان «مطالعات اولیه» [20] یاد میشود. جدول ۱ تعداد مطالعات اولیه استخراجشده از هر منبع را نشان میدهد. همچنان ممکن است جستجوی ما تمام مقالات مرتبط را به طور کامل پوشش نداده باشد، زیرا تمرکز ما بر زیرمجموعهای از ناشران معتبر بوده است. بااینحال، اطمینان داریم که روندهای کلی ارائهشده در این مقاله دقیق هستند و تصویری منصفانه از وضعیت کنونی دانش در حوزه فازینگ (fuzzing) ارائه میدهند.
۲.۴ خلاصه نتایج (Summary of Results)
در بخشهای بعدی، مطالعات اولیه خود را از جنبههای مختلف، شامل روند انتشار مقالات، محلهای انتشار (Venues)، نویسندگان و توزیع جغرافیایی پژوهشها در حوزه فازینگ، خلاصه و بررسی میکنیم.
۱) روند انتشار مقالات (Publication Trends): شکل (a)1 تعداد مقالات منتشر شده در حوزه فازینگ (Fuzzing) را در بازه زمانی ژانویه ۱۹۹۰ تا ۳۰ ژوئن ۲۰۱۷ نشان میدهد. نمودار بیانگر آن است که تعداد مقالات این حوزه از سال ۲۰۰۴ بهطور پیوسته افزایش یافته است؛ این افزایش به ویژه پس از سال ۲۰۰۹ چشمگیرتر بوده است. تعداد تجمعی (Cumulative) مقالات منتشر شده در شکل1(b) نشان داده شده است. با برازش (close fit) یک تابع درجه دوم به دادهها، مقدار بالایی برای ضریب تعیین (R² = 0.992) به دست آمد. این مقدار نشاندهنده رشد چندجملهای (Polynomial Growth) بسیار قوی در تعداد انتشارات است و بیانگر تداوم پویایی، سلامت و علاقه پژوهشی به این حوزه میباشد. چنانچه این روند ادامه پیدا کند، پیشبینی میشود که تا پایان سال ۲۰۱۸، تعداد مقالات مرتبط با فازینگ که توسط ناشران معتبر منتشر شدهاند، از ۲۰۰ مقاله فراتر رود؛ یعنی تقریباً سه دهه پس از معرفی اولیه این تکنیک.
۲) محل انتشار مقالات (Publication Venues): تعداد ۱۷۱ مطالعه اولیه (Primary Studies) در ۷۸ محل انتشار (Publication Venue) متمایز منتشر شدهاند. این موضوع نشان میدهد که حوزههای تحت پوشش پژوهشهای فازینگ بسیار گسترده و متنوع میباشند. احتمالاً دلیل این گستردگی آن است که فازینگ یک تکنیک بسیار کاربردی محسوب میشود و در حوزههای متعددی از جمله آزمون نرمافزار (Software Testing)، قابلیت اطمینان (Reliability) و امنیت (Security) به کار گرفته شده است. از نظر نوع محل انتشار (Type of Venue)، بیشترین تعداد مقالات در کنفرانسها و سمپوزیومها ارائه شدهاند (۷۳٪). پس از آن، مجلات علمی (Journals) با ٪۱۵، کارگاهها (Workshops) با ٪۹ و گزارشهای فنی (Technical Reports) با ٪۳ قرار دارند. جدول ۲ محلهای انتشاری را فهرست میکند که در هر یک، حداقل سه مقاله در زمینه فازینگ ارائه یا منتشر شده است.
شکل ۲. برترین مجامع علمی در حوزه فازینگ:
۳) توزیع جغرافیایی مقالات (Geographical Distribution of Publications): ما خاستگاه جغرافیایی هر یک از مطالعات اولیه را بر اساس کشور محل وابستگی سازمانی (Affiliation) نخستین نویسنده همکار (First Coauthor) تعیین کردیم. جالب توجه است که دریافتیم هر ۱۷۱ مطالعه اولیه متعلق به ۲۲ کشور مختلف بودهاند. همانطور که در جدول ۳ نشان داده شده است، ایالات متحده آمریکا، چین و آلمان سه کشور نخست از نظر تعداد مطالعات منتشرشده هستند. (در این جدول، تنها کشورهایی با بیش از چهار مقاله نمایش داده شدهاند). از نظر توزیع قارهای، ٪۴۳ از مقالات منشأ گرفته از قاره آمریکا، ٪۳۲ از اروپا، ٪۲۰ از آسیا و ٪۵ از اقیانوسیه هستند. این یافته نشان میدهد که جامعه پژوهشی فازینگ (Fuzzing Community) اگرچه از تعداد نسبتاً محدودی از کشورها تشکیل شده است، اما از نظر جغرافیایی توزیع نسبتاً متوازنی در سراسر جهان دارد.
جدول ۳. توزیع جغرافیایی نشریات حوزه فازینگ:
جدول ۴. ده نویسنده برتر در زمینه فازینگ:
۴) پژوهشگران و سازمانها (Researchers and Organizations): در ۱۷۱ مطالعه اولیه مورد بررسی، در مجموع ۱۲۵ نویسنده همکار متمایز شناسایی کردیم. جدول ۴ پژوهشگران برجسته در حوزه فازینگ (Fuzzing) و همچنین جدیدترین وابستگی سازمانی (Most Recent Affiliation) آنها را ارائه میکند.
۳. فرایند کلی فازینگ (GENERAL PROCESS OF FUZZING)
فازینگ یک تکنیک تست نرمافزار است که میتواند به طور خودکار موارد آزمون (test cases) تولید کند. بدین ترتیب، ما این موارد آزمون را روی برنامه هدف اجرا میکنیم و سپس رفتار متناظر برنامه را مشاهده میکنیم تا مشخص شود که آیا باگ یا آسیبپذیری در برنامه هدف وجود دارد یا خیر. فرایند کلی فازینگ در شکل ۲ نشان داده شده است.
برنامه هدف (Target Program): برنامه هدف، همان برنامهای است که تحت آزمون قرار میگیرد (Program Under Test). این برنامه میتواند به صورت کد باینری (Binary Code) یا کد منبع (Source Code) باشد. با این حال، معمولاً دسترسی به کد منبع نرمافزارهای دنیای واقعی بهآسانی امکانپذیر نیست؛ ازاینرو، فازرها اغلب کد باینری را به عنوان هدف آزمون قرار میدهند.
مانیتور (Monitor): این مؤلفه معمولاً در ساختار فازرهای جعبهسفید (White-box Fuzzer) یا جعبهخاکستری (Gray-box Fuzzer) تعبیه میشود. مانیتور با بهرهگیری از تکنیکهایی مانند ابزارگذاری کد (Code Instrumentation)، تحلیل آلودگی (Taint Analysis) و سایر روشهای مشابه، اطلاعات مفید زمان اجرا (Runtime Information) را از برنامه هدف استخراج میکند؛ از جمله پوشش کد (Code Coverage)، جریان دادههای آلوده (Taint Data Flow) و دیگر اطلاعات مرتبط با اجرای برنامه. وجود مانیتور در فازرهای جعبه سیاه (Black-box Fuzzer) ضروری نیست.
مولد موارد آزمون (Test Case Generator): فازرها برای تولید موارد آزمون (Test Cases) عمدتاً از دو روش اصلی استفاده میکنند: روش مبتنی بر جهش (Mutation-based) و روش مبتنی بر دستور زبان (Grammar-based) [1]. در روش نخست، ورودیهای آزمون با اعمال جهشهای تصادفی روی فایلهای بذر (Seed) معتبر و دارای قالب صحیح (Well-formed Seed Files) تولید میشوند، یا با استفاده از راهبردهای جهش از پیش تعریف شده (Predefined Mutation Strategies) ایجاد میگردند. این راهبردهای جهش میتوانند بر اساس اطلاعات مرتبط با برنامه هدف که در زمان اجرا (Runtime) جمعآوری میشوند، تنظیم و بهینه شوند. در مقابل، روش دوم به فایل فایلهای بذر (Seed) نیاز ندارد؛ بلکه ورودیها را بر اساس یک مشخصه (Specification)، مانند دستور زبان (Grammar)، تولید میکند. در بسیاری از موارد، موارد آزمون (test cases) در فازینگ بهصورت ورودیهای نیمهمعتبر (Semi-valid Inputs) هستند؛ به این معنا که ورودی به اندازهای معتبر است که بتواند از مراحل ابتدایی تجزیه (Parsing) عبور کند، اما به اندازهای نامعتبر است که بتواند در منطق عمیق برنامه هدف (Deep Logic) موجب فعالسازی و آشکارشدن باگها (Bugs) شود.
آشکارساز باگ (Bug Detector): به منظور کمک به کاربران در شناسایی باگهای بالقوه در برنامه هدف، یک مؤلفه آشکارساز باگ (Bug Detector Module) در فازر طراحی و پیادهسازی میشود. هنگامی که برنامه هدف کرش (Crash) میکند یا خطایی را گزارش میدهد، ماژول آشکارساز باگ، اطلاعات مرتبط، مانند Stack Traceها (رهگیری پشته) [22]، را جمعآوری و تحلیل میکند تا مشخص شود آیا باگی وجود دارد یا خیر. در برخی موارد، میتوان به صورت دستی از یک اشکالزدا (Debugger) برای ثبت اطلاعات مربوط به استثنا (Exception Information) [23]–[25] استفاده کرد و آن را به عنوان جایگزینی برای این ماژول به کار برد.
فیلتر باگ (Bug Filter): آزمایشکنندگان معمولاً بر باگهای مرتبط با درستی عملکرد (Correctness) یا امنیت (Security) تمرکز دارند. ازاینرو، تفکیک باگهای قابل بهرهبرداری (Exploitable Bugs)، یعنی آسیبپذیریها (Vulnerabilities)، از میان تمام باگهای گزارش شده، یک وظیفه مهم محسوب میشود که معمولاً بهصورت دستی انجام میگیرد [23]. این فرایند نهتنها زمانبر است، بلکه انجام آن نیز دشوار است. در حال حاضر، برخی پژوهشها [26] رویکردهای مختلفی را برای کاهش این مشکل پیشنهاد کردهاند. برای مثال، با مرتبسازی خروجیهای فازر (Fuzzer Outputs)، یعنی موارد آزمونی که موجب ایجاد باگ میشوند (Bug-inducing Test Cases)، موارد آزمون متنوع و جالبتوجه در اولویت قرار میگیرند. در نتیجه، آزمایشکنندگان دیگر نیازی ندارند باگهای موردنظر خود را بهصورت دستی جستوجو کنند؛ فرایندی که میتوان آن را به «جستوجوی یک سوزن در انبار کاه» تشبیه کرد. به منظور تشریح روشنتر فرایند فازینگ (Fuzzing)، در این مثال از (American Fuzzy Lop) AFL [27]، که یک فازر مبتنی بر جهش و هدایت شده با پوشش (Mutation-based Coverage-guided Fuzzer) است، برای آزمون برنامه png2swf، یعنی یک مبدل فایل (File Converter)، استفاده میکنیم. در این مثال، فایل اجرایی png2swf را به عنوان برنامه هدف (Target Program) در اختیار AFL قرار میدهیم. نخست، از آنجا که AFL از تکنیک مبتنی بر جهش (Mutation-based) استفاده میکند، چند فایل بذر (Seed) را در اختیار AFL قرار میدهیم. بذرهای (Seed) ایدهآل باید دارای قالب صحیح (Well-formed) و کمحجم باشند. دوم، AFL را با یک دستور ساده اجرا میکنیم؛ برای مثال:
afl-fuzz -i [input_directory] -o [output_directory] -Q -- [target_directory] (@@)
چنانچه برنامه هدف ورودی خود را از یک فایل دریافت کند، استفاده از @@ ضروری است. در این حالت، AFL محل @@ را با مسیر فایل ورودی تولید شده جایگزین کرده و آن فایل را به برنامه هدف ارائه میدهد. در طول فرایند آزمون، مؤلفه «مانیتور (Monitor)» در AFL با استفاده از ابزارگذاری باینری (Binary Instrumentation)، اطلاعات خاصی از زمان اجرای برنامه، یعنی در این مثال اطلاعات پوشش مسیر (Path Coverage Information)، را جمعآوری میکند و سپس این اطلاعات را به مؤلفه «مولد موارد آزمون (Test Case Generator)» منتقل میکند تا در هدایت فرایند تولید موارد آزمون مورد استفاده قرار گیرند. راهبرد کلی AFL این است که آن دسته از موارد آزمون را که قادر به پوشش مسیرهای جدید برنامه هستند، برای دور بعدی جهش (Mutation) حفظ کند و سایر موارد را کنار بگذارد.
سوم، موارد آزمون جدید تولید شده مجدداً به مؤلفه «مانیتور» بازگردانده میشوند تا به عنوان ورودیهای برنامه هدف مورد استفاده قرار گیرند. این فرایند به صورت تکرارشونده ادامه پیدا میکند تا زمانی که اجرای نمونه AFL را متوقف کنیم یا محدودیت زمانی تعیینشده فرا برسد. علاوه بر این، AFL در طول زمان اجرا اطلاعات مفیدی را نیز روی صفحه نمایش میدهد؛ از جمله زمان اجرای فازینگ (Execution Time)، تعداد کرشهای یکتا (Unique Crashes)، سرعت اجرای آزمون (Execution Speed) و موارد دیگر. بنابراین، در پایان میتوانیم مجموعهای از موارد آزمونی که قادر به ایجاد کرش در برنامه هدف هستند به دست آوریم.
در نهایت، این موارد آزمون را تحلیل کرده و با بررسی دستی یا با کمک ابزارهای دیگر، باگهای موجود در آنها را شناسایی میکنیم؛ بهویژه باگهایی که موجب کرش برنامه هدف میشوند. باگهایی که AFL عمدتاً قادر به کشف آنهاست، بیشتر به عملیات مرتبط با حافظه (Memory Operations) مربوط میشوند؛ برای مثال سرریز بافر (Buffer Overflow)، نقض دسترسی (Access Violation) و تخریب/درهمریختگی پشته (Stack Smash / Stack Corruption). این نوع باگها معمولاً موجب کرش (Crash) برنامه میشوند یا در برخی شرایط میتوانند توسط مهاجمان (Attackers) مورد سوءاستفاده قرار گیرند.
۴. سیاه، سفید یا خاکستری؟ (BLACK, WHITE, OR GRAY)
تکنیکهای فازینگ (Fuzzing) را میتوان بر اساس میزان اطلاعاتی که در زمان اجرا (Runtime) از برنامه هدف دریافت و استفاده میکنند، به سه دسته تقسیم کرد [28]: (۱) فازینگ جعبهسیاه (Black-box Fuzzing) (۲) فازینگ جعبهسفید (White-box Fuzzing) و (۳) فازینگ جعبهخاکستری (Gray-box Fuzzing). این اطلاعات میتوانند شامل پوشش کد (Code Coverage)، پوشش جریان داده (Data-flow Coverage)، میزان مصرف حافظه برنامه (Program Memory Usage)، میزان استفاده از CPU (CPU Utilization) یا هر نوع اطلاعات دیگری باشند که برای هدایت فرایند تولید مورد آزمون (Test Case Generation) مورد استفاده قرار میگیرند.
۴.۱ فازینگ جعبه سیاه (Black-Box Fuzzing)
فازینگ سنتی جعبهسیاه (Traditional Black-box Fuzzing) با عنوان «آزمون تصادفی جعبهسیاه (Black-box Random Testing)» نیز شناخته میشود. در این روش، برخلاف رویکردهایی که به اطلاعاتی از برنامه هدف یا قالب ورودی (Input Format) نیاز دارند، آزمون تصادفی جعبهسیاه از مجموعهای از قواعد از پیش تعریف شده (Predefined Rules) استفاده میکند تا فایلهای بذر (Seed) دارای قالب صحیح (Well-formed Seed File) را به صورت تصادفی جهش (Mutation) داده و ورودیهای مخدوش (Malformed Inputs) ایجاد کند. قواعد جهش میتوانند شامل عملیاتی مانند وارونسازی بیت (Bit Flips)، کپیکردن بایتها (Byte Copies) یا حذف بایتها (Byte Removals) [28] و موارد مشابه باشند. در فازینگ جعبهسیاه مدرن، علاوه بر این روشها، از دستور زبان (Grammar) [29] یا دانش اختصاصی مربوط به ورودی (Input-specific Knowledge) [30] نیز برای تولید ورودیهای نیمهمعتبر (Semivalid Inputs) استفاده میشود. فازرهای جعبهسیاه (Black-box Fuzzers)، مانند fuzz [31] و Trinity [32]، به دلیل اثربخشی در کشف باگها و همچنین سادگی استفاده، در صنعت نرمافزار از محبوبیت بالایی برخوردارند. به عنوان مثال، Trinity با هدف فازینگ رابطهای فراخوانی سیستمی (System Call Interfaces) در هسته لینوکس (Linux Kernel) طراحی شده است. آزمایشکنندگان ابتدا باید نوع ورودی را با استفاده از الگوهای از پیش ارائه شده (Provided Templates) توصیف کنند.
سپس Trinity میتواند ورودیهای معتبر بیشتری تولید کند که در نتیجه، امکان دستیابی به پوشش بالاتر (Higher Coverage) را فراهم میکنند. این فازر تاکنون توانسته است باگهای متعددی را کشف کند. با اینحال، نقطه ضعف این تکنیک نیز کاملاً آشکار است. تابع نشان داده شده در شکل ۳ را در نظر بگیرید. اگر پارامتر ورودی در خط ۱ به صورت تصادفی مقداردهی شود، احتمال رسیدن به تابع ()abort در خط ۷ تنها 1/232 است. این مثال بهصورت شهودی نشان میدهد که چرا فازینگ جعبهسیاه در تولید موارد آزمونی که بتوانند تعداد زیادی از مسیرهای اجرای برنامه هدف را پوشش دهند، با دشواری مواجه است. به دلیل همین ماهیت کور و عدم آگاهی از ساختار و رفتار برنامه (Blindness Nature)، فازینگ جعبهسیاه در عمل اغلب پوشش کد پایینی (Low Code Coverage) ارائه میدهد [33].
به همین دلیل، توسعهدهندگان فازر در سالهای اخیر عمدتاً بر تکنیکهایی مانند مهندسی معکوس (Reverse Engineering) [34]، ابزارگذاری کد (Code Instrumentation) [35]، تحلیل جریان داده آلوده (Taint Analysis) [23]، [36]، [37] و سایر تکنیکها تمرکز کردهاند تا فازر را «هوشمندتر» کنند و این مشکل را کاهش دهند. همین مسئله یکی از دلایلی است که باعث شده فازینگ جعبهسفید (White-box Fuzzing) و فازینگ جعبهخاکستری (Gray-box Fuzzing) در سالهای اخیر توجه بیشتری را به خود جلب کنند.
۴.۲ فازینگ جعبه سفید (White-Box Fuzzing)
فازینگ جعبهسفید (White-Box Fuzzing) بر اساس آگاهی از منطق داخلی برنامه هدف (Internal Logic of the Target Program) [17] عمل میکند. این روش از تکنیکی استفاده میکند که در تئوری میتواند تمامی مسیرهای اجرای برنامه هدف را مورد کاوش قرار دهد. این رویکرد نخستینبار توسط Godefroid و همکاران [38] مطرح شد. آنها با هدف غلبه بر ماهیت کورکورانه و عدم آگاهی از ساختار و رفتار برنامه فازینگ جعبهسیاه، به دنبال یافتن یک روش جایگزین بودند و آن را فازینگ جعبهسفید (White-box Fuzzing) نامیدند [14]. فازینگ جعبهسفید با استفاده از اجرای نمادین پویا (Dynamic Symbolic Execution)، که با عنوان اجرای کانکولیک (Concolic Execution) [39] نیز شناخته میشود، و همچنین یک الگوریتم جستوجوی ابتکاری با هدف بیشینهسازی پوشش (Coverage-maximizing Heuristic Search Algorithm)، میتواند فضای اجرای برنامه هدف را بهصورت جامع و با سرعت بالا کاوش کند.
برخلاف فازینگ جعبهسیاه (Black-box Fuzzing)، فازینگ جعبهسفید به اطلاعاتی از برنامه هدف نیاز دارد و از این اطلاعات برای هدایت فرایند تولید موارد آزمون (Test Case Generation) استفاده میکند. به طور مشخص، اجرای برنامه با یک ورودی مشخص و عینی (Concrete Input) آغاز میشود. سپس فازر جعبهسفید، در طول مسیر اجرای طی شده توسط این ورودی، در تمامی دستورات شرطی (Conditional Statements)، قیود نمادین (Symbolic Constraints) را جمعآوری میکند. بنابراین، پس از یک بار اجرای برنامه، فازر جعبهسفید تمام قیود نمادین بهدستآمده را با استفاده از عملگر منطقی AND با یکدیگر ترکیب میکند تا یک قید مسیر (Path Constraint یا بهاختصار PC) تشکیل دهد.
در مرحله بعد، فازر جعبهسفید بهصورت نظاممند یکی از قیود موجود در PC را نقض (Negate) کرده و قید مسیر جدید را حل میکند. در نتیجه، مورد آزمون جدید تولید شده باعث میشود برنامه در یک مسیر اجرای متفاوت اجرا شود. با استفاده از یک الگوریتم جستوجوی ابتکاری با هدف بیشینهسازی پوشش (Coverage-maximizing Heuristic Search Algorithm)، فازرهای جعبهسفید میتوانند با بیشترین سرعت ممکن به کاوش برنامه هدف پرداخته و باگهای موجود در آن را کشف کنند [38].
فازینگ جعبهسفید (White-box Fuzzing) در تئوری، میتواند موارد آزمونی تولید کند که تمام مسیرهای برنامه را پوشش دهند. بااینحال، در عمل، به دلیل مشکلات متعددی از جمله تعداد بسیار زیاد مسیرهای اجرا در سیستمهای نرمافزاری واقعی و همچنین عدم دقت در حل قیود طی اجرای نمادین (Symbolic Execution) (برای جزئیات بیشتر به بخش V-B مراجعه کنید)، پوشش کد حاصل از فازینگ جعبهسفید نمیتواند به ۱۰۰٪ برسد. یکی از مشهورترین فازرهای جعبهسفید، SAGE [14] است. SAGE، برنامههای ویندوزی در مقیاس بزرگ (Large-scale Windows Applications) را هدف قرار میدهد و برای مقابله با حجم بسیار زیاد Traceهای اجرایی (Execution Traces)، از چندین بهینهسازی (Optimization) استفاده میکند. این فازر قادر است باگهای نرمافزاری را به صورت خودکار شناسایی کند و نتایج چشمگیری در این زمینه به دست آورده است.
۴.۳ فازینگ جعبه خاکستری (Gray-Box Fuzzing)
روش دیگری که در فازینگ جعبهخاکستری مورد استفاده قرار میگیرد، تحلیل آلودگی (Taint Analysis) [23]، [43]–[45] است. این روش، قابلیتهای ابزارگذاری کد را برای ردیابی جریان دادههای آلوده (Taint Data Flow) گسترش میدهد. در نتیجه، فازر میتواند بر جهش دادن فیلدهای خاصی از ورودی تمرکز کند؛ فیلدهایی که میتوانند بر نقاط بالقوه حمله (Potential Attack Points) در برنامه هدف تأثیر بگذارند. فازینگ جعبهخاکستری و فازینگ جعبهسفید از این نظر شباهت زیادی به یکدیگر دارند که هر دو از اطلاعات مربوط به برنامه هدف برای هدایت فرایند تولید موارد آزمون استفاده میکنند. بااینحال، تفاوت آشکاری نیز میان این دو وجود دارد:
فازینگ جعبهخاکستری تنها از بخشی از اطلاعات زمان اجرای برنامه هدف، مانند پوشش کد (Code Coverage)، جریان داده آلوده (Taint Data Flow) و موارد مشابه، استفاده میکند تا مشخص کند کدام مسیرهای برنامه تاکنون کاوش شدهاند [28]. همچنین، فازینگ جعبهخاکستری صرفاً از اطلاعات بهدستآمده برای هدایت تولید موارد آزمون استفاده میکند و نمیتواند تضمین کند که استفاده از این اطلاعات الزاماً به تولید موارد آزمون بهتر برای پوشش مسیرهای جدید یا تحریک باگهای خاص منجر خواهد شد.
در مقابل، فازینگ جعبهسفید از کد منبع یا کد باینری برنامه هدف استفاده میکند تا به صورت نظاممند تمام مسیرهای اجرای برنامه را کاوش کند. فازینگ جعبهسفید با استفاده از اجرای کانکولیک (Concolic Execution) و یک حلکننده قیود (Constraint Solver) میتواند تضمین کند که موارد آزمون تولید شده، برنامه هدف را به سمت مسیرهای اجرای جدید هدایت خواهند کرد. ازاینرو، فازینگ جعبهسفید میتواند عدم آگاهی از ساختار و رفتار برنامه (Blindness) موجود در فرایند فازینگ را بهشکل جامعتری کاهش دهد.
BuzzFuzz [46] نمونه مناسبی برای تشریح نحوه عملکرد یک فازر جعبهخاکستری (Gray-box Fuzzer) است؛ هرچند توسعهدهندگان BuzzFuzz آن را یک فازر جعبهسفید (White-box Fuzzer) معرفی کردهاند. ما این ابزار را یک فازر جعبهخاکستری در نظر میگیریم، زیرا تنها دانش جزئی از برنامه هدف، یعنی جریان داده آلوده (Taint Data Flow)، را به دست میآورد. BuzzFuzz بهصورت زیر عمل میکند:
نخست، برنامه هدف را ابزارگذاری (Instrument) میکند تا بتواند دادههای ورودی معتبر و آلوده شده (Tainted Well-formed Input Data) را ردیابی کند. سپس، بر اساس اطلاعات جمعآوری شده درباره انتشار آلودگی (Taint Propagation)، مشخص میکند کدام بخش از دادههای ورودی میتواند بر نقاط حمله ازپیشتعریف شده (Predefined Attack Points) در برنامه هدف تأثیر بگذارد. BuzzFuzz، فراخوانیهای کتابخانه (Library Calls / Lib Calls) را بهعنوان نقاط حمله بالقوه در نظر میگیرد. در مرحله بعد، بخشهای حساس دادههای ورودی را جهش (Mutation) میدهد تا موارد آزمون (Test Cases) جدید ایجاد شوند. در نهایت، موارد آزمون جدید اجرا شده و بررسی میشود که آیا برنامه هدف کرش (Crash) میکند یا خیر. به این ترتیب، BuzzFuzz میتواند با رویکردی هدفمحورتر (Target-oriented) و اثربخشتر (Effective)، باگهای موجود در برنامه را شناسایی کند. مهمتر از آن، نقاط حمله (Attack Points) میتوانند بسته به هدف و نگرانی توسعهدهنده، به شکلهای مختلفی تعریف شوند؛ برای مثال، میتوان آنها را بهصورت فراخوانیهای مختص کتابخانه (Specific Lib Calls) یا الگوهای آسیبپذیری (Vulnerability Patterns) و موارد مشابه تعریف کرد.
۴.۴ چگونه انتخاب کنیم؟ (How to Choose)
بر اساس احتمال فعالسازی (trigger) یا کشف باگها، میتوان آنها را به دو دسته تقسیم کرد: «باگهای سطحی (Shallow Bugs) و باگهای پنهان (Hidden Bugs)». باگهایی که موجب کرش برنامه هدف در مراحل اولیه اجرای برنامه میشوند، باگهای سطحی در نظر گرفته میشوند؛ به عنوان مثال، یک عملیات بالقوه تقسیم بر صفر (Potential Divide-by-zero Operation) که هیچ شاخه شرطی قبلی (Precedent Conditional Branch) نداشته باشد. در مقابل، باگهایی که در لایههای عمیق منطق برنامه وجود دارند و فعالسازی آنها دشوار است، باگهای پنهان محسوب میشوند؛ برای مثال، باگهایی که درون شاخههای شرطی پیچیده (Complex Conditional Branches) قرار دارند. روش استانداردی برای تشخیص دقیق «باگهای سطحی» و «باگهای پنهان» وجود ندارد؛ بنابراین، معیارهای رایج برای ارزیابی عملکرد یک فازر (Fuzzer) عبارتاند از (۱) میزان پوشش کد (Code Coverage) حاصل شده؛ (۲) تعداد باگهای کشف شده و قابلیت بهرهبرداری از باگهای کشف شده (Exploitability).
بهطور کلی، یک فازر سنتی جعبهسیاه که صرفاً از روش جهش تصادفی (Random Mutation) برای تولید موارد آزمون استفاده میکند، نمیتواند به پوشش کد بالایی دست یابد و در نتیجه معمولاً باگهای سطحی را کشف میکند. بااینحال، این نوع فازر سبک (Lightweight)، سریع و ساده برای استفاده است. در مقابل، فازرهای جعبهسفید یا جعبهخاکستری میتوانند به پوشش کد بالاتری دست یابند و معمولاً در مقایسه با فازرهای جعبهسیاه، باگهای پنهان بیشتری را کشف میکنند. بااینحال، ساخت و پیادهسازی این فازرها پیچیدهتر است و فرایند فازینگ آنها نیز در مقایسه با فازرهای جعبهسیاه زمانبرتر است. تکنیکهای فازینگ که تنها از روشهای ساده جهش (Mutation) استفاده میکنند، معمولاً « فازینگ احمقانه» یا «Dumb Fuzzing» نامیده میشوند. نمونه مشهور آن، روش «۵ خط کد پایتون» است که توسطCharlie Miller استفاده شده است. این روش بدون داشتن هیچ اطلاعی از قالب یا ساختار ورودی (Input Format)، صرفاً برخی از بایتهای یک فایل ورودی را بهصورت تصادفی جهش میدهد.
در مقابل، تکنیکهایی که از مشخصات ورودی (Input Specification) یا سایر اطلاعات مرتبط استفاده میکنند، یا با بهرهگیری از اطلاعات زمان اجرا (Runtime Information)، مانند پوشش مسیر (Path Coverage)، فرایند تولید موارد آزمون (Test Case Generation) را هدایت میکنند، معمولاً «فازینگ هوشمند» یا «Smart Fuzzing» در نظر گرفته میشوند. بهطور کلی، روشهای «احمقانه» و «هوشمند» فازینگ دارای موازنههای متفاوت میان هزینه و دقت (Cost/Precision Trade-offs) هستند و هر یک برای شرایط و سناریوهای متفاوتی مناسب میباشند. انتخاب نوع فازر برای آزمایشکنندگان، عمدتاً به دو عامل بستگی دارد:
۱) نوع برنامه هدف و ۲) الزامات آزمون، مانند زمان، هزینه و سایر محدودیتها. چنانچه قالب ورودی (Input Format) برنامه هدف، برای مثال کامپایلر (Compiler)، فراخوانیهای سیستمی (System Calls) یا پروتکل شبکه (Network Protocol)، مشخص یا سختگیرانه باشد، انتخاب یک فازر مبتنی بر دستور زبان (Grammar-based Fuzzer) معمولاً اثربخشی بیشتری خواهد داشت. بسیاری از فازرهای این دسته، جعبهسیاه هستند؛ مانند Trinity [32]. با این حال، در سالهای اخیر فازرهای جعبهخاکستری نیز برای هدفگیری این نوع نرمافزارها توسعه یافتهاند؛ برای مثال Syzkaller [15]. در سایر موارد، آزمایشکنندگان باید توجه بیشتری به الزامات آزمون داشته باشند. اگر هدف اصلی آزمون، کارایی و سرعت (Efficiency) باشد و نه دقت (Precision) یا کیفیت بالای خروجی، فازینگ جعبهسیاه میتواند انتخاب مناسبی باشد. برای مثال، اگر یک سیستم نرمافزاری تاکنون مورد آزمون قرار نگرفته باشد و آزمایشکنندگان بخواهند باگهای سطحی (Shallow Bugs) را در سریعترین زمان ممکن شناسایی و برطرف کنند، فازینگ جعبهسیاه میتواند نقطه آغاز مناسبی باشد. در مقابل، اگر آزمایشکنندگان بیشتر بر کیفیت خروجی، یعنی تنوع، قابلیت بهرهبرداری (Exploitability) و تعداد باگهای کشف شده، متمرکز باشند و بخواهند به پوشش کد بالاتری دست یابند، معمولاً فازینگ جعبهخاکستری و در برخی موارد فازینگ جعبهسفید گزینه مناسبتری است [14]. فازینگ جعبهسفید در مقایسه با فازینگ جعبهخاکستری، در صنعت چندان عملی و رایج نیست (هرچند SAGE یک فازر جعبهسفید مشهور و شناخته شده در این حوزه است). دلیل اصلی این مسئله آن است که این تکنیک هزینه بسیار بالایی دارد و از نظر زمان و منابع محاسباتی پرمصرف است. علاوه بر این، فازینگ جعبه سفید با چالشهای متعددی مواجه است؛ از جمله انفجار مسیرها (Path Explosion)، مدلسازی حافظه (Memory Modeling)، حل قیود (Constraint Solving) و سایر چالشهای مرتبط. با این حال، فازینگ جعبهسفید همچنان یکی از حوزههای پژوهشی پرطرفدار و دارای ظرفیت و پتانسیل بالا محسوب میشود.
۵. مروری بر وضعیت کنونی دانش و روشهای پیشرفته فازینگ (TATE OF THE ART IN FUZZING)
بر اساس فرایند کلی فازینگ که در بخش ۳ تشریح شد، هنگام طراحی و ساخت یک فازر (Fuzzer) باید پرسشهای زیر مورد توجه قرار گیرند:
- چگونه میتوان بذرها (Seed) و سایر موارد آزمون (Test Cases) را تولید یا انتخاب کرد؟
- چگونه میتوان این ورودیها را در برابر مشخصات برنامه هدف (Specification of the Target Program) اعتبارسنجی کرد؟
- با موارد آزمونی که موجب کرش کردن (Crash) برنامه میشوند چگونه باید برخورد کرد؟
- چگونه میتوان از اطلاعات زمان اجرا (Runtime Information) بهره گرفت؟
- چگونه میتوان مقیاسپذیری فازینگ (Scalability of Fuzzing) را بهبود بخشید؟
در این بخش، با مرور و جمعبندی مهمترین دستاوردهای پژوهشی در پنج مسئله فوق، به پرسش پژوهشی اول (RQ1) پاسخ میدهیم. بهطور مشخص، مقالات مرتبط با تولید و انتخاب بذر (Seed) را در بخش 5.1، اعتبارسنجی ورودی و پوشش (Input Validation and Coverage) را در بخش V-B؛ اطلاعات زمان اجرا و اثربخشی (Runtime Information and Effectiveness) را در بخش 5.3؛ مدیریت موارد آزمون ایجاد کننده کرش (Crash-inducing Test Cases Handling) را در بخش 5.4 و مقیاسپذیری در فازینگ (Scalability in Fuzzing) را در بخش 5.6 مورد بررسی قرار میدهیم.
۵.۱ تولید و انتخاب بذر (Seeds Generation and Selection)
هنگامی که یک برنامه هدف برای فازینگ در اختیار داریم، آزمایشکننده ابتدا باید رابط ورودی (Input Interface) برنامه، مانند فایل stdin را شناسایی کند تا مشخص شود برنامه هدف چگونه میتواند ورودی را از یک فایل دریافت کند. سپس باید قالبهای فایلی (File Formats) قابلپذیرش توسط برنامه هدف را تعیین کرده و در نهایت، از میان فایلهای بذر (Seed) جمعآوریشده، زیرمجموعهای مناسب را برای فازینگ برنامه انتخاب کند. کیفیت فایلهای بذر میتواند تأثیر قابلتوجهی بر نتایج فازینگ داشته باشد. بنابراین، اینکه چگونه فایلهای بذر (Seed) مناسب را بهمنظور کشف باگهای بیشتر تولید یا انتخاب کنیم، یکی از مسائل مهم در فازینگ محسوب میشود. برای حل این مسئله، مطالعات پژوهشی مختلفی انجام شده است. Rebert و همکاران [47] شش نوع الگوریتم انتخاب را مورد آزمایش قرار دادند:
- الگوریتم پوشش مجموعه (Set Cover) مورد استفاده در Peach؛
- الگوریتم انتخاب تصادفی بذر (Random Seed Selection)؛
- پوشش مجموعه کمینه (Minimal Set Cover) که با Minset نیز شناخته میشود و میتوان آن را با استفاده از الگوریتم حریصانه (Greedy Algorithm) محاسبه کرد؛
- پوشش مجموعه کمینه وزندهیشده بر اساس اندازه (Size-weighted Minimal Set Cover)؛
- پوشش مجموعه کمینه وزندهیشده بر اساس زمان اجرا (Execution-time-weighted Minimal Set Cover)؛
- الگوریتم Hotset؛ در این روش، هر فایل بذر (Seed) به مدت t ثانیه تحت فازینگ قرار میگیرد، سپس بذرها بر اساس تعداد باگهای یکتای کشف شده (Number of Unique Bugs Found) رتبهبندی شده و در نهایت، چند بذر برتر از ابتدای این فهرست انتخاب میشوند.
آنها با اختصاص ۶۵۰ روز CPU به اجرای فازینگ روی Amazon Elastic Compute Cloud (Amazon EC2) و آزمایش ۱۰ برنامه کاربردی، به نتایج و جمعبندیهای زیر دست یافتند:
- الگوریتمهای مبتنی بر اکتشاف (Heuristic-based Algorithms) عملکرد بهتری نسبت به نمونهبرداری کاملاً تصادفی (Fully Random Sampling) دارند.
- الگوریتم Minset بدون وزندهی (Unweighted Minset) در میان این شش الگوریتم، بهترین عملکرد را دارد.
- در عمل، استفاده از یک مجموعه کاهشیافته از فایلهای بذر (Reduced Seed Set) نسبت به استفاده از مجموعه اولیه فایلهای بذر کارایی بیشتری دارد.
- مجموعه کاهشیافته بذرها را میتوان برای برنامههای کاربردی مختلفی که یک نوع قالب فایل یکسان را پردازش میکنند نیز به کار برد.
Kargén و Shahmehri [48] مطرح کردند که به جای اعمال جهش مستقیم روی یک ورودی دارای قالب صحیح (Well-formed Input)، میتوان جهشها را روی کد ماشین برنامه تولید کننده (Generating Program’s Machine Code) اعمال کرد. به این ترتیب، ورودیهای آزمون حاصل به قالب مورد انتظار برنامه تحت آزمون (Program Under Test) نزدیکتر خواهند بود و در نتیجه میتوانند پوشش کد بهتری ایجاد کنند. برای آزمون نرمافزارهای پیچیده، مانند PDF Readerها که معمولاً ورودیهای متنوعی را شامل چندین شیء مختلف، مانند فونتها و تصاویر، دریافت میکنند، Liang و همکاران [49] از اطلاعات ساختاری فایلهای فونت برای انتخاب فایلهای بذر (Seed) از میان مجموعهای از فونتهای ناهمگون استفاده کردند. Skyfire [50] یک مجموعه ورودی برای فازر (Corpus) و یک دستور زبان (Grammar) را به عنوان ورودی دریافت میکند و با بهرهگیری از دانش موجود در تعداد زیادی نمونه موجود (Existing Samples)، مجموعهای از بذرهای دارای توزیع مناسب (Well-distributed Seed Inputs) را برای فازینگ برنامههایی تولید میکند که ورودیهای دارای ساختار پیچیده (Highly Structured Inputs) را پردازش میکنند. همچنین، در پژوهش [51] الگوریتمی ارائه شده است که با در اختیار داشتن یک برنامه و یک ورودی بذر، با هدف بیشینهکردن تعداد باگهای کشف شده در فازینگ جعبهسیاه مبتنی بر جهش (Black-box Mutational Fuzzing) عمل میکند.
ایده اصلی این رویکرد، استفاده از تحلیل نمادین جعبهسفید (White-box Symbolic Analysis) بر روی رهگیری اجرای برنامه (Execution Trace) برای یک جفت مشخص از برنامه و بذر (Program–Seed) میباشد. هدف از این تحلیل، شناسایی وابستگی میان موقعیتهای بیتی ورودی (Bit Positions of an Input) و سپس استفاده از این رابطه وابستگی برای محاسبه نسبت جهش بهینه از نظر احتمالاتی (Probabilistically Optimal Mutation Ratio) برای همان زوج برنامه–بذر (Program–Seed) است.
علاوه بر این، Arcuri و همکاران [52] با در نظر گرفتن فازینگ به عنوان نمونهای از مسئله جمعآوری کوپن (Coupon Collector’s Problem) در چارچوب تحلیل احتمالاتی، کرانهای پایین بهینه و غیربدیهی (Nontrivial, Optimal Lower Bounds) را برای تعداد مورد انتظار موارد آزمون نمونهبرداری شده توسط آزمون تصادفی (Random Testing) به منظور پوشش اهداف از پیش تعریف شده (Predefined Targets) ارائه کرده و اثبات نمودند؛ هرچند در این پژوهش مشخص نشده است که چگونه میتوان در عمل به این کرانهای نظری دست یافت.
برای تولید تصادفی آزمونهای واحد (Unit Tests) در برنامههای شیءگرا (Object-oriented Programs)، Pacheco و همکاران [53] پیشنهاد کردند که از بازخورد حاصل از اجرای دنباله آزمون (Test Sequence)، همزمان با ساختهشدن آن، استفاده شود تا فرایند جستوجو به سمت دنبالههایی هدایت شود که حالتهای جدید و معتبر آبجکتها (New and Legal Object States) را ایجاد میکنند.
در نتیجه، ورودیهایی که موجب ایجاد حالتهای تکراری یا نامعتبر (Redundant or Illegal States) میشوند، هرگز به دنباله آزمون افزوده و گسترش داده نمیشوند. بااینحال، Yatoh و همکاران [54] استدلال کردند که هدایت مبتنی بر بازخورد (Feedback Guidance) ممکن است فرایند تولید را بیش از حد در یک جهت خاص هدایت کرده و در نتیجه، تنوع آزمونهای تولید شده (Diversity of Generated Tests) را محدود کند. آنها برای رفع این مشکل، الگوریتمی با نام آزمون تصادفی کنترلشده با بازخورد (Feedback-controlled Random Testing) پیشنهاد کردند که میزان استفاده از بازخورد را بهصورت تطبیقی (Adaptively) کنترل میکند.
چگونه میتوان در وهله نخست فایلهای بذر (Seed) را به دست آورد؟ برای برخی پروژههای متنباز (Open-source Projects)، نرمافزار همراه با حجم زیادی از دادههای ورودی مورد استفاده برای آزمون منتشر میشود که میتوان آنها را بهصورت رایگان دریافت کرد و بهعنوان بذرهای باکیفیت برای فازینگ مورد استفاده قرار داد. برای مثال، محیط آزمون خودکار FFmpeg (FATE) [55] انواع مختلفی از موارد آزمون (Test Cases) را فراهم میکند که جمعآوری آنها بهتنهایی برای آزمایشکنندگان میتواند دشوار باشد. گاهی دادههای آزمون بهصورت عمومی در دسترس نیستند، اما توسعهدهندگان حاضرند آنها را با افرادی که در مقابل، باگهای برنامه را گزارش میکنند به اشتراک بگذارند. برخی دیگر از پروژههای متنباز نیز مبدلهای قالب (Format Converters) ارائه میکنند. بنابراین، اگر مجموعهای متنوع از فایلها با یک قالب مشخص در اختیار باشد، آزمایشکننده میتواند با استفاده از یک مبدل قالب، بذرهای مناسب و قابلقبولی برای فازینگ تولید کند. برای مثال، cwebp [56] میتواند تصاویر TIFF/JPEG/PNG را به تصاویر WEBP تبدیل کند.
علاوه بر این، مهندسی معکوس (Reverse Engineering) نیز میتواند در فراهم ساختن ورودیهای بذر برای فازینگ مفید باشد. به عنوان مثال، Prospex [57] قادر است مشخصات پروتکلهای شبکه (Network Protocol Specifications)، از جمله ماشینهای حالت پروتکل (Protocol State Machines)، را استخراج کرده و از آنها برای تولید خودکار ورودی برای یک فازر حالتمند (Stateful Fuzzer) استفاده کند. آزمون تصادفی تطبیقی (Adaptive Random Testing — ART) [58]، آزمون تصادفی را با نمونهبرداری از فضای آزمون (Test Space) اصلاح میکند و تنها آزمونهایی را اجرا میکند که بر اساس یک معیار فاصله (Distance Metric) تعریف شده روی ورودیها، بیشترین فاصله را از تمام آزمونهای قبلاً اجرا شده دارند. با این حال، نشان داده نشده است که ART همواره برای برنامههای پیچیده و واقعی (Complex Real-world Programs) مؤثر میباشد [59] و این روش عمدتاً در برنامههایی با ورودیهای عددی (Numeric Inputs) به کار گرفته شده است. در مقایسه با رویکردهای فوق، جمعآوری فایلهای بذر (Seed) با خزیدن در اینترنت (Internet Crawling) روشی عمومیتر و فراگیرتر است. آزمایشکنندگان میتوانند بر اساس ویژگیهای مشخصی مانند پسوند فایل (File Extension)، بایتهای جادویی (Magic Bytes) و سایر مشخصهها، فایلهای بذر مورد نیاز را دانلود کنند.
اگر مجموعه ورودیهای (Corpus) جمعآوریشده بسیار حجیم باشند، لزوماً مشکل جدی ایجاد نمیکند؛ زیرا هزینه ذخیرهسازی پایین است و میتوان مجموعه ورودیها را به مجموعهای با اندازه کوچکتر فشرده یا کاهش داد (Compacted)، درحالی که به پوشش کد معادل (Equivalent Code Coverage) دست یافت [60]. برای کاهش تعداد فایلهای دارای خطای تزریق شده (Fault-inserted Files) و در عین حال حفظ حداکثر پوشش موارد آزمون (Maximum Test Case Coverage)، Kim و همکاران [61] پیشنهاد کردند که فیلدهای فایلهای دودویی را با ردیابی و تحلیل فریمهای پشته (Stack Frame)، کدهای اسمبلی و ثباتها (Registers)، همزمان با پردازش فایل توسط نرمافزار هدف، تحلیل کنند.
۵.۲ اعتبارسنجی ورودی و پوشش (Input Validation and Coverage)
توانایی فازینگ در تولید خودکار تعداد زیادی مورد آزمون (Test Cases) با هدف ایجاد رفتارهای غیرمنتظره در برنامه هدف، یکی از مزیتهای مهم این تکنیک محسوب میشود. با این حال، اگر برنامه هدف دارای مکانیزم اعتبارسنجی ورودی (Input Validation Mechanism) باشد، احتمال زیادی وجود خواهد داشت که این موارد آزمون در مراحل اولیه اجرای برنامه رد شوند. بنابراین، هنگامی که آزمایشکنندگان قصد دارند برنامهای دارای چنین سازوکاری را فاز کنند، چگونگی غلبه بر این مانع یکی از ملاحظات ضروری خواهد بود.
۱) اعتبارسنجی یکپارچگی (Integrity Validation): در حین انتقال و ذخیرهسازی دادهها، ممکن است خطاهایی در دادههای اولیه ایجاد شود. به منظور شناسایی این دادههای «دستکاریشده یا مخدوش (Distorted Data)»، در برخی قالبهای فایل، مانند PNG، و پروتکلهای شبکه، مانند TCP/IP، معمولاً از مکانیزم جمعآزما (Checksum) برای بررسی یکپارچگی دادههای ورودی استفاده میشود. در این روش، با استفاده از یک الگوریتم جمعآزما (Checksum) مانند یک تابع درهمسازی (Hash Function)، یک مقدار جمعآزما (Checksum) یکتا به دادههای اصلی اختصاص داده میشود. در سمت دریافتکننده، یکپارچگی داده دریافت شده با محاسبه مجدد مقدار جمعآزما (Checksum) با استفاده از همان الگوریتم و مقایسه آن با مقدار جمعآزمایی (Checksum) که همراه داده است، بررسی میشود. به منظور فازینگ چنین سیستمهایی، باید منطق اضافی در فازر پیادهسازی شود تا بتواند مقادیر صحیح جمعآزما (Checksum) مربوط به موارد آزمون جدید تولید شده را محاسبه کند. در غیر این صورت، توسعهدهنده باید از روشهای دیگری برای رفع این مانع استفاده کند. Wang و همکاران [36[، [62] روش جدیدی را برای حل این مشکل پیشنهاد کردند و فازری با نام TaintScope توسعه دادند.
TaintScope ابتدا با استفاده از تحلیل پویای آلودگی (Dynamic Taint Analysis) و مجموعهای از قواعد ازپیش تعریف شده (Predefined Rules)، نقاط بالقوه جمعآزما (Checksum) و همچنین بایتهای ورودی داغ (Hot Input Bytes) را شناسایی میکند؛ یعنی بایتهایی از ورودی که میتوانند رابطهای برنامهنویسی کاربردی حساس (Sensitive APIs) را در برنامه هدف آلوده کنند. سپس TaintScope با اعمال جهش (Mutation) روی بایتهای داغ (Hot Bytes)، موارد آزمون جدید ایجاد میکند و نقاط جمعآزما (Checksum) را تغییر میدهد تا تمام موارد آزمون تولید شده بتوانند اعتبارسنجی یکپارچگی (Integrity Validation) را پشت سر بگذارند. در مرحله نهایی، برای آن دسته از موارد آزمونی که قادرند موجب کرش (Crash) برنامه هدف شوند، مقدار جمعآزما (Checksum) را با استفاده از اجرای نمادین (Symbolic Execution) و حل قیود (Constraint Solving) اصلاح میکند.
به این ترتیب، TaintScope میتواند موارد آزمونی تولید کند که هم اعتبارسنجی یکپارچگی را با موفقیت پشت سر بگذارند و هم قادر به ایجاد کرش در برنامه هدف باشند. Höschele و Zeller [63] با در اختیار داشتن مجموعهای از ورودیهای نمونه (Sample Inputs)، از آلودگی پویا (Dynamic Tainting) برای ردیابی جریان داده هر یک از کاراکترهای ورودی استفاده کردند و سپس این قطعات ورودی را در قالب موجودیتهای واژگانی و نحوی (Lexical and Syntactical Entities) تجمیع کردند. خروجی این فرایند، یک دستور زبان مستقل از متن (Context-free Grammar) است که ساختار معتبر ورودی را بازنمایی میکند و میتواند برای فرایند فازینگ در مراحل بعدی مفید باشد. به منظور کاهش محدودیت فازرهای هدایت شده با پوشش (Coverage-based Fuzzers) در اجرای مسیرهایی که توسط مقایسههای بایتهای جادویی (Magic Bytes) محافظت میشوند، Steelix [64] از تحلیل ایستای سبک (Lightweight Static Analysis) و ابزارگذاری باینری (Binary Instrumentation) بهره میگیرد تا علاوه بر اطلاعات پوشش (Coverage Information)، اطلاعات مربوط به میزان پیشرفت در مقایسهها (Comparison Progress Information) را نیز در اختیار فازر قرار دهد. این اطلاعات مربوط به وضعیت برنامه (Program State Information) به فازر نشان میدهند که بایتهای جادویی (Magic Bytes) در کدام بخش از ورودی آزمون قرار دارند و برای تطبیق مؤثر با بایتهای جادویی، جهشها باید چگونه انجام شوند. پژوهشهای دیگری نیز [65]، [66] در راستای کاهش و رفع این مشکل انجام شدهاند و پیشرفتهایی در این زمینه به دست آوردهاند.
2) اعتبارسنجی قالب (Format Validation): پروتکلهای شبکه (Network Protocols)، کامپایلرها (Compilers)، مفسرها (Interpreters) و موارد مشابه، الزامات سختگیرانهای برای قالب ورودی (Input Format) دارند. ورودیهایی که این الزامات قالب را برآورده نکنند، معمولاً در مراحل ابتدایی اجرای برنامه رد میشوند. بنابراین، برای فازینگ چنین سیستمهای هدفی، به تکنیکهای اضافی نیاز است تا موارد آزمونی تولید شوند که بتوانند از مرحله اعتبارسنجی قالب عبور کنند. اغلب راهکارهای ارائه شده برای این مسئله، بر استفاده از دانش اختصاصی ورودی (Input-specific Knowledge) یا دستور زبان (Grammar) متکی هستند. Ruiter و Poll [30] با استفاده از فازینگ جعبهسیاه در ترکیب با یادگیری ماشین حالت (State Machine Learning)، نه پیادهسازی متداول پروتکل امنیت لایه انتقال (TLS) را ارزیابی کردند. آنها فهرستی از پیامهای انتزاعی (Abstract Messages)، که با عنوان الفبای ورودی (Input Alphabet) نیز شناخته میشوند، ارائه کردند. این پیامها میتوانند توسط مهار آزمون (Test Harness) به پیامهای عینی (Concrete Messages) تبدیل شده و برای سیستم تحت آزمون (System Under Test) ارسال شوند. Dewey و همکاران [67[، [68] روش جدیدی برای تولید برنامههای دارای نوع صحیح (Well-typed Programs) ارائه کردند که از سیستمهای نوع پیچیده (Complicated Type Systems) استفاده میکنند. این روش بر پایه برنامهنویسی منطقی مقید (Constraint Logic Programming – CLP) توسعه یافته و برای تولید برنامههای Rust و JavaScript به کار گرفته شده است. Cao و همکاران [69] ابتدا وضعیت اعتبارسنجی ورودی در سرویسهای سیستمی اندروید (Android System Services) را بررسی کردند و سپس برای دستگاههای اندرویدی، یک اسکنر آسیبپذیریهای اعتبارسنجی ورودی (Input Validation Vulnerability Scanner) توسعه دادند. این اسکنر میتواند آرگومانهای نیمهمعتبر (Semivalid Arguments) تولید کند که قادرند از بررسیهای اولیه (Preliminary Checks) پیادهسازیشده در متد سرویس سیستم هدف عبور کنند. پژوهشهای دیگری نیز، از جمله [24]، [25]، [70] و [71]، بر حل این مسئله تمرکز کردهاند.
۳) اعتبارسنجی محیط اجرا (Environment Validation): بسیاری از آسیبپذیریهای نرمافزاری تنها در شرایط محیطی خاصی آشکار میشوند؛ برای مثال، در پیکربندیهای مشخص یا زمانی که برنامه در یک وضعیت یا شرایط اجرایی خاص (Runtime Status/Condition) قرار داشته باشد. فازینگ متداول نمیتواند اعتبار نحوی و معنایی ورودی (Syntactic and Semantic Validity) یا درصد فضای ورودی کاوش شده (Percentage of the Explored Input Space) را تضمین کند. برای کاهش این مشکلات، Dai و همکاران [72] تکنیکی با عنوان فازینگ پیکربندی (Configuration Fuzzing) پیشنهاد کردند. در این روش، پیکربندی برنامه در حال اجرا در نقاط مشخصی از فرایند اجرا جهش داده میشود تا آسیبپذیریهایی شناسایی شوند که تنها تحت شرایط خاص بروز میکنند. FuzzDroid [73] نیز میتواند به صورت خودکار یک محیط اجرای اندروید (Android Execution Environment) ایجاد کند که در آن، یک برنامه کاربردی رفتار مخرب خود را آشکار میکند. FuzzDroid با ترکیب مجموعهای قابل توسعه از تحلیلهای ایستا و پویا و استفاده از یک الگوریتم مبتنی بر جستوجو (Search-based Algorithm)، اجرای برنامه را به سمت یک مکان هدف قابل پیکربندی (Configurable Target Location) هدایت میکند.
۴) پوشش ورودی (Input Coverage): Tsankov و همکاران [74] مفهوم «پوشش ورودی نیمهمعتبر» (Semivalid Input Coverage یا SVCov) را تعریف کردند که نخستین معیار پوشش برای آزمون فازینگ (Fuzz Testing) محسوب میشود. این معیار زمانی قابل استفاده است که ورودیهای معتبر را بتوان با مجموعهای متناهی از قیود (constraints) تعریف کرد. آنها با افزایش پوشش بر اساس SVCov، یک آسیبپذیری ناشناخته و پیشتر گزارش نشده را در یک پیادهسازی بالغ از پروتکل تبادل کلید اینترنت (Internet Key Exchange یا IKE) کشف کردند.
برای برطرف کردن کاستیهای الگوریتمهای موجودِ استنتاج دستور زبان (Grammar Inference)، که به شدت کُند و بیشازحد تعمیمیافته هستند، Bastani و همکاران [75] الگوریتمی را برای سنتز (ترکیب – synthes) یک دستور زبان مستقل از متن (Context-Free Grammar) ارائه کردند که زبانِ ورودیهای معتبر برنامه را از روی مجموعهای از نمونههای ورودی و دسترسی جعبهسیاه (Black-Box Access) به برنامه، رمزگذاری میکند. برخلاف بسیاری از روشها که از کرش (Crash) برنامه هدف برای تعیین مؤثر بودن یا نبودن یک ورودی استفاده میکنند، ArtFuzz [76] با هدف شناسایی آسیبپذیریهای سرریز بافر (Buffer Overflow) که منجر به کرش نمیشوند (Non-Crash)، طراحی شده است. این روش از اطلاعات نوع (Type Information) بهره میگیرد و بهصورت پویا چیدمانهای محتمل حافظه (Likely Memory Layouts) را شناسایی میکند تا به فرایند فازینگ کمک کند. چنانچه مرز یک بافر که بر اساس چیدمان حافظه شناسایی شده است، نقض گردد، یک خطا گزارش خواهد شد. با توجه به اینکه افزایش تنوع، به بهبود پوشش (coverage) و تشخیص خطا (fault detection) منجر میشود، Groce و همکاران [77] رویکردی کمهزینه و مؤثر به نام «آزمون ازدحام» (Swarm Testing) را به منظور افزایش تنوع موارد آزمون (Test Cases) تولید شده به صورت تصادفی پیشنهاد کردند. این رویکرد از مجموعهای متنوع از پیکربندیهای آزمون استفاده میکند که در هر یک از آنها، برخی فراخوانیهای API یا ویژگیهای ورودی، بهصورت عمدی حذف میشوند. افزون بر این، برای کاهش ناتوانی در تمرکز بر بخشی از سیستم تحت آزمون، «آزمون ازدحامی هدایت شده» (Directed Swarm Testing) [78] از آزمون ازدحام بهره گرفت و با ثبت دادههای آماری مربوط به نتایج آزمونهای گذشته، آزمونهای تصادفی جدیدی را تولید کرد که هر عنصر دلخواهی از کد منبع را هدف قرار میدهند. بر اساس این مشاهده که توسعهدهندگان گاهی یک مورد آزمون را همراه با وصلههای (Patch) ارسالی ارائه میکنند که کد جدید را بهصورت جزئی اجرا میکند، و از آنجا که میتوان بهسادگی از این مورد آزمون بهعنوان نقطه شروعی برای کاوش نمادین (Symbolic Exploration) استفاده کرد، Marinescu و Cadar [79] روشی خودکار برای تولید مجموعه آزمونهایی ارائه کردند که پوشش بالایی از وصلههای نرمافزاری به دست میآورند.
۵.۳ مدیریت موارد آزمون منجر به کرش (Handling Crash-Inducing Test Cases)
شرکتهای نرمافزاری (به عنوان مثال، Microsoft) و پروژههای متنباز (مانند لینوکس (Linux)) اغلب از فازینگ (Fuzzing) برای بهبود کیفیت و قابلیت اطمینان محصولات خود استفاده میکنند [17]. اگرچه فازینگ در تولید موارد آزمون منجر به کرش (Crash-Inducing Test Cases) عملکرد خوبی دارد، اما معمولاً به اندازه کافی هوشمند نیست که بتواند اهمیت این موارد آزمون را بهصورت خودکار تحلیل کند. چنانچه فرایند فازینگ منجر به تولید تعداد زیادی مورد آزمون خام و منجر به کرش شود، تحلیل این موارد آزمون برای یافتن خطاهای مختلف در برنامه هدف، زمان زیادی از آزمونگران میگیرد. توسعهدهندگان به دلیل محدودیتهای زمانی یا بودجهای، ترجیح میدهند ابتدا خطاهای شدید و بحرانی را برطرف کنند. در حال حاضر، تنها تعداد اندکی از پژوهشها بر چگونگی پالایش خروجیهای خام فازینگ تمرکز دارند تا نتایج حاصل از فازینگ برای آزمونگران کاربردیتر شوند. با فرض وجود مجموعه بزرگی از موارد آزمون که هر یک از آنها میتواند خطاهایی را در برنامه ایجاد کند، Chen و همکاران [26] روشی مبتنی بر رتبهبندی ارائه کردند که در آن، موارد آزمونی که خطاهای متفاوتی را ایجاد میکنند، در رتبههای بالاتر فهرست قرار میگیرند.
این روش مبتنی بر رتبهبندی در مقایسه با روشهای سنتی خوشهبندی (clustering methods) [80]، [81] کاربردیتر است. بنابراین، آزمونگران میتوانند بر تحلیل موارد آزمون منجر به کرش با رتبه بالاتر تمرکز کنند. افزون بر پالایش مستقیم موارد آزمون منجر به کرش، روشهای دیگری نیز برای کاهش کار دستی و پرهزینه وجود دارند؛ از جمله تولید موارد آزمون منجر به کرش منحصربهفرد، کوتاهسازی موارد آزمون (trimming test cases -Trimming در حوزه فازینگ به معنی کاهش حجم یا حذف بخشهای غیرضروری یک مورد آزمون (Test Case) میباشد)، و ارائه اطلاعات مفید برای اشکالزدایی (debug information). منحصربهفرد بودن موارد آزمون منجر به کرش (Crash) را میتوان با استفاده از پشته فراخوانی (Call Stack) Thread هدف و آدرس دستورالعمل ایجادکننده خطا (Fault-Causing Instruction) با قابلیت اطمینان نسبتاً بالایی تعیین کرد [82]. اگر دو مورد آزمون متمایز باعث شوند برنامه هدف با پشتههای فراخوانی یکسان کرش کند، بسیار محتمل است که این دو مورد آزمون به یک باگ یکسان مربوط باشند؛ بنابراین، تنها یکی از آنها برای تحلیل دستی نگه داشته میشود. برعکس، اگر این دو مورد آزمون باعث شوند برنامه هدف در یک مکان یکسان کرش کند، اما دارای رهگیری پشتهای (Stack Trace) متفاوتی باشند، کاملاً محتمل است که مربوط به دو باگ متمایز باشند و در نتیجه، هر دو ارزش تحلیل جداگانه را خواهند داشت.
در مقایسه با ثبت پشته فراخوانی، رهگیری مسیر اجرا (Execution Path Tracing) روشی سادهتر اما کماعتمادتر برای تعیین منحصربهفرد بودن است. AFL [27]، که یکی از محبوبترین فازرها (Fuzzers) میباشد، یک مورد آزمون منجر به کرش (Crash) را زمانی منحصربهفرد در نظر میگیرد که یک مسیر جدید بیابد و یا مسیر مشترکی پیدا نشود. این رویکرد که پیادهسازی آن آسان است، مشابه روش ثبت مسیر اجرا است که مبنای AFL را تشکیل میدهد. تولید موارد آزمون منحصربهفردِ منجر به کرش میتواند به کاهش خروجیهای تکراری فازینگ کمک کند و در نتیجه، زمان و تلاش موردنیاز برای تحلیل دستی را کاهش دهد.
اندازه موارد آزمون میتواند تأثیر قابلتوجهی بر کارایی تحلیل دستی داشته باشد، زیرا اجرای موارد آزمون بزرگتر و یافتن دستورالعملهای ایجادکننده خطا در آنها، به زمان بیشتری نیاز دارد. چنانچه در یک فازر مبتنی بر جهش (Mutation-Based Fuzzer)، از فایلهای بذر (Seed Files) کمکیفیت استفاده شود، اندازه موارد آزمون تولید شده ممکن است تحت برخی روشهای جهش، به صورت تکرارشونده افزایش یابد. از این رو، طی فرایند فازینگ، کوتاهسازی دورهای موارد آزمون تولید شده میتواند کارایی کلی را بهبود دهد و در نتیجه، حجم کار مربوط به تحلیل دستی موارد آزمون منجر به کرش را کاهش دهد. اصل کوتاهسازی (Trimming) ساده است: رفتار مورد آزمون پردازش شده باید با مورد آزمون اصلی یکسان باشد؛ به بیان دیگر، هر دو باید مسیر اجرای یکسانی را دنبال کنند. مراحل کلی کوتاهسازی عبارتاند از حذف متوالی بلوکهای داده از یک مورد آزمون و ارزیابی مجدد بخش باقیمانده مورد آزمون. بلوکهای دادهای که نمیتوانند بر مسیر اجرا تأثیر بگذارند، حذف خواهند شد. ارزیابی قابلیت بهرهبرداری از خروجیهای فازینگ معمولاً نیازمند تحلیل کد و فرایند اشکالزدایی (Debugging) میباشد که میتوان در این زمینه از ابزارهای تخصصی، مانند GDB، Valgrind [41]، AddressSanitizer [83] و غیره، استفاده کرد. این ابزارها اطلاعات زمینهای زمان اجرا (Runtime Context) برنامه هدف، مانند وضعیت پشته فراخوانی (Call Stack) و ثباتها (Registers)، آدرس دستورالعمل ایجادکننده خطا (address of fault-inducing instruction) و غیره، را فراهم میکنند و یا میتوانند انواع خاصی از خطاهای برنامه، مانند خطاهای حافظه (Memory Errors) را شناسایی کنند. با کمک این ابزارها، آزمونگران میتوانند با کارایی بیشتری باگهای برنامه را کشف و ارزیابی نمایند. افزون بر این، Pham و همکاران [84] روشی برای تولید ورودیهایی ارائه کردند که به یک مکان مشخصِ «بالقوه منجر به کرش» (Potentially Crashing) میرسند. ورودی آزمونی که با استفاده از روش آنها تولید میشود، به عنوان شاهدی برای وقوع کرش (Crash) مورد استفاده قرار گرفت.
۴.۵ بهرهگیری از اطلاعات زمان اجرا (Leveraging Runtime Information)
دو مورد از تکنیکهای رایج تحلیل برنامه، یعنی اجرای نمادین (Symbolic Execution) و تحلیل پویای آلودگی (Dynamic Taint Analysis) اغلب برای هوشمندتر کردن فرایند فازینگ مورد استفاده قرار میگیرند، زیرا این تکنیکها میتوانند اطلاعات زیادی از زمان اجرا، مانند پوشش کد (Code Coverage) و جریان دادههای آلوده (Taint Data Flow)، فراهم کنند و به فازینگ در یافتن باگهای «پنهان» کمک نمایند [85]، [86]. با این حال، مشکلات موجود در این تکنیکها نیز مانع از آن میشوند که فازینگ به کارایی بالاتری دست یابد [87]. در این بخش، مشکلاتی مانند انفجار مسیر (Path Explosion) و اجرای نمادین مبهم و غیردقیق (Imprecise Symbolic Execution) در اجرای کانکولیک (Concolic Execution) و همچنین ردیابی ناکافی دادههای آلوده (Undertainting) و ردیابی بیش از حد دادههای آلوده (Overtainting) در تحلیل پویای آلودگی را بررسی کرده و راهکارهای متناظر با آنها را جمعبندی میکنیم. آشنایی با این مشکلات و راهکارها میتواند به خوانندگان کمک کند تا درک جامعتری از فازینگ هوشمند (Smart Fuzzing) به دست آورند.
۱) انفجار مسیر (Path Explosion):
انفجار مسیر یکی از مشکلات ذاتی و در عین حال دشوارترین مشکلات در اجرای نمادین (Symbolic Execution) است، زیرا شاخههای شرطی موجود در برنامه هدف معمولاً بسیار زیاد هستند؛ بهطوریکه حتی یک برنامه با اندازه کوچک نیز میتواند تعداد بسیار زیادی مسیر اجرایی ایجاد کند. از دیدگاه روش تحلیل برنامه (program analysis method) و الگوریتم جستوجوی مسیر (path search algorithm)، پژوهشهای متعددی برای کاهش این مشکل انجام شدهاند. به عنوان مثال، خلاصهسازی توابع (Function Summaries) [88]،[89] برای توصیف ویژگیهای توابع سطح پایین استفاده میشود تا توابع سطح بالاتر بتوانند از این خلاصهها مجدداً استفاده کنند و در نتیجه تعداد مسیرهای اجرایی کاهش یابد. همچنین، هرس کردن مسیرهای زائد (Redundant Path Pruning) برای جلوگیری از اجرای مسیرهایی به کار میرود که دارای اثرات جانبی یکسانی با برخی مسیرهای پیشتر پوششدادهشده هستند. به عنوان نمونه، Boonstoppel و همکاران [90] تکنیکی برای شناسایی و حذف تعداد زیادی از مسیرهای زائد ارائه کردند که با ردیابی عملیات خواندن (Read) و نوشتن (Write) انجام شده توسط برنامه هدف، این مسیرها را شناسایی میکند.
ایده اصلی این تکنیک آن است که اگر یک مسیر، تحت همان شرایطی که برخی مسیرهای قبلاً کاوش شده به یک نقطه از برنامه رسیدهاند، به آن نقطه برسد، در صورتی که مسیر مورد نظر به اثر بعدی یکسانی (Identical Subsequent Effect) منجر شود، میتوان آن مسیر را هرس کرد. علاوه بر این، ادغام حالتها (State Merging) [91] که در مسیرهای مختلف به دست آمدهاند نیز میتواند فضای جستوجوی مسیر را کاهش دهد؛ با این حال، این روش بار محاسباتی تحمیلشده بر حلکننده (Solver) را افزایش میدهد. از سوی دیگر، الگوریتمهای جستوجوی ابتکاری (Heuristic Search Algorithms) میتوانند در یک بازه زمانی محدود، مرتبطترین مسیرهای اجرایی را در سریعترین زمان ممکن کاوش کنند. به عنوان مثال، انتخاب تصادفی مسیر (Random Path Selection) [92] و خلاصهسازی خودکار و جزئی حلقهها (Automatic Partial Loop Summarization) [93] در عمل موفقیتآمیز بودن خود را نشان دادهاند؛ عمدتاً به این دلیل که هنگام مواجهه با برخی حلقههای فشرده و محدود کننده، که میتوانند بهسرعت حالتهای جدیدی ایجاد کنند، از گرفتار شدن در آنها جلوگیری میکنند. نمونه دیگر، انتخاب مسیر هدایت شده توسط گراف جریان کنترل (Control Flow Graph یا CFG-Directed Path Selection) [94] است که از گراف جریان کنترل ایستا برای هدایت تولید موارد آزمون استفاده میکند تا نزدیکترین شاخه پوشش داده نشده را کاوش کند. آزمایشها نشان میدهند که این رویکرد حریصانه (Greedy) میتواند به بهبود سریعتر پوشش و دستیابی به درصد بالاتری از پوشش کد کمک کند.
علاوه بر این، جستوجوی مولد (Generational Search) [38] نیز وجود دارد که تمام زیرمسیرهای (Subpaths) هر اجرای گسترشیافته را کاوش میکند، به آنها امتیاز میدهد و در نهایت، مسیری را که بالاترین امتیاز را دارد برای اجرای بعدی انتخاب میکند. با توجه به اینکه ابزارهای موجود فازینگ جعبهسیاه/خاکستری مبتنی بر پوشش (Coverage-Based Grey-Box Fuzzing) در نواحی با چگالی یا تراکم بالا، تعداد بسیار زیادی حالت را بازدید میکنند، Böhme و همکاران [95] چندین راهبرد را پیشنهاد و پیادهسازی کردند تا AFL [27] را وادار کنند برای حالتهای موجود در یک ناحیه با تراکم بالا، ورودیهای کمتری تولید کند و در عوض، با بازدید از حالتهای بیشتری که در حالت عادی در نواحی با چگالی پایین پنهان باقی میمانند، آنها را مورد کاوش قرار دهد. DeepFuzz [96] به منظور کاهش مشکل انفجار مسیر (Path Explosion)، به مسیرهای اجرایی، احتمال اختصاص داد و یک راهبرد جستوجوی ابتکاری جدید (New Search Heuristic) را به کار گرفت که میتواند انفجار مسیر را بهطور مؤثری به لایههای عمیقتر باینری مورد آزمون به تعویق بیندازد. با در اختیار داشتن مجموعهای از موارد آزمون موجود، Zhang و همکاران [97] از روشهای کاهش (Reduction) و اولویتبندی موارد آزمون (Test Case Prioritization) برای بهبود کارایی اجرای نمادین مبتنی بر بذر (Seeded Symbolic Execution) استفاده کردند؛ هدف آنها دستیابی به پوشش افزایشی (Incremental Coverage) در سریعترین زمان ممکن بود.
۲) اجرای نمادین غیردقیق (Imprecise Symbolic Execution):
عدمدقت در اجرای نمادین (Symbolic Execution) عمدتاً ناشی از مدلسازی ساختارهای پیچیده برنامه (برای مثال، اشارهگرها (pointer))، فراخوانیهای کتابخانهای یا سیستمی، و حل قیود (Constraint Solving) است. به منظور عملی و قابل استفاده کردن اجرای نمادین، لازم است برخی روشهای سادهسازی در حوزههای مذکور استفاده شود. از این رو، نکته کلیدی برای توسعهدهندگان، یافتن تعادلی میان مقیاسپذیری (Scalability) و دقت (Precision) است. در حال حاضر، روشهایی ارائه شدهاند که اجرای نمادین را با هزینه کردن بخشی از دقت، عملیتر میکنند. در CUTE [98]، عملیات مربوط به اشارهگرها سادهسازی شده است؛ به این صورت که هنگام کار با متغیرهای اشارهگر نمادین، تنها گزارههای برابری (Equality) و نابرابری (Inequality) در نظر گرفته میشوند. در KLEE [92]، اشارهگرها بهصورت آرایه مدل میشوند. هنگامی که یک اشارهگر p به صورت غیرمستقیم به یا آبجکت (object) N اشاره میکند، KLEE حالت فعلی را N بار کپی میکند و در هر حالت، عملیات مناسب خواندن یا نوشتن را با این فرض انجام میدهد که p از محدوده شیء (object) متناظر خارج نشده باشد. در نقاطی که فراخوانی کتابخانهای یا سیستمی انجام میشود و کد منبع آن در دسترس نیست، در این نقاط، بهجای مقادیر نمادین (symbolic) از مقادیر مشخص (Concrete) استفاده میشود [99].
علاوه بر این، برای حل قیود (Constraint Solving)، بهینهسازیهای متعددی [100] به کار گرفته شدهاند؛ برای مثال، SAGE از حذف قیود نامرتبط (Unrelated Constraint Elimination)، کش کردن محلی قیود (Local Constraint Caching)، محدودیت تعداد وارونهسازیها (Flip Count Limit) و غیره استفاده میکند تا هنگام تولید قیود، میزان مصرف حافظه و سرعت پردازش را بهبود دهد. حتی میتوان دستور زبان ورودی (Input Grammar) را نیز در این فرایند دخیل کرد. برای مثال، Godefroid و همکاران [36] روشی را پیشنهاد کردند که در آن، قیود مبتنی بر دستور زبان ورودی میتوانند مستقیماً توسط اجرای نمادین تولید شوند. سپس، صدقپذیری (Satisfiability) این قیود توسط یک حلکننده سفارشی قیود (Customized Constraint Solver) که خود نیز از دستور زبان ورودی بهره میگیرد، بررسی میشود. در نتیجه، این روش میتواند ورودیهایی با ساختار بسیار منظم تولید کند. برای فازینگ کدهای ممیز شناور (Floating-Point یا FP) که ممکن است خود نیز به اجرای نمادین غیردقیق منجر شوند، Godefroid و Kinder [102] یک تحلیل ایستای سبک، محلی و مستقل از مسیر (Path-Insensitive) از نوع «ممکن و محتمل» (May) را برای دستورالعملهای FP، با یک تحلیل پویای سراسریِ برنامه، حساس به مسیر (Path-Sensitive) و با دقت بالا از نوع «الزامی» (Must) برای دستورالعملهای غیر-FP ترکیب کردند. Fu و Su [103] چالش آزمون کدهای ممیز شناور را به فرصتی برای بهکارگیری برنامهریزی مقید نشده (Unconstrained Programming) تبدیل کردند؛ روشی ریاضی برای محاسبه نقاط کمینه تابع در سراسر فضای جستوجو. آنها یک تابع نمایشدهنده (Representing Function) را از روی کد FP استخراج کردند که هر یک از نقاط کمینه آن، یک ورودی آزمون است که تضمین میکند یک شاخه جدید از برنامه مورد آزمون را اجرا کند.
۳) کمبرآورد کردن آلودگی داده (Undertainting):
Undertainting یعنی سیستم کمتر از میزان واقعی، دادهها را آلوده تشخیص میدهد و زمانی رخ میدهد که جریانهای ضمنی داده (Implicit Data Flows)، که در آنها انتقال داده با جریان کنترل (Control Flow)، عملیات روی آرایهها و موارد مشابه مرتبط است، بهطور کامل نادیده گرفته شوند. همانطور که در شکل ۴ نشان داده شده است، در فرایند تبدیل متن ساده (Plain Text) به قالب متن غنی (Rich Text Format)، مقدار متغیر ورودی بدون انجام یک تخصیص مستقیم (Direct Assignment)، به آرایه خروجی منتقل میشود. بنابراین، اگر ورودی آلوده باشد، نادیده گرفتن این جریان ضمنی داده باعث تشخیص ناکافی آلودگی داده (Undertainting) خواهد شد. Kang و همکاران [44] پیشرفتهایی در حل این مشکل ایجاد کردهاند. بر اساس آزمایشهای آنها، انتشار آلودگی (Taint Propagation) برای تمام جریانهای ضمنی نیز منجر به تشخیص بیشازحد و غیرقابلقبول دادههای آلوده (Overtainting) میشود. بنابراین، آنها تنها بر انتشار آلودگی در جریانهای ضمنیِ کاملاً حافظ اطلاعات (Complete Information-Preserving Implicit Flows) تمرکز کردند؛ مانند مثالی که در شکل ۴ نشان داده شده است.
۴) بیشبرآورد کردن آلودگی داده (Overtainting):
بیشبرآورد کردن آلودگی داده (Overtainting) زمانی رخ میدهد که انتشار آلودگی (Taint Propagation) با دانهبندی دقیقتر (یا ریزدانه) (Finer-Grained Granularity) پیادهسازی نشود. این مسئله باعث انفجار آلودگی (Taint Explosion) و ایجاد مثبت کاذب (False Positive) میشود. Yadegari و همکاران [104] رویکردی را پیشنهاد کردند که در آن انتشار آلودگی در سطح بیت (Bit Level) انجام میشود تا این مشکل کاهش یابد. روش دیگری برای مقابله با این مسئله، استفاده از تقریبهای زیرین (Underapproximations) برای بررسی ویژگیهای وجودیِ «برای برخی مسیرها» (For-Some-Path Properties) است. Godefroid [89] رویکرد جدیدی برای تولید آزمون (Test Generation) پیشنهاد کرد که در آن آزمونها از اثباتهای اعتبار (Validity Proofs) مربوط به فرمولهای منطق مرتبه اول (First-Order Logic) استخراج میشوند، نه از تخصیصهای صدقپذیری (Satisfying Assignments) فرمولهای منطق مرتبه اول بدون کمیت (Quantifier-Free First-Order Logic Formulas)، آنگونه که در بیشتر رویکردهای کنونی انجام میشود. برای اطلاعات جزئیتر درباره اجرای نمادین (Symbolic Execution) و تحلیل دادههای آلوده (Taint Analysis)، به منابع تخصصی [39]، [105] مراجعه کنید.
۴.۵ مقیاسپذیری در فازینگ (Scalability in Fuzzing)
با توجه به اندازه و پیچیدگی برنامههای کاربردی دنیای واقعی، فازرهای مدرن معمولاً در یکی از دو دسته قرار میگیرند: یا مقیاسپذیر (Scalable) هستند، اما در کاوش باگهایی که در لایهها یا بخشهای عمیقتر برنامه هدف قرار دارند، کارایی کافی ندارند؛ و یا مقیاسپذیری کمتری دارند، اما قادرند در برنامه نفوذ کرده و بخشهای عمیقتر آن را مورد کاوش قرار دهند. Arcuri و همکاران [106] مقیاسپذیری فازینگ را بررسی کردند و نشان دادند که فازینگ، تحت شرایط خاص، میتواند عملکرد بهتری نسبت به طیف گستردهای از تکنیکهای آزمون پارتیشنی (Partition Testing) داشته باشد. Bounimova و همکاران [107] تجربیات خود را از بهکارگیری فازینگ جعبهسفید مبتنی بر قیود (Constraint-Based White-Box Fuzzing) در محیط تولید گزارش کردند. این فازینگ بر روی صدها برنامه کاربردی بزرگ ویندوز و با بیش از ۵۰۰ سال-ماشین (Machine-Years) محاسبات، در فاصله سالهای ۲۰۰۷ تا ۲۰۱۳ انجام شد. آنها SAGE را با قابلیتهای ثبت رویدادها (Logging) و مکانیزمهای کنترل (Control Mechanisms) توسعه دادند تا بتوانند استقرارهایی را که چندین ماه به طول میانجامید، بر روی صدها پیکربندی متفاوت برنامه مدیریت کنند. آنها ادعا کردند که پژوهششان نخستین استفاده عملیاتی (Production Use) از فازینگ جعبهسفید و همچنین بزرگترین استقرار فازینگ جعبهسفید در آن زمان بوده است.
برخی رویکردها برای حل این مسئله از فازینگ آگاه از برنامه (Application-Aware Fuzzing) یا روشهای فازینگ مبتنی بر سرویسهای ابری (Fuzzing by Cloud Services) استفاده کردهاند. Rawat و همکاران [108] یک راهبرد فازینگ تکاملی آگاه از برنامه (Application-Aware Evolutionary Fuzzing) ارائه کردند که به هیچ دانش قبلی درباره برنامه یا قالب ورودی آن نیاز ندارد. آنها بهمنظور به حداکثر رساندن پوشش (Coverage) و کاوش مسیرهای عمیقتر، از ویژگیهای جریان کنترل (Control Flow) و جریان داده (Data Flow) مبتنی بر تحلیل ایستا و پویا استفاده کردند تا ویژگیهای بنیادی برنامه را استنتاج کنند. این کار امکان تولید بسیار سریعتر ورودیهای جالب و معنادار (Interesting Inputs) را در مقایسه با یک رویکرد مستقل از برنامه (Application-Agnostic) فراهم کرد.
یکی از روشهای بهبود مقیاسپذیری (Scalability)، کاهش دامنه تحلیل (Scope of Analysis) است. تحلیل رگرسیون (Regression Analysis) نمونه شناختهشدهای از این رویکرد است که در آن، تفاوتهای میان نسخههای مختلف برنامه بهعنوان مبنایی برای کاهش دامنه تحلیل مورد استفاده قرار میگیرند. DiSE [109] از دو مرحله تشکیل شده است: تحلیل ایستا (Static Analysis) و اجرای نمادین (Symbolic Execution). در مرحله نخست، مجموعه دستورالعملهای برنامه که تحت تأثیر تغییرات قرار گرفتهاند، تولید میشود. سپس اطلاعات حاصل از تحلیل ایستا برای هدایت اجرای نمادین مورد استفاده قرار میگیرد تا تنها بخشهایی از برنامه را که تحت تأثیر تغییرات قرار گرفتهاند، کاوش کند. این کار میتواند از کاوش تعداد زیادی از مسیرهای اجراییِ تحت تأثیر قرار نگرفته (Unaffected Execution Paths) جلوگیری کند.
برای آزمون برنامههای کاربردی موبایل بهصورت مقیاسپذیر، هر ورودی آزمون باید در طیف متنوعی از زمینههای اجرایی (Contexts) اجرا شود؛ از جمله ناهمگونی دستگاهها (Device Heterogeneity)، سرعتهای مختلف شبکه بیسیم، موقعیتهای مکانی و ورودیهای غیرقابلپیشبینی حسگرها. دامنه مقادیر ممکن برای هر یک از این زمینهها، برای مثال موقعیت مکانی، میتواند بسیار گسترده باشد. Liang و همکاران [110]، Caiipa را ارائه کردند؛ یک سرویس ابری برای آزمون برنامههای کاربردی که امکان آزمون مقیاسپذیر برنامهها را در یک فضای زمینهای گسترده موبایل فراهم میکند. این سامانه بر روی یک خوشهای از ماشینهای مجازی (VMs) و دستگاههای واقعی پیادهسازی شده است که میتوانند ترکیبهای مختلفی از زمینههای اجرایی را برای برنامههای موبایل شبیهسازی کنند. خط لوله کشف آسیبپذیری موبایل (MVDP – Mobile Vulnerability Discovery Pipeline) [111] نیز یک سامانه فازینگ جعبهسیاه توزیعشده (Distributed Black-Box Fuzzing System) برای دستگاههای Android و iOS است.
۶. ابزارهای فازینگ در حوزههای کاربردی مختلف (TOOLS IN DIFFERENT APPLICATION AREAS)
فازینگ (Fuzzing) یک تکنیک عملی برای آزمون نرمافزار (Software Testing) است که بهطور گسترده در صنعت مورد استفاده قرار گرفته است. هر نرمافزاری که ورودیهای کاربر را دریافت میکند، میتواند بهعنوان یک هدف فازینگ (Fuzzing Target) در نظر گرفته شود. در حال حاضر، فازرهای مختلفی برای هدف قرار دادن سامانههای نرمافزاری متفاوت وجود دارند. در این بخش، با بررسی برخی از محبوبترین و کارآمدترین فازرها که بر اساس حوزههای کاربردی (Application Areas)، یعنی نوع پلتفرم نرمافزاری هدف (Target Software Platform)، دستهبندی شدهاند، به پرسش پژوهشی دوم (RQ2) پاسخ میدهیم. جدولهای ۵ و ۶ فازرهای شاخصی را که در ادامه معرفی خواهیم کرد، بهترتیب از منظر حوزههای کاربردی (Application Areas) و حوزههای مسئله (Problem Domains) خلاصه میکنند.
جدول ۵. خلاصهای از فازرهای معمولی:
۶.۱ فازرهای همهمنظوره (General-Purpose Fuzzers)
۱) Peach:
Peach [112] یک فازر شناخته شده و همه منظوره است که رایجترین اهداف آن شامل درایورها (Drivers)، برنامههای مصرفکننده فایل (File Consumers)، پروتکلهای شبکه (Network Protocols)، دستگاههای نهفته (Embedded Devices)، سیستمها (Systems) و موارد مشابه است. این فازر از اجزای زیر تشکیل شده است:
- تعریفهای از پیش تعیینشده قالب ورودی (Predefined Input Format Definitions) کهPeach Pits نامیده میشوند. این تعاریف میتوانند بهصورت Pitهای منفرد یا گروههایی از Pitهای مرتبط با یکدیگر کهPit Packs نامیده میشوند، ارائه شوند.
- گذرگاههای آزمون (Test Passes) که میتوانند برای جهشدهندهها (Mutators) وزن تعیین کنند تا موارد آزمون بیشتری اجرا شوند.
- Minset که به کاهش تعداد فایلهای مورد نیاز برای دستیابی به پوشش موارد آزمون (Test Case Coverage) کمک میکند.
Peach در این حوزه نقش مهمی ایفا میکند، زیرا دارای ویژگیهای برجسته متعددی است؛ از جمله تشخیص تهدید (Threat Detection)، تعریفهای آماده فازینگ (Out-of-the-Box Fuzzing Definitions یا Peach Pits) و گزینههای آزمون مقیاسپذیر (Scalable Testing Options). بااینحال، Peach نیز با مشکلاتی مواجه است، بهویژه در نسخه متنباز (Open-Source Version). یکی از مشکلات اصلی این است که ایجاد یک فایل Pit با استفاده از نحوی که Peach برای توصیف قالب فایل هدف ارائه میکند، زمانبر است.eFuzz [113] که بر پایه Peach ساخته شده است، دستگاههای اندازهگیری هوشمند (Smart Metering Devices) را که بر اساس پروتکل ارتباطی DLMS/COSEM، یعنی پروتکل استاندارد مورد استفاده در اروپا، کار میکنند، برای شناسایی خطاهای احتمالی مورد آزمون قرار داد. Honggfuzz [114] نیز بر پایه Peach ساخته شده است.
۲) beSTORM:
beSTORM [115] یک فازر جعبهسیاه تجاری (Commercial Black-Box Fuzzer) است. از آن میتوان برای آزمون امنیت برنامه هدف یا بررسی کیفیت محصولات سختافزاری و نرمافزاری متصل به شبکه استفاده کرد. این ابزار به کد منبع (Source Code) نیاز ندارد و تنها به فایلهای باینری برنامه هدف (Target Program Binaries) نیازمند است. راهبرد فازینگ beSTORM ابتدا ناحیههای محتمل و رایج ایجادکننده خطا (Likely, Common Failure-Inducing Areas) را مورد آزمون قرار میدهد و سپس دامنه آزمون را به محدودهای تقریباً نامحدود از گونههای مختلف حمله (Attack Variations) گسترش میدهد؛ بنابراین میتواند نتایج را بهسرعت ارائه کند. beSTORM را میتوان برای آزمون پروتکلها، برنامههای کاربردی، سختافزار، فایلها، Wi-Fi و تضمین امنیت دستگاههای تعبیهشده (Embedded Device Security Assurance یا EDSA) استفاده کرد. برای مثال، این ابزار قادر است باگهای موجود در برنامهای را که استانداردهای EDSA 402 را پیادهسازی میکند، شناسایی کند.
جدول ۶. فازرهای رایج و حوزههای مسائلی که پوشش میدهند:
۶.۲ فازرهای کامپایلرها و مفسرها (Fuzzers for Compilers and Interpreters)
۱) jsfunfuzz:
jsfunfuzz [116] یک فازر جعبهسیاه مبتنی بر دستور زبان (Grammar-Based Black-Box Fuzzer) است که برای موتور جاوااسکریپت SpiderMonkey موزیلا (Mozilla) طراحی شده است. این ابزار نخستین فازر جاوااسکریپت بود که بهصورت عمومی در دسترس قرار گرفت. از زمان توسعه آن در سال ۲۰۰۷، jsfunfuzz بیش از ۲۰۰۰ باگ را در SpiderMonkey کشف کرده است. این فازر آزمون تفاضلی (Differential Testing) را با دانش دقیق درباره برنامه هدف ترکیب میکند؛ بنابراین میتواند با کارایی مناسبی هم باگهای مرتبط با صحت عملکرد (Correctness-Related Bugs) و هم باگهای منجر به کرش (Crash-Triggering Bugs) را در موتورهای مختلف جاوااسکریپت پیدا کند. با این حال، برای هر قابلیت جدیدی که به زبان اضافه میشود، jsfunfuzz باید خود را با آن قابلیت جدید سازگار کند تا بتواند آن را در فرایند فازینگ مورد آزمون قرار دهد.
۲) Csmith:
Csmith توسط Yang و همکاران [117] در سال ۲۰۱۱ پیشنهاد شد. این ابزار یک فازر کامپایلر C است که میتواند بر اساس دستورات مشخص شده مطابق با استاندارد C99، برنامههای تصادفی C تولید کند. Csmith از آزمون تفاضلی تصادفی (Random Differential Testing) [118] استفاده میکند تا باگهای مربوط به صحت عملکرد را که ناشی از رفتار بالقوه تعریف نشده (Potentially Undefined Behavior) و سایر مشکلات خاص زبان C هستند، شناسایی کند. Csmith سالها مورد استفاده قرار گرفته و صدها باگ ناشناخته قبلی را در کامپایلرهای C تجاری و متنباز کشف کرده است؛ از جمله مجموعه کامپایلرهای گنو (GNU Compiler Collection – GCC) و ماشین مجازی سطح پایین (Low Level Virtual Machine – LLVM). از آنجا که Csmith یک پروژه متنباز است، جدیدترین اطلاعات و نسخه آن را میتوان از [119] دریافت کرد. اگرچه Csmith یک فازر عملی و توانمند در تولید موارد آزمون ایجادکننده خطا (Error-Inducing Test Cases) است، اما مانند بسیاری از فازرهای دیگر، باگهای کشف شده را بر اساس اهمیت آنها اولویتبندی نمیکند. بنابراین، آزمونگران باید زمان زیادی صرف تعیین نوآوری (Novelty) و شدت (Severity) هر باگ کنند.
۳) LangFuzz:
Holler و همکاران [120] با الهام از jsfunfuzz، در سال ۲۰۱۲، LangFuzz را ارائه کردند. LangFuzz برای یک زبان خاص طراحی نشده است. تاکنون این ابزار روی JavaScript و Hypertext Preprocessor (PHP) آزمایش شده است. پس از بهکارگیری LangFuzz روی موتورهای JavaScript، این ابزار بیش از ۵۰۰ باگ ناشناخته قبلی را در SpiderMonkey کشف کرده است [26]. همچنین پس از اعمال آن روی مفسر PHP، موفق به کشف ۱۸ نقص جدید شد که میتوانستند منجر به کرش (Crash) شوند. LangFuzz برای ایجاد موارد آزمون از هر دو روش تولید تصادفی (Stochastic Generation) و جهش کد (Code Mutation) استفاده میکند، اما جهش را به عنوان تکنیک اصلی در نظر میگیرد. این ابزار بهعنوان یک فازر مستقل از زبان (Language-Independent Fuzzer) طراحی شده است، اما سازگار کردن آن با یک زبان جدید همچنان به ایجاد برخی تغییرات ضروری نیاز دارد.
۴) CLsmith:
Lidbury و همکاران [70] از آزمون تفاضلی تصادفی (Random Differential Testing) و آزمون همارزی پیمانهای نسبت به ورودی (Equivalence Modulo Inputs یا EMI) برای فازینگ کامپایلرهای چندهستهای (Many-Core Compilers) استفاده کردند. آنها بیش از ۵۰ باگ در کامپایلرهای OpenCL را شناسایی و گزارش کردند که در میان پیادهسازیهای تجاری، بیشترین تعداد گزارش شده محسوب میشد. بهطور مشخص، آنها آزمون تفاضلی تصادفی را در محیط چندهستهای (Many-Core) به کار گرفتند تا کرنلهای OpenCL قطعی، ارتباطپذیر و غنی از قابلیتها (Feature-Rich) تولید کنند. همچنین، تزریق کد مرده بهصورت ساختاری (Dead-by-Construction Code) را برای امکانپذیر کردن آزمون EMI در زمینه OpenCL پیشنهاد و ارزیابی کردند. فازرهای دیگری نیز در این دسته قرار میگیرند. به عنوان مثال فازر جاوااسکریپت MongoDB که طی دو چرخه انتشار، تقریباً ۲۰۰ باگ را شناسایی کرد [121]. Ifuzzer یک فازر برای مفسر جاوااسکریپت (JavaScript) است و از برنامهنویسی ژنتیک (Genetic Programming) استفاده میکند [122].
۶.۳ فازرهای نرمافزارهای کاربردی (Fuzzers for Application Software)
۱) SAGE:
SAGE [14] یک فازر جعبهسفید (White-Box Fuzzer) شناخته شده میباشد که توسط مایکروسافت (Microsoft) توسعه داده شده است. این ابزار برای فازینگ برنامههای بزرگ ویندوزی که فایل را میخوانند (File-Reading Applications)، مانند تحلیلگرهای اسناد (Document Parsers)، پخشکنندههای رسانه (Media Players)، پردازشگرهای تصویر (Image Processors) و موارد مشابه، که بر روی پلتفرم x86 اجرا میشوند، مورد استفاده قرار میگیرد. SAGE با ترکیب اجرای کانکولیک (Concolic Execution) و یک الگوریتم جستوجوی ابتکاری (Heuristic Search Algorithm) با هدف به حداکثر رساندن پوشش کد (Code Coverage)، تلاش میکند باگها را به صورت مؤثر شناسایی کند. از سال ۲۰۰۸، این ابزار به طور مداوم بر روی میانگین بیش از ۱۰۰ ماشین/هسته (Machines/Cores) در حال اجرا بوده و به صورت خودکار چند صد برنامه کاربردی مایکروسافت (Microsoft) را فازینگ کرده است. SAGE نخستین فازری است که تکنیک فازینگ جعبهسفید (White-Box Fuzzing) را محقق کرد و توانست برنامههای کاربردی دنیای واقعی (Real-World Applications) را مورد آزمون قرار دهد. امروزه مایکروسافت (Microsoft) در حال توسعه و ترویج یک پروژه فازینگ آنلاین با نام Springfield [123] است. این پروژه روشهای متعددی، از جمله فناوری فازینگ جعبهسفید مایکروسافت را برای شناسایی باگها در برنامههای باینریای که توسط مشتریان بارگذاری میشوند، فراهم میکند. کارهای آینده مربوط به SAGE شامل بهبود روش جستوجو، افزایش دقت اجرای نمادین و ارتقای قابلیت حل قیود (Constraint Solving) برای کشف باگهای بیشتر است [38].
۲) AFL:
AFL [27] یک فازر هدایت شده بر اساس پوشش کد (Code-Coverage-Guided Fuzzer) شناخته شده است. این ابزار اطلاعات مربوط به پوشش مسیرهای زمان اجرا (Runtime Path Coverage) را از طریق ابزارگذاری کد (Code Instrumentation) جمعآوری میکند. ابزارگذاری برای برنامههای متنباز، در زمان کامپایل (Compile Time) انجام میشود و برای فایلهای باینری، این ابزارگذاری در زمان اجرا (Runtime) و از طریق نسخه اصلاح شده QEMU [124] صورت میگیرد. موارد آزمونی که بتوانند مسیرهای اجرایی جدید را کاوش کنند، احتمال بیشتری دارند که در مرحله بعدی جهش انتخاب شوند. نتایج آزمایشها نشان میدهند که AFL در کشف باگها در موارد کاربردی دنیای واقعی کارآمد است؛ از جمله در کتابخانههای فشردهسازی فایل، پردازش و تحلیل رایج تصاویر و موارد مشابه. AFL از زبانهای C، C++، Objective-C و همچنین برنامههای اجرایی پشتیبانی میکند و بر روی سیستمعاملهای شبهلینوکس (Linux-Like OS) اجرا میشود. علاوه بر این، تلاشهایی برای گسترش حوزههای کاربرد AFL انجام شده است؛ برای مثال TriforceAFL [125] برای فازینگ فراخوانیهای سیستمی هسته (Kernel Syscalls) استفاده میشود. WinAFL [126] نیز، AFL را به محیط ویندوز (Windows) منتقل میکند. پژوهش انجام شده توسط ORACLE [127] از AFL برای فازینگ برخی سیستمهای فایل (Filesystems) استفاده میکند. اگرچه AFL کارآمد و استفاده از آن آسان است، همچنان جای زیادی برای بهبود دارد. همانند بسیاری از فازرهای نیروی مستقیم (Brute-Force Fuzzers)، AFL هنگامی که دادههای ورودی واقعی فشرده، رمزنگاریشده یا همراه با جمعآزما (Checksum) باشند، پوشش کد محدودی ارائه میدهد. علاوه بر این، AFL هنگام کار با باینریهای ۶۴ بیتی زمان بیشتری مصرف میکند و از فازینگ مستقیم سرویسهای شبکه (Network Services) پشتیبانی نمیکند.
۳) QuickFuzz:
QuickFuzz [128] از QuickCheck زبان Haskell، یعنی یک کتابخانه شناختهشده برای آزمون تصادفی مبتنی بر ویژگی (Property-Based Random Testing)، و Hackage، یعنی مخزن نرمافزار جامعه Haskell، در کنار فازرهای جهشی سطح بیت (Bit-Level Mutational Fuzzers) آمادهاستفاده استفاده میکند. این ترکیب امکان فازینگ خودکار بیش از دوازده قالب رایج فایل را فراهم میکند، بدون آنکه نیاز باشد مجموعهای خارجی از فایلهای ورودی فراهم شود یا برای انواع فایلهای موردنظر، مدلهای جداگانه توسعه داده شوند. QuickFuzz با ترکیب تکنیکهای فازینگ مبتنی بر دستور زبان (Grammar-Based Fuzzing) و فازینگ مبتنی بر جهش (Mutation-Based Fuzzing)، ورودیهای نامعتبر تولید میکند تا رفتارهای غیرمنتظره را در برنامه هدف شناسایی کند.
برای آزمون نرمافزارهای سمت سرور (Server-Side Software)، Davis و همکاران [129]، Node.fz را ارائه کردند. Node.fz یک فازر زمانبندی (Scheduling Fuzzer) برای برنامههای رویدادمحور (Event-Driven Programs) است که برای برنامههای Node.js سمت سرور طراحی شده است. Node.fz اجرای یک برنامه Node.js را بهصورت تصادفی دچار تغییر میکند و به توسعهدهندگان Node.js اجازه میدهد طیف متنوعی از زمانبندیهای احتمالی اجرا (Possible Execution Schedules) را بررسی کنند. کارهای دیگری نیز در این دسته قرار میگیرند؛ از جمله Dfuzzer [130] که یک فازر برای سرویس D-Bus است. برای آزمون برنامههای کاربردی موبایل نیز در سالهای اخیر فازرهای مختلفی ارائه شدهاند؛ از جمله: Droid-FF [131] ،Memory-Leak Fuzzer [132] ،DroidFuzzer [133] ،Intent Fuzzer [134] و Android Ripper MFT Tool [135] که برای فازینگ برنامههای اندروید استفاده میشوند.
۶.۴ فازرهای پروتکلهای شبکه (Fuzzers for Network Protocols)
1) Sulley:
Sulley [136] یک چارچوب فازینگ متنباز است که پروتکلهای شبکه را هدف قرار میدهد. این ابزار از یک رویکرد مبتنی بر بلوک (Block-based) برای تولید «درخواستهای (Requests)» مجزا استفاده میکند. Sulley قالبهای داده (Data Formats) متعددی را در اختیار کاربران قرار میدهد تا بتوانند توصیف پروتکلها را ایجاد کنند. پیش از انجام آزمایش، کاربران باید با استفاده از این قالبها، تمام بلوکهای موردنیاز را تعریف کنند؛ سپس این بلوکها در فرایند فازینگ جهش (Mutate) داده شده و با یکدیگر ادغام میشوند تا نمونههای آزمون (Test Cases) جدید ایجاد شوند. Sulley قادر است خطاهای شناساییشده را دستهبندی کند، فرایند فازینگ را بهصورت موازی (Parallel) اجرا کند و مسیر را تا رسیدن به یک توالی منحصربهفرد از یک مورد آزمون (Test Case) که باعث ایجاد خطا شده است، ردیابی کند. با این حال، این پروژه در حال حاضر بهخوبی نگهداری و توسعه داده نمیشود. Boofuzz [137] جانشین Sulley است.
2) TLS-Attacker:
Somorovsky [138] چارچوب TLS-Attacker را معرفی کرد؛ یک چارچوب متنباز برای ارزیابی امنیت کتابخانههای TLS. TLS-Attacker به مهندسان امنیت اجازه میدهد با استفاده از یک رابط ساده، جریانهای پیام TLS سفارشی (Customized TLS Message Flows) ایجاد کرده و محتوای پیامها را بهصورت دلخواه تغییر دهند تا رفتار کتابخانههای موردنظر را آزمایش کنند. این ابزار با موفقیت چندین آسیبپذیری را در کتابخانههای TLS پرکاربرد، از جمله OpenSSL، Botan و MatrixSSL، شناسایی کرده است. همچنین پژوهشهای دیگری در زمینه فازینگ پروتکلهای شبکه وجود دارد [139]، [140]. T-Fuzz [141] یک فازر مبتنی بر مدل (Model-based) برای آزمون مقاومت (Robustness Testing) پروتکلهای مخابراتی است؛ Secfuzz [142] برای پروتکل IKE طراحی شده است؛ و هر دو فازر SNOOZE [143] و KiF [144]، [145] پروتکل VOIP/SIP را هدف قرار میدهند.
۶.۵ فازرهای هسته سیستمعامل (Fuzzers for OS Kernels)
فازینگ مؤلفههای هسته سیستمعامل (OS Kernel Components) دشوار است، زیرا مکانیزمهای بازخورد، مانند پوشش کد هدایتشده (Guided Code Coverage)، بهسادگی قابل اعمال نیستند. علاوه بر این، غیرقطعیبودن (Nondeterminism) ناشی از وقفهها (Interrupts)، رشتههای هسته (Kernel Threads) و حالتمند بودن (Statefulness) نیز مشکلاتی ایجاد میکند [146]. علاوه بر این، اگر یک فرایند، هسته سیستمعامل خود را فازینگ کند، وقوع کرش در هسته (Kernel Crash) به دلیل نیاز به راهاندازی مجدد سیستمعامل، تأثیر شدیدی بر عملکرد فازر خواهد داشت.
۱) Trinity:
در سالهای اخیر، Trinity [147] در حوزه فازینگ هسته (Kernel Fuzzing) توجه زیادی را به خود جلب کرده است. این ابزار چندین روش برای ارسال آرگومانهای نسبتاً هوشمند (Semi-Intelligent Arguments) به فراخوانیهای سیستمی (System Calls / Syscalls) پیادهسازی میکند. روشهای مورد استفاده Trinity برای تولید آرگومانهای فراخوانیهای سیستمی به شرح زیر هستند:
- اگر یک فراخوانی سیستمی، نوع داده مشخصی را بهعنوان آرگومان انتظار داشته باشد، Trinity یک مقدار از همان نوع را به آن ارسال میکند؛ برای مثال، اگر فراخوانی سیستمی یک توصیفگر (Descriptor) انتظار داشته باشد، یک Descriptor به آن داده میشود.
- اگر یک فراخوانی سیستمی فقط مقادیر مشخصی را به عنوان آرگومان بپذیرد، مانند یک فیلد flags، Trinity فهرستی از تمام فلگهای (Flag) معتبر قابل ارسال را در اختیار دارد.
- اگر یک فراخوانی سیستمی تنها محدوده مشخصی از مقادیر را بپذیرد، معمولاً یک مقدار تصادفی که به آرگومان ارسال میشود، در همان محدوده قرار میگیرد.
Trinity از معماریهای متنوعی پشتیبانی میکند، از جمله x86-64، SPARC-64، S390x، S390، PowerPC-64، PowerPC-32، MIPS، IA-64، i386، ARM، AArch64 و Alpha.
۲) Syzkaller:
Syzkaller [15] یک فازر دیگر برای هدف قرار دادن هستههای لینوکس است. این ابزار به الگوهای از پیش تعریف شده (Predefined Templates) وابسته است که دامنه آرگومانهای (Argument Domains) هر فراخوانی سیستمی را مشخص میکنند. Syzkaller از اطلاعات پوشش کد (Code Coverage) برای هدایت فرایند فازینگ استفاده میکند. از آنجا که Syzkaller تکنیکهای فازینگ هدایت شده بر اساس پوشش (Coverage-Guided) و مبتنی بر الگو (Template-Based) را با یکدیگر ترکیب میکند، عملکرد آن بهتر از رویکردی است که صرفاً بر الگوی استفاده از آرگومانهای فراخوانیهای سیستمی تکیه داشته باشد. این ابزار در حال توسعه فعال (Active Development) است و نتایج اولیه آن امیدوارکننده به نظر میرسند.
۳) IOCTL Fuzzer:
IOCTL Fuzzer [148] ابزاری است که برای جستوجوی خودکار آسیبپذیریها در درایورهای هسته ویندوز طراحی شده است. در حال حاضر، این ابزار از نسخههای ویندوز ۷ در معماریهای x32 و x64 ، Windows Server 2008 ،Windows Server 2003 ، Windows Vista و Windows XP پشتیبانی میکند. اگر یک عملیات IOCTL با شرایط مشخصشده در فایل پیکربندی مطابقت داشته باشد، فازر فیلد ورودی آن را با دادههای تولیدشده بهصورت تصادفی جایگزین میکند.
۴) Kernel-AFL (kAFL):
Schumilo و همکاران [149] یک روش برای فازینگ هدایتشده بر اساس پوشش هسته (Coverage-Guided Kernel Fuzzing) ارائه کردند که بهصورت مستقل از سیستمعامل (OS-Independent) و با کمک سختافزار (Hardware-Assisted) انجام میشود. آنها از یک هایپروایزر (Hypervisor) برای تولید اطلاعات مربوط به پوشش و از فناوری رهگیری پردازنده (Processor Trace) شرکت اینتل (Intel) برای فراهم کردن اطلاعات مربوط به جریان کنترل (Control Flow) کد در حال اجرا استفاده کردند. آنها چارچوبی با نام kAFL توسعه دادند تا قابلیت اطمینان یا امنیت مؤلفههای هسته Linux، macOS و Windows را ارزیابی کنند. در میان کرشهای متعدد، آنها چندین نقص را در درایور ext4 لینوکس، سیستمهای فایل HFS و APFS در macOS و درایور NTFS ویندوز کشف کردند.
۵) CAB-FUZZ:
برای کشف آسیبپذیریها در سیستمعاملهای تجاری آماده استفاده (Commercial Off-the-Shelf Operating Systems یا COTS OSes)،Kim و همکاران [150] ابزار CAB-FUZZ را پیشنهاد کردند. CAB-FUZZ یک ابزار عملی برای آزمون کانکولیک (Concolic Testing) است که مسیرهای مرتبطی را که بیشترین احتمال ایجاد باگ را دارند، مورد کاوش قرار میدهد. این فازر حالتهای مرزی آرایهها و حلقهها (Boundary States of Arrays and Loops) را در اولویت قرار میدهد و از برنامههای واقعی که با سیستمعاملهای COTS تعامل دارند برای ایجاد زمینههای مناسب (Proper Contexts) استفاده میکند تا بتواند حالتهای عمیق و پیچیده هسته (Deep and Complex Kernel States) را بدون نیاز به اطلاعات اشکالزدایی (Debug Information) مورد کاوش قرار دهد. این ابزار ۲۱ Crash منحصربهفرد و افشاشدهنشده (Undisclosed Unique Crashes) را در Windows 7 و Windows Server 2008 شناسایی کرد که شامل سه آسیبپذیری بحرانی (Critical Vulnerabilities) بود. پنج مورد از آسیبپذیریهای کشفشده، به مدت ۱۴ سال در سیستم وجود داشتند و حتی در نسخه اولیه Windows XP نیز قابل تحریک (Trigger) بودند.
۶.۶ فازرهای دستگاههای تعبیهشده، درایورها و مؤلفهها (Fuzzers for Embedded Devices, Drivers and Components)
۱) YMIR:
Kim و همکاران [29] تولید خودکار گرامرهای فازینگ (Automatic Generation of Fuzzing Grammars) را با استفاده از آزمون کانکولیک در سطح API (API-Level Concolic Testing) پیشنهاد کردند و ابزاری با نام YMIR را برای خودکارسازی آزمون فازینگ جعبهسفید (White-Box Fuzz Testing) روی کنترلهای ActiveX پیادهسازی کردند. این ابزار یک کنترل ActiveX را بهعنوان ورودی دریافت میکند و گرامرهای فازینگ را بهعنوان خروجی تولید میکند. در آزمون کانکولیک در سطح API، قیود در سطح توابع کتابخانهای (Library Functions) جمعآوری میشوند، نه در سطح دستورالعملهای ماشین (Instruction Level). بنابراین این روش میتواند سریعتر اما کمدقتتر باشد.
۲) vUSBf:
vUSBf [151] نخستینبار در Black Hat Europe 2014 معرفی شد. این ابزار یک چارچوب فازینگ برای درایورهای USB (USB Driver Fuzzing Framework) است. این چارچوب یک فازر مجازی USB (Virtual USB Fuzzer) را بر پایه Kernel Virtual Machine (KVM) در Linux و پروتکل USB Redirection در QEMU پیادهسازی میکند. vUSBf امکان تعریف پویا (Dynamic Definition) چندین میلیون مورد آزمون را با استفاده از یک پیکربندی ساده XML فراهم میکند. هر آزمون با یک شناسه منحصربهفرد (Unique Identification) علامتگذاری میشود و در نتیجه قابل بازتولید (Reproducible) است. این ابزار قادر است باگهای زیر را در هسته لینوکس و درایورهای دستگاهها تحریک کند:
- Null-Pointer Dereference: عدم ارجاع به اشارهگر تهی
- Kernel Paging Request: درخواست صفحهبندی هسته
- Kernel Panic: ازکارافتادگی بحرانی هسته سیستمعامل
- Bad Page State: وضعیت نامعتبر صفحه
- Segmentation Fault: خطای دسترسی به بخش حافظه (Segmentation Fault)
پژوهشهای دیگری نیز در این حوزه انجام شدهاند؛ از جمله یک چارچوب مقرونبهصرفه برای آزمون USB [152] و VDF، یک فازر تکاملی هدفمند برای دستگاههای مجازی (Targeted Evolutionary Fuzzer of Virtual Devices) [153]. علاوه بر فازرهای ذکرشده، ابزارهای عملی دیگری نیز وجود دارند، از جمله perf_fuzzer [154] برای فراخوانی سیستمی perf_event_open() ، libFuzzer [155] برای فازینگ کتابخانهها ، Modbus/TCP Fuzzer [156] برای سیستمهای صنعتی متصل به شبکه ، یک فازر برای گذرگاههای I/O (I/O Buses) [157] ، یک فازر برای گواهیهای دیجیتال (Digital Certificates) [158] و Gaslight [159] برای چارچوبهای تحلیل جرمشناسی حافظه (Memory Forensics Frameworks) . علاوه بر این، با ترکیب فازرها با آشکارسازهای خطای حافظه (Memory Error Detectors)، مانند AddressSanitizer متعلق به Clang [83] و MemorySanitizer [160]، میتوان قابلیت فازرها را برای آشکارسازی باگهای پنهانتر، در مقایسه با باگهای سطحی، افزایش داد.
۷. مسیرهای پژوهشی آینده (FUTURE DIRECTIONS)
در این بخش، با بررسی برخی از مسیرهای پژوهشی احتمالی آینده در حوزه تکنیک فازینگ به RQ3 پاسخ میدهیم. اگرچه نمیتوانیم مسیرهای دقیقی را که پژوهشهای فازینگ در آینده دنبال خواهند کرد، با اطمینان پیشبینی کنیم، اما بر اساس مقالات بررسیشده میتوان برخی روندها (Trends) را شناسایی و جمعبندی کرد. این روندها میتوانند در تعیین و هدایت مسیرهای پژوهشی آینده مؤثر باشند. در ادامه، جهتگیریهای پژوهشی آینده را در محورهای زیر مورد بحث قرار خواهیم داد؛ با این امید که این بحث بتواند الهامبخش پژوهشها و فعالیتهای عملیاتی آینده باشد.
۷.۱ اعتبارسنجی ورودی و پوشش (Input Validation and Coverage)
زبانهای ورودی بیش از حد پیچیده، با مشخصات سهلانگارانه یا بهصورت نادرست پیادهسازیشده، که مجموعه ورودیهای معتبری را توصیف میکنند که یک برنامه کاربردی باید قادر به پردازش آنها باشد، ریشه بسیاری از آسیبپذیریهای امنیتی هستند [161]. برخی سیستمها نسبت به قالبهای ورودی سختگیر هستند (برای مثال، پروتکلهای شبکه، کامپایلرها و مفسرها و غیره)؛ ورودیهایی که الزامات قالب را برآورده نکنند، در مراحل اولیه اجرا رد میشوند. برای فازینگ این نوع برنامههای هدف، فازر باید موارد آزمونیای تولید کند که بتوانند از اعتبارسنجی ورودی عبور کنند. پژوهشهای بسیاری این مسئله را هدف قرار داده و پیشرفت چشمگیری در این زمینه داشتهاند؛ برای مثال، [162] در زمینه باگهای رشتهای، [163] و [164] در زمینه باگهای اعداد صحیح، [165] در زمینه فیلترهای ایمیل، و [166] در زمینه باگهای بافر.
مسائل حل نشده در این حوزه شامل پرداختن به عملیات ممیز شناور (FP) است (برای مثال، Csmith، که یک فازر شناختهشده برای کامپایلر C است، برنامههای دارای عملیات ممیز شناور تولید نمیکند)، و همچنین بهکارگیری تکنیکهای موجود برای زبانهای دیگر (برای مثال، اعمال CLP بر زبان C) و غیره. علاوه بر این، Rawat و همکاران [108] نشان دادند که استنتاج ویژگیهای ورودی از طریق تحلیل رفتار برنامه، راهبردی عملی و مقیاسپذیر برای بهبود عملکرد فازینگ و همچنین مسیری امیدبخش برای پژوهشهای آینده در این حوزه است. همانطور که در بخش V-A اشاره کردیم، اگرچه TaintScope میتواند نقاط جمعآزما (checksum) را با دقت مکانیابی کرده و اثربخشی فازینگ را بهطور چشمگیری افزایش دهد، همچنان جای پیشرفت وجود دارد. نخست، این ابزار قادر به پردازش امضای دیجیتال و سایر طرحهای بررسی امنیتی نیست. دوم، اثربخشی آن بهشدت تحت تأثیر دادههای ورودی رمزنگاریشده قرار میگیرد. سوم، وابستگیهای جریان کنترل را نادیده میگیرد و همه انواع دستورالعملهای x86 را ابزارگذاری نمیکند. این موارد همچنان مسائل حلنشده هستند.
۷.۲ فازینگ هوشمند (Smart Fuzzing)
بسیاری از تکنیکهای دیگر تحلیل برنامه در فازینگ هوشمند ادغام شدهاند [167]، [168]؛ از جمله اجرای کانکولیک (Concolic Execution)، تحلیل پویای جریان داده آلوده (Dynamic Taint Analysis) و غیره. اگرچه این تکنیکها مزایای بسیاری به همراه دارند، مشکلاتی را نیز ایجاد میکنند؛ از جمله انفجار مسیر (Path Explosion) و اجرای نمادین غیردقیق (Imprecise Symbolic Execution) در آزمون کانکولیک، و کمآلودگی (Undertainting) و بیشآلودگی (Overtainting) در تحلیل پویای جریان داده آلوده. بهعنوان نمونه، Dolan-Gavitt و همکاران [169] هزاران باگ را در هشت برنامه واقعی، از جمله bash، tshark و GNU Coreutils، تزریق کردند. آنها ارزیابی کردند و دریافتند که یک فازر برجسته و یک یابنده باگ مبتنی بر اجرای نمادین (Symbolic Execution-Based Bug Finder) توانستند برخی، اما نه همه، باگهای تزریقشده را مکانیابی کنند. علاوه بر این، انجام فازینگ بهصورت مقیاسپذیر و کارآمد همچنان چالشبرانگیز است. Bounimova و همکاران [107] چالشهای کلیدی اجرای فازینگ جعبهسفید در مقیاس بزرگ را ارائه کردند که شامل چالشهای موجود در اجرای نمادین، تولید و حل قیود، جستوجوی طولانیمدت فضای حالت، تنوع، تحمل خطا و استفاده مداوم هستند. همه این مسائل شایسته بررسی عمیقتر هستند.
۷.۳ فیلتر کردن خروجیهای فازینگ (Filtering Fuzzing Outputs)
در طول چرخه حیات توسعه نرمافزار، زمان و بودجه اختصاصیافته برای رفع باگها معمولاً محدود است. بنابراین، دغدغه اصلی توسعهدهنده، رفع باگهای شدیدتر در چارچوب این محدودیتهاست. برای مثال، Podgurski و همکاران [80] پشتیبانی خودکار برای دستهبندی خرابیهای گزارششده نرمافزار را با هدف تسهیل اولویتبندی آنها و تشخیص عللشان پیشنهاد کردند. Zhang و همکاران [170] پیشنهاد کردند که موارد آزمون بر اساس معیار شباهت موارد آزمون (Test Case Similarity Metric) انتخاب شوند تا معنای عمیق برنامه (Deep Program Semantics) مورد کاوش قرار گیرد. آزمون تفاضلی (Differential Testing) میتواند برای تعیین هزینه ارزیابی نتایج آزمون مفید باشد [171]، [172]. بهطور خلاصه، در حال حاضر پژوهش اندکی درباره فیلتر کردن موارد آزمون مهمترِ ایجادکننده خرابی از میان حجم زیادی از خروجیهای فازینگ انجام شده است. این مسیر پژوهشی از اهمیت عملی برخوردار است.
۷.۴ تولید و انتخاب بذر/ ورودی (Seed/Input Generation and Selection)
نتیجه فازینگ با کیفیت فایلهای بذر (Seed)/ورودی (Input) همبستگی دارد. بنابراین، چگونگی انتخاب فایلهای بذر مناسب به منظور کشف باگهای بیشتر، مسئلهای مهم است. با تلاش برای به حداکثر رساندن پوشش آزمون دامنه ورودی (Input Domain)، روشها یا الگوریتمهای مربوط به مدیریت موارد آزمون در ART [58]، [173]–[176] ممکن است مفید باشند. برای مثال، Pacheco و همکاران [53] یک تکنیک تولید آزمون تصادفی هدایتشده با بازخورد (Feedback-Directed Random Test Generation) ارائه کردند که در آن یک ورودی از پیش طراحیشده اجرا شده و در برابر مجموعهای از قراردادها (Contracts) و فیلترها (Filters) بررسی میشد. نتیجه اجرای برنامه تعیین میکند که آیا ورودی تکراری (Redundant)، غیرقانونی (Illegal)، ناقض قرارداد (Contract Violating) یا برای تولید ورودیهای بیشتر مفید (Useful) است.
بااینحال، Arcuri و Briand [59] در آزمایشهای گسترده نشان دادند که ART حتی در مسائل ساده نیز، هنگامی که محاسبات فاصله میان موارد آزمون در نظر گرفته شود، بسیار ناکارآمد است. Classfuzz [177] فایلهای کلاس بذر (Seed) را با استفاده از مجموعهای از عملگرهای جهش از پیش تعریف شده (Predefined Mutation Operators) جهش داد، از نمونهبرداری زنجیره مارکوف مونتکارلو (Markov Chain Monte Carlo Sampling) برای هدایت انتخاب جهشدهنده استفاده کرد و یکتایی پوشش (Coverage Uniqueness) را به عنوان معیاری برای پذیرش موارد نماینده به کار گرفت. Shastry و همکاران [178] پیشنهاد کردند که با تحلیل ایستای جریان کنترل و جریان داده برنامه (Static Analysis of Program Control and Data Flow)، یک فرهنگ ورودی (Input Dictionary) به صورت خودکار ساخته شود و این فرهنگ ورودی در اختیار یک فازر آماده استفاده (Off-the-Shelf Fuzzer) قرار گیرد تا بر تولید ورودی تأثیر بگذارد. طراحی و پیادهسازی الگوریتمهای مؤثرتر، صحیحتر و دقیقتر برای تولید و انتخاب بذر (Seed) همچنان یک مسئله پژوهشی حلنشده است.
۷.۵ ترکیب روشهای مختلف آزمون (Combining Different Testing Methods)
همانطور که در بخش ۴ بحث شد، روشهای فازینگ جعبهسیاه و جعبهسفید/جعبهخاکستری هرکدام مزایا و معایب خاص خود را دارند. بنابراین، چگونگی ترکیب این تکنیکها برای ساخت فازری که هم اثربخش و هم کارآمد باشد، یک مسیر پژوهشی جالب است. چند تلاش در این زمینه انجام شده است [124]، [179]، [48]؛ برای مثال، SYMFUZZ [51] فازینگ مبتنی بر جهش جعبهسیاه را با یک تکنیک جعبهسفید تقویت کرد که به محاسبه نسبت جهش بهینه بر اساس جفتهای برنامه-بذر (program-seed) داده شده کمک میکند. از دیدگاه خُرد، SYMFUZZ برای تولید موارد آزمون دو مرحله اصلی دارد و هر مرحله از یک تکنیک فازینگ متفاوت، یعنی فازینگ جعبهسفید و فازینگ جعبهسیاه، استفاده میکند. بااینحال، از دیدگاه کلان، این روش را میتوان نوعی فازینگ جعبهخاکستری نیز در نظر گرفت. از آنجا که نسبت جهش در فرایند فازینگ جعبهسیاه آن، در طول فرایند فازینگ جعبهسفید محاسبه میشود، کل فرایند فازینگ از دانش جزئی درباره برنامه هدف استفاده میکند و بنابراین میتوان آن را فازینگ جعبهخاکستری در نظر گرفت. ترکیب فازینگ با سایر تکنیکهای آزمون نیز یک مسیر پژوهشی جالب است. Chen و همکاران [180] گزارش کردند که چگونه آزمون دگردیسی (Metamorphic Testing) [181]–[183]، که یک روش آزمون نسبتاً جدید است و روابط میان ورودیها و خروجیهای چندین اجرای برنامه را بررسی میکند، توانسته است باگهای ناشناخته قبلی را در برنامههای کاربردی حیاتی دنیای واقعی شناسایی کند. این موضوع نشان میدهد که استفاده از دیدگاههای متنوع و ترکیب چندین روش میتواند به آزمون نرمافزار با قابلیت اطمینان یا امنیت بالاتر کمک کند. Garn و Simos [184] قابلیت کاربرد یک روش جامع را که آزمون ترکیبیاتی (Combinatorial Testing) و فازینگ را برای رابطهای فراخوانی سیستمی هسته Linux (Linux Kernel System Call Interfaces) به کار میگیرد، نشان دادند.
۷.۶ ترکیب سایر تکنیکها با فازینگ (Combining Other Techniques With Fuzzing)
فازرها به میزان پوشش آزمون و در دسترس بودن موارد آزمون مناسب محدود هستند. از آنجا که تحلیل ایستا میتواند جستوجوی گستردهتری را برای الگوهای آسیبپذیر کد انجام دهد، Shastry و همکاران [185] با شروع از تعداد اندکی از خرابیهای برنامه که توسط فازر کشف شده بودند، یک الگوریتم ساده اما مؤثر تطبیق و رتبهبندی (Match-Ranking) را پیادهسازی کردند که از دادههای پوشش آزمون برای متمرکز کردن توجه بر تطبیقهایی استفاده میکرد که شامل کد آزموننشده بودند و نشان دادند که تحلیل ایستا میتواند بهطور مؤثری مکمل فازینگ باشد. تکنیکهای تحلیل ایستا، مانند اجرای نمادین و تحلیل جریان کنترل/داده، میتوانند اطلاعات ساختاری مفیدی برای فازینگ فراهم کنند [186]؛ بااینحال، اجرای نمادین برای فازینگ دارای محدودیتهایی است و در نتیجه برخی مسائل حلنشده باقی میمانند: ۱) تنها ویژگیهای عمومی بررسی میشوند ــ بسیاری از انحرافات از رفتار مشخصشده شناسایی نمیشوند؛ و ۲) بسیاری از برنامهها بهطور کامل برای اجرای نمادین مناسب نیستند، زیرا قیود دشوار ایجاد میکنند و در نتیجه برخی بخشهای برنامه بدون پوشش باقی میمانند [187].
Havrikov [188] یک رویکرد ترکیبی پیشنهاد کرد که در آن فازینگ میتواند از تحلیلهای سبکوزن مختلف بهرهمند شود. این تحلیلها علاوه بر برنامه هدف، از منابع اطلاعاتی متعددی استفاده میکنند، مانند ورودی و اجرا (برای مثال، توصیف قالب ورودی هدف در قالب دستور زبانهای مستقل از متن توسعهیافته (Extended Context-Free Grammars)) یا شمارندههای سختافزاری (Hardware Counters). تکنیکهای یادگیری ماشین برای تولید خودکار گرامرهای ورودی برای فازینگ مبتنی بر گرامر مفید هستند [189]. نظریه بهینهسازی نیز میتواند برای ایجاد راهبردهای جستوجوی مؤثر در فازینگ مورد استفاده قرار گیرد [83]، [190]، [191]. برنامهریزی ژنتیک یا الگوریتمهای ژنتیک در [122]، [192] و [193] برای هدایت فازرهای مربوطه مورد استفاده قرار گرفتهاند. Dai و همکاران [194] یک تکنیک نوین فازینگ رابط کاربری (UI Fuzzing) پیشنهاد کردند که هدف آن اجرای برنامهها بهگونهای است که بتوان مسیرهای اجرایی متفاوت را مورد کاوش قرار داد؛ این روش مستلزم آن بود که آزمونگر یک پروفایل جامع شبکه (Comprehensive Network Profile) ایجاد کند. ما معتقدیم که همچنان امکان بهبود روشهای ترکیبی موجود و بهرهگیری از سایر تکنیکها در کنار فازینگ وجود دارد.
۸. نتیجهگیری
فازینگ یک تکنیک خودکار و مؤثر برای آزمون نرمافزار است که قادر به کشف هر دو نوع باگهای مربوط به صحت عملکرد (Correctness Bugs) و باگهای امنیتی (Security Bugs) میباشد. فازینگ را میتوان بر اساس میزان اطلاعاتی که از برنامه هدف به دست میآورد، به سه دسته جعبهسیاه، جعبهسفید و جعبهخاکستری تقسیم کرد. در فرایند فازینگ، روش پایه برای یافتن باگها، تولید تعداد زیادی مورد آزمون است که امید میرود بتوانند قطعهکدهای ایجادکننده باگ را در برنامه هدف فعال سازند. با این حال، در فازینگ الگوی ثابتی برای تولید موارد آزمون وجود ندارد و ازاینرو، این فرایند تا حد زیادی به خلاقیت توسعهدهندگان وابسته است. ما یک مطالعه مروری درباره فازینگ ارائه کردیم که ۱۷۱ مقاله منتشرشده بین ژانویه ۱۹۹۰ و ژوئن ۲۰۱۷ را پوشش میدهد. نتایج این مطالعه نشان میدهد که فازینگ موضوعی روبهرشد است و روند مشارکتهای پژوهشی در این زمینه نیز افزایشی است. در حال حاضر، تکنیکهای ترکیبشده با فازینگ شامل الگوریتم ژنتیک، تحلیل جریان داده آلوده، اجرای نمادین، روشهای هدایتشده بر اساس پوشش و غیره هستند. ابزارهای فازینگ موجود بهطور گسترده در انواع مختلف محصولات صنعتی، از جمله کامپایلرها، پروتکلهای شبکه، برنامههای کاربردی، هستههای سیستمعامل و غیره، از فایلهای دودویی گرفته تا کد منبع، به کار گرفته شدهاند و دهها هزار باگ نرمافزاری را کشف کردهاند که بسیاری از آنها قابل بهرهبرداری بودهاند. در نهایت، برخی از مسائل حل نشده مرتبط با فازینگ را مورد بحث قرار دادیم. ما پژوهشها و فعالیتهای عملی بیشتر را برای پرداختن به این مسائل، با هدف گسترش بهکارگیری فازینگ در یکپارچهسازی مداوم یک سیستم نرمافزاری، تشویق میکنیم.
منابع
[1] P. Oehlert, “Violating assumptions with fuzzing,” IEEE Security Privacy,vol. 3, no. 2, pp. 58–62, Mar. 2005.
[2] B. P. Miller, L. Fredriksen, and B. So, “An empirical study of the relia-bility of UNIX utilities,” Commun. ACM, vol. 33, pp. 2–44, 1990.
[3] B. P. Miller et al., “Fuzz revisited: A re-examination of the reliabilityof UNIX utilities and services,” Dept. Comput. Sci., Univ. Wisconsin-Madison, Madison, WI, USA, Tech. Rep. #1268, 1995.
[4] J. E. Forrester and B. P. Miller, “An empirical study of the robust-ness of windows NT applications using random testing,” in Proc. 4thConf. USENIX Windows Syst. Symp., Seattle, WA, USA, vol. 4, 2000,pp. 1–10.
[5] B. P. Miller, G. Cooksey, and F. Moore, “An empirical study of therobustness of MacOS applications using random testing,” in Proc. Int.Workshop Random Test., 2006, pp. 46–54.
[6] R. Hamlet, “Random testing,” in Encyclopedia of Software Engineering.New York, NY, USA: Wiley, 1994, pp. 970–978.
[7] G. McGraw, “Silver bullet talks with Bart Miller,” IEEE Security Privacy,vol. 12, no. 5, pp. 6–8, Sep. 2014.
[8] J. Viide et al., “Experiences with model inference assisted fuzzing,” inProc. Conf. USENIX Workshop Offensive Technol., 2008, Art. no. 2.
[9] H. Yang, Y. Zhang, Y. Hu, and Q. Liu, “IKE vulnerability discoverybased on fuzzing,” Security Commun. Netw., vol. 6, no. 7, pp. 889–901,2013.
[10] J. Yan, Y. Zhang, and D. Yang, “Structurized grammar-based fuzz testingfor programs with highly structured inputs,” Security Commun. Netw.,vol. 6, no. 11, pp. 1319–1330, 2013.
[11] N. Palsetia, G. Deepa, F. A. Khan, P. S. Thilagam, and A. R. Pais,“Securing native XML database-driven web applications from XQueryinjection vulnerabilities,” J. Syst. Softw., vol. 122, pp. 93–109, 2016.
[12] M. de Jonge and E. Visser, “Automated evaluation of syntax error re-covery,” in Proc. 27th IEEE/ACM Int. Conf. Autom. Softw. Eng., 2012,pp. 322–325.
[13] J. D. DeMott, R. J. Enbody, and W. F. Punch, “Systematic bug finding andfault localization enhanced with input data tracking,” Comput. Security, vol. 32, pp. 130–157, 2013.
[14] P. Godefroid, M. Y. Levin, and D. Molnar, “SAGE: Whitebox fuzzingfor security testing,” Queue, vol. 10, no. 1, pp. 20:20–20:27, 2012.
[15] D. Vyukov, Syzkaller—Linux Kernel Fuzzer. [Online]. Available:https://github.com/google/syzkaller. Accessed on: Jul. 12, 2016.
[16] D. Babic, “SunDew: Systematic automated security testing,” in Proc.24th ACM SIGSOFT Int. SPIN Symp. Model Checking Softw., SantaBarbara, CA, USA, 2017, p. 10.
[17] J. DeMott, “The evolving art of fuzzing,” in Proc. DEF CON Conf.,vol. 14, 2006, pp. 1–25.
[18] R. McNally, K. Yiu, D. Grove, and D. Gerhardy, “Fuzzing: The state ofthe art,” DTIC Document, 2012.
[19] T. L. Munea, H. Lim, and T. Shon, “Network protocol fuzz testing for in-formation systems and applications: A survey and taxonomy,” Multimed.Tools Appl., vol. 75, no. 22, pp. 14745–14757, Nov. 2016.
[20] B. Kitchenham, Procedures for Performing Systematic Reviews, KeeleUniv., NICTA, Keele, UK, 2004.
[21] J. Webster and R. T. Watson, “Analyzing the past to prepare for thefuture: Writing a literature review,” MIS Quart., vol. 26, pp. 1–12, 2002.
[22] M. Woo, S. K. Cha, S. Gottlieb, and D. Brumley, “Scheduling black-box mutational fuzzing,” in Proc. 2013 ACM SIGSAC Conf. Comput.Commun. Security, New York, NY, USA, 2013, pp. 511–522.
[23] S. Bekrar, C. Bekrar, R. Groz, and L. Mounier, “A taint based approachfor smart fuzzing,” in Proc. IEEE 5th Int. Conf. Softw. Test. VerificationValidation 2012, 2012, pp. 818–825.
[24] G. Wen, Y. Zhang, Q. Liu, and D. Yang, “Fuzzing the ActionScript vir-tual machine,” in Proc. 8th ACM SIGSAC Symp. Inf. Comput. Commun.Security, New York, NY, USA, 2013, pp. 457–468.
[25] R. Brummayer and A. Biere, “Fuzzing and delta-debugging SMTsolvers,” in Proc. 7th Int. Workshop Satisfiability Modulo Theories, 2009,pp. 1–5.
[26] Y. Chen et al., “Taming compiler fuzzers,” in Proc. 34th ACM SIGPLANConf. Program. Lang. Design Implementation, New York, NY, USA,2013, pp. 197–208.
[27] American Fuzzy Lop, AFL. [Online]. Available: http://lcamtuf.coredump.cx/afl/. Accessed on: Jul. 12, 2016.
[28] E. J¨a¨askel¨a, “Genetic algorithm in code coverage guided fuzz testing,”Dept. Comput. Sci. Eng., Univ. Oulu, 2016.
[29] S. Y. Kim, S. D. Cha, and D.-H. Bae, “Automatic and lightweight gram-mar generation for fuzz testing,” Comput. Security, vol. 36, pp. 1–11,2013.
[30] J. de Ruiter and E. Poll, “Protocol state fuzzing of TLS implementations,”in Proc. 24th USENIX Security Symp., 2015, pp. 193–206.
[31] B. P. Miller, L. Fredriksen, and B. So, “An empirical study of the relia-bility of UNIX utilities,” Commun. ACM, vol. 33, pp. 32–44, 1990.
[32] D. Jones, “Trinity: A linux system call fuzz tester.” [Online]. Available:http://codemonkey.org.uk/projects/trinity/. Accessed on: Jul. 12, 2016.
[33] E. Bazzoli, C. Criscione, F. Maggi, and S. Zanero, “XSS PEEKER:Dissecting the XSS exploitation techniques and fuzzing mechanismsof blackbox web application scanners,” in Proc. 31st IFIP Int. Conf. Inf. Security Privacy, Ghent, Belgium, May 30–Jun. 1, 2016, vol. 471,pp. 243–258.
[34] F. Duch`ene, S. Rawat, J. L. Richier, and R. Groz, “LigRE: Reverse-engineering of control and data flow models for black-box XSS detec-tion,” in Proc. 20th Working Conf. Reverse Eng., 2013, pp. 252–261.
[35] W. Drewry and T. Ormandy, “Flayer: Exposing application internals,”in Proc. 1st USENIX Workshop Offensive Technol., Boston, MA, USA,Aug. 6, 2007, pp. 1–9.
[36] T. Wang, T. Wei, G. Gu, and W. Zou, “TaintScope: A checksum-awaredirected fuzzing tool for automatic software vulnerability detection,” inProc. IEEE Symp. Security Privacy, 2010, pp. 497–512.
[37] V. Ganesh, T. Leek, and M. Rinard, “Taint-based directed whiteboxfuzzing,” in Proc. IEEE 31st Int. Conf. Softw. Eng., 2009, pp. 474–484.
[38] P. Godefroid, M. Y. Levin, and D. A. Molnar, “Automated whitebox fuzztesting,” in Proc. Netw. Distrib. Syst. Security Symp., San Diego, CA,USA, Feb. 10–13, 2008, pp. 1–16.
[39] C. Cadar and K. Sen, “Symbolic execution for software testing: Threedecades later,” Commun. ACM, vol. 56, no. 2, pp. 82–90, 2013.
[40] C.-K. Luk et al., “Pin: Building customized program analysis toolswith dynamic instrumentation,” in Proc. ACM SIGPLAN Conf. Program.Lang. Des. Implementation, New York, NY, USA, 2005, pp. 190–200.
[41] N. Nethercote and J. Seward, “Valgrind: A framework for heavyweightdynamic binary instrumentation,” in Proc. 28th ACM SIGPLAN Conf.Program. Lang. Des. Implementation, New York, NY, USA, 2007,pp. 89–100.
[42] R. L. J. Seagle, “A framework for file format fuzzing with genetic al-gorithms,” Ph.D. dissertation, Univ. Tennessee, Knoxville, TN, USA,2012.
[43] Y.-H. Choi, M.-W. Park, J.-H. Eom, and T.-M. Chung, “Dynamic binaryanalyzer for scanning vulnerabilities with taint analysis,” Multimed. ToolsAppl., vol. 74, no. 7, pp. 2301–2320, 2015.
[44] M. G. Kang, S. McCamant, P. Poosankam, and D. Song, “DTA++:Dynamic taint analysis with targeted control-flow propagation,” in Proc.Netw. Distrib. Syst. Security Symp., San Diego, CA, USA, Feb. 6–9,2011, pp. 1–14.
[45] S. Bekrar, C. Bekrar, R. Groz, and L. Mounier, “Finding software vul-nerabilities by smart fuzzing,” in Proc. 4th IEEE Int. Conf. Softw. Test.Verification Validation, 2011, pp. 427–430.
[46] S. K. Fayaz, T. Yu, Y. Tobioka, S. Chaki, and V. Sekar, “BUZZ: Testingcontext-dependent policies in stateful networks,” in Proc. USENIX Symp.Netw. Syst. Des. Implementation, 2016, pp. 275–289.
[47] A. Rebert et al., “Optimizing seed selection for fuzzing,” in Proc. 23rdUSENIX Security Symp., San Diego, CA, USA, 2014, pp. 861–875.
[48] U. Karg´en and N. Shahmehri, “Turning programs against each other:High coverage fuzz-testing using binary-code mutation and dynamicslicing,” in Proc. 10th Joint Meeting Found. Softw. Eng., New York, NY,USA, 2015, pp. 782–792.
[49] H. Liang, Y. Wang, H. Cao, and J. Wang, “Fuzzing the font parserof compound documents,” in Proc. 4th IEEE Int. Conf. Cyber Secu-rity Cloud Comput., New York, NY, USA, Jun. 26–28, 2017, pp. 237–242.
[50] J. Wang, B. Chen, L. Wei, and Y. Liu, “Skyfire: Data-driven seed genera-tion for fuzzing,” in Proc. IEEE Symp. Security Privacy, 2017, pp. 579–594.
[51] S. K. Cha, M. Woo, and D. Brumley, “Program-adaptive mu-tational fuzzing,” in Proc. IEEE Symp. Security Privacy, 2015, pp. 725–741.
[52] A. Arcuri, M. Z. Z. Iqbal, and L. C. Briand, “Formal analysis of theeffectiveness and predictability of random testing,” in Proc. 19th Int.Symp. Softw. Test. Anal., Trento, Italy, Jul. 12–16, 2010, pp. 219–230.
[53] C. Pacheco, S. K. Lahiri, M. D. Ernst, and T. Ball, “Feedback-directedrandom test generation,” in Proc. Int. Conf. Softw. Eng., 2007, pp. 75–84.
[54] K. Yatoh, K. Sakamoto, F. Ishikawa, and S. Honiden, “Feedback-controlled random test generation,” in Proc. Int. Symp. Softw. Test. Anal.2015, Baltimore, MD, USA, Jul. 12–17, 2015, pp. 316–326.
[55] FFmpeg. [Online]. Available: http://samples.ffmpeg.org/. Accessed on:Dec. 15, 2016.
[56] cwebp | WebP, cwebp, Google Developers. [Online]. Available:https://developers.google.com/speed/webp/docs/cwebp. Accessed on:Dec. 15, 2016.
[57] P. M. Comparetti, G. Wondracek, C. Kruegel, and E. Kirda, “Prospex:Protocol specification extraction,” in Proc. 30th IEEE Symp. SecurityPrivacy, 2009, pp. 110–125.
[58] T. Y. Chen, H. Leung, and I. K. Mak, “Adaptive random testing,” in Proc.Annu. Asian Comput. Sci. Conf., vol. 3321, 2004, pp. 320–329.
[59] A. Arcuri and L. C. Briand, “Adaptive random testing: An illusion ofeffectiveness?” in Proc. 20th Int. Symp. Softw. Test. Anal., Toronto, ON,Canada, Jul. 17–21, 2011, pp. 265–275.
[60] M. Jurczyk, “Effective file format fuzzing-thoughts techniques and re-sults,” in Proc. Black Hat Eur. Conf., London, U.K., 2016, pp. 1–133.
[61] H. C. Kim, Y. H. Choi, and D. H. Lee, “Efficient file fuzz testing usingautomated analysis of binary file format,” J. Syst. Archit., vol. 57, no. 3,pp. 259–268, 2011.
[62] T. Wang, T. Wei, G. Gu, and W. Zou, “Checksum-aware fuzzing com-bined with dynamic taint analysis and symbolic execution,” ACM Trans.Inf. Syst. Security, vol. 14, no. 2, pp. 15:1–15:28, 2011.
[63] M. H¨oschele and A. Zeller, “Mining input grammars from dynamictaints,” in Proc. 31st IEEE/ACM Int. Conf. Autom. Softw. Eng., 2016,pp. 720–725.
[64] Y. Li, B. Chen, M. Chandramohan, S.-W. Lin, Y. Liu, and A. Tiu, “Steelix:Program-state based binary fuzzing,” in Proc. 11th Joint Meeting Found.Softw. Eng., New York, NY, USA, 2017, pp. 627–637.
[65] X. Y. Zhu and Z. Y. Wu, “A new fuzzing technique using niche geneticalgorithm,” Adv. Mater. Res., vol. 756, pp. 4050–4058, 2013.
[66] X. Zhu, Z. Wu, and J. W. Atwood, “A new fuzzing method using multidata samples combination,” J. Comput., vol. 6, no. 5, pp. 881–888,May 2011.
[67] K. Dewey, J. Roesch, and B. Hardekopf, “Fuzzing the rust typecheckerusing CLP (T),” in Proc. 30th IEEE/ACM Int. Conf. Autom. Softw. Eng.,Lincoln, NE, USA, Nov. 9–13, 2015, pp. 482–493.
[68] K. Dewey, J. Roesch, and B. Hardekopf, “Language fuzzing using con-straint logic programming,” in Proc. 29th ACM/IEEE Int. Conf. Autom.Softw. Eng., New York, NY, USA, 2014, pp. 725–730.
[69] C. Cao, N. Gao, P. Liu, and J. Xiang, “Towards analyzing the inputvalidation vulnerabilities associated with android system services,” inProc. 31st Annu. Comput. Security Appl. Conf., New York, NY, USA,2015, pp. 361–370.
[70] C. Lidbury, A. Lascu, N. Chong, and A. F. Donaldson, “Many-corecompiler fuzzing,” in Proc. 36th ACM SIGPLAN Conf. Program. Lang.Des. Implementation, New York, NY, USA, 2015, pp. 65–76.
[71] J. Zhao, Y. Wen, and G. Zhao, “H-Fuzzing: A new heuristic method forfuzzing data generation,” in Network and Parallel Computing, E. Altmanand W. Shi, Eds. Berlin, Germany: Springer, 2011, pp. 32–43.
[72] H. Dai, C. Murphy, and G. E. Kaiser, “CONFU: Configuration fuzzingtesting framework for software vulnerability detection,” Int. J. SecureSoftw. Eng., vol. 1, no. 3, pp. 41–55, 2010.
[73] S. Rasthofer, S. Arzt, S. Triller, and M. Pradel, “Making malory behavemaliciously: Targeted fuzzing of android execution environments,” inProc. 39th Int. Conf. Softw. Eng., Piscataway, NJ, USA, 2017, pp. 300–311.
[74] P. Tsankov, M. T. Dashti, and D. A. Basin, “Semi-valid input coveragefor fuzz testing,” in Proc. Int. Symp. Softw. Test. Anal., 2013, pp. 56–66.
[75] O. Bastani, R. Sharma, A. Aiken, and P. Liang, “Synthesizing programinput grammars,” in Proc. 38th ACM SIGPLAN Conf. Program. Lang.Des. Implementation, New York, NY, USA, 2017, pp. 95–110.
[76] K. Chen, Y. Zhang, and P. Liu, “Dynamically discovering likely memorylayout to perform accurate fuzzing,” IEEE Trans. Rel., vol. 65, no. 3,pp. 1180–1194, Sep. 2016.
[77] A. Groce, C. Zhang, E. Eide, Y. Chen, and J. Regehr, “Swarm testing,” inProc. Int. Symp. Softw. Test. Anal., Minneapolis, MN, USA, Jul. 15–20,2012, pp. 78–88.
[78] M. A. Alipour, A. Groce, R. Gopinath, and A. Christi, “Generating fo-cused random tests using directed swarm testing,” in Proc. 25th Int.Symp. Softw. Test. Anal., Saarbr¨ucken, Germany, Jul. 18–20, 2016,pp. 70–81.
[79] P. D. Marinescu and C. Cadar, “High-coverage symbolic patch test-ing,” in Proc. 19th Int. Workshop Model Checking Softw., Oxford, U.K.,vol. 7385, Jul. 23–24, 2012, pp. 7–21.
[80] A. Podgurski et al., “Automated support for classifying software failurereports,” in Proc. 25th Int. Conf. Softw. Eng., Washington, DC, USA,2003, pp. 465–475.
[81] P. Francis, D. Leon, M. Minch, and A. Podgurski, “Tree-based methodsfor classifying software failures,” in Proc. 15th Int. Symp. Softw. Rel.Eng., Saint-Malo, Bretagne, France, Nov. 2–5, 2004, pp. 451–462. 1216 IEEE TRANSACTIONS ON RELIABILITY, VOL. 67, NO. 3, SEPTEMBER 2018[82] Research Insights Volume 9—Modern Security Vulnerability Discovery,NCC Group, 2016. [Online]. Available: https://www.nccgroup.trust/uk/our-research/research-insights-vol-9-modern-security-vulnerability-discovery/. Accessed on: Nov. 15, 2016.
[83] K. Serebryany, D. Bruening, A. Potapenko, and D. Vyukov, “AddressSanitizer: A fast address sanity checker,” in Proc. USENIX Annu. Tech.Conf., Boston, MA, USA, Jun. 13–15, 2012, pp. 309–318.
[84] V. T. Pham, W. B. Ng, K. Rubinov, and A. Roychoudhury, “Hercules:Reproducing crashes in real-world application binaries,” in Proc. 37thIEEE Int. Conf. Softw. Eng., vol. 1, 2015, pp. 891–901.
[85] A. Lanzi, L. Martignoni, M. Monga, and R. Paleari, “A smart fuzzer for×86 executables,” in Proc. 3rd Int. Workshop Softw. Eng. Secure Syst.,2007, pp. 1–8.
[86] I. Haller, A. Slowinska, M. Neugschwandtner, and H. Bos, “Dowsing foroverflows: A guided fuzzer to find buffer boundary violations,” in Proc.22th USENIX Security Symp., Washington, DC, USA, Aug. 14–16, 2013, pp. 49–64.
[87] Y. Shoshitaishvili et al., “SOK: (State of) The art of war: Offensivetechniques in binary analysis,” in Proc. IEEE Symp. Security Privacy,2016, pp. 138–157.
[88] P. Godefroid, “Compositional dynamic test generation,” in Proc. 34thAnnu. ACM SIGPLAN-SIGACT Symp. Principles Program. Lang., NewYork, NY, USA, 2007, pp. 47–54.
[89] P. Godefroid, “Higher-order test generation,” in Proc. 32nd ACM SIG-PLAN Conf. Program. Lang. Des. Implementation, New York, NY, USA,2011, pp. 258–269.
[90] P. Boonstoppel, C. Cadar, and D. R. Engler, “RWset: Attacking path ex-plosion in constraint-based test generation,” in Proc. 14th Int. Conf. ToolsAlgorithms Construction Anal. Syst., Budapest, Hungary, vol. 4963, Mar.29–Apr. 6, 2008, pp. 351–366.
[91] V. Kuznetsov, J. Kinder, S. Bucur, and G. Candea, “Efficient state merg-ing in symbolic execution,” in Proc. 33rd ACM SIGPLAN Conf. Pro-gram. Lang. Des. Implementation, New York, NY, USA, 2012, pp. 193–204.
[92] C. Cadar, D. Dunbar, and D. R. Engler, “KLEE: Unassisted and auto-matic generation of high-coverage tests for complex systems programs,”in Proc. 8th USENIX Symp. Operating Syst. Des. Implementation, SanDiego, CA, USA, Dec. 8–10, 2008, pp. 209–224.
[93] P. Godefroid and D. Luchaup, “Automatic partial loop summarization indynamic test generation,” in Proc. Int. Symp. Softw. Test. Anal., Toronto,ON, Canada, 2011, pp. 23–33.
[94] J. Burnim and K. Sen, “Heuristics for scalable dynamic test generation,” in Proc. 23rd IEEE/ACM Int. Conf. Autom. Softw. Eng., L’Aquila, Italy,Sep. 15–19, 2008, pp. 443–446.
[95] M. B¨ohme, V.-T. Pham, and A. Roychoudhury, “Coverage-based grey-box fuzzing as Markov chain,” in Proc. ACM SIGSAC Conf. Comput.Commun. Security, New York, NY, USA, 2016, pp. 1032–1043.[96] K. B¨ottinger and C. Eckert, “DeepFuzz: Triggering vulnerabilities deeplyhidden in binaries,” in Proc. 13th Int. Conf. Detection Intrusions Malware Vulnerability Assessment, San Sebasti´an, Spain, Jul. 7–8, 2016, pp. 25–34.[97] C. Zhang, A. Groce, and M. A. Alipour, “Using test case reduction andprioritization to improve symbolic execution,” in Proc. Int. Symp. Softw.Test. Anal., San Jose, CA, USA, Jul. 21–26, 2014, pp. 160–170.
[98] K. Sen, D. Marinov, and G. Agha, “CUTE: A concolic unit testingengine for C,” in Proc. 10th Eur. Softw. Eng. Conf. 13th ACM SIGSOFTInt. Symp. Found. Softw. Eng., New York, NY, USA, 2005, pp. 263–272.
[99] V. Chipounov, V. Kuznetsov, and G. Candea, “S2E: A platform for in-vivo multi-path analysis of software systems,” in Proc. 16th Int. Conf.Archit. Support Program. Lang. Oper. Syst., Newport Beach, CA, USA,Mar. 5–11, 2011, pp. 265–278.
[100] M. Mouzarani, B. Sadeghiyan, and M. Zolfaghari, “A smart fuzzingmethod for detecting heap-based vulnerabilities in executable codes,”Security Commun. Netw., vol. 9, no. 18, pp. 5098–5115, 2016.
[101] P. Godefroid, A. Kiezun, and M. Y. Levin, “Grammar-based whiteboxfuzzing,” in Proc. 29th ACM SIGPLAN Conf. Program. Lang. Des. Im-plementation, New York, NY, USA, 2008, pp. 206–215.
[102] P. Godefroid and J. Kinder, “Proving memory safety of floating-pointcomputations by combining static and dynamic program analysis,” inProc. 19th Int. Symp. Softw. Test. Anal., Trento, Italy, Jul. 12–16, 2010,pp. 1–12.
[103] Z. Fu and Z. Su, “Achieving high coverage for floating-point code viaunconstrained programming,” in Proc. 38th ACM SIGPLAN Conf. Pro-gram. Lang. Des. Implementation, New York, NY, USA, 2017, pp. 306–319.
[104] B. Yadegari and S. Debray, “Bit-level taint analysis,” in Proc. 14thIEEE Int. Working Conf. Source Code Anal. Manipulation, Victoria,BC, Canada, Sep. 28–29, 2014, pp. 255–264.
[105] E. J. Schwartz, T. Avgerinos, and D. Brumley, “All you ever wantedto know about dynamic taint analysis and forward symbolic execu-tion (but might have been afraid to ask),” in Proc. 31st IEEE Symp. Security Privacy, Berleley/Oakland, CA, USA, May 16–19, 2010,pp. 317–331.
[106] A. Arcuri, M. Z. Iqbal, and L. Briand, “Random testing: Theoreticalresults and practical implications,” IEEE Trans. Softw. Eng., vol. 38,no. 2, pp. 258–277, Mar. 2012.
[107] E. Bounimova, P. Godefroid, and D. A. Molnar, “Billions and billions ofconstraints: Whitebox fuzz testing in production,” in Proc. 35th Int. Conf.Softw. Eng., San Francisco, CA, USA, May 18–26, 2013, pp. 122–131.
[108] S. Rawat, V. Jain, A. Kumar, L. Cojocar, C. Giuffrida, and H. Bos,“VUzzer: Application-aware evolutionary fuzzing,” in Proc. 24th Annu.Netw. Distrib. Syst. Security Symp., San Diego, CA, USA, Feb. 26–Mar.1, 2017.
[109] S. Person, G. Yang, N. Rungta, and S. Khurshid, “Directed incrementalsymbolic execution,” in Proc. 32nd ACM SIGPLAN Conf. Program.Lang. Des. Implementation, San Jose, CA, USA, Jun. 4–8, 2011, pp. 504–515.
[110] C.-J. M. Liang et al., “Caiipa: Automated large-scale mobile app test-ing through contextual fuzzing,” in Proc. 20th Annu. Int. Conf. MobileComput. Netw., 2014, pp. 519–530.
[111] L. W. Hao, M. S. Ramanujam, and S. P. T. Krishnan, “On design-ing an efficient distributed black-box fuzzing system for mobile de-vices,” in Proc. 10th ACM Symp. Inf. Comput. Commun. Security, 2015, pp. 31–42.[112] Peach Fuzzer: Discover Unknown Vulnerabilities, Peach, Peach Fuzzer.[Online]. Available: http://www.peachfuzzer.com/. Accessed on: Jul. 13,2016.
[113] H. Dantas, Z. Erkin, C. Doerr, R. Hallie, and G. van der Bij, “eFuzz:A fuzzer for DLMS/COSEM electricity meters,” in Proc. 2nd WorkshopSmart Energy Grid Security, Scottsdale, AZ, USA, 2014, pp. 31–38.
[114] Honggfuzz by Google, Honggfuzz. [Online]. Available: https://google.github.io/honggfuzz/. Accessed on: Jul. 13, 2016.
[115] Dynamic Testing (Fuzzing) on the ISASecure EDSA Certifica-tion 402 Ethernet by beSTORM, beSTORM. [Online]. Available:http://www.beyondsecurity.com/dynamic_fuzzing_testing_embedded_device_security_assurance_402_ethernet. Accessed on: Jul. 19, 2016.[116] MozillaSecurity/funfuzz, jsfunfuzz, GitHub. [Online]. Available:https://github.com/MozillaSecurity/funfuzz. Accessed on: Dec. 16,2016.[117] X. Yang, Y. Chen, E. Eide, and J. Regehr, “Finding and under-standing bugs in C compilers,” in Proc. 32nd ACM SIGPLAN Conf.Program. Lang. Des. Implementation, New York, NY, USA, 2011,pp. 283–294.
[118] W. M. McKeeman, “Differential testing for software,” Digit. Tech. J.,vol. 10, no. 1, pp. 100–107, 1998.
[119] Csmith. [Online]. Available: https://embed.cs.utah.edu/csmith/. Ac-cessed on: Dec. 16, 2016.
[120] C. Holler, K. Herzig, and A. Zeller, “Fuzzing with code fragments,” inProc. 21th USENIX Security Symp., Bellevue, WA, USA, Aug. 8–10,2012, pp. 445–458.
[121] R. Guo, “MongoDB’s JavaScript fuzzer,” Commun. ACM, vol. 60, no. 5,pp. 43–47, 2017.
[122] S. Veggalam, S. Rawat, I. Haller, and H. Bos, “IFuzzer: An evolutionaryinterpreter fuzzer using genetic programming,” in Proc. Eur. Symp. Res.Comput. Security, vol. 9878, 2016, pp. 581–601.
[123] Project Springfield, Springfield. [Online]. Available: https://www.microsoft.com/en-us/springfield/. Accessed on: Apr. 15, 2017.
[124] N. Stephens et al., “Driller: Augmenting fuzzing through selective sym-bolic execution,” in Proc. 23nd Annu. Netw. Distrib. Syst. Security Symp.,San Diego, CA, USA, Feb. 21–24, 2016, pp. 1–16.
[125] Project Triforce: Run AFL on Everything!, TriforceAFL. [Online]. Avail-able: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2016/june/project-triforce-run-afl-on-everything/. Accessed on: Jul. 13, 2016.
[126] ivanfratric/winafl, WinAFL, GitHub. [Online]. Available: https://github.com/ivanfratric/winafl. Accessed on: Dec. 16, 2016.
[127] AFL Filesystem Fuzzing, Vault 2016_0.pdf, Oracle Linux and VMDevelopment, 2016. [Online]. Available: http://events.linuxfoundation.org/sites/events/files/slides/AFL%20filesystem%20fuzzing%2C%20Vault%202016_0.pdf. Accessed on: Jul. 13, 2016.LIANG et al.: FUZZING: STATE OF THE ART 1217
[128] G. Grieco, M. Ceresa, and P. Buiras, “QuickFuzz: An automatic randomfuzzer for common file formats,” in Proc. Int. Symp. Haskell, 2016,pp. 13–20.
[129] J. Davis, A. Thekumparampil, and D. Lee, “Node.Fz: Fuzzing the server-side event-driven architecture,” in Proc. 12th Eur. Conf. Comput. Syst.,New York, NY, USA, 2017, pp. 145–160.
[130] M. Marhefka and P. M¨uller, “Dfuzzer: A D-bus service fuzzing tool,” inProc. IEEE 7th Int. Conf. Softw. Test. Verification Validation Workshops,2014, pp. 383–389.
[131] A. Joseph, “Droid-FF: The first android fuzzing framework,” in Proc.Hack Box Security Conf., Amsterdam, The Netherlands, 2016. [Onl-ine]. Available: http://conference.hitb.org/hitbsecconf2016ams/sessions/hitb-lab-droid-ff-the-first-android-fuzzing-framework/
[132] H. Shahriar, S. North, and E. Mawangi, “Testing of memory leak inandroid applications,” in Proc. IEEE 15th Int. Symp. High-Assurance Syst. Eng., 2014, pp. 176–183.[133] H. Ye, S. Cheng, L. Zhang, and F. Jiang, “DroidFuzzer: Fuzzing the an-droid apps with intent-filter tag,” in Proc. Int. Conf. Adv. Mobile Comput.Multimed., 2013, pp. 1–7.
[134] R. Sasnauskas and J. Regehr, “Intent fuzzer: Crafting intents of death,”in Proc. Joint Int. Workshop Dyn. Anal. Softw. Syst. Perform. Test.Debugging Anal., 2014, pp. 1–5.
[135] D. Amalfitano, N. Amatucci, A. R. Fasolino, P. Tramontana, E.Kowalczyk, and A. M. Memon, “Exploiting the saturation effect in au-tomatic random testing of android applications,” in Proc. 2nd ACM Int.Conf. Mobile Softw. Eng. Syst., 2015, pp. 33–43.
[136] OpenRCE/sulley, Sulley, GitHub. [Online]. Available: https://github.com/OpenRCE/sulley. Accessed on: Jul. 12, 2016.
[137] jtpereyda/boofuzz, Boofuzz, GitHub. [Online]. Available: https://github.com/jtpereyda/boofuzz. Accessed on: Jul. 23, 2016.
[138] J. Somorovsky, “Systematic fuzzing and testing of TLS libraries,” inProc. 2016 ACM SIGSAC Conf. Comput. Commun. Security, New York,NY, USA, 2016, pp. 1492–1504.
[139] D. Aitel, “The advantages of block-based protocol analysis for securitytesting,” Immunity Inc., vol. 105, pp. 349–352, 2002.
[140] T. Rontti, A. M. Juuso, and A. Takanen, “Preventing DoS attacks in NGNnetworks with proactive specification-based fuzzing,” IEEE Commun.Mag., vol. 50, no. 9, pp. 164–170, Sep. 2012.
[141] W. Johansson, M. Svensson, U. E. Larson, M. Almgren, and V. Gulisano,“T-Fuzz: Model-based fuzzing for robustness testing of telecommunica-tion protocols,” in Proc. IEEE 7th Int. Conf. Softw. Test. VerificationValidation, 2014, pp. 323–332.
[142] P. Tsankov, M. T. Dashti, and D. Basin, “SecFuzz: Fuzz-testing secu-rity protocols,” in Proc. 7th Int. Workshop Autom. Softw. Test, Zurich,Switzerland, 2012, pp. 1–7.
[143] G. Banks, M. Cova, V. Felmetsger, K. C. Almeroth, R. A. Kem-merer, and G. Vigna, “SNOOZE: Toward a Stateful NetwOrk prOto-col fuzZEr,” in Proc. Int. Conf. Inf. Security, vol. 4176, 2006, pp. 343–358.
[144] H. J. Abdelnur, R. State, and O. Festor, “KiF: A stateful SIP fuzzer,”in Proc. 1st Int. Conf. Principles Syst. Appl. IP Telecommun., 2007,pp. 47–56.
[145] H. J. Abdelnur, R. State, and O. Festor, “Advanced fuzzing in the VoIPspace,” J. Comput. Virol., vol. 6, no. 1, pp. 57–64, 2010.
[146] A. Prakash, E. Venkataramani, H. Yin, and Z. Lin, “Manipulating seman-tic values in kernel data structures: Attack assessments and implications,”in Proc. 43rd Annu. IEEE/IFIP Int. Conf. Dependable Syst. Netw., 2013,pp. 1–12.
[147] D. Vyukov, Trinity: A Linux System Call Fuzzer, 2016. [Online]. Avail-able: http://codemonkey.org.uk/projects/trinity/. Accessed on: Jul. 12,2016.
[148] GitHub—Cr4sh/ioctlfuzzer: Automatically Exported From code.google.com/p/ioctlfuzzer, IOCTL. [Online]. Available: https://github.com/Cr4sh/ioctlfuzzer. Accessed on: Jul. 13, 2016.
[149] S. Schumilo, C. Aschermann, R. Gawlik, S. Schinzel, and T. Holz,“kAFL: Hardware-assisted feedback fuzzing for OS kernels,” in Proc.26th USENIX Security Symp., Vancouver, BC, Canada, 2017, pp. 167–182.
[150] S. Y. Kim et al., “CAB-Fuzz: Practical concolic testing techniques forCOTS operating systems,” in Proc. USENIX Annu. Tech. Conf., SantaClara, CA, USA, 2017, pp. 689–701.
[151] vUSBf–QEMU/KEMU USB-Fuzzing Framework, hucktech, FirmwareSecurity, Feb. 8, 2016.
[152] R. van Tonder and H. A. Engelbrecht, “Lowering the USB fuzzing bar-rier by transparent two-way emulation,” in Proc. USENIX Workshop Offensive Technol., 2014, pp. 1–8.
[153] A. Henderson, H. Yin, G. Jin, H. Han, and H. Deng, “VDF: Tar-geted evolutionary fuzz testing of virtual devices,” in Proc. 20th Int.Symp. Res. Attacks Intrusions Defenses, Atlanta, GA, USA, 2017,pp. 3–25.
[154] perf_fuzzer perf_event syscall fuzzer, perf_fuzzer. [Online]. Avail-able: http://web.eece.maine.edu/∼vweaver/projects/perf_events/fuzzer/.Accessed on: Jul. 13, 2016.
[155] libFuzzer—A Library for Coverage-Guided Fuzz Testing. LLVM 3.9Documentation, libFuzzer. [Online]. Available: http://www.llvm.org/docs/LibFuzzer.html. Accessed on: Jul. 13, 2016.
[156] A. G. Voyiatzis, K. Katsigiannis, and S. Koubias, “A modbus/TCP fuzzerfor testing internetworked industrial systems,” in Proc. IEEE 20th Conf.Emerg. Technol. Factory Autom., 2015, pp. 1–6.
[157] F. L. Sang, V. Nicomette, and Y. Deswarte, “A tool to analyze potentialI/O attacks against PCs,” IEEE Security Privacy, vol. 12, no. 2, pp. 60–66,Mar. 2014.
[158] B. Chandrasekar, B. Ramesh, V. Prabhu, S. Sajeev, P. K. Mohanty, andG. Shobha, “Development of intelligent digital certificate fuzzer tool,”in Proc. Int. Conf. Cryptogr. Security Privacy, Wuhan, China, 2017,pp. 126–130.[159] A. Case, A. K. Das, S.-J. Park, J. R. Ramanujam, and G. G. Richard III,“Gaslight: A comprehensive fuzzing architecture for memory forensics frameworks,” Digit. Investigation, vol. 22, pp. S86–S93, 2017.[160] E. Stepanov and K. Serebryany, “MemorySanitizer: Fast detector ofuninitialized memory use in C++,” in Proc. 13th Annu. IEEE/ACM Int.Symp. Code Gener. Optim., San Francisco, CA, USA, Feb. 7–11, 2015pp. 46–55.
[161] E. Poll, J. D. Ruiter, and A. Schubert, “Protocol state machines andsession languages: Specification, implementation, and security flaws,” inProc. IEEE Security Privacy Workshops, 2015, pp. 125–133.
[162] S. Rawat and L. Mounier, “An evolutionary computing approach forhuntingbuffer overflow vulnerabilities: A case of aiming in dim light,”in Proc. Eur. Conf. Comput. Netw. Defense, 2010, pp. 37–45.
[163] R. B. Dannenberg et al., “As-If infinitely ranged integer model,” in Proc.IEEE 21st Int. Symp. Softw. Rel. Eng., 2010, pp. 91–100.
[164] T. Wang, T. Wei, Z. Lin, and W. Zou, “IntScope: Automatically detectinginteger overflow vulnerability in X86 binary using symbolic execution,”in Proc. Netw. Distrib. Syst. Security Symp., 2009, pp. 1–14.
[165] S. Palka and D. McCoy, “Fuzzing E-mail filters with generative gram-mars and n-gram analysis,” in Proc. Workshop Offensive Technol., 2015,pp. 1–10.
[166] M. Mouzarani, B. Sadeghiyan, and M. Zolfaghari, “A smart fuzzingmethod for detecting heap-based buffer overflow in executable codes,”in Proc. IEEE 21st Pacific Rim Int. Symp. Dependable Comput., 2015,pp. 42–49.
[167] C. C. Yeh, H. Chung, and S. K. Huang, “CRAXfuzz: Target-aware sym-bolic fuzz testing,” in Proc. IEEE 39th Annu. Comput. Softw. Appl. Conf.,vol. 2, 2015, pp. 460–471.
[168] S. K. Huang, M. H. Huang, P. Y. Huang, H. L. Lu, and C. W. Lai, “Soft-ware crash analysis for automatic exploit generation on binary programs,”IEEE Trans. Rel., vol. 63, no. 1, pp. 270–289, Mar. 2014.
[169] B. Dolan-Gavitt et al., “LAVA: Large-scale automated vulnerability ad-dition,” in Proc. IEEE Symp. Security Privacy, 2016, pp. 110–121.
[170] D. Zhang et al., “SimFuzz: Test case similarity directed deep fuzzing,”J. Syst. Softw., vol. 85, no. 1, pp. 102–111, 2012.
[171] W. M. McKeeman, “Differential testing for software,” Digit. Tech. J.,vol. 10, no. 1, pp. 100–107, 1998.
[172] S. Kyle, H. Leather, B. Franke, D. Butcher, and S. Monteith, “Applicationof domain-aware binary fuzzing to aid android virtual machine testing,” in Proc. 11th ACM SIGPLAN/SIGOPS Int. Conf. Virtual Execution Env-iron., New York, NY, USA, 2015, pp. 121–132.
[173] T. Y. Chen, F.-C. Kuo, H. Liu, and W. E. Wong, “Code coverage ofadaptive random testing,” IEEE Trans. Rel., vol. 62, no. 1, pp. 226–237,Mar. 2013.
[174] T. Y. Chen, F.-C. Kuo, and H. Liu, “Application of a failure driven testprofile in random testing,” IEEE Trans. Rel., vol. 58, no. 1, pp. 179–192,Mar. 2009.
[175] A. F. Tappenden and J. Miller, “A novel evolutionary approach for adap-tive random testing,” IEEE Trans. Rel., vol. 58, no. 4, pp. 619–633, Dec.2009.1218 IEEE TRANSACTIONS ON RELIABILITY, VOL. 67, NO. 3, SEPTEMBER 2018
[176] E. Rogstad and L. C. Briand, “Clustering deviations for black box regres-sion testing of database applications,” IEEE Trans. Rel., vol. 65, no. 1,pp. 4–18, Mar. 2016.
[177] Y. Chen, T. Su, C. Sun, Z. Su, and J. Zhao, “Coverage-directed differ-ential testing of JVM implementations,” in Proc. 37th ACM SIGPLANConf. Program. Lang. Des. Implementation, New York, NY, USA, 2016,pp. 85–99.
[178] B. Shastry et al., “Static program analysis as a fuzzing aid,” in Proc. 20thInt. Symp. Res. Attacks Intrusions Defenses, Atlanta, GA, USA, 2017,pp. 26–47.
[179] V.-T. Pham, M. B¨ohme, and A. Roychoudhury, “Model-based whiteboxfuzzing for program binaries,” in Proc. 31st IEEE/ACM Int. Conf. Autom.Softw. Eng., New York, NY, USA, 2016, pp. 543–553.
[180] T. Y. Chen et al., “Metamorphic testing for cybersecurity,” Computer,vol. 49, no. 6, pp. 48–55, Jun. 2016.
[181] T. Y. Chen, T. H. Tse, and Z. Zhou, “Fault-based testing without the needof oracles,” Inf. Softw. Technol., vol. 45, no. 1, pp. 1–9, 2003.
[182] H. Liu, F.-C. Kuo, D. Towey, and T. Y. Chen, “How effectively doesmetamorphic testing alleviate the oracle problem?” IEEE Trans. Softw.Eng., vol. 40, no. 1, pp. 4–22, Jan. 2014.
[183] T. Y. Chen et al., “Metamorphic testing: A review of challenges andopportunities,” ACM Comput. Surv., vol. 51, no. 1, pp. 4:1–4:27, Jan.2018.
[184] B. Garn and D. E. Simos, “Eris: A tool for combinatorial testing of thelinux system call interface,” in Proc. IEEE 7th Int. Conf. Softw. Test.Verification Validation Workshops, 2014, pp. 58–67.
[185] B. Shastry, F. Maggi, F. Yamaguchi, K. Rieck, and J.-P. Seifert,“Static exploration of taint-style vulnerabilities found by fuzzing,”in Proc. 11th USENIX Workshop Offensive Technol., Vancouver, BC,Canada, 2017.
[186] L. Ma, C. Artho, C. Zhang, H. Sato, J. Gmeiner, and R. Ramler, “GRT:Program-analysis-guided random testing (T),” in Proc. 30th IEEE/ACMInt. Conf. Autom. Softw. Eng., Lincoln, NE, USA, vol. 2015, Nov. 9–13,2015, pp. 212–223.
[187] E. Alatawi, T. Miller, and H. Søndergaard, “Using metamorphic testingto improve dynamic symbolic execution,” in Proc. 24th Australas. SoftwEng. Conf., 2015, pp. 38–47.
[188] N. Havrikov, “Efficient fuzz testing leveraging input, code, and execu-tion,” in Proc. 39th Int. Conf. Softw. Eng., Buenos Aires, Argentina,vol. 2017, May 20–28, 2017, pp. 417–420.
[189] P. Godefroid, H. Peleg, and R. Singh, “Learn&Fuzz: Machine learningfor input fuzzing,” in Proc. 32nd IEEE/ACM Int. Conf. Autom. Softw.Eng., Urbana, IL, USA, Oct. 30–Nov. 3, 2017, pp. 50–59.
[190] K. B¨ottinger, “Fuzzing binaries with L´evy flight swarms,” EURASIP J.Inf. Security, vol. 2016, no. 1, Nov. 2016, Art. no. 28.
[191] K. B¨ottinger, “Hunting bugs with levy flight foraging,” in Proc. IEEESecurity Privacy Workshops, 2016, pp. 111–117.
[192] F. Duchene, S. Rawat, J.-L. Richier, and R. Groz, “KameleonFuzz: Evo-lutionary fuzzing for black-box XSS detection,” in Proc. ACM Conf.Data Appl. Security Privacy, 2014, pp. 37–48.
[193] F. Duchene, R. Groz, S. Rawat, and J. L. Richier, “XSS vulnerabilitydetection using model inference assisted evolutionary fuzzing,” in Proc.IEEE 5th Int. Conf. Softw. Test. Verification Validation, 2012, pp. 815–817.
[194] S. Dai, A. Tongaonkar, X. Wang, A. Nucci, and D. Song, “NetworkPro-filer: Towards automatic fingerprinting of Android apps,” in Proc. IEEEInt. Conf. Comput. Commun., 2013, pp. 809–817