Systems and Internet Infrastructure Security Network and Security Research Center Department of Computer Science and Engineering Pennsylvania State University, University Park PA CMPSC 497 Other Memory Vulnerabilities Trent Jaeger Systems and Internet Infrastructure Security (SIIS) Lab Computer Science and Engineering Department Pennsylvania State University Page 1
Memory Error A memory error allows a program statement to access memory beyond that allocated for the variables processed in the statement Common case: Buffer overflow But, there are other ways to exploit memory errors to access unauthorized memory No need to overflow a buffer Two examples Use-after-free Type confusion Page 2
Use After Free Flaw: Program frees data on the heap, but then references that memory as if it were still valid Accessible: Adversary can control data written using the freed pointer Exploit: Another write-what-where vulnerability Page 3
Use After Free What happens here? int main(int argc, char **argv) { char *buf1r1; char *buf2r1; char *buf2r2; char *buf3r2; buf1r1 = (char *) malloc(bufsizer1); buf2r1 = (char *) malloc(bufsizer1); free(buf2r1); buf2r2 = (char *) malloc(bufsizer2); buf3r2 = (char *) malloc(bufsizer2); } strncpy(buf2r1, argv[1], BUFSIZER1-1); free(buf1r1); free(buf2r2); free(buf3r2); Page 4
Use After Free When the second R1 buffer (buf2r1) is freed that memory is available for reuse right away buf1r1 = (char *) malloc(bufsizer1); buf2r1 = (char *) malloc(bufsizer1); free(buf2r1); Then, the R2 buffers are allocated within that memory region (buf2r1s) buf2r2 = (char *) malloc(bufsizer2); buf3r2 = (char *) malloc(bufsizer2); Finally, the write using the freed pointer will overwrite the R2 buffers (and metadata between) strncpy(buf2r1, argv[1], BUFSIZER1-1); Page 5
Use After Free Most effective attacks exploit data of another type struct A { void (*fnptr)(char *arg); char buffer[40]; }; struct B { }; int B1; int B2; char info[32]; Page 6
Use After Free Free A, and allocate B does what? struct A { void (*fnptr)(char *arg); char buffer[40]; }; x = (struct A *)malloc(sizeof(struct A)); free(x); y = (struct B *)malloc(sizeof(struct B)); struct B { }; int B1; int B2; char info[32]; Page 7
Use After Free How do you think you exploit this? struct A { void (*fnptr)(char *arg); char buffer[40]; }; x = (struct A *)malloc(sizeof(struct A)); free(x); y = (struct B *)malloc(sizeof(struct B)); struct B { }; int B1; int B2; char info[32]; Page 8
Use After Free How do you think you exploit this? struct A { void (*fnptr)(char *arg); x = (struct A *)malloc(sizeof(struct A)); free(x); char buffer[40]; y = (struct B *)malloc(sizeof(struct B)); }; y->b1 = 0xDEADBEEF; struct B { }; int B1; int B2; char info[32]; x->fnptr(buf); Page 9
Use After Free Adversary chooses function pointer value Adversary may also choose address for buf To implement a write-what-where struct A { void (*fnptr)(char *arg); char buffer[40]; }; y->b1 = 0xDEADBEEF; struct B { int B1; }; int B2; char info[32]; x = (struct A *)malloc(sizeof(struct A)); free(x); y = (struct B *)malloc(sizeof(struct B)); x->fnptr(buf); Page 10
Use After Free Flaw: program frees data on the heap, but then references that memory as if it were still valid Accessible: Adversary can control data written using the freed pointer Exploit: Another write-what-where vulnerability Become a popular vulnerability to exploit over 60% of CVEs http://blog.tempest.com.br/breno-cunha/perspectiveson-exploit-development-and-cyber-attacks.html Page 11
Prevent Use After Free Difficult to detect because these often occur in complex runtime states Allocate in one function Free in another function Use in a third function Are all uses accessing a valid (not freed) reference? In all possible runtime states It is not fun to check source code for all possible pointers Page 12
Prevent Use After Free What can you do that is not too complex? Page 13
Prevent Use After Free What can you do that is not too complex? You can set all freed pointers to NULL Then, no one can use them after they are freed Page 14
Related Problem: Double Free What is going on here? main(int argc, char **argv) { buf1r1 = (char *) malloc(bufsize2); buf2r1 = (char *) malloc(bufsize2); free(buf1r1); free(buf2r1); buf1r2 = (char *) malloc(bufsize1); strncpy(buf1r2, argv[1], BUFSIZE1-1); } free(buf2r1); free(buf1r2); Page 15
Double Free Free the R1 buffers free(buf1r1); free(buf2r1); Allocate a new buffer R2 and supply data buf1r2 = (char *) malloc(bufsize1); strncpy(buf1r2, argv[1], BUFSIZE1-1); Free the R1 again, which uses R2 data as metadata free(buf2r1); Then, free R2 which uses really messed up metadata enabling a write-what-where attack (like heap overflow) free(buf1r2); Page 16
Double Free So, double free achieves the same effect as the heap overflow vulnerabilities So, can be addressed in the same way But, you can also save yourself some headache by setting freed pointers to NULL But, we are only still talking about this https://wiki.sei.cmu.edu/confluence/pages/viewpage.action? pageid=87152148 Hopefully, will be part of systems in the near future, but people don t like to tinker with the C language spec Page 17
Type Confusion Cause the program to process data of one type when it expects data of another type Provides same affect as we did with use-after-free But, without the free just need an ambiguous use Page 18
Type Confusion Cause the program to process data of one type when it expects data of another type Provides same affect as we did with use-after-free But, without the free just need an ambiguous use Where s the error below? class Ancestor { int x; } class Descendent : Ancestor { int y; } Ancestor *A = new A; Descendant *D = static cast <Ancestor *> A; D->y = 7; HexType Jeon et al. ACM CCS 2017 Page 19
Type Confusion Cause the program to process data of one type when it expects data of another type Provides same affect as we did with use-after-free But, without the free just need an ambiguous use Where s the error below? class Ancestor { int x; } class Descendent : Ancestor { int y; } Ancestor *A = new A; Descendant *D = static cast <Ancestor *> A; D->y = 7; // not part of memory referenced by D cast from A HexType Jeon et al. ACM CCS 2017 Page 20
Type Hierarchies C++ allows you to construct type hierarchies Upcast Downcast HexType Jeon et al. ACM CCS 2017 Page 21
Type Hierarchies C++ allows you to construct type hierarchies Which type of cast is safe and why? Upcast Downcast HexType Jeon et al. ACM CCS 2017 Page 22
Type Confusion Safety Upcasts are always safe because they only reduce the type structure That is, subtypes extend the structure definitions only Thus, downcasts (as in the example) and arbitrary casts (that do not follow the hierarchy) are unsafe However, programming environments trust programmers to do the right thing Page 23
Type Confusion (Flash) Flash is notorious for type confusion vulnerabilities From reading https://googleprojectzero.blogspot.com/2015/07/oneperfect-bug-exploiting-type_20.html var filter = new flash.filters.blurfilter(); object.filters = [filter]; flash.filters.blurfilter = flash.filters.convolutionfilter; var f = object.filters; var d = f[0]; Page 24
Type Confusion (Flash) What does this code do? Creates a BlurFilter assigned to object.filters var filter = new flash.filters.blurfilter(); object.filters = [filter]; Resets constructor BlurFilter to ConvolutionFilter flash.filters.blurfilter = flash.filters.convolutionfilter; Getter method called creates an ConvolutionFilter object instead var f = object.filters; var d = f[0]; Page 25
Type Confusion (Flash) What does this code do? Creates a BlurFilter assigned to object.filters var filter = new flash.filters.blurfilter(); object.filters = [filter]; Resets constructor BlurFilter to ConvolutionFilter flash.filters.blurfilter = flash.filters.convolutionfilter; Getter method called here creates an ConvolutionFilter object instead so, what is f? var f = object.filters; var d = f[0]; Page 26
Type Confusion (Flash) So what is f? Can be a lot of things Displacement MapFilter <super> BitmapData *bitmap int posx int posy <internal> Bevel Filter <super> int hcolor int scolor float blurx float blury int quality Page 27
Type Confusion (Flash) Attack goal is to modify the vtable in BitmapData (or any object) to control the program execution Displacement MapFilter <super> BitmapData *bitmap int posx int posy <internal> BitmapData <vtable> void *bits Bevel Filter <super> int hcolor int scolor float blurx float blury int quality Page 28
Type Confusion (Flash) By accessing hcolor and scolor fields, we can compute the bitmap pointer Displacement MapFilter <super> BitmapData *bitmap int posx int posy <internal> Bevel Filter <super> int hcolor int scolor float blurx float blury int quality Page 29
Type Confusion (Flash) Can retrieve vtable by setting the bitmapdata address to posx and posy and read matrix Displacement MapFilter <super> BitmapData *bitmap int posx int posy <internal> BitmapData <vtable> void *bits Convolution Filter <super> int matx int maty float *matrix int quality Page 30
Type Confusion (Flash) Then, idea is to create a matrix referencing the BitmapData as a vtable of your choice Displacement MapFilter <super> BitmapData *bitmap int posx int posy <internal> BitmapData <vtable> void *bits Convolution Filter <super> int matx int maty float *matrix int quality Page
Preventing Type Confusion Casts may be checked at runtime to verify that they are safe Research project: HexType converts all static checks to runtime checks Is it true that we only want to allow (safe) upcasts if programmers manually create unsafe casts? Or are these just programmer errors? Can some forms of downcasts or arbitrary casts be made safe? Determining an acceptable policy that balances function and security can be hard Page 32
Format String Vulnerabilities Who uses printf in their programs? printf ("This class is %s\n", string); In some cases, printf can be exploited Page 33
Format String Vulnerabilities Who uses printf in their programs? printf ("This class is %s\n", string); In some cases, printf can be exploited Printf takes a format string and an arbitrary number of subsequent arguments Format string determines what to print Including a set of format parameters Arguments supply input for format parameters Which may be values (e.g., %d) or references (e.g., %s) An argument for each format parameter Page 34
Format String Vulnerabilities Who uses printf in their programs? In some cases, printf can be exploited As usual, arguments are retrieved from the stack What happens when the following is done? printf( %s%s%s%s ); Page 35
Format String Vulnerabilities Who uses printf in their programs? In some cases, printf can be exploited As usual, arguments are retrieved from the stack What happens when the following is done? printf( %s%s%s%s ); Traditionally, compilers do not check for a match between arguments and format string do now So, printf would print strings using next four values on stack as string addresses whatever they are Page 36
Printf and the Stack Address of Format str Arg 1 Arg 2 Arg 3 Remember these are parameters to a function call So, the function expects them on the stack Printf will just start reading whatever is above the format string address 37 Page
Format String Vulnerabilities Who uses printf in their programs? In some cases, printf can be exploited As usual, arguments are retrieved from the stack What happens when the following is done? printf(arg); Page 38
Format String Vulnerabilities Who uses printf in their programs? In some cases, printf can be exploited As usual, arguments are retrieved from the stack What happens when the following is done? printf(arg); Printf can take a variable as an argument treated as a format string If an adversary can control this argument and put values on the stack, they can direct printf to access that memory %s%s%s Page 39
Format String Vulnerabilities Who uses printf in their programs? In some cases, printf can be exploited As usual, arguments are retrieved from the stack What happens when the following is done? printf(arg); An interesting format parameter type %n %n in a format string tells the printf to write the number of bytes written via the format string processing up to that point to an address specified by the argument Page 40
Printf and the Stack Address of Format str Arg 1 Arg 2 Arg 3 Suppose format string generates an adversarycontrolled number of bytes Suppose adversary controls Arg1-Arg3 on stack Adversary can control number of bytes generated by format string with Arg1 and Arg2 Adversary can direct where to write that number (of bytes) using %n with address at Arg3 41 Page
Printf-oriented Programming Address of Format str Arg 1 Arg 2 Arg 3 If the program has a loop that calls printf under adversary control An adversary can supply inputs to write to any memory address Over and over To control the execution of the program arbitrarily (Turing complete) 42 Page
Prevent Format String Vulnerabilities Preventing format string vulnerabilities means limiting the ability of adversaries to control the format string Hard-coded strings w/ no arguments when you can Hard-coded format strings at least no printf(arg) Do not use %n Be careful with other references - %s and sprintf can be used to created disclosure attacks Compiler support to match printf arguments with format string Page 43
Take Away There are other ways to implement powerful attacks besides overflow vulnerabilities We examined a few of the common ones Use-after-free and double-free Type confusion Format string vulnerabilities Each are capable of implementing write-whatwhere attacks that give an adversary arbitrary control of memory We will want to prevent these vulnerabilities Page 44