Detecting and mitigating: GIFShell

Anton Wadström

Detecting and mitigating: GIFShell


  1. Background.
  2. Detection.
  3. Mitigation.
  4. Q&A.
  5. References.

1.     Background

BleepingComputer recently wrote about a new attack technique called ‘GIFShell’ which allows threat actors to abuse Microsoft Teams for novel phishing attacks and covertly executing commands to steal data using GIFs.

Asurgent SOC analyzed and tested the proof-of-concept code in a testing environment with Defender for Endpoint and Microsoft Sentinel to see if the threat was as hard to detect as the security researcher that found the vulnerability claimed. (Spoiler: this attack is really sneaky!)

  1. The malicious actor prepares the stager with information about the Command and Control server and their webhook uri, then gets the stager on the victim machine through any viable method
  2. The victim downloads and executes the stager
  3. The stager continuously reads the log file in %appdata%\Microsoft\Teams\IndexedDB\\
  4. The malicious actor embeds a GIF with a base64 encoded command and sends it via Teams chat to the victim – the victim only sees the fully functional GIF
  5. The message with the malicious GIF is logged in the log file as clear text, exposing the base64 encoded command embedded within
  6. The stager decodes the base64 encoded command and executes it
  7. The stager creates a “GIF endpoint” that consists of the command and control server address followed by the base64 encoded result of the executed command and adds “.gif”, for example “http://{c2server}/{base64_encoded_results}.gif”. This endpoint is then referenced in a Teams message card as an “activityImage” property.
  8. The Teams message card is sent to the attacker controlled Teams webhook
  9. Microsoft Teams attempts to fetch the “activityImage” from the GIF endpoint, which calls out to the C2 server which can then decode the base64 encoded results and see the clear text output from their command.

Steps 4-9 can then be repeated until the stager is removed, or the victim machine is isolated or shut down.

Note: Defender for Endpoint did not flag the stager as malicious or give any warnings at all on the victim machine!

2.  Detection

Detecting GIFShell turned out to be really tricky since all Command and Control traffic are routed over Microsoft hosted infrastructure – no communication channel is established directly between the actor and the victim.

Even though we tested the stager on a fully up-to-date Windows 11 client onboarded to Defender for Endpoint, no warnings were raised (the stager is basically reading a file and sending data to a webhook – something that could be a completely legitimate business use case!)

By leveraging Microsoft Sentinel and raw logs ingested from Defender for Endpoint, we could however build a query that looks at the TTPs, the behaviour, of the attack:

  • A script file is created on the victim machine at some point (the stager)
  • The stager will at some point send requests to {actor_office_365_tenant}

A sample query that detects this event chain:

let recentLookback = 1h;
let scriptExtensions = dynamic(["ps1", "bat", "py", "sh"]);
let scriptCreationEvents = DeviceFileEvents
  | where TimeGenerated >= ago(recentLookback)
  | where ActionType == "FileCreated"
  | where FileName has_any (scriptExtensions)
  | where InitiatingProcessFileName != "MsSense.exe"
  | where InitiatingProcessParentFileName != "SenseIR.exe"
  | summarize scriptName = make_set(FileName) by DeviceId;
| join (DeviceNetworkEvents
  | where TimeGenerated >= ago(recentLookback)
  | where RemoteUrl contains ""
) on DeviceId
| mv-expand kind=array scriptName
| where InitiatingProcessCommandLine has tostring(scriptName)
| project-away DeviceId1

In our testing environment this query could detect that a suspiciously named script had been created and then made connections to a webhook hosted in a different Office 365 tenant:

Another sample query can detect when a process opens the log file containing the raw Teams messages on the victim machine, however, due to Defender for Endpoint not logging FileAccess events, we cannot see these files being accessed by the malicious stager – but we can detect if someone is actively poking around with the log file.

let GIFShellRegex = @"Microsoft\\Teams\\IndexedDB\\\\.*.log";
| where ProcessCommandLine matches regex GIFShellRegex or InitiatingProcessCommandLine matches regex GIFShellRegex

Other queries can be created that look at network traffic for requests sent to the Teams GIF lookup server with unusually long GIF filenames in the style of “<c2server>/<base64encoded>.gif”

3.  Mitigation

The best mitigation at this point is to configure your organizations’ Teams tenant to only allow external communication with domains that you trust. This is an aggressive action which might cause communication downtime with your partners if you don’t thoroughly go through which domains your organization is actively communicating with.

This is done in the Teams admin center ( or with Microsoft Teams Powershell module.

Or with Powershell:

Import-Module -Name MicrosoftTeams

$list = New-Object Collections.Generic.List[String]

Set-CsTenantFederationConfiguration -AllowedDomainsAsAList $list

Did you know that Asurgent’s tool, drag0nfly, can scan your Microsoft 365 tenant for known insecure configurations, such as Teams tenant federation settings, and present you with mitigating recommendations?

Finding external chat members

To find the external users your organization have been chatting with, you can perform the following steps:

  1. Register an application in Azure AD with the following application API permissions:
      1. Directory.Read.All
      2. Chat.ReadBasic.All

  2. Take note of the tenant id and client id in the overview page of the application
  3. Create a secret for the application and save it for later
  4. Download the script ‘Get-ExternalTeamsChatMembers’ from Asurgent’s public Github repository (cloudops-public/Get-ExternalTeamsChatMembers.ps1 at master · asurgent/cloudops-public (
  5. Open Powershell Core and navigate to the path containing the script
  6. Execute it as in the below example (requires the Microsoft.Graph and MSAL.PS modules)
    $tenantId = ‘tenant_id noted from step 2’
    $clientId = ‘client_id noted from step 2’
    $clientSecret = ConvertTo-SecureString -AsPlainText ‘client_secret from step 3’ 
    .\Get-ExternalTeamsChatMembers.ps1 -tenantId $tenantId -clientId $clientId -clientSecret $clientSecret -outpath (optional path to export the results to, defaults to C:\Temp)

  7. The script will parse all chats for all users and extract the members whose tenant id is not your organization’s tenant id, and export the results to a CSV-file in the location specified in the -outpath parameter


4.  Q&A

Q: Can we mitigate this attack vector by disabling Giphy in Teams messaging policies?

A: Unfortunately not. By disabling Giphy in the organization through Teams messaging policies you disable the possibility for your organization to use Giphy in Teams messages, it does not prevent external users from sending GIFs to your organization.

Q: Can our users detect if they are being targeted by this attack?

A: Yes they can! If they are suddenly contacted on Teams by an external user that are sending several GIFs, it might be an indicator that a threat actor is executing commands and exfiltrating information from the compromised user. The below example would be a clear indicator (even without the text in the actual GIF) that a user have been compromised, but an actual threat actor would most likely send different GIFs and mix in some actual messages to avoid raising suspicion from the target.

5.  References


Upptäck mer