Professional Documents
Culture Documents
Exercise Sheet 1
Michael Backes, Christian Hammer, Matteo Maei Fabian Bendun, Manuel Reinert, Malte Skoruppa Saarland University
/usr/bin/pkexec /usr/bin/gpasswd /usr/bin/passwd /usr/bin/X /usr/bin/sudo /usr/bin/chsh /usr/bin/chfn Choose 3 of these programs and explain the common reason why they need to have the setuid-bit. 5. (2 bonus points) In Linux and other avors of Unix, the setuid-bit works only when it is set for binary executables, but is intentionally ignored when it is set for interpreted scripts. Explain why?
The exploit byte code that needs to be executed in order to get root privileges consists of 45 bytes. Construct an exploit input for argv such that a shell is started where the command whoami outputs root. Do this by answering the following questions for all 3 source code snippets given below: 1. What is the idea of your exploit? Briey explain why it works. 2. How does the stack look like in the moment your input overows the code execution? Hint: Aleph Ones Smashing The Stack For Fun And Prot may contain some useful insights. Next, we give an example target together with a sample solution. Answer the questions in a similar way for the targets Target 1-3 in Figures 2, 3 and 4. Example Target:
1 2 3 4 5 6 7 8 9 10 11 i n t bar ( char arg , char out ) { s t r c p y ( out , a r g ) ; return 0; } i n t foo ( char argv [ ] ) { char buf [ 1 2 8 ] ; bar ( argv [ 1 ] , buf ) ; } 12 13 14 15 16 17 18 19 20 21 i n t main ( i n t a r g c , c h a r a r g v [ ] ) { i f ( a r g c != 2 ) { f p r i n t f ( s t d e r r , t a r g e t : a r g c != 2\ n ) ; e x i t ( EXIT FAILURE ) ; } foo ( argv ) ; return 0; }
Sample solution: The idea of the exploit is to overow buf until the return adress of the method foo is modied. Figure 1 shows the important parts of the stack at the moment when the method strcpy in bar is executed. The exploiting argument argv[1] of the executed program has a size of 137 bytes. In the rst 45 bytes is the exploit code executing a shell, and in the last (137th ) byte is a \0 symbol for strcpy to terminate. The 4 bytes preeceding \0, i.e., the bytes 133 to 136 contain the memory address of argv[1] of method main (note that this address can be determined by running a debugger, e.g. gdb) alternatively, the bytes 133 to 136 may also contain the memory address of the local variable buf of the method foo. In between, the exploiting argument simply contains some junk. Now, upon the execution of strcpy in method bar (line 3), the rst 128 bytes of the exploiting argument will overwrite buf, which now contains our shell code in the rst 45 bytes. Furthermore, the last 4 bytes 133 to 136 will exactly overwrite the return address ret of the method foo (note that both the saved frame pointer sfp and the return value ret have a length of one word, i.e. 4 bytes). After the execution of strcpy, the function bar will return, and then the function foo will return; but since we overwrote the return address of foo, the instruction pointer will now jump to our shellcode, giving us a root shell.
Submission Instructions
The solutions to this exercise sheet must be handed in on Friday, November 9 before the lecture starts or be sent until 12:00 noon on Friday, November 9 to the following email address: security-submissions@mail-infsec.cs.uni-saarland.de Attach your solutions as a plain text or PDF le and start the message subject with [<tutorialnumber>][ExerciseSheet1]. Make sure the message includes your name and matriculation number. Please use this address only for submitting solutions (for asking questions you can use the mailing list). You may work together with one fellow student (i.e., each team can consist of at most 2 members). In this case, please denote the collaboration on the sheet, but, still, submit your own version using your own words. Every team member has to be able to explain the solutions.
Target 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 i n t gee ( ) { return 0; } i n t bar ( char arg , char out ) { s t r c p y ( out , a r g ) ; return 0; } i n t foo ( char argv [ ] ) { char buf [ 1 0 0 ] ; i n t ( fp ) ( ) ; i n t canary [ 1 0 ] ; canary [ 0 ] = 0; f p = &g e e ; bar ( argv [ 1 ] , buf ) ; i f ( canary [ 0 ] ) { e x i t ( EXIT FAILURE ) ; } ( fp ) ( ) ; }
25 26 27 28 29 30 31 32 33 34
24 25 26 27 28 29 30 31 32 33
Figure 3: Target 2
Target 3:
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 i n t main ( i n t a r g c , c h a r a r g v [ ] ) { i n t canary [ 1 0 ] ; canary [ 0 ] = 0; i f ( a r g c != 2 ) { f p r i n t f ( s t d e r r , t a r g e t : a r g c != 2\ n ) ; e x i t ( EXIT FAILURE ) ; } foo ( argv [ 1 ] , s t r l e n ( argv [ 1 ] ) ) ; i f ( c a n a r y [ 0 ] != 0 ) { e x i t ( EXIT FAILURE ) ; } return 0; }
1 2 3 4 5 6 7 8 9
i n t foo ( char arg , s h o r t a r g l e n ) { i n t maxlen = 4032; char buf [ 4 0 3 2 ] ; i f ( a r g l e n < maxlen ) memcpy ( buf , a r g , s t r l e n ( a r g ) ) ; return 0; }
Figure 4: Target 3