Functions/Test-JwtSecret.ps1
function Test-JwtSecret { <# .SYNOPSIS Attempts to obtain the secret for an HS256, HS384 or HS512-signed JSON Web Token. .DESCRIPTION Attempts to obtain the secret for an HS256, HS384 or HS512-signed JSON Web Token from a wordlist containing potential secrets. .PARAMETER JsonWebToken The target JSON Web Token to test the list of secrets against. .PARAMETER HashAlgorithm The RSA hash algorithm for the signature. Acceptable values are SHA256, SHA384, and SHA512. Default value is SHA256. .PARAMETER WordListFilePath The wordlist file containing typical passwords/secrets to test the JWT against. .EXAMPLE $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MDYxNDEwOTMsIm5iZiI6MTYwNjE0MTA5MywiZXhwIjoxNjA2MTQxMzkzLCJqdGkiOiI1Njk5YTBlYTk3YzM0Yzc2OTlkZGZlNzNmNTIzOTI1MiIsInN1YiI6InVzZXJuYW1lQGNvbXBhbnkuY29tIn0.Ej86QALzH37R1zB7QhwwYdFjXL1UhG2E3n6nezEYONY" $jwt | Test-JwtSecret -WordListFilePath ./wordlist.txt Tests an HMAC-SHA256 signed JWT signature against a wordlist. .EXAMPLE $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE2NzYzMDg2MTksIm5iZiI6MTY3NjMwODYxOSwiZXhwIjoxNjc2MzA4OTE5LCJzdWIiOiJ1c2VybmFtZUBjb21wYW55LmNvbSIsImp0aSI6ImVlODczMzc1MmQ0YTQxNzNiOTA0ODcxZjFjODMxNzQ2In0.rKDBCWkALz7FBTavX9G4HNnaLcyQY8i1WurAs1aQpfDA5Tmi3EtKn6K1k2OO9V-J-94t0ToaypxrtePyc0h8rA" $jwt | Test-JwtSecret -HashAlgorithm SHA512 -WordListFilePath ./wordlist.txt Tests an HMAC-SHA512 signed JWT signature against a wordlist. .INPUTS System.String A string is received by the JsonWebToken parameter. .OUTPUTS System.String .LINK https://tools.ietf.org/html/rfc7519 #> [CmdletBinding()] [Alias('tjwts')] [OutputType([System.String])] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [ValidateLength(16, 8192)][Alias("JWT", "Token")][String]$JsonWebToken, [Parameter(Mandatory = $false, Position = 1)][ValidateSet("SHA256", "SHA384", "SHA512")][String]$HashAlgorithm = "SHA256", [Parameter(Mandatory = $true, ValueFromPipeline = $false, Position = 2)][Alias("Path", "FilePath")] [ValidateScript({ if ( -Not ($_ | Test-Path) ) { $fileNotFoundExceptionMessage = "Wordlist file not found in the following path: {0}" -f $_ $FileNotFoundException = [System.IO.FileNotFoundException]::new($fileNotFoundExceptionMessage) throw $FileNotFoundException } return $true })][System.IO.FileInfo]$WordListFilePath ) BEGIN { $decodeExceptionMessage = "Unable to decode JWT." $ArgumentException = New-Object -TypeName ArgumentException -ArgumentList $decodeExceptionMessage } PROCESS { [bool]$hasValidJwtStructure = Test-JwtStructure -JsonWebToken $JsonWebToken -VerifySignaturePresent if (-not($hasValidJwtStructure)) { Write-Error -Exception $ArgumentException -Category InvalidArgument -ErrorAction Stop } $wordList = [System.IO.File]::ReadAllLines($WordListFilePath) [int]$wordCount = $wordList.Count [int]$currentIndex = 1 [bool]$secretDiscovered = $false [string]$outputMessage = "Secret not found." foreach ($secret in $wordList) { if ($secret.Trim().Length -ge 1) { $verboseMessage = "Tested $currentIndex of $wordCount secrets." $currentIndex++ Write-Verbose -Message $verboseMessage [bool]$cracked = Test-JwtSignature -JsonWebToken $JsonWebToken -Key $secret.Trim() -HashAlgorithm $HashAlgorithm if ($cracked) { $outputMessage = "The following value is the correct token signing key: {0}" -f $secret Write-Output -InputObject $outputMessage $secretDiscovered = $true break } } } if (-not($secretDiscovered)) { Write-Output -InputObject $outputMessage } } } |