Fuzzing Open Source Applications
Inleiding
Fuzzing is een geautomatiseerde softwaretesttechniek die voornamelijk wordt gebruikt om bugs en zwakke plekken in de beveiliging van software te ontdekken. Het gaat om het genereren van vele echte, willekeurige, semi-willekeurige en foutieve inputs om een softwareprogramma te laten crashen of zich onverwacht te laten gedragen. Hier zijn enkele belangrijke aspecten van fuzzing:
- Willekeurige invoer: Fuzzers genereren onverwachte, willekeurige of misvormde invoer waar een gewone gebruiker misschien niet aan denkt. Deze invoer kan randgevallen onthullen waar tijdens het ontwikkelproces geen rekening mee is gehouden..
- Bugdetectie Door te observeren hoe het programma met deze invoer omgaat, kunnen ontwikkelaars fouten identificeren en herstellen die kunnen leiden tot crashes, buffer overflows, geheugenlekken of andere soorten kwetsbaarheden.
- Automatisering: Fuzzing is sterk geautomatiseerd, waardoor het duizenden tot miljoenen invoergevallen kan testen in een korte tijd. Deze automatisering maakt het een effectieve manier om robuustheid en veiligheid te testen zonder al te veel handmatige tussenkomst van de tester..
Soorten Fuzzing:
- Black-box Fuzzing: De fuzzer heeft geen kennis van de interne structuur van het programma en behandelt de software als een zwarte doos, waarbij invoer wordt onderzocht om fouten of onverwachte resultaten te vinden.
- White-box fuzzing: Hierbij wordt kennis van de broncode of binaire code van het programma gebruikt om het invoergeneratieproces te sturen, meestal met technieken als symbolische uitvoering..
- Grey-box fuzzing: Combineert elementen van zowel black-box als white-box fuzzing door gedeeltelijke kennis te hebben van de interne structuren, vaak met behulp van instrumentatie om de programma-uitvoering te controleren.
AFL++
AFL++ (American Fuzzy Lop Plus Plus) is een verbeterde versie van de originele AFL (American Fuzzy Lop) fuzzing tool ontwikkeld door lcamtuf, die algemeen erkend is in de beveiliging- en softwareontwikkelingsgemeenschappen voor zijn effectiviteit in het vinden van bugs en beveiligingslekken door middel van geautomatiseerde invoergeneratie. AFL++ bevat een reeks verbeteringen en nieuwe functies die ontworpen zijn om fuzzing efficiënter en flexibeler te maken. Hier zijn enkele belangrijke aspecten van AFL++:
- Verbeterde prestaties en bruikbaarheid AFL++ is ontwikkeld met prestatie-optimalisaties en bruikbaarheidsverbeteringen ten opzichte van het originele AFL. Het bevat betere planningsalgoritmen, verbeterde afhandeling van de fuzzing wachtrij en verfijnde instrumentatietechnieken..
- Uitgebreide functionaliteit: De tool bevat extra functies zoals krachtigere mutators, verbeterde afhandeling van crashes en ondersteuning voor nieuwe typen doelen en omgevingen, zoals die oorspronkelijk niet goed werden ondersteund door AFL.
- Gemeenschapsgestuurde ontwikkeling: AFL++ wordt onderhouden en verbeterd door een gemeenschap van ontwikkelaars, zodat het up-to-date blijft met de nieuwste technologie en technieken in fuzzing-technologie en beveiligingstesten..
- Open Source: Net als het originele AFL is AFL++ open source, waardoor gebruikers de software kunnen wijzigen, verbeteren en verspreiden in overeenstemming met de licentievoorwaarden. Deze openheid bevordert wijdverspreide adoptie en voortdurende verbetering van de wereldwijde en softwareontwikkelingsgemeenschappen.
Onze omgeving instellen
Het opzetten van AFL++ is vrij eenvoudig, maar vereist de installatie van verschillende correct geïnstalleerde en geconfigureerde pakketten. Deze gids leidt je door het opzetten van AFL++ op een Ubuntu 24.04 LTS of later.:
- Uw systeem bijwerken: Voordat je nieuwe software installeert, is het een goed idee om je systeem bij te werken. Open een terminal en voer de volgende commando's uit:
sudo apt update && sudo apt upgrade -y
- Afhankelijkheden installeren: AFL++ vereist de installatie van enkele pakketten op je systeem. Je kunt deze afhankelijkheden installeren met het volgende commando:
sudo apt install -y build-essential gcc g++ make cmake python3-dev python3-pip git llvm clang
- AFL++ installeren: Kloon de AFL++ repo van GitHub en compileer het:
git clone https://github.com/AFLplusplus/AFLplusplus.git
cd AFLplusplus
make
sudo make install
- Configuratie na installatie: Om ervoor te zorgen dat AFL++ correct kan werken, moeten we enkele systeemaanpassingen maken. Houd er rekening mee dat deze aanpassingen slechts tijdelijk zijn en dat je systeem terug zal gaan naar de standaardinstellingen nadat je je machine opnieuw hebt opgestart.:
sudo su
echo core >/proc/sys/kernel/core_pattern
cd /sys/devices/system/cpu
echo performance | tee*/cpufreq/scaling_governor
Fuzzing met AFL++
Nu we de saaie dingen uit de weg hebben, kunnen we eindelijk beginnen met fuzzing, maar daarvoor hebben we een doel nodig. We zullen EasyEXIF gebruiken, wat een:
Een kleine ISO-conforme C++ EXIF parsing bibliotheek. EasyEXIF is een kleine, lichtgewicht C++ bibliotheek die basisinformatie uit JPEG-bestanden parseert. Het gebruikt alleen de std::string bibliotheek en is verder puur C++. U geeft het de binaire inhoud van een JPEG-bestand en het parseert verschillende van de belangrijkste EXIF-velden voor u.
Lijkt eenvoudig genoeg, dus laten we het programma klaarmaken voor fuzzing:
- Clone the repo: *insert funny and educational text here xD*
git clone https://github.com/mayanklahiri/easyexif.git
De Makefile wijzigen: Standaard wordt het programma gecompileerd zonder enige instrumentatie, waardoor het nutteloos wordt voor onze doeleinden, dus laten we de Makefile veranderen:
# Change the CXX
CXX=afl-clang-fast++
make
- De broncode compileren: We zullen afl-clang-fast++ gebruiken, een helperapplicatie die dient als een drop-in vervanging voor clang, gebruikt om code van derden te hercompileren met de vereiste runtime-instrumentatie voor afl-fuzz
make
Het programma compileert zonder problemen en je zou de volgende uitvoer moeten zien:
afl-clang-fast++ -O2 -pedantic -Wall -Wextra -ansi -std=c++11 -c exif.cpp
afl-cc++4.21a by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: LLVM-PCGUARD
SanitizerCoveragePCGUARD++4.21a
[+] Instrumented 415 locations with no collisions (non-hardened mode) of which are 24 handled and 0 unhandled selects.
afl-clang-fast++ -O2 -pedantic -Wall -Wextra -ansi -std=c++11 -o demo exif.o demo.cpp
afl-cc++4.21a by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: LLVM-PCGUARD
SanitizerCoveragePCGUARD++4.21a
[+] Instrumented 55 locations with no collisions (non-hardened mode) of which are 0 handled and 0 unhandled selects.
Als bonus zal afl-clang-fast++ AFL++ toestaan om de binary snel achter elkaar uit te voeren - veel sneller als we het zouden compileren met andere methodes.
- Mapstructuur & testgevallen: AFL++ heeft 2 mappen nodig, één waar we onze testgevallen opslaan (data die door AFL++ wordt gebruikt om de binary te fuzz'en) en een uitvoermap
mkdir in
mkdir out
- Voorbeeldafbeeldingen downloaden: Onze binary heeft JPEG-afbeeldingen nodig, laten we een aantal testafbeeldingen downloaden
cd in
wget filesamples.com/samples/image/jpeg/sample_640%C3%97426.jpeg
wget filesamples.com/samples/image/jpeg/sample_1280%C3%97853.jpeg
wget filesamples.com/samples/image/jpeg/sample_1920%C3%971280.jpeg
wget filesamples.com/samples/image/jpeg/sample_5184%C3%973456.jpeg
- Let's rock 'n roll: We zijn er allemaal klaar voor, dus laten we afl-fuzz opstarten en beginnen met fuzzing
cd ..
afl-fuzz -i in -o out ./demo @@
AFL++ zal de binary fuzzing starten en je zou een scherm moeten zien dat er als volgt uitziet
Het krankzinnige is dat AFL++ de binary 6090 keer per seconde kan uitvoeren. Dit proces vereist geen interactie van de gebruiker, dus je bent vrij om andere dingen te doen en over ongeveer 30 minuten terug te komen om te zien hoe AFL++ het doet..
Tot mijn niet zo grote verrassing kon AFL++ geen crashes vinden en dit kan zijn omdat:
- Het programma is veilig en bevat geen bugs.
- Onze testgevallen zijn eigenlijk niet goed genoeg.
De eerste optie accepteren is letterlijk een nederlaag accepteren. Laten we dus teruggaan naar de tekentafel zodat we ons kunnen wapenen met een nieuwe strategie.
Als je bekend bent met de badeendjestechniek, laten we onze kleine vriend dan uitleggen wat we tot nu toe hebben gedaan:
- Het programma gecompileerd met afl-clang-fast++
- Geef het programma een aantal JPEG-bestanden
- Het programma deed waarvoor het ontworpen was
- We betraden de leegte van verdriet en teleurstelling
Het moet nu duidelijk zijn; we hebben het programma niet voorzien van... defecte en beschadigde JPEG-afbeeldingen.
Het verspreiden van corruptie door het hele land
Corrupte JPEG-bestanden die beschadigd of gewijzigd zijn op een manier waardoor ze niet goed kunnen worden weergegeven of verwerkt - de sleutel hier is verwerkt. Corruptie kan verschillende oorzaken hebben, waaronder:
- Fouten bij bestandsoverdracht: Er kunnen fouten optreden tijdens de overdracht van bestanden tussen opslagapparaten, het netwerk of via het internet, wat kan leiden tot onvolledige of defecte bestanden..
- Problemen met opslagmedia: Problemen met de opslagmedia, zoals een defecte harde schijf, slechte sectoren of fysieke schade aan de opslagmedia, kunnen bestanden beschadigen die op het apparaat zijn opgeslagen..
Software fouten: Bugs in software die JPEG-bestanden maakt, bewerkt of beheert, kunnen fouten introduceren in de bestanden, wat kan leiden tot corruptie..- Onjuiste bewerking: JPEG-bestanden verkeerd bewerken of opslaan met ongeschikte software kan ook corruptie veroorzaken.
- Aanvallen door virussen of malware: Verberg je kinderen, verberg je vrouwen, want virussen of andere kwaadaardige software kunnen JPEG-bestanden opzettelijk of onopzettelijk beschadigen.
Wanneer een JPEG-bestand beschadigd is, kan het zijn dat het helemaal niet wordt geopend of dat het verkeerd wordt weergegeven, vreemde kleuren of patronen vertoont of slechts gedeeltelijk wordt weergegeven. De ernst van de corruptie en de delen van de bestandsgegevens die zijn gewijzigd, bepalen welke symptomen zullen verschijnen.
Als kind uit de jaren 90 heb ik mijn deel aan defecte afbeeldingen gezien, waardoor ik niet de sappige details kon zien die ik hoopte te zien (stop met giechelen). Laten we een paar opzettelijk beschadigde afbeeldingen downloaden:
cd in
wget upload.wikimedia.org/wikipedia/commons/6/66/Example_snapshot_of_corrupted_image.jpg
wget https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/JPEG_Corruption.jpg/800px-JPEG_Corruption.jpg
Gewapend met corruptie kunnen we AFL++ opstarten en wachten op resultaten
Het kostte AFL++ ongeveer een minuut om de binary te laten crashen, dus laten we nog meer plezier hebben en wachten om te zien hoeveel crashes AFL++ kan produceren.
In ongeveer 30 minuten was AFL++ in staat om de binary meer dan 6 miljoen keer uit te voeren, 345 testgevallen te produceren, 24 cycli te voltooien en de binary 68 keer te laten crashen. Dat is geweldig!
Triage van de crash
Triaging van een crash verwijst naar het proces van het analyseren en prioriteren van de crashes die zijn ontdekt door de fuzzer. Dit proces is essentieel om de oorzaak, ernst en potentiële impact van elke crash te bepalen. Hier is hoe triaging typisch werkt:
- Identificeer de crash: Controleer eerst of de crash echt en reproduceerbaar is. Dit houdt in dat je ervoor moet zorgen dat de crash consistent plaatsvindt onder dezelfde omstandigheden of met dezelfde invoer..
- Analyseer de crash: Bestudeer de details van de crash, zoals de stack trace, geheugendumps en logboeken om te begrijpen waar en waarom de crash plaatsvond. Dit kan het gebruik van debug-gereedschappen inhouden, zoals GDB, om de toestand van het programma op het moment van de crash te inspecteren. Dit valt buiten het bestek van deze blogpost, maar we zullen hier in de toekomst naar kijken, dus houd dat in de gaten ;)
- De ernst classificeren: Bepaal de ernst van de crash op basis van factoren zoals of deze leidt tot een DoS, geheugenlekkage, ongeautoriseerde toegang, code-uitvoering of andere schadelijke (en ontzagwekkende) gevolgen. Dit helpt bij het prioriteren van welke crashes het eerst moeten worden aangepakt.
- Exploiteerbaarheid beoordelen: Evalueer hoe exploiteerbaar de crash is in termen van het gebruik ervan door een aanvaller om een systeem te compromitteren. Dit omvat het controleren of de crash mogelijk kan leiden tot willekeurige code-uitvoering of escalatie van privileges (nu dat is geweldig).
- Document en verslag: Documenteer de bevindingen en rapporteer ze, indien nodig, aan de relevante belanghebbenden, waaronder interne ontwikkelteams, softwareleveranciers of zelfs publiekelijk als het gaat om open-source software (zoals hier het geval is) en het probleem bredere bekendheid nodig heeft. Je kunt hiervoor beloond worden, bijdragen aan een veiliger internet, je carrière een boost geven omdat een CVE op je naam je cv een boost geeft en je langs de beruchte HR-filter helpt....
Conclusion
Fuzzing stands as a cornerstone in the domain of cybersecurity due to its unmatched efficacy in pre-emptively identifying vulnerabilities that might otherwise remain undetected until exploited by malicious entities. By automatically injecting a multitude of unpredictable inputs into software systems, fuzzing uncovers hidden bugs and security flaws that standard testing methods might overlook. This proactive approach to security testing enables developers to fortify their applications against potential attacks, thus significantly reducing the risk of security breaches. Moreover, as cyber threats continue to evolve in complexity and stealth, fuzzing's role becomes even more critical, providing a dynamic and adaptable defence mechanism that keeps pace with emerging vulnerabilities. Ultimately, the integration of fuzzing into the cybersecurity strategy not only enhances the robustness of digital infrastructures but also upholds the integrity and trustworthiness of technology in an increasingly interconnected world.
Keep an eye out for future blogpost on this topic and if you have any questions, please get in touch with me and I'd be happy to help however I can.