diff --git a/src/pentesting-web/rsql-injection.md b/src/pentesting-web/rsql-injection.md index 8026c6398..db20b94c7 100644 --- a/src/pentesting-web/rsql-injection.md +++ b/src/pentesting-web/rsql-injection.md @@ -7,7 +7,7 @@ ## RSQLインジェクション ## RSQLとは何ですか? -RSQLは、RESTful APIにおける入力のパラメータ化されたフィルタリングのために設計されたクエリ言語です。FIQL(Feed Item Query Language)に基づいており、元々はMark NottinghamによってAtomフィードをクエリするために指定されました。RSQLは、そのシンプルさと、HTTP上でコンパクトかつURI準拠の方法で複雑なクエリを表現する能力で際立っています。これにより、RESTエンドポイント検索のための一般的なクエリ言語として優れた選択肢となります。 +RSQLは、RESTful APIにおける入力のパラメータ化されたフィルタリングのために設計されたクエリ言語です。FIQL(Feed Item Query Language)に基づいており、元々はMark NottinghamによってAtomフィードのクエリ用に指定されました。RSQLは、そのシンプルさと、HTTP上でコンパクトかつURI準拠の方法で複雑なクエリを表現できる能力で際立っています。これにより、RESTエンドポイント検索の一般的なクエリ言語として優れた選択肢となります。 ## 概要 RSQLインジェクションは、RESTful APIでRSQLをクエリ言語として使用するウェブアプリケーションにおける脆弱性です。[SQLインジェクション](https://owasp.org/www-community/attacks/SQL_Injection)や[LDAPインジェクション](https://owasp.org/www-community/attacks/LDAP_Injection)と同様に、この脆弱性はRSQLフィルタが適切にサニタイズされていない場合に発生し、攻撃者が悪意のあるクエリを注入して、データに対するアクセス、変更、または削除を無許可で行うことを可能にします。 @@ -37,18 +37,18 @@ Or even take advantage to extract sensitive information with Boolean queries or |:----: |:----: |:------------------:| | `;` / `and` | 論理 **AND** 演算子。*両方*の条件が*真*である行をフィルタリング | `/api/v2/myTable?q=columnA==valueA;columnB==valueB` | | `,` / `or` | 論理 **OR** 演算子。*少なくとも1つ*の条件が*真*である行をフィルタリング| `/api/v2/myTable?q=columnA==valueA,columnB==valueB` | -| `==` | **等しい**クエリを実行します。*columnA*の値が*queryValue*と正確に等しい*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA==queryValue` | -| `=q=` | **検索**クエリを実行します。*columnA*の値が*queryValue*を含む*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=q=queryValue` | -| `=like=` | **like**クエリを実行します。*columnA*の値が*queryValue*のような*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=like=queryValue` | -| `=in=` | **in**クエリを実行します。*columnA*が*valueA*または*valueB*を含む*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=in=(valueA, valueB)` | -| `=out=` | **除外**クエリを実行します。*columnA*の値が*valueA*でも*valueB*でもない*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=out=(valueA,valueB)` | -| `!=` | *等しくない*クエリを実行します。*columnA*の値が*queryValue*と等しくない*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA!=queryValue` | -| `=notlike=` | **not like**クエリを実行します。*columnA*の値が*queryValue*のようでない*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=notlike=queryValue` | -| `<` & `=lt=` | **未満**クエリを実行します。*columnA*の値が*queryValue*より小さい*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA `/api/v2/myTable?q=columnA=lt=queryValue` | -| `=le=` & `<=` | **未満**または**等しい**クエリを実行します。*columnA*の値が*queryValue*より小さいか等しい*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA<=queryValue`
`/api/v2/myTable?q=columnA=le=queryValue` | -| `>` & `=gt=` | **より大きい**クエリを実行します。*columnA*の値が*queryValue*より大きい*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA>queryValue`
`/api/v2/myTable?q=columnA=gt=queryValue` | -| `>=` & `=ge=` | **等しい**または**より大きい**クエリを実行します。*columnA*の値が*queryValue*と等しいかそれ以上の*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA>=queryValue`
`/api/v2/myTable?q=columnA=ge=queryValue` | -| `=rng=` | **範囲**クエリを実行します。*columnA*の値が*fromValue*以上かつ*toValue*以下の*myTable*のすべての行を返します | `/api/v2/myTable?q=columnA=rng=(fromValue,toValue)` | +| `==` | **等しい**クエリを実行。*columnA*の値が*queryValue*と正確に等しい*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA==queryValue` | +| `=q=` | **検索**クエリを実行。*columnA*の値が*queryValue*を含む*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=q=queryValue` | +| `=like=` | **like**クエリを実行。*columnA*の値が*queryValue*のような*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=like=queryValue` | +| `=in=` | **in**クエリを実行。*columnA*が*valueA*または*valueB*を含む*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=in=(valueA, valueB)` | +| `=out=` | **除外**クエリを実行。*columnA*の値が*valueA*でも*valueB*でもない*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=out=(valueA,valueB)` | +| `!=` | *等しくない*クエリを実行。*columnA*の値が*queryValue*と等しくない*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA!=queryValue` | +| `=notlike=` | **not like**クエリを実行。*columnA*の値が*queryValue*のようでない*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=notlike=queryValue` | +| `<` & `=lt=` | **未満**クエリを実行。*columnA*の値が*queryValue*より小さい*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA `/api/v2/myTable?q=columnA=lt=queryValue` | +| `=le=` & `<=` | **未満**または**等しい**クエリを実行。*columnA*の値が*queryValue*以下の*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA<=queryValue`
`/api/v2/myTable?q=columnA=le=queryValue` | +| `>` & `=gt=` | **より大きい**クエリを実行。*columnA*の値が*queryValue*より大きい*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA>queryValue`
`/api/v2/myTable?q=columnA=gt=queryValue` | +| `>=` & `=ge=` | **等しい**または**より大きい**クエリを実行。*columnA*の値が*queryValue*と等しいかそれ以上の*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA>=queryValue`
`/api/v2/myTable?q=columnA=ge=queryValue` | +| `=rng=` | **範囲**クエリを実行。*columnA*の値が*fromValue*以上で、*toValue*以下の*myTable*のすべての行を返す | `/api/v2/myTable?q=columnA=rng=(fromValue,toValue)` | **注意**: テーブルは[**MOLGENIS**](https://molgenis.gitbooks.io/molgenis/content/)および[**rsql-parser**](https://github.com/jirutka/rsql-parser)アプリケーションの情報に基づいています。 @@ -70,10 +70,10 @@ Or even take advantage to extract sensitive information with Boolean queries or | フィルター | 説明 | 例 | |--------|------------|---------| | `filter[users]` | 特定のユーザーによる結果をフィルタリング | `/api/v2/myTable?filter[users]=123` | -| `filter[status]` | ステータス(アクティブ/非アクティブ、完了など)でフィルタリング | `/api/v2/orders?filter[status]=active` | +| `filter[status]` | ステータス(アクティブ/非アクティブ、完了など)によるフィルタリング | `/api/v2/orders?filter[status]=active` | | `filter[date]` | 日付範囲内の結果をフィルタリング | `/api/v2/logs?filter[date]=gte:2024-01-01` | -| `filter[category]` | カテゴリまたはリソースタイプでフィルタリング | `/api/v2/products?filter[category]=electronics` | -| `filter[id]` | 一意の識別子でフィルタリング | `/api/v2/posts?filter[id]=42` | +| `filter[category]` | カテゴリまたはリソースタイプによるフィルタリング | `/api/v2/products?filter[category]=electronics` | +| `filter[id]` | 一意の識別子によるフィルタリング | `/api/v2/posts?filter[id]=42` | ## 一般的なパラメーター これらのパラメーターはAPIの応答を最適化するのに役立ちます: @@ -105,7 +105,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### 反応 +### レスポンス ``` HTTP/1.1 400 Date: Sat, 22 Mar 2025 14:47:14 GMT @@ -179,7 +179,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### レスポンス +### 反応 ``` HTTP/1.1 200 Date: Sat, 22 Mar 2025 14:19:46 GMT @@ -209,7 +209,7 @@ Access-Control-Allow-Origin: * } ``` ## 認可回避 -このシナリオでは、基本的な役割を持つユーザーから始まり、データベースに登録されているすべてのユーザーのリストにアクセスするための特権的な権限(例:管理者)がない状態です: +このシナリオでは、基本的な役割を持つユーザーから始まり、データベースに登録されているすべてのユーザーのリストにアクセスするための特権的な権限(例:管理者)がない状態です。 ### リクエスト ``` GET /api/users HTTP/1.1 @@ -227,7 +227,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### 反応 +### レスポンス ``` HTTP/1.1 403 Date: Sat, 22 Mar 2025 14:40:07 GMT @@ -314,7 +314,7 @@ Access-Control-Allow-Origin: * ................ ``` ## 権限昇格 -ユーザーの役割を通じてユーザー権限をチェックする特定のエンドポイントを見つけることが非常に可能性があります。例えば、権限を持たないユーザーを扱っています: +ユーザーの役割を通じてユーザー権限を確認する特定のエンドポイントを見つける可能性が非常に高いです。例えば、権限を持たないユーザーを扱っています: ### リクエスト ``` GET /api/companyUsers?include=role HTTP/1.1 @@ -396,7 +396,7 @@ Access-Control-Allow-Origin: * }] } ``` -管理者ユーザーの識別子を知った後、対応するフィルターを管理者の識別子に置き換えたり追加したりすることで、特権昇格を悪用することが可能になります。そして、同じ特権を得ることができます: +管理者ユーザーの識別子を知った後、対応するフィルターを管理者の識別子に置き換えたり追加したりすることで、特権昇格を悪用し、同じ特権を得ることが可能になります: ### Request ``` GET /api/functionalities/allPermissionsFunctionalities?filter[companyUsers]=user.id=='94****************************' HTTP/1.1 @@ -414,7 +414,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### 反応 +### レスポンス ``` HTTP/1.1 200 Date: Sat, 22 Mar 2025 18:53:00 GMT @@ -459,7 +459,7 @@ Access-Control-Allow-Origin: * }, { ....... ``` -## なりすましまたは不適切な直接オブジェクト参照 (IDOR) +## なりすましまたは不正な直接オブジェクト参照 (IDOR) `filter` パラメータの使用に加えて、結果に特定のパラメータ(例:言語、国、パスワードなど)を含めることを可能にする `include` のような他のパラメータを使用することもできます。 次の例では、私たちのユーザープロファイルの情報が表示されます: @@ -480,7 +480,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### 反応 +### レスポンス ``` HTTP/1.1 200 Date: Sat, 22 Mar 2025 19:47:27 GMT @@ -534,7 +534,7 @@ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site ``` -### レスポンス +### 反応 ``` HTTP/1.1 200 Date: Sat, 22 Mar 2025 19:50:07 GMT