โ† Back to Writeups
CVSS 9.8CRITICAL

Image Upload Gone Wild: Blind SQLi to Superadmin in Disguise

#Blind SQL Injection#Second-Order Injection#Privilege Escalation#Business Logic

Published: November 20, 2024

๐Ÿง  TL;DR

"It's just an image upload form. What's the worst that could happen?"

Turns out: quite a lot. Blind SQL injection through the filename of an uploaded image led to a stored update, which allowed me to take over a superadmin account and exfiltrate DB metadata via a second endpoint.

๐ŸŽฏ Discovery: Where Curiosity Kicked In

I started by fuzzing the image upload endpoints and watching how the server used the filename parameter.

Observed request (multipart/form-data; filename param):

Request: multipart form-data with filename parameter

Request capture showing the filename field inside multipart form-data.

Initial payload attempts and basic variations exposed interesting server behavior (the app tried to treat the filename as SQL-relevant in some DB update flow):

Initial requests and basic payload attempts

A selection of initial attempts โ€” typical filename-based injection strings.

๐Ÿ›‘ First Barrier: Forced .jpg Extension

The server appended .jpg to filenames, which initially broke naive payloads (they became syntactically invalid in the constructed SQL statements).

Example of how the forced extension caused malformed SQL:

Full crafted payload and server reaction

Server response showing the constructed SQL and how the appended .jpg affected parsing.

๐Ÿง  Round Two: Bypass the Extension with SQL Functions

The workaround was to use SQL functions: concat() and char() to reconstruct dots and email addresses so the appended .jpg didn't break the payload logic.

Filename-based SQL injection example (using char(46) to insert dots):

Filename-based SQL injection using concat and char

Screenshot showing the filename field containing concat/char constructs to bypass forced .jpg behavior.

๐Ÿ’ฃ Payload Mechanics (what I injected)

The final payload pattern closed the original SQL literal, injected an UPDATE that set the target user's email / fname, and commented out the rest. Example (conceptual):

Rocky', email=concat('dilip',char(46),'prasad@'security,char(46),'io'), fname='dilip' where email=concat('fapatrick1230@gmail',char(46),'com')#

Below is a request snapshot of the crafted payload being sent in the filename parameter and the server response reflecting the UPDATE action.

Full crafted payload and confirmation of update in server response

Same capture shown again for emphasis on the actual SQL UPDATE call constructed server-side.

๐Ÿ” Adding Account Attempts & Interesting Server Responses

Some attempts caused server-side errors or redirects โ€” those responses helped refine where the DB update was happening and what fields were affected.

Server response showing failure or unusual response

Response capture showing a server error/redirect after a particular filename payload.

๐Ÿ‘ฃ Step into Superadmin Shoes (post-exploit)

After I successfully updated the target user's email to one I control, I authenticated and found the account had escalated privileges.

Logged in as the compromised superadmin user - profile

Profile page showing the compromised superadmin account details.

Full admin interface and user management were accessible:

Superadmin dashboard and user management view

Superadmin dashboard & user list demonstrating privileges obtained.

๐Ÿ” Second-Order Injection & Data Exfiltration

I then planted a value (e.g. (select @@version)) into a field and retrieved it via another endpoint โ€” classic second-order SQLi.

Second-order injection revealing @@version via an endpoint

Endpoint response showing DB/server metadata leaked back (version etc.).

๐Ÿšจ Impact Summary

  • โœ… Superadmin account takeover via filename-based stored SQL UPDATE
  • โœ… Second-order injection allowed metadata exfiltration (DB version, server info)
  • โœ… Persistent risk โ€” uploaded filenames are stored and used by other flows

๐Ÿ› ๏ธ Tools & Skills

Burp Suite for capturing requests, careful SQL function composition (concat/char) to bypass forced extension, and logic-driven testing to discover second-order sinks.

๐Ÿ”’ Recommendations

๐Ÿ” Use parameterized queries for all DB operations (including filenames)

๐Ÿงน Sanitize & normalize filenames on server-side

๐Ÿ” Audit all places that consume uploaded filenames (second-order sinks)

๐Ÿ Final Thoughts

This exploit is a reminder that even seemingly harmless metadata โ€” filenames โ€” can become powerful attack vectors when they cross application logic boundaries.