This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Cannot exec() program outside of /bin if PATH is unset


On Sep 15 16:35, Christian Franke wrote:
> Peter Rosin wrote:
> >On 2014-09-13 12:00, Christian Franke wrote:
> >>Note that setting PATH=/bin on Cygwin does not fix the security problem in the DLL search order. Even with "SafeDllSearchMode" enabled, the current directory is always checked before PATH. Running some Cygwin program from /usr/sbin, /usr/local/bin, /usr/libexec, ... would load a possible malicious cyg*.dll from current directory regardless of PATH setting. Only programs in /bin are safe.
> >>
> >>Using SetDllDirectory("c:\\cygwin\\bin") somewhere in cygwin1.dll would fix this also.
> >How could a call inside a DLL fix the library search order used
> >to find that same DLL? Yes, it is possible (or likely) that
> >SetDllDirectory fixes the immediate problem for processes that
> >are started *by* cygwin1.dll, but it is not effective for Cygwin
> >processes that are started by some direct use of the Win32 API.
> 
> Of course, and the same is true for any non-Cygwin program. The security fix
> is effective only for any CreateProcess()/LoadLibrary() call within the
> process which called SetDllDirectory(DIR_OF_SUBSYSTEM_DLLs).
> 
> 
> >Also, SetDllDirectory will kill all attempts to run 32-bit
> >Cygwin programs from 64-bit Cygwin (and vice versa).
> 
> For programs in /bin directory, there is no problem because the EXE's
> directory is always searched first for required DLLs. SetDllDirectory() then
> has no effect for cyg*.dll search order.
> 
> For other programs it also works because Windows (at least 7) apparently
> skips 32-bit DLLs when searching for 64-bit ones (and vice versa). It is
> then required that PATH contains the other Cygwin's /bin directory.
> 
> Testcase for calling 64-bit from 32-bit:
> 
> exe in /bin:
> 
>   SetDllDirectory("c:\\cygwin\\bin");
>   unsetenv("PATH");
>   execl("/cygdrive/c/cygwin64/bin/uname", "uname", "-a", (const char*)0);
> 
> exe not in /bin:
> 
>   SetDllDirectory("c:\\cygwin\\bin");
>   setenv("PATH", "/cygdrive/c/cygwin64/bin", 1);
>   execl("/cygdrive/c/cygwin64/usr/sbin/alternatives", "alternatives", (const
> char*)0);
> 
> In both cases, the SetDllDirectory() call does not break anything.

I'm somewhat reluctant to add a call to SetDllDirectory to the Cygwin
DLL for two reasons.

- Calling SetDllDirectory with an explicit dir doesn't just add this dir
  to the search path, it also removes the CWD from the search path.
  While I agree that this is a good thing from a security POV, can we be
  sure that this behaviour isn't needed somewhere, by somebody?

- The fact that SetDllDirectory affects searching linked DLLs in calls
  to CreateProcess is undocumented.  Per the original MSDN pages,
  SetDllDirectory affects calls to LoadLibrary and LoadLibraryEx, but
  not linked DLLs when starting a child process.  The latter is only
  mentioned in a Community Addition:

  http://msdn.microsoft.com/en-us/library/windows/desktop/ms686203%28v=vs.85%29.aspx

Having said that, we can certainly test this, but I'm wondering
if an upstream Cygwin patch might be ok.  Something similar has been
applied to the portable OpenSSH repository years ago, so there's
precedent.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

Attachment: pgpccNfmaQwQz.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]