安全修复:加固CSRF与凭证保护并修复越权风险
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from cryptography.fernet import Fernet
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
@@ -27,18 +28,37 @@ ENCRYPTION_KEY_FILE = os.environ.get('ENCRYPTION_KEY_FILE', 'data/encryption_key
|
||||
ENCRYPTION_SALT_FILE = os.environ.get('ENCRYPTION_SALT_FILE', 'data/encryption_salt.bin')
|
||||
|
||||
|
||||
def _ensure_private_dir(path: Path) -> None:
|
||||
if not path:
|
||||
return
|
||||
os.makedirs(path, mode=0o700, exist_ok=True)
|
||||
try:
|
||||
os.chmod(path, 0o700)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _ensure_private_file(path: Path) -> None:
|
||||
try:
|
||||
os.chmod(path, 0o600)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _get_or_create_salt():
|
||||
"""获取或创建盐值"""
|
||||
salt_path = Path(ENCRYPTION_SALT_FILE)
|
||||
if salt_path.exists():
|
||||
_ensure_private_file(salt_path)
|
||||
with open(salt_path, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
# 生成新的盐值
|
||||
salt = os.urandom(16)
|
||||
os.makedirs(salt_path.parent, exist_ok=True)
|
||||
_ensure_private_dir(salt_path.parent)
|
||||
with open(salt_path, 'wb') as f:
|
||||
f.write(salt)
|
||||
_ensure_private_file(salt_path)
|
||||
return salt
|
||||
|
||||
|
||||
@@ -102,6 +122,7 @@ def get_encryption_key():
|
||||
key_path = Path(ENCRYPTION_KEY_FILE)
|
||||
if key_path.exists():
|
||||
logger.info(f"从文件 {ENCRYPTION_KEY_FILE} 读取加密密钥")
|
||||
_ensure_private_file(key_path)
|
||||
with open(key_path, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
@@ -127,9 +148,10 @@ def get_encryption_key():
|
||||
|
||||
# 生成新的密钥
|
||||
key = Fernet.generate_key()
|
||||
os.makedirs(key_path.parent, exist_ok=True)
|
||||
_ensure_private_dir(key_path.parent)
|
||||
with open(key_path, 'wb') as f:
|
||||
f.write(key)
|
||||
_ensure_private_file(key_path)
|
||||
logger.info(f"已生成新的加密密钥并保存到 {ENCRYPTION_KEY_FILE}")
|
||||
logger.warning("请立即备份此密钥文件,并建议设置 ENCRYPTION_KEY_RAW 环境变量!")
|
||||
return key
|
||||
@@ -137,14 +159,17 @@ def get_encryption_key():
|
||||
|
||||
# 全局Fernet实例
|
||||
_fernet = None
|
||||
_fernet_lock = threading.Lock()
|
||||
|
||||
|
||||
def _get_fernet():
|
||||
"""获取Fernet加密器(懒加载)"""
|
||||
global _fernet
|
||||
if _fernet is None:
|
||||
key = get_encryption_key()
|
||||
_fernet = Fernet(key)
|
||||
with _fernet_lock:
|
||||
if _fernet is None:
|
||||
key = get_encryption_key()
|
||||
_fernet = Fernet(key)
|
||||
return _fernet
|
||||
|
||||
|
||||
@@ -187,8 +212,8 @@ def decrypt_password(encrypted_password: str) -> str:
|
||||
# 解密失败,可能是旧的明文密码或密钥不匹配
|
||||
if is_encrypted(encrypted_password):
|
||||
logger.error(f"密码解密失败(密钥可能不匹配): {e}")
|
||||
else:
|
||||
logger.warning(f"密码解密失败,可能是未加密的旧数据: {e}")
|
||||
return ''
|
||||
logger.warning(f"密码解密失败,可能是未加密的旧数据: {e}")
|
||||
return encrypted_password
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user