Skip to content

Commit c35769c

Browse files
authored
Add files via upload
1 parent 76348fc commit c35769c

File tree

4 files changed

+309
-0
lines changed

4 files changed

+309
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
<#
3+
Scenario 1 – Org-only SAT (working)
4+
5+
This script generates a tenant-specific OAuth URL for a single-tenant app (AzureADMyOrg) and redirects
6+
to your GitHub Pages training page (success.html). The goal is to show how legit Microsoft login + app
7+
names can mislead users, and to teach verification of publisher and permissions.
8+
9+
Prerequisites, TODO:
10+
- GitHub Pages enabled for https://rolling-code.github.io/PowerShell-Scripts/
11+
- The file 'docs/success.html' MUST exist in your repo (served by Pages).
12+
- Azure CLI installed and logged in (az login).
13+
- Your app must be registered in YOUR org (AzureADMyOrg) and have the redirect URI(s) added.
14+
15+
Consistency CLI (run once to set up the app):
16+
1) Login to Azure
17+
az login
18+
# Authenticate to Azure CLI in the org where the app will live
19+
20+
2) Create the app registration (captures appId)
21+
az ad app create `
22+
--display-name "TODO Security Portal" ` # Neutral name; avoid 'Microsoft', 'Teams', etc.
23+
--sign-in-audience AzureADMyOrg `
24+
--web-redirect-uris "https://rolling-code.github.io/PowerShell-Scripts/success.html" `
25+
--enable-id-token-issuance true
26+
# Creates the app and enables ID tokens
27+
# Save the returned "appId" (client ID) and your tenant ID/domain
28+
29+
3) Create the service principal
30+
az ad sp create --id <APP_ID> # Use your appId here
31+
# Links the app to your tenant so users can sign in
32+
33+
4) Declare Graph delegated scopes (User.Read, etc.)
34+
# We do this programmatically by calling scope_declaration_function() below
35+
# Ensures the consent screen shows the same permissions as requested in the URL
36+
37+
5) (Optional) Add another redirect URI if desired
38+
az ad app update `
39+
--id <APP_ID> ` # Use your appId here
40+
--web-redirect-uris "https://rolling-code.github.io/PowerShell-Scripts/success.html" `
41+
"https://rolling-code.github.io/PowerShell-Scripts/"
42+
# Keep URIs synchronized with your GitHub Pages files
43+
44+
6) Run this script to generate the URL and test in a browser
45+
#>
46+
47+
[CmdletBinding()]
48+
param(
49+
[string] $RedirectUri = "https://rolling-code.github.io/PowerShell-Scripts/success.html", # TODO MUST exist in GitHub /docs
50+
[string] $ClientId = "TODO", # TODO Use YOUR appId here (from Step 2)
51+
[string] $Tenant = "TODO", # TODO or "acme.onmicrosoft.com"
52+
[string] $Scope = "openid profile email User.Read"
53+
)
54+
55+
# ---- include helper ----
56+
. .\helper_scopes.ps1
57+
58+
# Ensure app's required resource access matches scopes requested
59+
# Fails if not az logged in, fine if already done.
60+
# Presumable if you created the app for this URL you were logged in or are logged in.
61+
scope_declaration_function -AppId $ClientId -IncludeMailAndFiles # (optional) add Mail.Read + Files.Read
62+
63+
function Encode([string] $s) { [System.Uri]::EscapeDataString($s) }
64+
65+
# Exact match is required: redirect in URL must equal the registered URI (including path)
66+
$encRedirect = Encode $RedirectUri
67+
$encScope = Encode $Scope
68+
$state = "sim-" + [Guid]::NewGuid().ToString()
69+
70+
# Single-tenant app => use tenant-specific authority
71+
$base = "https://login.microsoftonline.com/$Tenant/oauth2/v2.0/authorize"
72+
73+
$authUrl = "$base" +
74+
"?client_id=$ClientId" +
75+
"&response_type=code" +
76+
"&redirect_uri=$encRedirect" +
77+
"&scope=$encScope" +
78+
"&state=$state"
79+
80+
Write-Host ([Environment]::NewLine + "--- OAuth Simulation URL (Org-only) ---") -ForegroundColor Green
81+
Write-Host $authUrl -ForegroundColor Yellow
82+
83+
try {
84+
$authUrl | clip
85+
Write-Host ([Environment]::NewLine + "(Copied to clipboard.)") -ForegroundColor Cyan
86+
} catch {
87+
Write-Verbose ('Clipboard copy failed: ' + $_)
88+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
<#
3+
Scenario 2 – Spoofed Microsoft app (intentional error)
4+
5+
This script builds an OAuth URL using a Microsoft-owned client ID to demonstrate that a trusted app name
6+
is NOT enough. The flow breaks after sign-in with AADSTS50011 because the redirect URI is not one of the
7+
official URIs registered for that Microsoft app.
8+
9+
Prerequisites:
10+
- GitHub Pages enabled; 'docs/index.html' should exist for your base landing page.
11+
- No app registration changes are possible for Microsoft-owned client IDs.
12+
13+
Consistency CLI (no app create here; demonstration only):
14+
1) TODO Confirm GitHub Pages is serving your landing page:
15+
https://rolling-code.github.io/PowerShell-Scripts/
16+
17+
2) Run this script and open the URL. Observe:
18+
- Microsoft login and trusted app name
19+
- Then AADSTS50011 redirect mismatch (by design)
20+
#>
21+
22+
[CmdletBinding()]
23+
param(
24+
[string] $RedirectUri = "https://rolling-code.github.io/PowerShell-Scripts/", # TODO MUST exist in GitHub /docs
25+
[string] $ClientId = "00000002-0000-0ff1-ce00-000000000000", # Exchange Online public appId
26+
[string] $Scope = "openid profile email"
27+
)
28+
29+
# ---- include helper (guarded) ----
30+
. .\helper_scopes.ps1
31+
32+
# Guard: skip scope configuration for Microsoft-owned client IDs (helper detects & warns)
33+
scope_declaration_function -AppId $ClientId | Out-Null
34+
35+
function Encode([string] $s) { [System.Uri]::EscapeDataString($s) }
36+
37+
$encRedirect = Encode $RedirectUri
38+
$encScope = Encode $Scope
39+
$state = "sim-" + [Guid]::NewGuid().ToString()
40+
41+
# Public Microsoft app => /common authority
42+
$base = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
43+
44+
$authUrl = "$base" +
45+
"?client_id=$ClientId" +
46+
"&response_type=code" +
47+
"&redirect_uri=$encRedirect" +
48+
"&scope=$encScope" +
49+
"&state=$state"
50+
51+
Write-Host ([Environment]::NewLine + "--- OAuth URL (Spoof Microsoft App; expect AADSTS50011) ---") -ForegroundColor Green
52+
Write-Host $authUrl -ForegroundColor Yellow
53+
54+
try {
55+
$authUrl | clip
56+
Write-Host ([Environment]::NewLine + "(Copied to clipboard.)") -ForegroundColor Cyan
57+
} catch {
58+
Write-Verbose ('Clipboard copy failed: ' + $_)
59+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
<#
3+
Scenario 3 – Multi-tenant attacker-style (realistic consent phishing)
4+
5+
This script generates an OAuth URL for a multi-tenant app (AzureADMultipleOrgs) and redirects to pwndstars.html.
6+
It demonstrates how attackers use the real Microsoft sign-in page and a convincing consent prompt to obtain
7+
access/refresh tokens (if consent is granted). For SAT, we DO NOT exchange codes for tokens.
8+
9+
Prerequisites:
10+
- GitHub Pages enabled; the file 'docs/pwndstars.html' MUST exist and be published.
11+
- Your multi-tenant app must be registered and the redirect URI(s) added.
12+
13+
Consistency CLI (run once to set up the app):
14+
1) Login to Azure
15+
az login
16+
# Authenticate to Azure CLI in the tenant where you own this app
17+
18+
2) Create the multi-tenant app (captures appId)
19+
az ad app create `
20+
--display-name "TODO Security Portal" ` # Neutral name; avoid 'Microsoft', 'Teams', etc.
21+
--sign-in-audience AzureADMultipleOrgs `
22+
--web-redirect-uris "https://rolling-code.github.io/PowerShell-Scripts/pwndstars.html" `
23+
--enable-id-token-issuance true
24+
# Save the returned "appId" (client ID)
25+
26+
3) Create the service principal (optional but recommended)
27+
az ad sp create --id <APP_ID> # Use YOUR appId here
28+
# Makes the app manageable under Enterprise applications
29+
30+
4) Declare Graph delegated scopes (identical across scenarios)
31+
# We do this programmatically by calling scope_declaration_function() below
32+
# Ensures the consent screen shows User.Read, Mail.Read, Files.Read (and offline_access requested in URL)
33+
34+
5) Add additional redirect URIs if needed
35+
az ad app update `
36+
--id <APP_ID> ` # Use YOUR appId here
37+
--web-redirect-uris "https://rolling-code.github.io/PowerShell-Scripts/pwndstars.html" `
38+
"https://rolling-code.github.io/PowerShell-Scripts/"
39+
# Keep URIs synchronized with GitHub
40+
41+
6) Run this script to generate the URL and test in a browser
42+
#>
43+
44+
[CmdletBinding()]
45+
param(
46+
[string] $RedirectUri = "https://rolling-code.github.io/PowerShell-Scripts/pwndstars.html", # TODO MUST exist in GitHub /docs
47+
[string] $ClientId = "TODO", # TODO Use YOUR appId here (from Step 2)
48+
[string] $Scope = "openid profile offline_access User.Read Mail.Read Files.Read"
49+
)
50+
51+
# ---- include helper ----
52+
. .\helper_scopes.ps1
53+
54+
# Configure app's required resource access so consent screen matches URL scopes
55+
# Fails if not az logged in, fine if already done.
56+
# Presumable if you created the app for this URL you were logged in or are logged in.
57+
scope_declaration_function -AppId $ClientId -IncludeMailAndFiles
58+
59+
function Encode([string] $s) { [System.Uri]::EscapeDataString($s) }
60+
61+
$encRedirect = Encode $RedirectUri
62+
$encScope = Encode $Scope
63+
$state = "sim-" + [Guid]::NewGuid().ToString()
64+
65+
# Multi-tenant app => /common authority
66+
$base = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
67+
68+
$authUrl = "$base" +
69+
"?client_id=$ClientId" +
70+
"&response_type=code" +
71+
"&redirect_uri=$encRedirect" +
72+
"&scope=$encScope" +
73+
"&state=$state"
74+
75+
Write-Host ([Environment]::NewLine + "--- OAuth URL (Multi-tenant pwnd demo) ---") -ForegroundColor Green
76+
Write-Host $authUrl -ForegroundColor Yellow
77+
78+
try {
79+
$authUrl | clip
80+
Write-Host ([Environment]::NewLine + "(Copied to clipboard.)") -ForegroundColor Cyan
81+
} catch {
82+
Write-Verbose ('Clipboard copy failed: ' + $_)
83+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
<#
3+
helper_scopes.ps1
4+
5+
Configures Microsoft Graph delegated scopes on an app registration so the consent prompt
6+
shows the same permissions the OAuth URL requests.
7+
8+
Prereqs:
9+
- Azure CLI installed and logged in (az login).
10+
- AppId must be YOUR app's client ID (not a Microsoft-owned client ID).
11+
#>
12+
13+
function scope_declaration_function {
14+
[CmdletBinding()]
15+
param(
16+
[Parameter(Mandatory = $true)]
17+
[string] $AppId, # TODO
18+
19+
[Parameter(Mandatory = $false)]
20+
[switch] $IncludeMailAndFiles, # add Mail.Read & Files.Read
21+
22+
[Parameter(Mandatory = $false)]
23+
[switch] $UseTempFile # fallback: write JSON to temp file and pass by path
24+
)
25+
26+
# Microsoft Graph resource app ID (fixed)
27+
$graphAppId = "00000003-0000-0000-c000-000000000000"
28+
29+
# Guard: refuse Microsoft-owned client IDs (we can't modify those anyway)
30+
if ($AppId -match '^(00000002-0000-0ff1-ce00-000000000000|1fec8e78-bce4-4aaf-ab1b-5451d15019d1)$') {
31+
Write-Warning "AppId '$AppId' looks like a Microsoft-owned client ID. Skipping scope configuration."
32+
return
33+
}
34+
35+
# Delegated scope GUIDs
36+
$UserRead = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" # User.Read
37+
$MailRead = "570282fd-fa5c-430d-a7fd-fc8dc98a9dca" # Mail.Read
38+
$FilesRead = "df85f4d6-205c-4ac5-a5ea-6bf408dba283" # Files.Read
39+
40+
# Build the resourceAccess array
41+
$resourceAccess = @(
42+
@{ id = $UserRead; type = "Scope" }
43+
)
44+
45+
if ($IncludeMailAndFiles) {
46+
$resourceAccess += @{ id = $MailRead; type = "Scope" }
47+
$resourceAccess += @{ id = $FilesRead; type = "Scope" }
48+
}
49+
50+
# Full payload (array of one item)
51+
$payload = @(
52+
@{
53+
resourceAppId = $graphAppId
54+
resourceAccess = $resourceAccess
55+
}
56+
)
57+
58+
# Serialize to compact JSON (no comments, no line breaks)
59+
$json = $payload | ConvertTo-Json -Depth 6 -Compress
60+
61+
Write-Host "Applying required resource access to appId $AppId ..." -ForegroundColor Cyan
62+
63+
# Try direct pass first
64+
$result = az ad app update --id $AppId --required-resource-access $json 2>&1
65+
if ($LASTEXITCODE -ne 0) {
66+
Write-Warning "Direct JSON pass failed; retrying with a temp file..."
67+
# Fallback: write to temp file and pass by path (quoted string so PowerShell doesn't treat '@' specially)
68+
$tmp = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "reqresaccess.$([Guid]::NewGuid().ToString()).json")
69+
Set-Content -Path $tmp -Value $json -Encoding UTF8
70+
$result = az ad app update --id $AppId --required-resource-access "@$tmp" 2>&1
71+
Remove-Item $tmp -ErrorAction SilentlyContinue
72+
}
73+
74+
if ($LASTEXITCODE -ne 0) {
75+
Write-Error "Failed to update scopes. Azure CLI returned:`n$result"
76+
} else {
77+
Write-Host "Scopes updated successfully." -ForegroundColor Green
78+
}
79+
}

0 commit comments

Comments
 (0)