Files
unknown 07284c56c7 v0.9.0
2023-06-29 08:29:28 +02:00

276 lines
9.9 KiB
PowerShell

# Get's tokens using CBA
# May 24th 2022
function Get-AdminPortalAccessTokenUsingCBA
{
<#
.SYNOPSIS
Gets Access Tokens using CBA
.DESCRIPTION
Gets Access Tokens using Certificate Based Authentication (CBA). Returns tokens for Portal and Business Store.
Assumes that CN of the given certificate contains upn with domain name.
.Parameter PfxFileName
Name of the certificate file to be used
.Parameter PfxPassword
Password of the certificate file to be used
.Example
Get-AADIntAccessTokenForAADGraph
.Example
PS C:\>$tokens = Get-AADIntAdminPortalAccessTokenUsingCBA -PfxFileName .\my_cert.pfx -PfxPassword "my supersecret password"
Logged in as user@company.com
PS C:\>Read-AADIntAccesstoken $tokens[0] | Select aud,iss,appid,amr | fl
aud : https://portal.office.com/
iss : https://sts.windows.net/25dc721a-d37f-44ec-b8dc-cc5783e9ec56/
appid : 00000006-0000-0ff1-ce00-000000000000
amr : {rsa, mfa}
#>
[cmdletbinding()]
Param(
[Parameter(ParameterSetName="File",Mandatory=$True)]
[string]$PfxFileName,
[Parameter(ParameterSetName="File",Mandatory=$False)]
[string]$PfxPassword,
[Parameter(ParameterSetName="Certificate",Mandatory=$True)]
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
)
Process
{
if($Certificate -eq $null)
{
$Certificate = Load-Certificate -FileName $PfxFileName -Password $PfxPassword -Exportable
}
$TenantId = Get-TenantID -Domain $certificate.SubjectName.Name.Split("@")[1]
# Create a web session
$webSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$webSession.Cookies.Add((New-Object System.Net.Cookie("x-portal-routekey", "wuk", "/", "admin.microsoft.com")))
# Invoke the first request to get redirect url
$response = Invoke-WebRequest2 -Uri "https://admin.microsoft.com/login?ru=%2FAdminportal%2FHome%3F%26source%3Dapplauncher" -Method Get -WebSession $webSession -MaximumRedirection 0 -ErrorAction SilentlyContinue
$url = $response.Headers.'Location'
# Get the login parameters and cookies with the certificate
$loginInfo = Get-LoginParametersUsingCBA -Url $url -TenantId $TenantId -Certificate $certificate -WebSession $webSession
# Send parameters to redirect_url
$response2 = Invoke-RestMethod -UseBasicParsing -Uri "https://admin.microsoft.com/landing" -Method Post -Body $loginInfo.parameters -MaximumRedirection 0 -ErrorAction SilentlyContinue -WebSession $webSession
# Return an array of access tokens
$retVal = @()
$retVal += Get-AccessTokenUsingAdminAPI -TokenType PortalAT -WebSession $webSession
$retVal += Get-AccessTokenUsingAdminAPI -TokenType BusinessStoreAT -WebSession $webSession
return $retVal
}
}
# Get's tokens using CBA
# May 24th 2022
function Get-PortalAccessTokenUsingCBA
{
<#
.SYNOPSIS
Gets Access Tokens using CBA
.DESCRIPTION
Gets Access Tokens using Certificate Based Authentication (CBA).
Returns tokens for Graph, Office search, Substrate, Loki, and Portal
Assumes that CN of the given certificate contains upn with domain name.
.Parameter PfxFileName
Name of the certificate file to be used
.Parameter PfxPassword
Password of the certificate file to be used
.Example
Get-AADIntAccessTokenForAADGraph
.Example
PS C:\>$tokens = Get-AADIntPortalAccessTokenUsingCBA -PfxFileName .\my_cert.pfx -PfxPassword "my supersecret password"
Logged in as user@company.com
PS C:\>Read-AADIntAccesstoken $tokens[0] | Select aud,iss,appid,amr | fl
aud : https://graph.microsoft.com
iss : https://sts.windows.net/25dc721a-d37f-44ec-b8dc-cc5783e9ec56/
appid : 4765445b-32c6-49b0-83e6-1d93765276ca
amr : {rsa, mfa}
#>
[cmdletbinding()]
Param(
[Parameter(ParameterSetName="File",Mandatory=$True)]
[string]$PfxFileName,
[Parameter(ParameterSetName="File",Mandatory=$False)]
[string]$PfxPassword,
[Parameter(ParameterSetName="Certificate",Mandatory=$True)]
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
)
Process
{
if($Certificate -eq $null)
{
$Certificate = Load-Certificate -FileName $PfxFileName -Password $PfxPassword -Exportable
}
$TenantId = Get-TenantID -Domain $certificate.SubjectName.Name.Split("@")[1]
# Create a web session
$webSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
# Invoke the first request to get redirect url
$response = Invoke-WebRequest2 -Uri "https://www.office.com/login?ru=%2F%3Ffrom%3DPortalHome" -Method Get -WebSession $webSession -MaximumRedirection 0 -ErrorAction SilentlyContinue
$url = $response.Headers.'Location'
# Get the login parameters and cookies with the certificate
$loginInfo = Get-LoginParametersUsingCBA -Url $url -TenantId $TenantId -Certificate $certificate -WebSession $webSession
# Send parameters to redirect_url
$response2 = Invoke-RestMethod -UseBasicParsing -Uri "https://www.office.com/landingv2" -Method Post -Body $loginInfo.parameters -MaximumRedirection 1 -ErrorAction SilentlyContinue -WebSession $webSession
# Parse tokens from the html
$tokens = (Get-Substring -String $response2 -Start '<div id="primaryTokensInfo" style="display: none;">' -End "</div>").replace('&quot;','"') | ConvertFrom-Json
# Return an array of access tokens
$retVal = @()
foreach($token in ($tokens | Get-Member -MemberType NoteProperty))
{
$value = $tokens | Select -ExpandProperty $token.Name
$retVal += $value.TokenValue
}
return $retVal
}
}
function Get-LoginParametersUsingCBA
{
[cmdletbinding()]
Param(
[Parameter(Mandatory=$True)]
[String]$Url,
[Parameter(Mandatory=$True)]
[String]$TenantId,
[Parameter(Mandatory=$True)]
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate,
[Parameter(Mandatory=$True)]
[Microsoft.PowerShell.Commands.WebRequestSession]$WebSession
)
Process
{
function Get-Config
{
Param(
[Parameter(Mandatory=$True)]
[String]$Content
)
Process
{
$strConfig = Get-Substring -String $Content -Start '$Config=' -End ";`n"
if([string]::IsNullOrEmpty($strConfig))
{
Throw "Could not parse config"
}
try
{
return $strConfig | ConvertFrom-Json
}
catch
{
Throw "Coud not parse config"
}
}
}
$nonce = (New-Guid).ToString()
# Make an initial request to login.microsoftonline.com to get required tokens and config
$response1 = Invoke-WebRequest -UseBasicParsing -Uri $Url -Method Get -WebSession $WebSession -ErrorAction SilentlyContinue
# Extract the config
$config = Get-Config -Content $response1.Content
# Make request to https://certauth.login.microsoftonline.com/<tenantid>/certauth
$body = @{
"ctx"=$config.sCtx
"flowToken"=$config.sFT
}
$response2 = Invoke-RestMethod -UseBasicParsing -Uri "https://certauth.login.microsoftonline.com/$TenantId/certauth" -Method Post -Body $body -Certificate $Certificate
# Parse the hidden form fields
$parameters = @{}
foreach($e in $response2.html.body.form.input)
{
$parameters[$e.name]=$e.value
}
# Make the final request to login.microsoftonline.com to get cookies
$response3 = Invoke-WebRequest -UseBasicParsing -Uri "https://login.microsoftonline.com/common/login" -Method Post -Headers @{"Referer"="https://certauth.login.microsoftonline.com/"} -Body $parameters
# Parse the config
$config = Get-Config -Content $response3.content
if(-not [string]::IsNullOrEmpty($config.strMainMessage))
{
Throw $config.strServiceExceptionMessage
}
# Get the cookies
foreach($cookie in $response3.Headers.'Set-Cookie'.Split(","))
{
$parts = $cookie.Split(";")[0].Split("=")
switch($parts[0])
{
"ESTSAUTH" { $estsauth = $parts[1] }
"ESTSAUTHLIGHT" { $estsauthlight = $parts[1] }
}
}
Write-Host "Logged in as $($config.sPOST_Username)" -ForegroundColor Green
# Make a request to login.microsoftonline.com/kmsi to get code and id_token
$body = @{
"LoginOptions" = "3"
"type" = "28"
"ctx" = $config.sCtx
"hpgrequestid" = $config.sessionId
"flowToken" = $config.sFT
"canary" = $config.canary
"i19" = "2326"
}
$response4 = Invoke-RestMethod -UseBasicParsing -Uri "https://login.microsoftonline.com/kmsi" -Method Post -WebSession $WebSession -Body $body
# Parse the hidden form fields
$parameters = @{}
foreach($e in $response4.html.body.form.input)
{
$parameters[$e.name]=$e.value
}
if(-not $parameters.ContainsKey("code"))
{
$config = Get-Config -Content $response4
if(-not [string]::IsNullOrEmpty($config.strMainMessage))
{
Throw $config.strServiceExceptionMessage
}
Throw "Could not get authorization code!"
}
# Return
return New-Object psobject -Property @{
"parameters" = $parameters
"ESTSAUTH" = $estsauth
}
}
}