https://bugs.winehq.org/show_bug.cgi?id=49334
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |wineserver Severity|major |normal Keywords| |download, source Ever confirmed|0 |1 URL| |https://github.com/pyinstal | |ler/pyinstaller CC| |focht@gmx.net Summary|Binaries compiled with |onefile applications |PyInstaller on Wine crash |created with PyInstaller |with error, affects |3.6 fail, reporting |Anaconda installation, too. |'INTERNAL ERROR: cannot | |create temporary directory' | |(improper handling of owner | |rights SID '{S-1-3-4}') Status|UNCONFIRMED |NEW Version|5.0.1 |5.0
--- Comment #1 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
The upstream change that caused this breakage is here:
https://github.com/pyinstaller/pyinstaller/commit/42a67148b3bdf9211fda8499fd... (master branch, included in 3.6 release)
--- quote --- [SECURITY] Bootloader: Fix insecure directory permissions of sys._MEI…
…PATH.
Important: This security fix effects *all Windows software frozen by PyInstaller* in "onefile" mode.
This fix prevents a Local Privilege Escalation vulnerability that is present only on Windows and in this particular case: If a software frozen by PyInstaller in "onefile" mode is launched by a (privileged) user who has his/her "TempPath" resolving to a world writable directory. This is the case e.g. if the software is launched as a service or as a scheduled task using a system account (in which case TempPath will default to `C:\Windows\Temp`).
All Windows version have been vulnerable, since _wmkdir() does not enforce restricted permissions. On Posix-systems mkdtemp() is used, which already enforce permissions, so they have not been affected.
The fix is done by implementing a new pyi_win32_mkdir() that enforces proper permissions for the created directory.
While PyInstaller itself was not vulnerable, all Windows software frozen by PyInstaller in "onefile" mode is vulnerable. If you are using PyInstaller to freeze Windows software using "onefile" mode, you should upgrade PyInstaller and rebuild your software.
Fixes CVE-2019-16784.
Co-authored-by: Hartmut Goebel h.goebel@crazy-compilers.com --- quote ---
The code:
--- snip --- /* Create a directory at path with restricted permissions. * The directory owner will be the only one with permissions on the created * dir. Calling this function is equivalent to callin chmod(path, 0700) on * Posix. * Returns 0 on success, -1 on error. */ int pyi_win32_mkdir(const wchar_t *path) { wchar_t stringSecurityDesc[] = // ACE String : L"D:" // DACL (D) : L"(A;" // Authorize (A) L";FA;" // FILE_ALL_ACCESS (FA) L";;S-1-3-4)"; // For the current directory owner (SID: S-1-3-4) // no other permissions are granted
SECURITY_ATTRIBUTES securityAttr; PSECURITY_DESCRIPTOR *lpSecurityDesc; securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES); securityAttr.bInheritHandle = FALSE; lpSecurityDesc = &securityAttr.lpSecurityDescriptor;
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW( stringSecurityDesc, SDDL_REVISION_1, lpSecurityDesc, NULL)) { return -1; } if (!CreateDirectoryW(path, &securityAttr)) { return -1; }; return 0; } --- snip ---
Recipe for reproduction:
https://github.com/pyinstaller/pyinstaller/issues/4628#issuecomment-58680694...
--- snip --- $ wget https://www.python.org/ftp/python/3.8.1/python-3.8.1-amd64.exe $ wine ./python-3.8.1-amd64.exe /passive $ wine py -m pip install --upgrade pip $ wine py -m pip install pyinstaller
$ wget https://github.com/pinobatch/lorom-template/raw/master/tools/wav2brr.py $ wine \path\to\pyinstaller.exe --onefile -d bootloader wav2brr.py --- snip ---
Relevant part of trace log running the onefile app:
--- snip --- $ WINEDEBUG=+seh,+relay,+server,+advapi,+security wine ./wav2brr.exe >>log.txt 2>&1 ... 00c0:Call advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW(002198b8 L"D:(A;;FA;;;S-1-3-4)",00000001,002198a8,00000000) ret=140005964 00c0:Call sechost.ConvertStringSecurityDescriptorToSecurityDescriptorW(002198b8 L"D:(A;;FA;;;S-1-3-4)",00000001,002198a8,00000000) ret=7bca06ef ... 00c0:trace:security:parse_acl L"(A;;FA;;;S-1-3-4)" ... 00c0:Ret sechost.ConvertStringSecurityDescriptorToSecurityDescriptorW() retval=00000001 ret=7bca06ef 00c0:Ret advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW() retval=00000001 ret=140005964 00c0:Call KERNEL32.CreateDirectoryW(0011f710 L"C:\users\focht\Temp\_MEI1882",002198a0) ret=14000598c 00c0:Call kernelbase.CreateDirectoryW(0011f710 L"C:\users\focht\Temp\_MEI1882",002198a0) ret=7bca06ef 00c0:Call ntdll.RtlDosPathNameToNtPathName_U(0011f710 L"C:\users\focht\Temp\_MEI1882",00219728,00000000,00000000) ret=7b01447e 00c0:Ret ntdll.RtlDosPathNameToNtPathName_U() retval=00000001 ret=7b01447e 00c0:Call ntdll.NtCreateFile(00219720,80100000,00219738,00219768,00000000,00000080,00000001,00000002,00000021,00000000,00000000) ret=7b014536 00c0: create_file( access=80100000, sharing=00000001, create=2, options=00000021, attrs=00000080, objattr={rootdir=0000,attributes=00000040,sd={control=00000004,owner=<not present>,group=<not present>,sacl={},dacl={{AceType=ACCESS_ALLOWED_ACE_TYPE,Mask=1f01ff,AceFlags=0,Sid={S-1-3-4}}}},name=L""}, filename="/home/focht/.wine/dosdevices/c:/users/focht/Temp/_MEI1882" ) 00c0: create_file() = ACCESS_DENIED { handle=0000 } 00c0:Ret ntdll.NtCreateFile() retval=c0000022 ret=7b014536 ... 00c0:Call ntdll.RtlNtStatusToDosError(c0000022) ret=7b01454f 00c0:Ret ntdll.RtlNtStatusToDosError() retval=00000005 ret=7b01454f 00c0:Ret kernelbase.CreateDirectoryW() retval=00000000 ret=7bca06ef 00c0:Ret KERNEL32.CreateDirectoryW() retval=00000000 ret=14000598c --- snip ---
No SD owner is present so the owner derived from the process token. This obviously can't work together with specified owner rights SID '{S-1-3-4}'.
sid = '{S-1-3-4}' (from SD) user = '{S-1-5-21-0-0-0-1000}' (derived from process token) owner = '{S-1-5-21-0-0-0-1000}' (derived from process token)
https://source.winehq.org/git/wine.git/blob/HEAD:/server/file.c#l533
--- snip --- ... 533 case ACCESS_ALLOWED_ACE_TYPE: 534 aa_ace = (const ACCESS_ALLOWED_ACE *)ace; 535 sid = (const SID *)&aa_ace->SidStart; 536 mode = file_access_to_mode( aa_ace->Mask ); 537 if (security_equal_sid( sid, security_world_sid )) 538 { 539 mode = (mode << 6) | (mode << 3) | mode; /* all */ 540 new_mode |= mode & bits_to_set; 541 bits_to_set &= ~mode; 542 } 543 else if ((security_equal_sid( user, owner ) && 544 token_sid_present( current->process->token, sid, FALSE ))) 545 { 546 mode = (mode << 6) | (mode << 3); /* user + group */ 547 new_mode |= mode & bits_to_set; 548 bits_to_set &= ~mode; 549 } 550 else if (security_equal_sid( sid, owner )) 551 { 552 mode = (mode << 6); /* user only */ 553 new_mode |= mode & bits_to_set; 554 bits_to_set &= ~mode; 555 } 556 break; ... --- snip ---
---
I've changed the reported version field back to Wine 5.0 because that's the earliest version the people reported the problem with. See referenced links to Github PRs.
$ wine --version wine-5.10-39-g1752958240
Regards