Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscall: guard against Windows DLL preloading attacks #14959

Closed
bradfitz opened this issue Mar 25, 2016 · 38 comments

Comments

Projects
None yet
8 participants
@bradfitz
Copy link
Member

commented Mar 25, 2016

Taru Karttunen noted that Go should be more paranoid by default when loading DLLs.

Background:
https://textplain.wordpress.com/2015/12/18/dll-hijacking-just-wont-die/

Microsoft's guidelines:
https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx

LoadLibraryEx docs:
https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx

@rsc proposed:

  1. Change syscall.LoadDLL to call LoadLibraryEx with flags=LOAD_LIBRARY_SEARCH_SYSTEM32 instead of calling LoadLibrary. That is, LoadDLL is now secure by default and cannot load DLLs from the directory containing the executable.
  2. Add a LoadLibraryEx to x/sys/win so that users can still get at the old behavior if they want it (by appropriate passing of flags).

CL forthcoming.

/cc @alexbrainman @adg @broady @jbuberel @ianlancetaylor

@bradfitz bradfitz self-assigned this Mar 25, 2016

@bradfitz bradfitz added the Security label Mar 25, 2016

@bradfitz bradfitz added this to the Go1.6.1 milestone Mar 25, 2016

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2016

/cc @taruti, too.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2016

@minux

This comment has been minimized.

Copy link
Member

commented Mar 25, 2016

I'm not convinced that Go needs to solve this problem because dso hijack is
equally easy on Unix (e.g. via LD_PRELOAD) and yet we don't protect from it
(I actually think it's a feature, not a bug.)

Besides, this is not backward compatible as we silently changed the semantics
of syscall.LoadDLL.

I'm fine if we only change the runtime to load ntdll.dll, kernel32.dll, etc. with
LOAD_LIBRARY_SEARCH_SYSTEM32, but we should definitely preserve
the existing syscall.LoadDLL behavior.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2016

Your analogy isn't complete.

Windows users download binaries and double-click those binaries from their Downloads folder. Windows users can get (malicious) DLLs silently downloaded to their Downloads folder just by browsing the web. Windows users don't need to set LD_PRELOAD to shoot themselves in the foot. The gun is always pointed down towards the foot by default on Windows.

@gopherbot

This comment has been minimized.

Copy link

commented Mar 25, 2016

CL https://golang.org/cl/21140 mentions this issue.

@mattn

This comment has been minimized.

Copy link
Member

commented Mar 25, 2016

FYI, the order of paths for searching dll(s)

https://msdn.microsoft.com/en-us/library/7d83bc18.aspx

  • The directory where the executable module for the current process is located.
  • The current directory.
  • The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
  • The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
  • The directories listed in the PATH environment variable.
@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 25, 2016

Background:
https://textplain.wordpress.com/2015/12/18/dll-hijacking-just-wont-die/

I read the article, and I don't see what the problem is. I went to the page pointed by the article which is suppose to automatically download malicious DLL, but my Chrome actually refused to download the DLL. Chrome told me that DLL looks suspicious and I shouldn't be downloading it.

As to CL 21140, I think it breaks existing valid programs. Somehow CL assumes that syscall.LoadDLL is onle used to load "system" DLLs. But that is not true. It is quite common to put application specific DLLs into application directory - directory where executable is located. How do you propose we handle this scenario if CL 21140 is accepted?

If you think there is something for us to fix here, perhaps we could create new syscall.LoadSystemDLL (or similar) that does what you want, and change all standard packages to use syscall.LoadSystemDLL.

Alex

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2016

but my Chrome actually refused to download the DLL. Chrome told me that DLL looks suspicious and I shouldn't be downloading it.

Chrome was updated according to the comments. The post also mentions the Edge browser (the default Microsoft browser) and comments suggest it hasn't been updated. I haven't tried.

As to CL 21140, I think it breaks existing valid programs.

https://golang.org/doc/go1compat says "A security issue in the specification or implementation may come to light whose resolution requires breaking compatibility. We reserve the right to address such security issues."

I believe calling syscall.LoadDLL(".\\foo.dll") is unchanged in behavior, if people really need to use the standard library to load DLLs out of the current directory.

If you think there is something for us to fix here, perhaps we could create new syscall.LoadSystemDLL (or similar) that does what you want, and change all standard packages to use syscall.LoadSystemDLL.

The proposal is to add that not to the standard library, but to x/sys. (See the original comment at the top of this bug).

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 25, 2016

I believe calling syscall.LoadDLL(".\foo.dll") is unchanged in behavior, if people really need to use the standard library to load DLLs out of the current directory.

Current directory yes, but that is not what I was talking about. Some apps store DLLs in the directory where EXE is located. How do you propose people load these DLLs?

Alex

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2016

Current directory yes, but that is not what I was talking about. Some apps store DLLs in the directory where EXE is located. How do you propose people load these DLLs?

See the top comment in this bug: "2) Add a LoadLibraryEx to x/sys/win so that users can still get at the old behavior if they want it (by appropriate passing of flags)."

(A flags of 0 would mean the current behavior)

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 26, 2016

Here is one of many programs I use on my PC.

C:\Program Files (x86)\Git\bin>objdump -p git.exe | grep Load
LoaderFlags             00000000
Entry a 00000000 00000000 Load Configuration Directory
        19cc7c    524  LoadLibraryA     7dd7499f

C:\Program Files (x86)\Git\bin>dir *.dll
 Volume in drive C has no label.
 Volume Serial Number is F0C8-6DFE

 Directory of C:\Program Files (x86)\Git\bin

07/12/2014  06:01 PM         1,154,665 libapr-0-0.dll
07/12/2014  06:01 PM           992,438 libaprutil-0-0.dll
07/12/2014  06:01 PM         1,724,229 libcrypto.dll
07/12/2014  06:01 PM           360,448 libcurl.dll
07/12/2014  06:01 PM           958,945 libexpat-0.dll
07/12/2014  06:01 PM           443,550 libgsasl-7.dll
07/12/2014  06:01 PM         1,241,889 libiconv-2.dll
07/12/2014  06:01 PM           293,380 libintl-8.dll
07/12/2014  06:01 PM         2,076,008 libneon-25.dll
07/12/2014  06:01 PM         4,884,531 libpoppler-7.dll
07/12/2014  06:01 PM           391,048 libssl.dll
07/12/2014  06:01 PM         1,218,359 libsvn_client-1-0.dll
07/12/2014  06:01 PM           851,272 libsvn_delta-1-0.dll
07/12/2014  06:01 PM           798,881 libsvn_diff-1-0.dll
07/12/2014  06:01 PM           792,459 libsvn_fs-1-0.dll
07/12/2014  06:01 PM         1,028,321 libsvn_fs_fs-1-0.dll
07/12/2014  06:01 PM           759,216 libsvn_ra-1-0.dll
07/12/2014  06:01 PM         1,017,784 libsvn_ra_dav-1-0.dll
07/12/2014  06:01 PM           800,669 libsvn_ra_local-1-0.dll
07/12/2014  06:01 PM           930,046 libsvn_ra_svn-1-0.dll
07/12/2014  06:01 PM         1,055,893 libsvn_repos-1-0.dll
07/12/2014  06:01 PM         1,248,729 libsvn_subr-1-0.dll
07/12/2014  06:01 PM           864,473 libsvn_swig_perl-1-0.dll
07/12/2014  06:01 PM         1,253,965 libsvn_wc-1-0.dll
07/12/2014  06:01 PM           812,063 libW11.dll
07/12/2014  06:01 PM           194,947 libz.dll
07/12/2014  06:01 PM           777,544 msys-1.0.dll
07/12/2014  06:01 PM         1,282,560 msys-crypto-1.0.0.dll
07/12/2014  06:01 PM            19,968 msys-minires.dll
07/12/2014  06:01 PM           939,520 msys-perl5_8.dll
07/12/2014  06:01 PM            82,852 msys-regex-1.dll
07/12/2014  06:01 PM           328,192 msys-ssl-1.0.0.dll
07/12/2014  06:01 PM            91,792 msys-z.dll
07/12/2014  06:01 PM            52,064 msysltdl-3.dll
07/12/2014  06:01 PM            65,124 pthreadGC2.dll
07/12/2014  06:01 PM         1,152,701 tcl85.dll
07/12/2014  06:01 PM            30,023 tclpip85.dll
07/12/2014  06:01 PM         1,410,875 tk85.dll
              38 File(s)     34,381,423 bytes
               0 Dir(s)  94,420,832,256 bytes free

C:\Program Files (x86)\Git\bin>

Just to demonstrate that behaviour you're about to break is actually used by some products.

See the top comment in this bug: "2) Add a LoadLibraryEx to x/sys/win so that users can still get at the old behavior if they want it (by appropriate passing of flags)."

(A flags of 0 would mean the current behavior)

But that will still break my existing code. I don't personally have problem like described in https://textplain.wordpress.com/2015/12/18/dll-hijacking-just-wont-die/. Why should I suffer? Why cannot we do what I suggested above? What is the downside?

Alex

@minux

This comment has been minimized.

Copy link
Member

commented Mar 26, 2016

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 26, 2016

I propose we add the new x/sys/windows.LoadLibraryEx function and proactively fix all known public code on Github to use the new x/sys function instead of syscall.LoadLibrary.

@minux, @alexbrainman, I consider both of you advanced users who would use syscall.LoadDLL, but I don't suspect there is much total code out there that would be affected.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 27, 2016

I propose we add the new x/sys/windows.LoadLibraryEx function

I don't think this will work for what your broke. Since you changed syscall.LoadDLL (in CL 21140), you would have to provide similar alternative. In syscall package too. Otherwise people would have to change too much code if they need to import x/sys/windows as well as syscall, and things can get messy. I don't use x/sys/windows myself, it is difficult for me to see what can go wrong here.

Alex

@mattn

This comment has been minimized.

Copy link
Member

commented Mar 27, 2016

I checked loading dll from go.

#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) {
    switch (dwReason) {
    case DLL_PROCESS_ATTACH:
        MessageBox(0, "Evil", "Wow!", MB_OK);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

build kernel32.dll

gcc -static -o kernel32.dll -shared kernel32.c

loader written in go

package main

import (
    "os"
    "syscall"
)

func main() {
    kernel32 := syscall.NewLazyDLL(os.Args[1])
    procGetCurrentThreadId := kernel32.NewProc("GetCurrentThreadId")
    procGetCurrentThreadId.Call()
}

then, pass argument pointed path to kernel32.dll like below

go run main.go [Argument]
Argument Result
kernel32 OK
kernel32.dll OK
./kernel32 Evail
./kernel32.dll Evail

problems seem to not occur unless the program point to kernel32.dll relatively or point to kernel32.dll directly.

@taruti

This comment has been minimized.

Copy link
Contributor

commented Mar 28, 2016

@mattn, That is because Windows registry has a list of dlls that will always be loaded from a system directory first. That covers some, but not all of the dlls that are used by Go stdlib.

I see at least three possible solutions:
A) Fix LoadDll and make applications deal with it.
B) Have a syscall.LoadDllSafe and change stdlib to use that (or even internal/syscall/windows.LoadDllSafe) and change nothing for custom user code.
C) Do nothing

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 28, 2016

I see at least three possible solutions:
A) Fix LoadDll and make applications deal with it.
B) Have a syscall.LoadDllSafe and change stdlib to use that (or even internal/syscall/windows.LoadDllSafe) and change nothing for custom user code.
C) Do nothing

I think your solution A must include some plan for Go users on how to fix their breakage. I am worried they will just start copying runtime code. And some will make mistakes along the way. And maybe even copying code will not work for some reason or other.

As to my preference, I like your B approach (we can do better than syscall.LoadDllSafe name). I can be arm twisted into doing C :-), but B is not much harder, and it will make all standard library code safe for this current issue. And it won't break any user code. We can mention new syscall.LoadDllSafe function in release notes, and let our users decide if it is important for their projects. syscall.LoadDllSafe could be a simple replacement for syscall.LoadDLL, so it should be a trivial change for everyone who decides to follow our advice.

Alex

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 29, 2016

I've updated https://go-review.googlesource.com/21140 to hopefully be non-controversial. It now makes sure that all DLLs loaded by Go itself are safe, but does nothing to protect users using syscall.LoadLibrary or syscall.NewLazyDLL themselves.

@taruti

This comment has been minimized.

Copy link
Contributor

commented Mar 29, 2016

That seems like a good way forward.

Would exposing that to third party code via the sys-repo be fine? I can submit that, if it is ok.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 30, 2016

To write a proper test for https://golang.org/cl/21140, I would like a DLL which, when loaded, does something we can check easily in a test. Maybe it can write to stdout, or crash the process with a certain error code.

@mattn, could you provide such a minimal DLL & source code? From #14959 (comment) it looks like you know how to make them easily. I only have gomote+trybots for Windows testing. I don't have a Windows development machine at the moment. I found some information online about how to generate Windows DLLs from Linux which I can try otherwise.

One DLL is probably fine, but maybe a 32-bit one and a 64-bit one would be better?

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 30, 2016

@taruti, adding x/sys/windows API for all the possibilities is not controversial. It's only new API in the standard library that we want to avoid. If you'd like to do the x/sys change(s) already, feel free. I'd be happy to review.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 30, 2016

To write a proper test for https://golang.org/cl/21140, I would like a DLL which, when loaded, does something we can check easily in a test.

I think we already have TestStdcallAndCDeclCallbacks that does what you want. I wonder why the test didn't fail with your CL 21140 changes are applied.

Alex

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Mar 30, 2016

Oh, nice.

Maybe the builders don't have gcc?

func TestStdcallAndCDeclCallbacks(t *testing.T) {
        if _, err := exec.LookPath("gcc"); err != nil {
            t.Skip("skipping test: gcc is missing")
        }

Will investigate.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Mar 31, 2016

Maybe the builders don't have gcc?

They surely do. misc/cgo tests wouldn't run without gcc.

Alex

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Apr 1, 2016

@alexbrainman, TestStdcallAndCDeclCallbacks didn't fail because it's using an absolute path to the DLL, which is unaffected by https://golang.org/cl/21140:

$ gomote run user-bradfitz-windows-amd64-gce-0 go/bin/go test -v -run=TestStdcallAndCDeclCallbacks runtime
=== RUN   TestStdcallAndCDeclCallbacks
--- PASS: TestStdcallAndCDeclCallbacks (0.35s)
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\test.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
        syscall_windows_test.go:400: MustLoading DLL "C:\\Users\\WINGOP~1\\AppData\\Local\\Temp\\TestCDeclCallback016371391\\testO2.dll" ...
PASS
ok      runtime 0.392s

I'll write a new similar test using a base filename ("test_bad.dll") and verify it doesn't search for it in the current directory once "test_bad.dll" is registered as requiring system32.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Apr 1, 2016

x/sys counterpart for discussion: https://go-review.googlesource.com/21388

@gopherbot

This comment has been minimized.

Copy link

commented Apr 1, 2016

CL https://golang.org/cl/21388 mentions this issue.

@blinksmith

This comment has been minimized.

Copy link

commented Apr 1, 2016

@bradfitz Go should not paranoid when loading DLLs.
its not Go developer problem, its Window's user problem.

Search Path behavior should remaining same https://msdn.microsoft.com/en-us/library/7d83bc18.aspx

its not Go's fault when loaded dll is fake, it is user fault executing unknown program in their environment.

I am Windows user, I consider this as a feature we can try and load newer dlls without the need to replace original system32 dlls. so udating software is much easier.

  • every downloaded file must be unblocked.
  • every Windows user must have antivirus.

Win User know it, and they already have their own guards.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Apr 1, 2016

@blinksmith, we're only altering the DLL search path for DLLs used by Go. syscall.LoadDLL will remain unchanged for other DLLs. It is a non-goal for people to be able to manually update their system DLLs in non-standard locations and have Go respect them from those paths. You should use the normal Windows system update mechanism.

x/sys/windows is getting a new LoadLibraryEx in https://golang.org/cl/21388 for having more control.

gopherbot pushed a commit that referenced this issue Apr 1, 2016

runtime, syscall: only search for Windows DLLs in the System32 directory
Make sure that for any DLL that Go uses itself, we only look for the
DLL in the Windows System32 directory, guarding against DLL preloading
attacks.

(Unless the Windows version is ancient and LoadLibraryEx is
unavailable, in which case the user probably has bigger security
problems anyway.)

This does not change the behavior of syscall.LoadLibrary or NewLazyDLL
if the DLL name is something unused by Go itself.

This change also intentionally does not add any new API surface. Instead,
x/sys is updated with a LoadLibraryEx function and LazyDLL.Flags in:
    https://golang.org/cl/21388

Updates #14959

Change-Id: I8d29200559cc19edf8dcf41dbdd39a389cd6aeb9
Reviewed-on: https://go-review.googlesource.com/21140
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

gopherbot pushed a commit to golang/sys that referenced this issue Apr 2, 2016

windows: add LoadLibraryEx, add LazyDLL.System
Updates golang/go#14959

Change-Id: Ib91c359c3df919df0b30e584d38e56f79f3e3dc9
Reviewed-on: https://go-review.googlesource.com/21388
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
@gopherbot

This comment has been minimized.

Copy link

commented Apr 2, 2016

CL https://golang.org/cl/21428 mentions this issue.

gopherbot pushed a commit that referenced this issue Apr 2, 2016

syscall: point to x/sys in DLL loading docs, update syscall generator
Updates the syscall generator for patchset 4 of https://golang.org/cl/21388.

Updates #14959

Change-Id: Icbd6df489887d3dcc076dfc73d4feb1376abaf8b
Reviewed-on: https://go-review.googlesource.com/21428
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
@adg

This comment has been minimized.

Copy link
Contributor

commented Apr 7, 2016

What's left to fix this?

@adg adg added the Release-OK label Apr 7, 2016

@mattn

This comment has been minimized.

Copy link
Member

commented Apr 7, 2016

Please wait bradfitz. Now he's trying to buy Windows XP at Best Buy maybe.

@bradfitz

This comment has been minimized.

Copy link
Member Author

commented Apr 7, 2016

Nothing's left, other than to ship Go1.6.1. @alexbrainman confirmed all.bat passes on his Windows XP machine, and the new test fails (skips) as expected on XP.

@gopherbot

This comment has been minimized.

Copy link

commented Apr 8, 2016

CL https://golang.org/cl/21639 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Apr 8, 2016

CL https://golang.org/cl/21680 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Apr 8, 2016

CL https://golang.org/cl/21696 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Apr 8, 2016

CL https://golang.org/cl/21697 mentions this issue.

gopherbot pushed a commit that referenced this issue Apr 8, 2016

runtime, syscall: only search for Windows DLLs in the System32 directory
Make sure that for any DLL that Go uses itself, we only look for the
DLL in the Windows System32 directory, guarding against DLL preloading
attacks.

(Unless the Windows version is ancient and LoadLibraryEx is
unavailable, in which case the user probably has bigger security
problems anyway.)

This does not change the behavior of syscall.LoadLibrary or NewLazyDLL
if the DLL name is something unused by Go itself.

This change also intentionally does not add any new API surface. Instead,
x/sys is updated with a LoadLibraryEx function and LazyDLL.Flags in:
    https://golang.org/cl/21388

Updates #14959

Change-Id: I8d29200559cc19edf8dcf41dbdd39a389cd6aeb9
Reviewed-on: https://go-review.googlesource.com/21140
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/21639
Run-TryBot: Andrew Gerrand <adg@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

gopherbot pushed a commit that referenced this issue Apr 8, 2016

syscall: point to x/sys in DLL loading docs, update syscall generator
Updates the syscall generator for patchset 4 of https://golang.org/cl/21388.

Updates #14959

Change-Id: Icbd6df489887d3dcc076dfc73d4feb1376abaf8b
Reviewed-on: https://go-review.googlesource.com/21428
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-on: https://go-review.googlesource.com/21680
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

gopherbot pushed a commit that referenced this issue Apr 8, 2016

runtime, syscall: only search for Windows DLLs in the System32 directory
Make sure that for any DLL that Go uses itself, we only look for the
DLL in the Windows System32 directory, guarding against DLL preloading
attacks.

(Unless the Windows version is ancient and LoadLibraryEx is
unavailable, in which case the user probably has bigger security
problems anyway.)

This does not change the behavior of syscall.LoadLibrary or NewLazyDLL
if the DLL name is something unused by Go itself.

This change also intentionally does not add any new API surface. Instead,
x/sys is updated with a LoadLibraryEx function and LazyDLL.Flags in:
    https://golang.org/cl/21388

Updates #14959

Change-Id: I8d29200559cc19edf8dcf41dbdd39a389cd6aeb9
Reviewed-on: https://go-review.googlesource.com/21140
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/21696
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

gopherbot pushed a commit that referenced this issue Apr 8, 2016

syscall: point to x/sys in DLL loading docs, update syscall generator
Updates the syscall generator for patchset 4 of https://golang.org/cl/21388.

Updates #14959

Change-Id: Icbd6df489887d3dcc076dfc73d4feb1376abaf8b
Reviewed-on: https://go-review.googlesource.com/21428
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-on: https://go-review.googlesource.com/21697
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

@bradfitz bradfitz closed this Apr 26, 2016

@gopherbot

This comment has been minimized.

Copy link

commented May 12, 2016

CL https://golang.org/cl/23025 mentions this issue.

gopherbot pushed a commit to golang/exp that referenced this issue May 13, 2016

shiny/driver: only load Windows DLLs from the System32 directory
See issue golang/go#14959 for details.

Change-Id: I7c06b23b5cb98e4330fb85c025cad2cbd3db37ae
Reviewed-on: https://go-review.googlesource.com/23025
Reviewed-by: Nigel Tao <nigeltao@golang.org>

@golang golang locked and limited conversation to collaborators May 12, 2017

gopherbot pushed a commit that referenced this issue Mar 10, 2019

runtime: safely load DLLs
While many other call sites have been moved to using the proper
higher-level system loading, these areas were left out. This prevents
DLL directory injection attacks. This includes both the runtime load
calls (using LoadLibrary prior) and the implicitly linked ones via
cgo_import_dynamic, which we move to our LoadLibraryEx. The goal is to
only loosely load kernel32.dll and strictly load all others.

Meanwhile we make sure that we never fallback to insecure loading on
older or unpatched systems.

This is CVE-2019-9634.

Fixes #14959
Fixes #28978
Fixes #30642

Change-Id: I401a13ed8db248ab1bb5039bf2d31915cac72b93
Reviewed-on: https://go-review.googlesource.com/c/go/+/165798
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.