Learn linux command by playing wargame from OverTheWire. This wargame doesn’t require any knowledge about programming - just a bit of common sense and some knowledge about basic *nix commands. Leviathan Below is the solution of Level 2 → Level 3. In this post we will learn how to use a debugging tool to exploit a program and a vulnerability in known as race (Time of Check to Time of Update). We will learn how to create in Linux. ltrace access() TOCTOU symbolic files Previous Posts Leviathan Level 0 to Level 1 Command to login is and password is . ssh leviathan2@leviathan.labs.overthewire.org -p 2223 ougahZi8Ta In the directory we have a binary file which can run as user leviathan3. Using this file we tried to see the password for next level using command but we received an output “ ”. printfile ./printfile /etc/leviathan_pass/leviathan3 You cant have that file… Using with the above command we found that access function returns , that means we do not have read permissions for the file. But we have read permission for the file . ltrace ltrace ./printfile /etc/leviathan_pass/leviathan3 -1 /etc/leviathan_pass/leviathan2 After running command we found that first function returns for the file means we have read permission for it. Then function writes a string consisting of and file path. Then function is called which displays the content of the file. ltrace ./printfile /etc/leviathan_pass/leviathan2 access 0 snprintf /bin/cat system int access(const char *pathname, int mode); checks whether the calling process can access the file . If is a symbolic link, it is dereferenced. access() pathname pathname The specifies the accessibility to be performed and specifies read permission. mode check(s) 4 On success (all requested permissions granted), is returned. On error (at least one bit in mode asked for a permission that is denied, or some other error occurred), is returned. 0 -1 int snprintf( char * restrict dest, size_t n, const char * restrict format, ... ); The function is similar to , but writes its output as a string in the buffer referenced by the first pointer argument, , rather than to stdout. Furthermore, the second argument, , specifies the maximum number of characters that may write to the buffer, including the terminating null character. snprintf() printf() dest n snprintf() The return value is the number of characters (not counting the terminating null character) that would have been written if had been large enough. n The function has a vulnerability ( ). The program calls the , then it calls the . In the small time between the two calls, the file may have changed. A malicious user could substitute a file he has access to for a symbolic link to something he doesn’t have access to between the and the calls. access TOCTOU race Time of Check to Time of Update access() open() access() open() So we create a file with symbolic link to . But we cannot pass with binary file, so we create another file a space. The name of another file is . Instead if creating two files we can create on file . symlink /etc/leviathan_pass/leviathan3 symlink symlink space symlink space We pass with the binary file and the function will accept the complete path of the file but /bin/cat will treat and as different files and it will only accept the . When the function is called it will output the content in the file linked by . symlink space access symlink space symlink system symlink mkdir /tmp/pc123 /tmp/pc123 touch symlink\ space cd Command to create symbolic link ln -s /etc/leviathan_pass/leviathan3 /tmp/pc123/symlink Then run command and the password is . ./printfile /tmp/pc123/symlink\ space Ahdiemoo1j Reference : access(2) - Linux man page Unix / Linux - File Permission / Access Modes snprintf How is using acces() opening a security hole? access() Security Hole Fixing Races for Fun and Profit: How to use access(2) Next Posts Leviathan Level 3 to Level 4 Leviathan Level 5 to Level 6