security: P3+ — 面板密码哈希 + 上传类型白名单 + CSRF Token
面板密码安全: - 支持哈希存储 (password_hash/password_salt) - 登录使用 secrets.compare_digest 时序安全比较 - 回退明文兼容旧配置 - 默认密码 admin 时打印 CRITICAL 警告 文件上传安全: - 拒绝危险扩展名: .exe/.dll/.so/.sh/.bat/.ps1 等 - 拒绝敏感文件名: .htaccess/Makefile/Dockerfile 等 - 上传时检查并返回 403 CSRF 防护: - panel_auth(csrf_protect=True) 参数 - 写操作需 X-CSRF-Token header 匹配 session token - 保护范围: 文件删除/写入/创建/上传/重命名 + 项目启停 + 代理管理 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,19 +3,35 @@
|
||||
|
||||
import os
|
||||
import logging
|
||||
import hashlib
|
||||
import secrets
|
||||
from pathlib import Path
|
||||
from aiohttp import web
|
||||
from .routes import auth, status, plugins, commands, logs, projects, proxy, plugin_web, files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _hash_pw(password: str, salt: str) -> str:
|
||||
return hashlib.sha256((password + salt).encode()).hexdigest()
|
||||
|
||||
|
||||
class WebPanelManager:
|
||||
def __init__(self, config: dict, service_manager):
|
||||
panel_cfg = config.get('panel', {}).get('entrance', {})
|
||||
self.base_path = panel_cfg.get('path', '/panel')
|
||||
self.panel_user = os.environ.get('SENSU_PANEL_USER', panel_cfg.get('username', 'admin'))
|
||||
self.panel_pass = os.environ.get('SENSU_PANEL_PASS', panel_cfg.get('password', 'admin'))
|
||||
|
||||
|
||||
raw = os.environ.get('SENSU_PANEL_PASS') or panel_cfg.get('password', 'admin')
|
||||
salt = panel_cfg.get('password_salt', '') or secrets.token_hex(16)
|
||||
pw_hash = panel_cfg.get('password_hash', '') or _hash_pw(raw, salt)
|
||||
self.panel_pass = raw # 保留向后兼容
|
||||
self._pw_hash = pw_hash
|
||||
self._pw_salt = salt
|
||||
|
||||
if raw == 'admin' and not panel_cfg.get('password_hash'):
|
||||
logger.critical("⚠️ 面板使用默认密码 admin!")
|
||||
|
||||
self.base_path = f"/{self.base_path.strip('/')}"
|
||||
self.sm = service_manager
|
||||
self.project_root = Path(__file__).resolve().parent.parent.parent
|
||||
@@ -37,8 +53,10 @@ class WebPanelManager:
|
||||
app['panel_config'] = {
|
||||
'username': self.panel_user,
|
||||
'password': self.panel_pass,
|
||||
'password_hash': self._pw_hash,
|
||||
'password_salt': self._pw_salt,
|
||||
'index_path': self.project_root / "static" / "web_panel" / "index.html",
|
||||
'home_path': self.project_root / "static" / "web_panel" / "home.html" # 🟢 新增
|
||||
'home_path': self.project_root / "static" / "web_panel" / "home.html",
|
||||
}
|
||||
|
||||
# 注册静态文件
|
||||
|
||||
Reference in New Issue
Block a user