Panther medium experimental python

Azure VS Code OAuth Phishing

Detects OAuth authorization flows where Visual Studio Code successfully authenticates to Microsoft Graph. While legitimate for developers, this pattern is commonly abused in phishing campaigns where attackers use the trusted VS Code client ID to trick users into granting OAuth tokens.

View Source

Detection Logic

from panther_azuresignin_helpers import (
    actor_user,
    azure_signin_alert_context,
    azure_signin_success,
    is_sign_in_event,
)

# Visual Studio Code first-party application ID
VSCODE_APP_ID = "aebc6443-996d-45c2-90f0-388ff96faa56"

# Microsoft Graph resource ID
MS_GRAPH_RESOURCE_ID = "00000003-0000-0000-c000-000000000000"


def rule(event):
    if not is_sign_in_event(event) or not azure_signin_success(event):
        return False

    # Check if Visual Studio Code application is being used
    app_id = event.deep_get("properties", "appId", default="")
    user_agent = event.deep_get("properties", "userAgent", default="").lower()
    is_vscode = app_id == VSCODE_APP_ID or "visual studio code" in user_agent

    # Check if accessing Microsoft Graph
    resource_id = event.deep_get("properties", "resourceId", default="")
    resource_name = event.deep_get("properties", "resourceDisplayName", default="").lower()
    accessing_graph = resource_id == MS_GRAPH_RESOURCE_ID or "microsoft graph" in resource_name

    # Alert on VS Code OAuth to Microsoft Graph
    return is_vscode and accessing_graph


def title(event):
    principal = actor_user(event)
    if principal is None:
        principal = "<NO_PRINCIPALNAME>"

    ip_address = event.deep_get("properties", "ipAddress", default="<UNKNOWN_IP>")

    return f"VS Code OAuth to Microsoft Graph: [{principal}] from [{ip_address}]"


def alert_context(event):
    context = azure_signin_alert_context(event)

    # Add OAuth phishing-specific context
    context["app_id"] = event.deep_get("properties", "appId", default="<NO_APP_ID>")
    context["app_display_name"] = event.deep_get("properties", "appDisplayName", default="<NO_APP>")
    context["user_agent"] = event.deep_get("properties", "userAgent", default="<NO_USER_AGENT>")
    context["authentication_protocol"] = event.deep_get(
        "properties", "authenticationProtocol", default="<NO_PROTOCOL>"
    )
    context["token_issuer_type"] = event.deep_get(
        "properties", "tokenIssuerType", default="<NO_ISSUER_TYPE>"
    )
    context["is_interactive"] = event.deep_get("properties", "isInteractive", default=None)

    return context

Field Validations

Loading…

Comments (0)

Loading comments...