To read this page in English, please use your best translator.
J’ai analysé les fichiers clés :
safebox.py,
security.py,
functions.py,
safebox_setup.py,
safebox_update.py,
logger_config.py
et
constants.py.
Le projet utilise de bonnes primitives cryptographiques
(bcrypt,
PBKDF2HMAC,
Fernet)
mais la conception et l’usage logiciel présentent plusieurs faiblesses importantes.
Fichiers concernés : config.local.json, safebox.json, settings.json, lang.json
Risque :
Exploitation :
Correction :
Exemple :
import tempfile
import stat
def secure_write_json(path, data):
os.makedirs(os.path.dirname(path), exist_ok=True)
fd, tmp_path = tempfile.mkstemp(
dir=os.path.dirname(path),
suffix=".tmp"
)
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
f.flush()
os.fsync(f.fileno())
os.replace(tmp_path, path)
try:
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
except OSError:
pass
finally:
if os.path.exists(tmp_path):
os.remove(tmp_path)
Fichiers : safebox_update.py, constants.py
Risque :
settings.json.Correction :
TRUSTED_BASE_URL = "https://raw.githubusercontent.com/Gwigzz/test_version/main/"
URL_VERSIONS = TRUSTED_BASE_URL + "version.json"
Correction :
def load_config():
config = load_json_file(get_config_path())
if not config or not isinstance(config, dict):
raise ValueError("config.local.json invalide")
if "password_hash" not in config or "salt" not in config:
raise ValueError("config.local.json incomplet")
return config
Correction :
def validate_master_password(password):
if len(password) < 12:
return False
if not any(c.islower() for c in password):
return False
if not any(c.isupper() for c in password):
return False
if not any(c.isdigit() for c in password):
return False
if not any(c in "!@#$%^&*()-_=+[]{};:'\",.<>?/\\|" for c in password):
return False
return True
def save_vault(data):
vault_path = get_safebox_file()
dir_name = os.path.dirname(vault_path)
os.makedirs(dir_name, exist_ok=True)
tmp_path = vault_path + ".tmp"
with open(tmp_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
f.flush()
os.fsync(f.fileno())
os.replace(tmp_path, vault_path)
import ctypes
def set_hidden_file(path):
FILE_ATTRIBUTE_HIDDEN = 0x02
ctypes.windll.kernel32.SetFileAttributesW(
str(path),
FILE_ATTRIBUTE_HIDDEN
)
Sur Windows, il est préférable d'utiliser les API de sécurité
(SetNamedSecurityInfoW) afin de restreindre réellement les ACL.
Le projet utilise des primitives cryptographiques solides, mais plusieurs défauts d'implémentation diminuent son niveau de sécurité.
La mise en œuvre des recommandations proposées permettra d'améliorer sensiblement la robustesse de l'application.