Stegosploit: Owned By A JPG

We’re primarily hardware hackers, but every once in a while we see a software hack that really tickles our fancy. One such hack is Stegosploit, by [Saumil Shah]. Stegosploit isn’t really an exploit, so much as it’s a means of delivering exploits to browsers by hiding them in pictures. Why? Because nobody expects a picture to contain executable code.

stegosploit_diagram[Saumil] starts off by packing the real exploit code into an image. He demonstrates that you can do this directly, by encoding characters of the code in the color values of the pixels. But that would look strange, so instead the code is delivered steganographically by spreading the bits of the characters that represent the code among the least-significant bits in either a JPG or PNG image.

OK, so the exploit code is hidden in the picture. Reading it out is actually simple: the HTML canvas element has a built-in getImageData() method that reads the (numeric) value of a given pixel. A little bit of JavaScript later, and you’ve reconstructed your code from the image. This is sneaky because there’s exploit code that’s now runnable in your browser, but your anti-virus software won’t see it because it wasn’t ever written out — it was in the image and reconstructed on the fly by innocuous-looking “normal” JavaScript.

232115_1366x1792_scrotAnd here’s the coup de grâce. By packing HTML and JavaScript into the header data of the image file, you can end up with a valid image (JPG or PNG) file that will nonetheless be interpreted as HTML by a browser. The simplest way to do this is send your file myPic.JPG from the webserver with a Content-Type: text/html HTTP header. Even though it’s a totally valid image file, with an image file extension, a browser will treat it as HTML, render the page and run the script it finds within.

The end result of this is a single image that the browser thinks is HTML with JavaScript inside it, which displays the image in question and at the same time unpacks the exploit code that’s hidden in the shadows of the image and runs that as well. You’re owned by a single image file! And everything looks normal.

We like this because it combines two sweet tricks in one hack: steganography to deliver the exploit code, and “polyglot” files that can be read two ways, depending on which application is doing the reading. A quick tag-search of Hackaday will dig up a lot on steganography here, but polyglot files are a relatively new hack.

[Ange Ablertini] is the undisputed master of packing one file type inside another, so if you want to get into the nitty-gritty of [Ange]’s style of “polyglot” file types, watch his talk on “Funky File Formats” (YouTube). You’ll never look at a ZIP file the same again.

Sweet hack, right? Who says the hardware guys get to have all the fun?

34 thoughts on “Stegosploit: Owned By A JPG

        1. Like [Truth] said, it depends. Sites that don’t rely a lot on JS work just fine, even sites that rely heavily on it generally ‘work’. Script blockers also typically allow you to whitelist individual scripts, or script sources. As an example you would whitelist and it’s sub domains but block, twitter, facebook, and quite a few ad servers. Sites that require you to log are beginning to require social media and their CDNs, but that’s only if you want to log in.

          After a while you get an idea of the common CDNs ( for instance) and what scripts need to run for music/video’s to work. You can then build your own whitelist or run them on as-needed basis.There’s a steep learning curve, but it’s not always as disruptive as you may think.

      1. I use uMatrix on Chrome. Each site gets specific limitations on cookies, css, images, plugins, scripts, XHR and “other” for each and every domain that they call data from. As I have it set, 1st party stuff gets most access, and everything else is denied until I tell it otherwise.

        Took about a day of browsing to get the normal sites I read up to usable, because I’d need to enable some obscure script or XHR to a domain I didn’t recognize (usually a google ad domain or a cache service). A week to get the random sites I visit when linked to work and, occasionally, if I’m really impatient, I just “allow all” and read an article and disable things again; this isn’t my secure machine.

        Which means I should ask, which random scripts, XHR, frames, etc do the crew at HAD need enabled to make ad revenue? wordpress and three subdomains, wp and 4 subs, typekit and it’s ilk, supply-frame, quantserve, and google-analytics….some of those have to be important to you guys and I’d like to turn them on, but since I often have about 10 to 20 tabs open I got tired of every other site having some small flash advert that just happened to reverse a gig of ram. Getting Chrome’s built in flash down to 14 megs ram is, unfortunately, too important to me.

    1. HD should stay with electronics.

      this is a toy. in the software and security world this ranks lower than arduino projects in the electronic world.

      the real vulnerability is running javascript code where you are not supposed to. if you have that, it is end game. transferring payload after you have that is the most trivial thing in the world. you have ajax, frames, js, cookies from other domains, flash, etc, etc, etc.

      using a rubegoldberg image and canvas etc will only do two things: limit the browsers you can deliver the payload; and make it much easier for anti-virus/firewalls to detect you (hint: they will ignore the payload and focus on the complex code to unwrap it, which now will flare up on anyones radar)

      also this is old. sad to see the author still living it up. for better software hacks, post anything (literally) from CCC or anything that is happening this quarter.

      1. I’m not knocking it. This is certainly interesting enough to warrant a post.
        It opens up a whole host of possibilities being able to execute code by displaying a picture.
        I wonder if inserting one of those annoying little mouse followers might be possible.

  1. This isn’t going to be any less detectable by vulnerability scanners than any other common means of encoding and hiding exploit code. And it still relies on having a vulnerability to exploit in the first place.

  2. The irony lol.

    So yeah you can hide obstructed code in an image and use JavaScript to re-assemble it so your anti-virus software doesn’t detect it.

    This works on some browsers because they’re dumb enough to accept the mime type from the server rather than read it from the file or some similar combination.

    Even better if you are hand writing your own code then you don’t need to hide it from the anti-virus because the anti-virus has never heard of it and doesn’t know what it is. All you need is a browser that accepts a mime type from a somewhere that can be manipulated.

    So here is a much easier attack vector.

    Now you could use your own server to send a file with the wrong mime type that would be kind of dumb.

    Plan B is to use someone else’s server but how to get it to send the wrong mime type???

    Well it turns out that it the really easy part. Most server code is written by amateurs and most of that is in php.

    Rather than read the mime type from the data in an uploaded file, most servers just look at the file extension ie if it’s a .png .jpeg .jpg .gif .bmp (often excluded as *nix .bmp != windows .bmp) then it is accepted as an image that can be placed somewhere on the site.

    So now – if you upload something that can be executed (and not a direct .exe) then you just have to rename the extension.

    If the browser reads mime type from the file rather than the extension then the attack vector is complete.

    And now back to the irony – Well @[Elliot Williams] right now I can think of a server that does exactly that ie has that weakness where a mime type is ‘assumed’ from the file extension. Any idea why I can think of one right now and why perhaps that is ‘ironic’ lol.

    1. “This works on some browsers because they’re dumb enough to accept the mime type from the server rather than read it from the file or some similar combination.”

      That’s not a vulnerability – that’s working as designed. Content auto-detection, as practiced by earlier versions of IE, is broken, contrary to specifications, and causes any number of bugs.

      1. And remote execution of arbitrary code is *NOT* a bug?

        You say it’s not a vulnerability because browser. I say yes it is because server. I can upload incorrect mime type to server and effect your browser! So you are effectively giving control of security for you browser to unknown third parties (servers). And the hacker takes control from weaknesses on that server.

        As for design? By writing php that accepts invalid mime types they are ‘designing’ the system to be vulnerable. Design really doesn’t mean anything when you talk about security because *most* system have ‘designed in’ vulnerabilities.

        Content auto-detection is one thing. Content handling ie accept or reject is another.

        I did WAN LAN network security before I started web server maintenance / coding. All I could say is – looking at the security standards for php, even professionally coded php – Mind blown!!!

        1. “And remote execution of arbitrary code is *NOT* a bug?”

          Yes, of course it is, but you haven’t demonstrated that. Your evil plan looks something like:
          1. Serve up one type of content disguised as another
          2. …
          3. Profit!

          Number 2 is pretty important, and telling the browser the content is one thing when it’s actually another doesn’t actually do any good, in the absence of something to exploit.

          1. Ok I will write a couple of day zero’s for you, to demonstrate the difference between a attack vector and an exploit … wait this bypasses anti-virus detection so it doesn’t have to be a day zero so in that case there would be thousands of exploits out there in the wild that could use this attack vector, a simple google will find them and there free unlike a day zero that you either write yourself or pay hundreds of thousands of dollars for.

          2. You still haven’t explained how serving up one content-type while claiming it’s another in any way compromises security.

            Also, they’re called zero-days, not “day zeros”.

  3. You know this has been around for ages, right HaD? What’s wrong, slow news day so you’re scraping the bottom of the barrel? Why don’t you run some never-ending contests instead?

    1. Well, in the old days you did not have to hide it in a header, you could just create any kind of script, rensame it .jpg and browsers (at least IE) would happily run it no questions asked.
      It took years for that to be somewhat resolved. But I guess they wanted to keep a backdoor open and allow for this shit.

      Seems so many ‘flaws’ are there on purpose and more added (or replaced) with each new iteration of browser and HTML version. And I say on purpose because it’s very often completely obvious that it’s a hole in security and sometimes requires quite some coding to make sure it’s a vulnerability.

      Same for that ‘flaw’ that allows you to hack airliner’s control system via the passenger WiFi. That shit isn’t an accident, it takes a lot of engineering to enable that kind of ‘flaw’, to have a control system that is completely separate and independent and of a different design and vendor to merge with a public WiFi.. it’s actually quite a good engineering effort when you think about it. And it probably required both a software and hardware engineering team.


  4. I’m pretty sure this is a dupe. When it was first presented there was a discussion about the (then) misleading title because it claimed to be a way of getting the hidden code to run as well.

  5. “You’re owned by a single image file! And everything looks normal.”

    “Owning” means the program has taken privileged control of your computer. This is just running javascript in the browser. Your computer would be no more owned than it is by just about any website you visit today.

    1. Yeah, I’m confused by this too.
      I mean, if AV software really works by looking at raw source code then this gets around it….but do they actually do that? And couldn’t any form of compression of the code achieve the same result?

      The important exploits to worry about are the ones that any running javascript in the browser can cause – and other then crafty social engineering stuff – normally browser makers are fairly ontop of it these days.

      I mean, if people know a good exploit, then make some money.

      1. The Anti-Virus software sits (as a proxy) between the last protocol layer and the browser. It has to be the after the last protocol layer so that ssl is back to plain text and compressed files are uncompressed.

        This exploit assembles the Javascript that is obstetrical in an image file that has been scanned by the AV in the way in. As the Javascript is assembled inside the browser there is no scanning by the AV.

        A non-protocol layer form of compression could work for the same reasons however most normal compression works in the protocol layers.

  6. Non-malicious use:

    Pack up an entire website in a few photos. Would be useful for getting data in and out of oppressive countries, fill an SD card with what looks like a bunch of vacation photos, but are in reality an unabridged copy of censored webpages. The customs folk would just see a bunch of harmless images on your camera and move you along and think nothing of it.

    Or even do this online by hosting a photo album page where the images are sent out as standard image files, but present a magic cookie (specific key strokes, coming over from a specific webpage, specific user agent / IP, etc) and the web server will send you a page where the images are sent down as text/HTML.

  7. If you can upload the image to someone else’s server and rename it as HTML then you’re already in. All the messing around with polyglot files is just making it harder for yourself and being “clever” for the sake of it.

    If your interested in polyglot files, take a look at GIFAR.

  8. So what’s the trick, that virus scanners don’t check JPEGs? Really I suppose they should be checking the MIME type from the server, rather than the file’s extension. How does it actually end up doing damage from within a browser? Javascript security holes? If that’s the case, the holes are the problem to start with.

    On a related issue, Microsoft’s decision, since way back when, to default to hiding the three-letter extension on files, is a good candidate for stupidest computer decision EVER. The existence of dirtypicture.jpg.exe was just waiting to happen, anyone with any sense could’ve seen that coming before it happened. More of Microsoft’s user-interface philosophy, where instead of studying and building a proper interface, they just hide all the messy bits. Thing is it doesn’t take 5 minutes to teach your granny the concept of file extensions, and “watch out for .exe”.

    I will devote the rest of this post to criticising the decision further – stupid, stupid, stupid, stupid, stupid, stupid, stupid, stupid, stupid. Etc.

  9. A much more useful application of the content type ‘hack’ is used by asynchronous script loaders to download many javascript files at once. By downloading them as images, the loader script is able to download more than 2 files at once which used to be the limit of concurrent html/javascript/css(?) files the browser would load. This workaround is needed less today, with such restrictions reduced, but is neat nonetheless.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.