Stack Canaries
StackGuard en StackShield
StackGuard voeg 'n spesiale waarde bekend as 'n kanarie in voor die EIP (Extended Instruction Pointer), spesifiek 0x000aff0d
(wat nul, nuwe lyn, EOF, karretjieterugkeer verteenwoordig) om teen buffer-oorvloeiing te beskerm. Tog bly funksies soos recv()
, memcpy()
, read()
, en bcopy()
kwesbaar, en dit beskerm nie die EBP (Base Pointer) nie.
StackShield neem 'n meer gesofistikeerde benadering as StackGuard deur 'n Globale Terugkeerstapel te handhaaf, wat alle terugkeeradressse (EIPs) stoor. Hierdie opstelling verseker dat enige oorvloeiing geen skade veroorsaak nie, aangesien dit 'n vergelyking tussen gestoorde en werklike terugkeeradressse toelaat om oorvloeiingsgebeurtenisse op te spoor. Daarbenewens kan StackShield die terugkeeradres teen 'n grenswaarde toets om te bepaal of die EIP na buite die verwagte data-ruimte wys. Nietemin kan hierdie beskerming omseil word deur tegnieke soos Return-to-libc, ROP (Return-Oriented Programming), of ret2ret, wat aandui dat StackShield ook nie plaaslike veranderlikes beskerm nie.
Stack Smash Protector (ProPolice) -fstack-protector
:
-fstack-protector
:Hierdie meganisme plaas 'n kanarie voor die EBP, en herorganiseer plaaslike veranderlikes om buffers by hoër geheue-adresse te posisioneer, wat voorkom dat hulle ander veranderlikes oorskryf. Dit kopieer ook argumente wat op die stapel bokant plaaslike veranderlikes oorgedra word veilig en gebruik hierdie kopieë as argumente. Dit beskerm egter nie rye met minder as 8 elemente of buffers binne 'n gebruiker se struktuur nie.
Die kanarie is 'n lukrake nommer afgelei van /dev/urandom
of 'n verstekwaarde van 0xff0a0000
. Dit word in TLS (Thread Local Storage) gestoor, wat gedeelde geheue-ruimtes oor drade toelaat om draadspesifieke globale of statiese veranderlikes te hê. Hierdie veranderlikes word aanvanklik van die ouerproses gekopieer, en kinderprosesse kan hul data verander sonder om die ouer of broers en susters te beïnvloed. Nietemin, as 'n fork()
sonder die skep van 'n nuwe kanarie gebruik word, deel alle prosesse (ouer en kinders) dieselfde kanarie, wat dit kwesbaar maak. Op die i386-argitektuur word die kanarie by gs:0x14
gestoor, en op x86_64 by fs:0x28
.
Hierdie plaaslike beskerming identifiseer funksies met buffers wat kwesbaar is vir aanvalle en spuit kode in die begin van hierdie funksies in om die kanarie te plaas, en aan die einde om sy integriteit te verifieer.
Wanneer 'n webbediener fork()
gebruik, maak dit 'n brute force-aanval moontlik om die kanarie byte vir byte te raai. Tog maak die gebruik van execve()
na fork()
die geheue-ruimte oorskryf, wat die aanval nietig maak. vfork()
laat die kinderproses toe om sonder duplisering uit te voer totdat dit probeer skryf, waarna 'n duplikaat geskep word, wat 'n ander benadering tot proseskeuring en geheuehantering bied.
Lengtes
In x64
binêre lêers is die kanariekoek 'n 0x8
byte qword. Die eerste sewe bytes is lukraak en die laaste byte is 'n nul byte.
In x86
binêre lêers is die kanariekoek 'n 0x4
byte dword. Die eerste drie bytes is lukraak en die laaste byte is 'n nul byte.
Die minst betekenisvolle byte van beide kanaries is 'n nul byte omdat dit die eerste in die stapel vanaf laer adresse is en daarom funksies wat strings lees sal ophou voordat dit dit lees.
Oorwinnings
Die lek van die kanarie en dit dan oorskryf (bv. buffer-oorvloeiing) met sy eie waarde.
As die kanarie in kinderprosesse gevork is, kan dit moontlik wees om dit een byte op 'n slag brute force:
As daar 'n interessante lek of arbitrêre lees-kwesbaarheid in die binêre lêer is, kan dit moontlik wees om dit te lek:
Oorskryf van stapel gestoorde aanwysers
Die stapel wat kwesbaar is vir 'n stapeloorvloeiing kan adresse na strings of funksies wat oorskryf kan word, bevat om die kwesbaarheid te benut sonder om die stapelkanarie te bereik. Kontroleer:
Pointer RedirectingWysig beide meester- en draadkanarie
'N Buffer oorvloeiing in 'n geskroefde funksie wat met 'n kanarie beskerm word, kan gebruik word om die meesterkanarie van die draad te wysig. As gevolg hiervan is die mitigasie nutteloos omdat die toets met twee kanaries wat dieselfde is (hoewel gewysig) gebruik word.
Verder kan 'n buffer oorvloeiing in 'n geskroefde funksie wat met 'n kanarie beskerm word, gebruik word om die meesterkanarie wat in die TLS gestoor is, te wysig. Dit is omdat dit moontlik kan wees om die geheueposisie waar die TLS gestoor word (en dus die kanarie) te bereik via 'n bof in die stapel van 'n draad. As gevolg hiervan is die mitigasie nutteloos omdat die toets met twee kanaries wat dieselfde is (hoewel gewysig) gebruik word. Hierdie aanval word uitgevoer in die skryfstuk: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
Kyk ook na die aanbieding van https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 wat noem dat gewoonlik die TLS deur mmap
gestoor word en wanneer 'n stapel van 'n draad geskep word, word dit ook deur mmap
gegenereer volgens hierdie, wat die oorvloeiing soos in die vorige skryfstuk mag toelaat.
Wysig die GOT-invoer van
__stack_chk_fail
As die binêre lêer gedeeltelike RELRO het, kan jy 'n arbitrêre skryf gebruik om die GOT-invoer van __stack_chk_fail
te wysig sodat dit 'n dummiefunksie is wat die program nie blokkeer as die kanarie gewysig word nie.
Hierdie aanval word uitgevoer in die skryfstuk: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
Verwysings
Last updated