Fuzzing - Fuzzing
Fuzzing eller fuzz -testning är en automatiserad mjukvarutestningsteknik som innebär att ogiltiga, oväntade eller slumpmässiga data tillhandahålls som ingångar till ett datorprogram . Programmet övervakas sedan för undantag som kraschar , misslyckade inbyggda kodhävdar eller potentiella minnesläckor . Normalt används fuzzers för att testa program som tar strukturerade ingångar. Denna struktur specificeras, t.ex. i ett filformat eller protokoll och skiljer giltigt från ogiltig inmatning. En effektiv fuzzer genererar halvgiltiga ingångar som är "tillräckligt giltiga" genom att de inte direkt avvisas av parsern, men skapar oväntade beteenden djupare i programmet och är "ogiltiga nog" för att avslöja hörnfall som inte har behandlats korrekt. med.
För säkerhets skull är input som passerar en förtroendegräns ofta den mest användbara. Till exempel är det viktigare att fuzz -kod som hanterar uppladdning av en fil av någon användare än att fuzz koden som analyserar en konfigurationsfil som endast är tillgänglig för en privilegierad användare.
Historia
Uttrycket "fuzz" härstammar från ett höstprojekt 1988 i examen Advanced Operating Systems -klassen (CS736), undervisad av prof. Barton Miller vid University of Wisconsin, vars resultat därefter publicerades 1990. Att fuzz -testa ett UNIX -verktyg innebar att automatiskt generera slumpmässiga inmatnings- och kommandoradsparametrar för verktyget. Projektet var utformat för att testa tillförlitligheten hos UNIX -kommandoradsprogram genom att köra ett stort antal slumpmässiga ingångar snabbt efter varandra tills de kraschade. Millers team kunde krascha 25 till 33 procent av de verktyg som de testade. De felsökte sedan var och en av krascherna för att fastställa orsaken och kategoriserade varje upptäckt fel. För att låta andra forskare utföra liknande experiment med annan programvara, gjordes källkoden för verktygen, testprocedurerna och rådata -data offentligt tillgängliga. Denna tidiga fuzzing skulle nu kallas black box, generationell, ostrukturerad (dum) fuzzing.
Detta fuzzpapper från 1990 noterade också förhållandet mellan tillförlitlighet och säkerhet: "För det andra orsakades en av buggarna som vi hittade på grund av samma programmeringsmetod som gav ett av säkerhetshålen till internetmasken (" får finger "-felet). Vi har hittat ytterligare buggar som kan indikera framtida säkerhetshål. " (Med hänvisning till Morris -masken från november 1988.)
Det ursprungliga fuzz -projektet bidrog 1995, 2000, 2006 och senast 2020:
- 1995: "Fuzz revisited" -papperet bestod av fyra delar. (1) Reproducerade den ursprungliga kommandoradsstudien, inklusive ett större antal UNIX -system och fler verktyg. Studien visade att, om något, tillförlitligheten hade blivit sämre. Detta var den första studien som inkluderade GNU- och Linux -verktyg med öppen källkod som intressant nog var betydligt mer tillförlitliga än de från de kommersiella UNIX -systemen. (2) Introducerade fuzz-testning av GUI-program (fönsterbaserade) under X-Windows. Denna studie använde både ostrukturerade och strukturerade (giltiga sekvenser av mus- och tangentbordshändelser) inmatningsdata. De kunde krascha 25% av X-Windows-programmen. Dessutom testade de X-Windows-servern och visade att den var motståndskraftig mot kraschar. (3) Införde fuzz -testning av nätverkstjänster, igen baserat på strukturerad testinmatning. Ingen av dessa tjänster kraschade. (4) Införde slumpmässig testning av systembibliotekets anropsreturvärden, specifikt slumpmässigt återkommande noll från malloc -funktionsfamiljen. Nästan hälften av UNIX -standardprogrammen misslyckades med att korrekt kontrollera sådana returvärden.
- 2000: Tillämpad fuzz -testning på det nyligen släppta Windows NT -operativsystemet, testning av program som kördes under Win32 -fönstersystemet. De kunde krascha 21% av applikationerna och hänga ytterligare 24% av de testade. Återigen testade applikationer med både ostrukturerad och strukturerad (giltigt tangentbord och mushändelser) ingång, vilket kraschade nästan hälften av de program som de testade. De identifierade orsakerna till misslyckandena och fann att de liknade tidigare studier.
- 2006: Tillämpad fuzz -testning på Mac OS X , för både kommandorad och fönsterbaserade applikationer. De testade 135 kommandoradsverktygsprogram och kraschade 7% av de testade. Dessutom testade de 30 applikationer som kördes under fönstersystemet MacOS Aqua , vilket kraschade 73% av de testade.
- 2020: Senast använde de den klassiska generationen, svart låda, ostrukturerad testning på nuvarande UNIX -system, särskilt Linux, FreeBSD och MacOS, för att se om de ursprungliga teknikerna fortfarande var relevanta och om nuvarande verktygsprogram var resistenta mot denna typ av tester. De testade cirka 75 verktyg på varje plattform, med fel på 12% på Linux, 16% på MacOS och 19% på FreeBSD. (Observera att dessa felfrekvenser var sämre än resultaten från tidigare test av samma system.) När de analyserade varje fel och kategoriserade dem, fann de att de klassiska kategorierna av fel, såsom pekar- och matrisfel och att inte kontrollera returkoder, var fortfarande i stort sett närvarande i de nya resultaten. Dessutom orsakar nytt fel ett komplext programtillstånd och algoritmer som inte har skalats med ingångsstorleken eller komplexiteten. De testade också UNIX -verktyg som skrevs nyare i Rust och fann att de var av liknande tillförlitlighet som de som skrevs i C, men (som förväntat) mindre sannolikt att de har minnesfel.
I april 2012 tillkännagav Google ClusterFuzz, en molnbaserad fuzzing-infrastruktur för säkerhetskritiska komponenter i Chromium-webbläsaren . Säkerhetsforskare kan ladda upp sina egna fuzzers och samla bug bounties om ClusterFuzz hittar en krasch med den uppladdade fuzzer.
I september 2014 avslöjades Shellshock som en familj av säkerhetsbuggar i det mycket använda UNIX Bash -skalet ; de flesta sårbarheterna hos Shellshock hittades med fuzzer AFL . (Många Internet-vända tjänster, till exempel vissa webbserverutplaceringar, använder Bash för att behandla vissa förfrågningar, så att en angripare kan få sårbara versioner av Bash att utföra godtyckliga kommandon . Detta kan tillåta en angripare att få obehörig åtkomst till ett datorsystem.)
I april 2015 visade Hanno Böck hur fuzzer AFL kunde ha hittat 2014 års Heartbleed -sårbarhet. ( Heartbleed -sårbarheten avslöjades i april 2014. Det är en allvarlig sårbarhet som gör att motståndare kan dechiffrera annars krypterad kommunikation . Sårbarheten infördes av misstag i OpenSSL som implementerar TLS och används av majoriteten av servrarna på internet. Shodan rapporterade 238 000 maskiner fortfarande sårbara i april 2016; 200 000 i januari 2017.)
I augusti 2016 höll Defense Advanced Research Projects Agency (DARPA) finalen i den första Cyber Grand Challenge , en helautomatisk capture-the-flag- tävling som varade i 11 timmar. Målet var att utveckla automatiska försvarssystem som kan upptäcka, utnyttja och korrigera programvarufel i realtid . Fuzzing användes som en effektiv offensiv strategi för att upptäcka brister i motståndarnas programvara. Det visade en enorm potential i automatiseringen av sårbarhetsdetektering. Vinnaren var ett system som heter "Mayhem" som utvecklats av teamet ForAllSecure under ledning av David Brumley .
I september 2016 tillkännagav Microsoft Project Springfield, en molnbaserad fuzz-testtjänst för att hitta säkerhetskritiska buggar i programvara.
I december 2016 tillkännagav Google OSS-Fuzz som möjliggör kontinuerlig fuzzing av flera säkerhetskritiska projekt med öppen källkod.
Vid Black Hat 2018 demonstrerade Christopher Domas användningen av fuzzing för att avslöja förekomsten av en dold RISC -kärna i en processor. Denna kärna kunde kringgå befintliga säkerhetskontroller för att utföra Ring 0 -kommandon från Ring 3.
I september 2020 Microsoft släppte OneFuzz en egen värd fuzzing-as-a-service-plattform som automatiserar upptäckten av programvarufel . Den stöder Windows och Linux.
Tidig slumpmässig testning
Testprogram med slumpmässiga inmatningar går tillbaka till 1950 -talet då data fortfarande lagrades på stansade kort . Programmerare skulle använda stansade kort som drogs från papperskorgen eller kortdäck med slumpmässiga nummer som inmatning till datorprogram. Om en körning avslöjade oönskat beteende hade ett fel upptäckts.
Utförandet av slumpmässiga ingångar kallas också slumpmässig testning eller aptestning .
År 1981 undersökte Duran och Ntafos formellt effektiviteten av att testa ett program med slumpmässiga ingångar. Medan slumpmässiga tester allmänt uppfattades vara det sämsta sättet att testa ett program, kunde författarna visa att det är ett kostnadseffektivt alternativ till mer systematiska testtekniker.
År 1983 utvecklade Steve Capps på Apple "The Monkey", ett verktyg som skulle generera slumpmässiga ingångar för klassiska Mac OS -applikationer, till exempel MacPaint . Den figurativa "apan" hänvisar till den oändliga apsatsen som säger att en apa som slår slumpmässigt på tangenterna på ett skrivmaskinstangentbord under en oändlig mängd tid så småningom kommer att skriva ut hela Shakespeares verk. Vid test skulle apan skriva den specifika sekvensen av ingångar som skulle utlösa en krasch.
1991 släpptes crashme-verktyget, som var avsett att testa robustheten hos Unix och Unix-liknande operativsystem genom att slumpmässigt köra systemsamtal med slumpmässigt valda parametrar.
Typer
En fuzzer kan kategoriseras på flera sätt:
- En fuzzer kan vara generationsbaserad eller mutationsbaserad beroende på om ingångar genereras från grunden eller genom att modifiera befintliga ingångar.
- En fuzzer kan vara dum (ostrukturerad) eller smart (strukturerad) beroende på om den är medveten om ingångsstrukturen.
- En fuzzer kan vara vit-, grå- eller svart-box, beroende på om den är medveten om programstrukturen.
Återanvändning av befintliga ingångsfrön
En mutationsbaserad fuzzer utnyttjar en befintlig korpus av fröinmatningar under fuzzing. Det genererar input genom att modifiera (eller snarare mutera ) de tillhandahållna fröerna. Till exempel vid användningen av bildbiblioteket libpng skulle användaren tillhandahålla en uppsättning giltiga PNG- bildfiler som frön medan en mutationsbaserad fuzzer skulle modifiera dessa frön för att producera halvgiltiga varianter av varje utsäde. Korpus av seed -filer kan innehålla tusentals potentiellt liknande ingångar. Automatiserat fröval (eller minskning av testpaket) tillåter användare att välja de bästa fröerna för att maximera det totala antalet buggar som hittats under en fuzz -kampanj.
En generationsbaserad fuzzer genererar ingångar från grunden. Till exempel tar en smart generationsbaserad fuzzer inmatningsmodellen som användaren tillhandahåller för att generera nya ingångar. Till skillnad från mutationsbaserade fuzzers beror en generationsbaserad fuzzer inte på existensen eller kvaliteten på en korpus av fröinmatningar.
Vissa fuzzers har förmågan att göra båda, för att generera insatser från grunden och för att generera insatser genom mutation av befintliga frön.
Medveten om inmatningsstruktur
Typiskt fuzzers används för att generera ingångar för program som tar strukturerade ingångar såsom en fil , en sekvens av tangentbord eller mus händelser , eller en sekvens av meddelanden . Denna struktur skiljer giltig input som accepteras och bearbetas av programmet från ogiltig input som snabbt avvisas av programmet. Vad som utgör en giltig inmatning kan uttryckligen anges i en ingångsmodell. Exempel på indatamodeller är formell grammatik , filformat , GUI -modeller och nätverksprotokoll . Även artiklar som normalt inte betraktas som inmatning kan vara fuzzed, till exempel innehållet i databaser , delat minne , miljövariabler eller exakt sammanfogning av trådar . En effektiv fuzzer genererar halvgiltiga ingångar som är "tillräckligt giltiga" så att de inte direkt avvisas från parsern och "ogiltiga nog" så att de kan betona hörnfall och utöva intressanta programbeteenden.
En smart (modellbaserad, grammatikbaserad eller protokollbaserad) fuzzer utnyttjar ingångsmodellen för att generera en större andel giltiga ingångar. Till exempel, om ingången kan modelleras som ett abstrakt syntaxträd , skulle en smart mutationsbaserad fuzzer använda slumpmässiga transformationer för att flytta hela subträd från en nod till en annan. Om ingången kan modelleras av en formell grammatik skulle en smart generationsbaserad fuzzer instansera produktionsreglerna för att generera ingångar som är giltiga med avseende på grammatiken. Men i allmänhet måste inmatningsmodellen uttryckligen tillhandahållas, vilket är svårt att göra när modellen är proprietär, okänd eller mycket komplex. Om en stor mängd giltiga och ogiltiga ingångar är tillgängliga skulle en grammatikinduktionsteknik , till exempel Angluins L* -algoritm , kunna generera en inmatningsmodell.
En dum fuzzer kräver inte inmatningsmodellen och kan därmed användas för att fuzz ett större antal program. Till exempel är AFL en dum mutationsbaserad fuzzer som modifierar en seedfil genom att vända slumpmässiga bitar , genom att ersätta slumpmässiga byte med "intressanta" värden och genom att flytta eller ta bort block av data. En dum fuzzer kan dock generera en lägre andel giltiga inmatningar och stressa parserkoden snarare än huvudkomponenterna i ett program. Nackdelen med dumma fuzzers kan illustreras med hjälp av konstruktionen av en giltig kontrollsumma för en cyklisk redundanskontroll (CRC). En CRC är en feldetekterande kod som säkerställer att integriteten för data som finns i inmatningsfilen bevaras under överföringen . En kontrollsumma beräknas över indata och registreras i filen. När programmet behandlar den mottagna filen och den inspelade kontrollsumman inte matchar den omberäknade kontrollsummen, avvisas filen som ogiltig. Nu är det osannolikt att en fuzzer som är omedveten om CRC genererar rätt kontrollsumma. Det finns dock försök att identifiera och beräkna en potentiell kontrollsumma i den muterade ingången, när en dum mutationsbaserad fuzzer har modifierat de skyddade data.
Medveten om programstruktur
Normalt anses en fuzzer vara mer effektiv om den uppnår en högre grad av kodtäckning . Motiveringen är att om en fuzzer inte utövar vissa strukturella element i programmet, kan den inte heller avslöja buggar som gömmer sig i dessa element. Vissa programelement anses vara mer kritiska än andra. Till exempel kan en divisionsoperatör orsaka ett division med nollfel, eller så kan ett systemanrop krascha programmet.
En black-box fuzzer behandlar programmet som en black box och är inte medveten om intern programstruktur. Till exempel betraktas ett slumpmässigt testverktyg som genererar inmatningar slumpmässigt som en blackbox -fuzzer. Därför kan en blackbox -fuzzer utföra flera hundra ingångar per sekund, kan enkelt parallelliseras och kan skala till program av godtycklig storlek. Blackbox -fuzzers får dock bara repa ytan och avslöja "ytliga" buggar. Därför finns det försök att utveckla blackbox -fuzzers som gradvis kan lära sig om programmets interna struktur (och beteende) under fuzzing genom att observera programmets utgång med en ingång. Till exempel använder LearnLib aktivt lärande för att generera en automat som representerar beteendet hos en webbapplikation.
En white-box fuzzer utnyttjar programanalys för att systematiskt öka kodtäckningen eller för att nå vissa kritiska programplatser. Till exempel utnyttjar SAGE symboliskt utförande för att systematiskt utforska olika vägar i programmet. Om programmets specifikation är tillgänglig kan en whitebox-fuzzer utnyttja tekniker från modellbaserade tester för att generera ingångar och kontrollera programutgångarna mot programspecifikationen. En whitebox fuzzer kan vara mycket effektiv för att avslöja buggar som gömmer sig djupt i programmet. Den tid som används för analys (av programmet eller dess specifikation) kan dock bli oöverkomlig. Om whitebox -fuzzer tar relativt för lång tid att generera en ingång blir en blackbox -fuzzer mer effektiv. Därför finns det försök att kombinera effektiviteten hos blackbox fuzzers och effektiviteten hos whitebox fuzzers.
En grå låda fuzzer utnyttjar instrumentering snarare än programanalys för att få information om programmet. Till exempel använder AFL och libFuzzer lätt instrumentering för att spåra grundläggande blockövergångar som utövas av en ingång. Detta leder till en rimlig prestanda, men informerar fuzzer om ökningen av kodtäckning under fuzzing, vilket gör gråboxfuzzers extremt effektiva sårbarhetsdetekteringsverktyg.
Användningsområden
Fuzzing används mest som en automatiserad teknik för att avslöja sårbarheter i säkerhetskritiska program som kan utnyttjas med skadlig avsikt. Mer allmänt används fuzzing för att visa förekomsten av buggar snarare än deras frånvaro. Att köra en fuzzing -kampanj i flera veckor utan att hitta ett fel visar inte att programmet är korrekt. När allt kommer omkring kan programmet fortfarande misslyckas för en ingång som inte har körts ännu; att köra ett program för alla ingångar är oöverkomligt dyrt. Om målet är att bevisa att ett program är korrekt för alla ingångar måste en formell specifikation finnas och tekniker från formella metoder måste användas.
Att avslöja buggar
För att avslöja buggar måste en fuzzer kunna skilja förväntat (normalt) från oväntat (buggy) programbeteende. En maskin kan dock inte alltid skilja en bugg från en funktion. I automatiserad mjukvarutestning kallas detta också testorakelproblemet .
Vanligtvis skiljer en fuzzer mellan kraschar och icke-kraschar ingångar i avsaknad av specifikationer och för att använda ett enkelt och objektivt mått. Krascher kan lätt identifieras och kan tyda på potentiella sårbarheter (t.ex. avslag på tjänsten eller exekvering av godtycklig kod ). Frånvaron av en krasch indikerar dock inte att det inte finns någon sårbarhet. Till exempel kan ett program skrivet i C krascha eller inte när en ingång orsakar ett buffertflöde . Snarare är programmets beteende odefinierat .
För att göra en fuzzer mer känslig för andra fel än kraschar kan desinfektionsmedel användas för att injicera påståenden som kraschar programmet när ett fel upptäcks. Det finns olika desinfektionsmedel för olika typer av buggar:
- att detektera minnesrelaterade fel, såsom buffertspill och användning-efter-fria (med användning av minnes debuggers såsom AddressSanitizer ),
- för att upptäcka tävlingsförhållanden och dödlägen (ThreadSanitizer),
- för att upptäcka odefinierat beteende (UndefinedBehaviorSanitizer),
- för att upptäcka minnesläckor (LeakSanitizer) eller
- för att kontrollera kontrollflödesintegritet (CFISanitizer).
Fuzzing kan också användas för att upptäcka "differentiella" buggar om en referensimplementering är tillgänglig. För automatiserad regressionstest körs de genererade ingångarna på två versioner av samma program. För automatiserad differentialtest körs de genererade ingångarna på två implementeringar av samma program (t.ex. lighttpd och httpd är båda implementeringar av en webbserver). Om de två varianterna producerar olika utdata för samma ingång kan en vara buggig och bör undersökas närmare.
Validerar statiska analysrapporter
Statisk programanalys analyserar ett program utan att faktiskt köra det. Detta kan leda till falska positiva effekter där verktyget rapporterar problem med programmet som faktiskt inte finns. Fuzzing i kombination med dynamisk programanalys kan användas för att försöka generera en input som faktiskt bevittnar det rapporterade problemet.
Webbläsarsäkerhet
Moderna webbläsare genomgår omfattande fuzzing. Den Chromium koden för Google Chrome kontinuerligt fuzzed av Chrome Security Team med 15.000 kärnor. För Microsoft Edge och Internet Explorer , Microsoft utförs fuzzed testning med 670 maskin år under produktutvecklingen, genererar mer än 400 miljarder DOM manipulationer från 1 miljard HTML-filer.
Verktygskedja
En fuzzer producerar ett stort antal ingångar på relativt kort tid. Till exempel producerade Google OSS-fuzz-projektet 2016 cirka 4 biljoner inmatningar i veckan. Därför tillhandahåller många fuzzers en verktygskedja som automatiserar annars manuella och tråkiga uppgifter som följer den automatiska generationen av felinducerande ingångar.
Automatiserad buggtriage
Automatiserad buggtriage används för att gruppera ett stort antal felinducerande ingångar efter rotorsak och att prioritera varje enskild bugg efter svårighetsgrad. En fuzzer producerar ett stort antal ingångar, och många av de felinducerande kan effektivt avslöja samma programvarufel . Endast några av dessa buggar är säkerhetskritiska och bör korrigeras med högre prioritet. Till exempel tillhandahåller CERT Coordination Center Linux -triageverktygen som grupperar kraschinmatningar av den producerade stackspårningen och listar varje grupp efter deras sannolikhet att vara exploaterbar . Microsoft Security Research Center (MSEC) utvecklade det! Exploaterbara verktyget som först skapar en hash för en kraschar ingång för att bestämma dess unika och sedan tilldelar ett betyg:
- Möjlig att utnyttja
- Förmodligen exploaterbar
- Förmodligen inte exploaterbart, eller
- Okänd.
Tidigare orapporterade, triagerade buggar kan automatiskt rapporteras till ett buggspårningssystem . OSS-Fuzz kör till exempel stora, långvariga fuzzing-kampanjer för flera säkerhetskritiska programvaruprojekt där varje tidigare orapporterad, distinkt bugg rapporteras direkt till en buggspårare. OSS-Fuzz bug tracker informerar automatiskt underhållaren om den sårbara programvaran och kontrollerar med jämna mellanrum om felet har åtgärdats i den senaste revisionen med hjälp av den uppladdade minimerade felinducerande ingången.
Automatiserad ingångsminimering
Automatiserad ingångsminimering (eller minskning av testfall) är en automatisk felsökningsteknik för att isolera den del av den felinducerande ingången som faktiskt orsakar felet. Om den felinducerande ingången är stor och mestadels missbildad kan det vara svårt för en utvecklare att förstå vad som exakt orsakar felet. Med tanke på den felinducerande ingången skulle ett automatiserat minimeringsverktyg ta bort så många ingångsbytes som möjligt samtidigt som den ursprungliga buggningen fortfarande reproduceras. Exempelvis är Delta Debugging en automatiserad input minimeringsteknik som använder en utökad binär sökalgoritm för att hitta en sådan minimal input.
Se även
- Amerikansk fuzzy lop (fuzzer)
- Konkoliskt test
- Aptest
- Slumpmässig testning
- Ansvarsfullt avslöjande
- Runtime error detection
- Säkerhetstestning
- Rökprovning (programvara)
- Symboliskt utförande
- Systemtestning
- Testa automatisering
Referenser
Vidare läsning
- Ari Takanen, Jared D. DeMott, Charles Miller, Fuzzing for Software Security Testing and Quality Assurance , 2008, ISBN 978-1-59693-214-2
- Michael Sutton, Adam Greene och Pedram Amini. Fuzzing: Brute Force Vulnerability Discovery , 2007, ISBN 0-321-44611-9 .
- H. Pohl, kostnadseffektiv identifiering av nolldagars sårbarheter med hjälp av hotmodellering och fuzzing , 2011
- Fabien Duchene, upptäckt av webbsårbarheter via modellinferens assisterade evolutionärt fuzzing, 2014, doktorsavhandling
- Bratus, S., Darley, T., Locasto, M., Patterson, ML, Shapiro, RB, Shubina, A., Beyond Planted Bugs in "Trusting Trust": The Input-Processing Frontier , IEEE Security & Privacy Vol 12, Utgåva 1, (jan-feb 2014), s. 83–87 —Belyser i grunden varför fuzzing fungerar så bra: eftersom ingången är tolkens kontrollprogram.
externa länkar
- Fuzzing Project , innehåller självstudier, en lista över säkerhetskritiska projekt med öppen källkod och andra resurser.
- University of Wisconsin Fuzz Testing (det ursprungliga fuzz -projektet) Källa till papper och fuzz -programvara.
- Designa ingångar som gör att programvaran misslyckas , konferensvideo inklusive suddig testning
- Länk till Uleåborg (Finland) University Secure Programming Group
- Bygga "Protocol Aware" Fuzzing Frameworks