מודולים של Fuzz

יש תמיכה ב-Rust fuzzing דרך תיבת libfuzzer-sys, שמספקת קשירות למנוע ה-fuzzing של libFuzzer של LLVM. מידע נוסף זמין במאגר libfuzzer-sys ובדף הפרויקט LLVM libFuzzer.

מודול rust_fuzz מייצר קובץ בינארי של Fuzzer שמתחיל ב-fuzzing כשהוא מופעל (בדומה למודולים של cc_fuzz). הכלי Fuzzer משתמש במנוע libFuzzerfuzzing, ולכן אפשר להשתמש במספר ארגומנטים כדי לשלוט ב-fuzzing. הם מפורטים במסמכי התיעוד של libFuzzer.

מודולים של rust_fuzz הם הרחבה של מודולים של rust_binary, ולכן יש להם את אותן תכונות ושיקולים. בנוסף, הם מטמיעים הרבה מאותן תכונות ופונקציות כמו מודולי cc_fuzz.

כשיוצרים מודולים של rust_fuzz, מופעל הדגל --cfg fuzzing, שאפשר להשתמש בו כדי לתמוך בהידור מותנה של קוד הספרייה ולשפר את הבדיקה.

כתיבת כלי בסיסי לטשטוש ב-Rust

אפשר להגדיר מודול פאזל בקובץ build‏ Android.bp באמצעות הקוד הזה:

rust_fuzz {
    name: "example_rust_fuzzer",
    srcs: ["fuzzer.rs"],

    // Config for running the target on fuzzing infrastructure can be set under
    // fuzz_config. This shares the same properties as cc_fuzz's fuzz_config.
    fuzz_config: {
        fuzz_on_haiku_device: true,
        fuzz_on_haiku_host: false,
    },

    // Path to a corpus of sample inputs, optional. See https://llvm.org/docs/LibFuzzer.html#corpus
    corpus: ["testdata/*"],

    // Path to a dictionary of sample byte sequences, optional. See https://llvm.org/docs/LibFuzzer.html#dictionaries
    dictionary: "example_rust_fuzzer.dict",
}

הקובץ fuzzer.rs מכיל כלי פשוט לבדיקת חולשות אבטחה:

fn heap_oob() {
    let xs = vec![0, 1, 2, 3];
    let val = unsafe { *xs.as_ptr().offset(4) };
    println!("Out-of-bounds heap value: {}", val);
}

fuzz_target!(|data: &[u8]| {
    let magic_number = 327;
    if data.len() == magic_number {
        heap_oob();
    }
});

כאן fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); מגדיר את נקודת הכניסה של יעד ה-fuzzing שנקראת על ידי מנוע libFuzzer. הארגומנט data הוא רצף של בייטים שמסופק על ידי מנוע libFuzzer כדי שיעבור מניפולציה כקלט לטשטוש הפונקציה הממוקדת.

בפונקציית הפאזינג הזו, רק האורך של הנתונים נבדק כדי לקבוע אם לקרוא לפונקציה heap_oob, והקריאה הזו גורמת לקריאה מחוץ לגבולות. ‫libFuzzer הוא כלי לטשטוש נתונים שמבוסס על כיסוי, ולכן הוא מתכנס במהירות לאורך הבעייתי, כי הוא קובע ש-326 הבייטים הראשונים של הנתונים לא מובילים לנתיבי ביצוע חדשים.

אפשר למצוא את הדוגמה הזו בתוך העץ בכתובת tools/security/fuzzing/example_rust_fuzzer/‎. כדי לראות דוגמה קצת יותר מורכבת של כלי אחר ליצירת נתונים אקראיים (שיוצר נתונים אקראיים עבור rustlib תלות) בתוך העץ, אפשר לעיין ב-legacy_blob_fuzzer.

במדריך הזה מוסבר איך לכתוב fuzzers ב-Rust שמודעים למבנה. אפשר גם לעיין בספר Rust Fuzz, שהוא התיעוד הרשמי של פרויקט Rust Fuzz.