Phishing mobile devices, with DeviceCode phishing and QR codes

As protections for endpoints (Laptops, Virtual-Desktops, …) are getting better and sometimes really tough to bypass, it might be time to move along. One of the next weaker devices might be mobile ones, in that case smartphones. Imho the MDM is weaker nowadays then a fully featured EDR with webproxies and packet inspection.

For a good user experience, we can combine “E-Mails, QR-Codes, DeviceCode phishing and Azure CDN fronting”.


  • E-Mails without links, attachments and images will often make it to inbox
  • QRCodes do not need to be images, they can also be Unicode or html tables
  • Azure CDN Fronting spares the handling of a trusted domain, SSL certificate and all the nasty things around
  • DeviceCode phishing is still doing great in most environments
  • A GraphAPI token for Azure is quite powerful
  • Depending on the kind of phishing the loot might be even a fully featured PRT!


When targeting mobile devices, it might not be the best idea to just phish credentials, as most of the time people will not type them in, because it is just annoying to do so. Another problem is MFA and passwordless logins. Of course, you can also use things like VNC phishing or full transparent proxies (evilginx), but those things are mostly difficult to setup, as a lot of protections are in place nowadays.

Another problem is, how to ensure, that the link / payload is executed on a mobile device.


Mobile devices are typically joined to the O365 environment, if existing ofc, because employees should get emails and teams messages outside the office. If there is also a browser logged in, which is quite often the case, as links to documents e.g. via Teams will be opened in the browser at first, the chances of having a DeviceCode Phishing without the user need to enter his credentials are quite high.

Of course, there are a lot of ways to harden the Azure environments and also the devices itself, but this risk is always present from attacker perspective.

Build it

Sending an email

To send an email, we can simply rely on a Azure developer tenant. Details can be found here:

PS: MSRC stated, that it might not be good that emails can be send from the developer tenants, but the “risk is below the bar for immediately servicing”, so I guess we can use this for a while Ooooookay

Another ways to get some emails in the inbox might be:

What to send

When targeting mobile devices a good question is what to send. Malicious apps sound way better then they are, as a MDM managed device will not be able to install. 1-click 0-day exploits? Sure, nice, if you have one, but I guess you might not burn that for a Red Teaming.

The idea for this post is to send a QR code to the victim, which it will hopefully then open on it’s working client and scan with the smartphone.

QRCode in a HTML message rendered in Outlook

What happens when that link is opened? Using a tool like we can either send a second mail to the victim or show a code for device code phishing directly on the browser. It depends on the customer, which version is better, if you want to use O365 to send the initial email it is really annoying to connect squarephish to it. O365 does not support SMTP anymore and a lot of stuff simply seems broken / obsolete at that point.

For our PoC we are going to use a webpage in the layout of the MS Authenticator as most people are used to it by now. The adjustments to deliver a webpage with the flask server of squarephish are minimal. Just return a template with same variables, like this:

#       if not emailed:
#           logging.error(f"[{target_email}] Failed to send victim device code email")

       #return DeviceCode_response["user_code"]
       return render_template('DeviceCode_email.html', code=DeviceCode_response["user_code"]) """

Be creative for the rendered page, a quite simple and lazy example might be:


Further improvements would to change the parameter names and values, e.g. from the cleartext email to something non-obvious like base32 or base56.

How to build

MS recently started to detect links and QR codes in general, but it seems that they are only scanning in attachments and images embedded in the message.

So how could we bypass this? Who said, that a QR Code must be an image, it is just a bunch of squares in black and white.

qrencode -o - "" -l H -t UTF8
████ ▄▄▄▄▄ █ ▀▄█ ██▀ ▀▀▀▄▀█▄ █ ▄▄▄▄▄ ████
████ █   █ █▄█ ▄▄ ▀ ████ ▄  ▄█ █   █ ████
████ █▄▄▄█ █▀▄█▀ ▄▀█▄▄▀██▄██▄█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ ▀▄█▄█ █ █ ▀ ▀ █ █▄▄▄▄▄▄▄████
████▀█   ▀▄█▄ █▄█ █ █ ████▄▀▄  ▄█▀▄  ████
███████ █▄▄ ▄▄█ ▀▄▄▀  ▀▄ █▄▀▄▀▀▄█ ▀ █████
████▀█▀▄█ ▄▄ ▀   ▄▀▀█ █  ▄▄ ▄█▀▄▀ █▄ ████
██████▀█▀█▄   ▀█▀  ▄▀█▀ ▀▀ ██▄▀▄ ▀█▄▀████
████▄▄█▀█▄▄█▀ ▀█  ▄█ ▄▄▀▀▀█ ▀ ▀▄▄█▄█▄████
████▄ █ █▀▄▄▄▄▄▄▀ █▀▀▀▀▄▀▀▀▀▀▀██ ▀ ▀█████
████ ▄▀▄▄█▄█▄▄▄  ▀ ████▀██ █▄▀█▄▄▄▀▄ ████
████ █▄  █▄ ▄▀▄▄▀█ ██   ▄▀  ▄██ ▄ ▀▄▀████
████▄█▄█▄▄▄▄  ▀▀  █▀█▀▄▀ ▀▄▄ ▄▄▄ ▄▀█▀████
████ ▄▄▄▄▄ ███ ▄▄ ▀ ▄▀▄▀█ ▀▄ █▄█  ▀ ▀████
████ █   █ █  █▄▄▄ ▄▀▀██ ▄▀█  ▄▄ █▀ ▄████
████ █▄▄▄█ █▄▀▀  ▀▀▀█▀▄  █▄▄▄  ▀█▄ ██████

Even with the line distance in markdown the QRCodes are easily scanable

You can either go for the plain text message here, or if you use HTML the layout can be further improved. The results with a Monospace font and font size of 8 looks quite good Outlook. If you go for HTML, you should ensure, that you layout keeps intact, e.g. if you have multiple Spaces in a row they might get truncated, which of course breaks the QRCode. Easy fix: Replace “ “ with “ ”

qrencode -o - "" -l H -t UTF8| sed 's/ /\&nbsp;/g' | sed -e 's/^/    <div style="direction: ltr; margin: 0cm;"><span style="font-family: \&quot;Courier New\&quot;; font-size: 8pt; color: rgb(0, 0, 0); white-space: pre-wrap;">/' -e 's/$/<\/span><\/div>/'
<div style="direction: ltr; margin: 0cm;"><span style="font-family: &quot;Courier New&quot;; font-size: 8pt; color: rgb(0, 0, 0); white-space: pre-wrap;">█████████████████████████████████████████</span></div>

QRCode shown by Firefox

Another great advantage of not having the QR code as picture is, that typically pictures are not shown immediately to prevent tracking and to respect some privacy. So we are also sailing around this protection as we typically have no interest in the tracking mechanism.

Device Code phishing

We can go with some “normal” DeviceCode phishing for a Graph-API token and then use it to exfiltrate stuff, e.g. with the great GraphRunner or we customize our server to go for a Primary-Refresh-Token (PRT) with the absolute great technique from here: One of the biggest advantages of the PRT is quite unlimited access to Azure resources but also a long lifetime, typically > 30 days.

There is a working PoC available here:
Note: This technique uses device registration, which can be blocked in the victim’s tenant, but mostly isn’t

It is a little bit tricky to setup with squarefish, a not beautiful but working way is to just call the python script asynchronous from the flask server, write the output to a file and deliver the DevicePhishingCode to the victim. Keep in mind, that the MS API is getting polled after that, so ensure that the script continues running.

Protect the landingpage

To protect the landingpage we can use Azure CDN Classic. It allows us to choose a subdomain for “”, costs typically only a few cents, comes with a Microsoft signed SSL certificate and is trusted by the most web proxies.

This wonderful certificate is used and trusted by most webproxies

We can then either host the real server also in Azure, use some serverless functions, or take anything else. A way to go is to just spawn a VPS and point there from the CDN. Remember to narrow the access directly to the VPS, all traffic should come from the CDN

The setup is really simple, just remember to turn of compression and the cache. Another great feature is, that the CDN can filter for geolocations, user agents, cookies and all those stuff, via an easy to configure webinterface.

CDN settings can be easily adjusted


So our final flow is:

  • Use an Azure dev tenant to send an email with an “spoofed” sender
  • embed a QR code as Unicode
  • The QR code is pointing to a DeviceCode phishing server, customized squarefish in this case
  • The landing page is protected by an AZURE CDN, filtering the user agent
  • If the victim falls for the DeviceCode phishing, and we can register a device, we get a fully featured PRT!
  • With the PRT we can e.g. use RoadTools to start a browser instance or do other enumeration stuff.
  • Play with your token, a PRT can be transformed to almost everything else

There might be a PoC video in the nearer future


Phishing mobile devices might be an effective way to get access to Azure and the O365 part. Microsoft started to counter those attacks with QR-Codes getting scanned but it seems that there is still a lot of improvements. And also the Defender for Office O365 is not available for everyone.

As usual, if you want to discuss stuff, have some remarks or additions feel free to contact me on Twitter (it will always stay twitter not X…) PfiatDe

Countermeasures and indicators

  • Turn off external collaboration for unknown domains / tenants.
  • Block messages, despite your own tenant. This might have some unwanted side effects.
  • Prevent normal users from registering and joining a device
  • Block the DeviceCode login via Conditional Access, unfortunately disabling it is not possible by a simple way
  • Prevent access to the GraphAPI


Work and inspiration from others: