How I Turned an Image Upload Feature into Full Server Access Using DNS Queries

Hey everyone,

I’m back with another interesting finding. This time we’re diving into a classic image processing vulnerability that’s still lurking in production systems. Grab your coffee and let’s get into it.

The Discovery

I was testing a photography portfolio platform where photographers could upload and showcase their work. Pretty standard stuff until I noticed something, they had an “Import from URL” feature that let you add images by providing a URL instead of uploading directly.

The feature worked like this:

https://target.com/portfolio/import?image_url=http://attacker.com/photo.jpg

You give them a URL, they fetch your image, process it, and add it to your gallery. Simple enough, right?

But here’s where things got interesting. When I tested it with a legitimate image URL, I noticed the application wasn’t just linking to my URL. Instead, it was processing the image and storing it on their own servers. My test image from Google ended up hosted at:

https://cdn.target.com/galleries/user123/processed_abc123.jpg

This caught my attention immediately. Server-side image processing often opens up some serious attack vectors.

Understanding the Infrastructure

I wanted to see where these requests were actually coming from, so I set up a simple listener on my server:

nc -lvvv 8088

Then I submitted my test payload pointing to my server. Within seconds, I got a connection:

GET /test.png HTTP/1.1
User-Agent: ImageProcessor/2.0
Accept: */*
Accept-Encoding: deflate, gzip
Host: attacker.com
Connection: keep-alive

The request came from their infrastructure with a custom user agent suggesting specialized image processing software. This looked like a properly isolated image processing server, which is actually good security practice, but it doesn’t mean it’s invulnerable.

The First Attack Vector

Now came the fun part. I knew the application was processing images server-side, so I started testing different attack vectors.

My first thought was SVG-based attacks. SVG files are XML by design, which means they can sometimes be exploited for Server-Side Request Forgery (SSRF) or XML External Entity (XXE) attacks. I crafted a malicious SVG and submitted it, but nothing happened. The application either wasn’t processing SVG files or had proper protections in place.

Time for plan B.

Many image processing libraries have known vulnerabilities, and the most famous one involves improper handling of certain image formats that allows command injection. I created a test payload that exploits how these libraries interpret processing directives:

The exploit works by crafting a specially formatted image file that contains shell commands embedded in the processing instructions. When the vulnerable library processes this file, it interprets those backticks and executes the command.

I saved this as exploit.png and submitted it through the image_url parameter. Then I waited at my listener:

And waited… and waited… Nothing. No connection. No callback.

Facepalm moment.

The Critical Question

But then I asked myself something important: What if the server can execute commands, but outbound HTTP connections are blocked by a firewall?

This is actually pretty common in security-conscious environments. Many organizations block outbound connections on standard ports like 80 and 443 to prevent data exfiltration and malware callbacks. But there’s one thing they often forget to block: DNS queries.

Enter DNS Exfiltration

DNS exfiltration is one of those techniques that sounds complex but is actually beautifully simple. The idea is to use DNS queries to smuggle data out of a restricted network. Even if all outbound HTTP/HTTPS ports are blocked, DNS usually works because servers need it to function.

Here’s how it works. You control a domain and set up your own DNS server. When you execute commands on the target server, instead of making HTTP requests, you make DNS queries to subdomains of your domain. Your DNS server logs these queries, effectively transmitting data through DNS lookups.

For example, if you want to send the word “test”, you make a DNS query for test.attacker.com. Your DNS server receives and logs this query, and boom, you've exfiltrated data.

Why does this work so well? DNS is essential for almost every server operation, it’s rarely blocked, often unmonitored, requires no authentication, and works through pretty much any firewall. Port 53 is almost always allowed outbound.

Testing the Theory

I modified my payload to test this DNS exfiltration theory:

Where attacker.com is a domain I control with custom DNS logging enabled. I submitted the exploit and checked my DNS logs...

Bingo! The server made a DNS query to my domain. This confirmed three critical things: the image processing library was vulnerable, command execution was possible, and while outbound HTTP was blocked, DNS queries were going through just fine.

Building the Full Exploit

Now that I had confirmed command execution, I needed to prove the impact. But I couldn’t just use regular HTTP requests — I had to exfiltrate data through DNS queries.

Mapping the Filesystem

I crafted a payload to list directory contents:

This clever payload executes ls / to list the root directory, then for each file or folder, it makes a DNS query like home.attacker.com, bin.attacker.com, etc. My DNS server logs these queries, revealing the directory structure.

The results started flowing in:

Perfect! I could see the entire filesystem structure through DNS queries.

Identifying the User Context

Next, I wanted to gather more information about the server environment. I executed the id command to see what user the process was running as:

The DNS logs showed:

The process was running as nobody, a low-privileged user. Still, that's enough to read configuration files and potentially access sensitive data.

Exfiltrating File Contents

Now I needed to exfiltrate actual file contents. But there’s a challenge here: DNS queries have character limitations and special characters can break the query.

The solution? Base32 encoding.

Base32 is actually better than Base64 for DNS exfiltration. It only uses alphanumeric characters (A-Z, 2–7), has no special characters that could break DNS queries, and is more reliable for encoding arbitrary data.

Here’s my final payload:

My DNS logs would then show queries like:

I could decode this back to get the original data:

This technique successfully exfiltrated file contents from the server, proving full remote code execution with the ability to access sensitive system information even through network egress restrictions.


Thanks for reading!

you can follow me on social media to see more Write-Ups and tips

Xarrow-up-right

linkedinarrow-up-right

Last updated