Lock down backup directory ACLs, and let the uninstaller reach IIS
Two findings from the installer review, both of which fail silently. Database dumps were readable by every authenticated user. A directory created under ProgramData inherits BUILTIN\Users:(I)(OI)(CI)(RX), and a dump contains every row including the users table and its password hashes. The installer applied an owner-only ACL, but only in the branch that CREATED the directory, so a directory created first by the console (shopdb-admin.ps1 backup) kept the inherited permissions and the installer could never repair it. The ACL is now re-applied on every run rather than only on creation, and the grants are made inheritable with (OI)(CI) so dumps written into the directory later are covered too. shopdb-admin.ps1 applies the same hardening for the default location, and for an operator-named path says the dump holds password hashes rather than silently rewriting the ACL of a directory that is theirs. Verified on Windows: before, the directory carried BUILTIN\Users:(I)(OI)(CI) (RX); after, only SYSTEM and Administrators, and a file created inside inherits exactly those two. Without (OI)(CI) that file would not have been covered. The uninstaller could not remove anything in IIS. [UninstallRun] launched a bare "powershell.exe", and the Inno uninstaller is a 32-bit process, so WOW64 resolved it to the 32-bit PowerShell, which cannot see the IIS provider. The site, application pool and application survived, pointing at a directory that HAD been deleted, while Windows reported a clean uninstall. It now uses the same Sysnative path as the [Run] entry, which was the last unshielded launch site in the file.
This commit is contained in:
@@ -372,9 +372,28 @@ function Backup-Db {
|
||||
Head 'Database backup'
|
||||
$db = Get-DbParts
|
||||
if (-not $db) { Say ' no .env found - cannot determine the database' 'Red'; return }
|
||||
$usingDefault = -not $Dest
|
||||
if (-not $Dest) { $Dest = 'C:\ProgramData\ShopDB-Flask\backups' }
|
||||
if (-not (Test-Path $Dest)) { New-Item -ItemType Directory -Path $Dest -Force | Out-Null }
|
||||
|
||||
# A dump holds every row, including the users table and its password hashes.
|
||||
# A directory created under ProgramData INHERITS Users:RX, so those hashes
|
||||
# were readable by every authenticated user on the server whenever this
|
||||
# command created the directory rather than the installer.
|
||||
#
|
||||
# Re-applied on every backup, not only on creation, because this may be
|
||||
# repairing a directory made by an earlier version.
|
||||
#
|
||||
# Only for the default location. A path the operator named is theirs, and
|
||||
# silently rewriting its ACL is not this command's business - say so instead.
|
||||
if ($usingDefault) {
|
||||
& icacls.exe $Dest '/inheritance:r' `
|
||||
'/grant' 'BUILTIN\Administrators:(OI)(CI)(F)' `
|
||||
'/grant' 'NT AUTHORITY\SYSTEM:(OI)(CI)(F)' 2>&1 | Out-Null
|
||||
} else {
|
||||
Say ' note: this dump contains password hashes - check who can read that directory' 'Yellow'
|
||||
}
|
||||
|
||||
$mysql = Find-MysqlClient
|
||||
if (-not $mysql) { Say ' mysql client not found' 'Red'; return }
|
||||
$dump = Join-Path (Split-Path $mysql -Parent) 'mysqldump.exe'
|
||||
|
||||
Reference in New Issue
Block a user