mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
fix: write the admin password file without following symlinks
In Docker, migrate runs as root while data/ belongs to www-data, so a planted data/admin_password symlink would make root overwrite its target. Remove any existing path first and create the file with O_CREAT|O_EXCL|O_NOFOLLOW (mode set via fchmod). install.sh's /tmp fallback log is now created with mktemp instead of a fixed name.
This commit is contained in:
parent
02dd838a56
commit
40822e7184
3 changed files with 21 additions and 4 deletions
|
|
@ -40,10 +40,14 @@ def _store_generated_password(password):
|
|||
path = os.path.join(str(settings.BASE_DIR), "data", "admin_password")
|
||||
try:
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
||||
# Never write through a pre-existing file or symlink (this runs as
|
||||
# root in Docker, while data/ belongs to www-data).
|
||||
if os.path.lexists(path):
|
||||
os.unlink(path)
|
||||
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
|
||||
os.fchmod(fd, 0o600)
|
||||
with os.fdopen(fd, "w") as f:
|
||||
f.write(password + "\n")
|
||||
os.chmod(path, 0o600)
|
||||
print(f"\033[1m* \033[93mGenerated admin password written to {path}\033[0m")
|
||||
except OSError:
|
||||
print(f"\033[1m* \033[93mGenerated random admin password: {password}\033[0m")
|
||||
|
|
|
|||
|
|
@ -38,3 +38,17 @@ class GeneratedAdminPasswordTestCase(TestCase):
|
|||
self.assertNotIn(password, output)
|
||||
self.assertIn(str(password_file), output)
|
||||
self.assertIsNotNone(authenticate(username="admin", password=password))
|
||||
|
||||
def test_does_not_follow_a_planted_symlink(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
(Path(tmp) / "data").mkdir()
|
||||
victim = Path(tmp) / "victim"
|
||||
victim.write_text("original\n")
|
||||
(Path(tmp) / "data" / "admin_password").symlink_to(victim)
|
||||
|
||||
self._run_create_admin(tmp)
|
||||
|
||||
password_file = Path(tmp) / "data" / "admin_password"
|
||||
self.assertEqual(victim.read_text(), "original\n")
|
||||
self.assertFalse(password_file.is_symlink())
|
||||
self.assertEqual(stat.S_IMODE(password_file.stat().st_mode), 0o600)
|
||||
|
|
|
|||
|
|
@ -83,8 +83,7 @@ chmod 744 "$INSTALLER"
|
|||
LOG_FILE="/var/log/webvirtcloud-install.log"
|
||||
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
|
||||
if ! touch "$LOG_FILE" 2>/dev/null; then
|
||||
LOG_FILE="/tmp/webvirtcloud-install.log"
|
||||
touch "$LOG_FILE"
|
||||
LOG_FILE="$(mktemp /tmp/webvirtcloud-install.XXXXXX)"
|
||||
fi
|
||||
chmod 600 "$LOG_FILE" 2>/dev/null || true
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue