当前位置: 首页 > news >正文

Python点击劫持防护

"""
Python 点击劫持防护 —— 通过 HTTP 响应头防御点击劫持攻击
涵盖 X-Frame-Options、CSP frame-ancestors 和 Django/Flask 中间件实现
"""

# 点击劫持(Clickjacking)攻击者通过透明 iframe 覆盖诱导用户点击
# 防御核心:禁止页面在 iframe 中加载或仅允许同源加载

from typing import Dict, Optional, List
from enum import Enum

# ========== 第一部分:X-Frame-Options 响应头 ==========

class XFrameOptions(Enum):
"""
X-Frame-Options 头的三个可选值:
- DENY:完全禁止在 iframe 中加载
- SAMEORIGIN:仅允许同源页面在 iframe 中加载
- ALLOW-FROM:允许指定来源加载(已废弃,改用 CSP)
"""
DENY = "DENY"
SAMEORIGIN = "SAMEORIGIN"
ALLOW_FROM = "ALLOW-FROM"


# ========== 第二部分:Content-Security-Policy 头 ==========

class CSPDirectiveBuilder:
"""
Content-Security-Policy 的 frame-ancestors 指令构建器。
这是现代浏览器推荐的点击劫持防护方式,比 X-Frame-Options 更灵活。
frame-ancestors 指定哪些来源可以将当前页面嵌入为 iframe。
"""

def __init__(self):
# 默认完全禁止
self._directives: List[str] = []

def deny(self) -> "CSPDirectiveBuilder":
"""
禁止任何页面嵌入(等效于 X-Frame-Options: DENY)。
"""
self._directives = ["'none'"]
return self

def same_origin(self) -> "CSPDirectiveBuilder":
"""
仅允许同源页面嵌入(等效于 X-Frame-Options: SAMEORIGIN)。
"""
self._directives = ["'self'"]
return self

def allow(self, *origins: str) -> "CSPDirectiveBuilder":
"""
允许指定的来源嵌入页面。
来源可以是域名、协议+域名或具体 URL。
"""
for origin in origins:
self._directives.append(origin)
return self

def build(self) -> str:
"""
生成完整的 frame-ancestors 指令字符串。
"""
if not self._directives:
return "frame-ancestors 'none'"
# 'self' 必须在最前面(如果有的话)
directives = sorted(
self._directives,
key=lambda x: (0 if x == "'self'" else 1)
)
return f"frame-ancestors {' '.join(directives)}"


# ========== 第三部分:Flask 中间件实现 ==========

class FrameOptionsMiddleware:
"""
Flask 中间件 —— 自动为响应添加点击劫持防护头。
支持按路由配置不同的防护策略。
"""

def __init__(self, app, default_policy: str = "DENY"):
self.app = app
self.default_policy = default_policy
# 按端点配置例外策略
self._exempt_routes: Dict[str, str] = {}

def add_exemption(self, endpoint: str, policy: str = "SAMEORIGIN"):
"""
为特定端点配置不同的帧策略。
例如支付页面可能需要被允许在特定第三方嵌入。
"""
self._exempt_routes[endpoint] = policy

def __call__(self, environ, start_response):
"""
WSGI 中间件调用入口。
拦截响应并添加安全头。
"""

def _start_response(status, headers, exc_info=None):
# 获取当前请求路径
path = environ.get("PATH_INFO", "/")

# 确定使用的策略
policy = self._exempt_routes.get(path, self.default_policy)

# 添加 X-Frame-Options 头
if policy == "DENY":
headers.append(("X-Frame-Options", "DENY"))
elif policy == "SAMEORIGIN":
headers.append(("X-Frame-Options", "SAMEORIGIN"))
elif policy.startswith("ALLOW-FROM"):
headers.append(("X-Frame-Options", policy))

# 同时添加 CSP frame-ancestors(双保险)
csp_builder = CSPDirectiveBuilder()
if policy == "DENY":
csp_value = csp_builder.deny().build()
elif policy == "SAMEORIGIN":
csp_value = csp_builder.same_origin().build()
elif policy.startswith("ALLOW-FROM"):
# 提取允许的来源
origin = policy.replace("ALLOW-FROM ", "")
csp_value = csp_builder.allow(origin).build()
else:
csp_value = csp_builder.deny().build()

headers.append(("Content-Security-Policy", csp_value))
return start_response(status, headers, exc_info)

return self.app(environ, start_response)


# ========== 第四部分:Django 中间件实现 ==========

class DjangoFrameOptionsMiddleware:
"""
Django 中间件 —— 自动添加帧防护头。
在 Django 的 settings.MIDDLEWARE 中注册使用。
"""

def __init__(self, get_response):
self.get_response = get_response
# 按 URL 前缀配置例外
self._exempt_prefixes: Dict[str, str] = {}

def add_exempt_prefix(self, prefix: str, policy: str = "SAMEORIGIN"):
"""为特定 URL 前缀设置不同的帧策略"""
self._exempt_prefixes[prefix] = policy

def __call__(self, request):
response = self.get_response(request)

# 判断使用哪种策略
policy = self.default_policy
for prefix, exempt_policy in self._exempt_prefixes.items():
if request.path.startswith(prefix):
policy = exempt_policy
break

# 添加安全头
response["X-Frame-Options"] = policy

# 添加 CSP 头(如果尚未设置)
if "Content-Security-Policy" not in response:
csp = self._build_csp(policy)
response["Content-Security-Policy"] = csp

return response

def _build_csp(self, policy: str) -> str:
"""根据策略生成对应的 CSP 值"""
builder = CSPDirectiveBuilder()
if policy == "DENY":
return builder.deny().build()
elif policy == "SAMEORIGIN":
return builder.same_origin().build()
return builder.deny().build()

@property
def default_policy(self) -> str:
return "DENY"


# ========== 第五部分:HTML 级别的额外防护 ==========

def generate_frame_busting_script() -> str:
"""
生成客户端框架破坏(Frame Busting)JavaScript 代码。
作为 HTTP 头的补充防护措施,兼容不支持 X-Frame-Options 的旧浏览器。
注意:某些现代浏览器可能限制这种脚本的执行。
"""
return """

"""


# ========== 第六部分:演示 ==========

def demo_clickjacking_protection():
"""
演示各种点击劫持防护策略的配置和效果。
"""
print("=== 点击劫持防护演示 ===\n")

# 1. 显示 X-Frame-Options 策略
print("--- X-Frame-Options 策略 ---")
for policy in XFrameOptions:
print(f" {policy.value}: {policy.name}")

# 2. 演示 CSP frame-ancestors 构建
print("\n--- CSP frame-ancestors 构建 ---")

builder = CSPDirectiveBuilder()
print(f" DENY: {builder.deny().build()}")

builder = CSPDirectiveBuilder()
print(f" SAMEORIGIN: {builder.same_origin().build()}")

builder = CSPDirectiveBuilder()
print(f" 允许特定来源: {builder.allow('https://trusted.com', 'https://partner.com').build()}")

# 3. 综合建议
print("\n--- 推荐配置 ---")
print("""
生产环境推荐采用"纵深防御"策略:
1. HTTP 头:X-Frame-Options: SAMEORIGIN
2. CSP 头:Content-Security-Policy: frame-ancestors 'self'
3. 敏感页面(如支付):X-Frame-Options: DENY
4. 需要被第三方嵌入的页面:使用 CSP 白名单方式
5. 关键操作增加二次确认步骤(如验证码)
""")

# 4. 生成 Frame Busting 脚本示例
print("--- Frame Busting 脚本(备用防护)---")
print(generate_frame_busting_script()[:100] + "...")


if __name__ == "__main__":
demo_clickjacking_protection()

http://www.rkmt.cn/news/1435495.html

相关文章:

  • 2026降AI率工具红黑榜:降AIGC网站怎么选?用过才敢说!
  • 2026 西安黄金回收真实案例分享 实力商家卖价高口碑稳居前列 - 薛定谔的梨花猫
  • WeChatMsg:重新定义你的数字记忆主权,让每一段对话都值得被珍藏
  • Keyviz技术深度解析:跨平台键盘鼠标事件可视化架构剖析
  • 别再死磕EKF了!用ESKF搞定IMU+激光雷达融合,误差状态建模实战(附Python代码)
  • 胜菱智能技术实力多维度解析:精度刚性与速度指标对比 - 资讯纵览
  • 如何永久保存微信聊天记录:WeChatMsg完整指南与实战技巧
  • Translumo:终极实时屏幕翻译工具免费完整指南
  • 如何5分钟完成黑苹果配置:OpCore Simplify图形化工具终极指南
  • 终极指南:如何使用baidu-wangpan-parse突破百度网盘限速
  • Day06|用生产硬核笔记逆向解构《DDIA》:数据分区与高并发局部战争的路由抽象
  • 长沙黄金回收 2026 全攻略|5.31今日金价 + 正规门店榜单 + 避坑指南 - 资讯纵览
  • 3分钟掌握跨平台直播聚合的智能方案:Simple Live技术深度解析
  • 搞定GC10-DET数据集预处理:手把手教你用Python脚本清理无标签图片和修正XML标签错误
  • 为什么开了 `open_file_cache` 图片会不显示?
  • Xenia Canary终极指南:3步快速上手Xbox 360游戏模拟器
  • 别再手动写测试了!用Python+机器学习,5分钟搞定芯片验证的激励生成
  • Arduino Lint:项目结构静态分析工具,提升代码规范与协作效率
  • 2026年GEO培训机构选品指南与优质机构汇总 - 榜单测评
  • 华硕笔记本终极性能优化指南:GHelper轻量级控制工具完全解析
  • 2026年泡沫消火栓箱:解读行业三大核心趋势 - 资讯纵览
  • 2026年郑州GEO优化公司盘点:5家机构实力解析与选型指南 - 资讯纵览
  • 如何完全掌控微信聊天记录?WeChatMsg三步实现永久保存与智能分析
  • 2216 A
  • 2026 广州搬厂公司收费标准 合理报价防溢价指南 - 从来都是英雄出少年
  • 豆包推广哪家好?2026深圳GEO优化品牌推广服务商靠谱10家推荐 - 资讯纵览
  • 如何高效使用OpCore-Simplify:专业用户的完整黑苹果配置策略指南
  • 2026爆火!5款AI论文网站实测,告别拖延症,初稿3天搞定!
  • 3步搭建个人抖音视频解析服务:DouYinBot实战指南
  • 鸣潮自动化助手深度解析:从智能识别到全流程自动化