浏览代码

loadlibrary: Only load system DLLs from the system directory

Inspiration provided by: Daniel Stenberg and Ray Satiro

Bug: https://curl.haxx.se/docs/adv_20160530.html

Ref: Windows DLL hijacking with curl, CVE-2016-4802
Steve Holme 8 年之前
父节点
当前提交
6df916d751
共有 7 个文件被更改,包括 180 次插入8 次删除
  1. 2 2
      lib/Makefile.inc
  2. 2 1
      lib/Makefile.vc6
  3. 4 3
      lib/curl_sspi.c
  4. 130 0
      lib/system_win32.c
  5. 39 0
      lib/system_win32.h
  6. 2 1
      lib/telnet.c
  7. 1 1
      packages/Symbian/group/libcurl.mmp

+ 2 - 2
lib/Makefile.inc

@@ -53,7 +53,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c               \
   curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
-  x509asn1.c http2.c smb.c curl_endian.c curl_des.c
+  x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
 
 LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
@@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
-  curl_printf.h
+  curl_printf.h system_win32.h
 
 LIB_RCFILES = libcurl.rc
 

+ 2 - 1
lib/Makefile.vc6

@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -616,6 +616,7 @@ X_OBJS= \
 	$(DIROBJ)\speedcheck.obj \
 	$(DIROBJ)\splay.obj \
 	$(DIROBJ)\ssh.obj \
+	$(DIROBJ)\system_win32.obj \
 	$(DIROBJ)\vauth.obj \
 	$(DIROBJ)\cleartext.obj \
 	$(DIROBJ)\cram.obj \

+ 4 - 3
lib/curl_sspi.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,6 +27,7 @@
 #include <curl/curl.h>
 #include "curl_sspi.h"
 #include "curl_multibyte.h"
+#include "system_win32.h"
 #include "warnless.h"
 
 /* The last #include files should be: */
@@ -117,9 +118,9 @@ CURLcode Curl_sspi_global_init(void)
 
     /* Load SSPI dll into the address space of the calling process */
     if(securityDll)
-      s_hSecDll = LoadLibrary(TEXT("security.dll"));
+      s_hSecDll = Curl_load_library(TEXT("security.dll"));
     else
-      s_hSecDll = LoadLibrary(TEXT("secur32.dll"));
+      s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
     if(!s_hSecDll)
       return CURLE_FAILED_INIT;
 

+ 130 - 0
lib/system_win32.c

@@ -0,0 +1,130 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2016, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(WIN32)
+
+#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
+                                  defined(USE_WINSOCK))
+
+#include <curl/curl.h>
+#include "system_win32.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
+#define LOAD_WITH_ALTERED_SEARCH_PATH  0x00000008
+#endif
+
+#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
+#define LOAD_LIBRARY_SEARCH_SYSTEM32   0x00000800
+#endif
+
+/* We use our own typedef here since some headers might lack these */
+typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
+
+/* See function definitions in winbase.h */
+#ifdef UNICODE
+#  ifdef _WIN32_WCE
+#    define LOADLIBARYEX  L"LoadLibraryExW"
+#  else
+#    define LOADLIBARYEX  "LoadLibraryExW"
+#  endif
+#else
+#  define LOADLIBARYEX    "LoadLibraryExA"
+#endif
+
+/*
+ * Curl_load_library()
+ *
+ * This is used to dynamically load DLLs using the most secure method available
+ * for the version of Windows that we are running on.
+ *
+ * Parameters:
+ *
+ * filename  [in] - The filename or full path of the DLL to load. If only the
+ *                  filename is passed then the DLL will be loaded from the
+ *                  Windows system directory.
+ *
+ * Returns the handle of the module on success; otherwise NULL.
+ */
+HMODULE Curl_load_library(LPCTSTR filename)
+{
+  HMODULE hModule = NULL;
+  LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
+
+  /* Get a handle to kernel32 so we can access it's functions at runtime */
+  HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
+  if(!hKernel32)
+    return NULL;
+
+  /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
+     and above */
+  pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
+
+  /* Detect if there's already a path in the filename and load the library if
+     there is. Note: Both back slashes and forward slashes have been supported
+     since the earlier days of DOS at an API level although they are not
+     supported by command prompt */
+  if(_tcspbrk(filename, TEXT("\\/")))
+    hModule = pLoadLibraryEx ?
+      pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
+      LoadLibrary(filename);
+  /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
+     supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
+     Server 2008 R2 with this patch or natively on Windows 8 and above */
+  else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
+    /* Load the DLL from the Windows system directory */
+    hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+  }
+  else {
+    /* Attempt to get the Windows system path */
+    UINT systemdirlen = GetSystemDirectory(NULL, 0);
+    if(systemdirlen) {
+      /* Allocate space for the full DLL path (Room for the null terminator
+         is included in systemdirlen) */
+      size_t filenamelen = _tcslen(filename);
+      TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
+      if(path && GetSystemDirectory(path, systemdirlen)) {
+        /* Calculate the full DLL path */
+        _tcscpy(path + _tcslen(path), TEXT("\\"));
+        _tcscpy(path + _tcslen(path), filename);
+
+        /* Load the DLL from the Windows system directory */
+        hModule = pLoadLibraryEx ?
+          pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
+          LoadLibrary(path);
+
+        free(path);
+      }
+    }
+  }
+
+  return hModule;
+}
+
+#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
+
+#endif /* WIN32 */

+ 39 - 0
lib/system_win32.h

@@ -0,0 +1,39 @@
+#ifndef HEADER_CURL_SYSTEM_WIN32_H
+#define HEADER_CURL_SYSTEM_WIN32_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2016, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(WIN32)
+
+#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
+                                  defined(USE_WINSOCK))
+
+/* This is used to dynamically load DLLs */
+HMODULE Curl_load_library(LPCTSTR filename);
+
+#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
+
+#endif /* WIN32 */
+
+#endif /* HEADER_CURL_SYSTEM_WIN32_H */

+ 2 - 1
lib/telnet.c

@@ -51,6 +51,7 @@
 #include "telnet.h"
 #include "connect.h"
 #include "progress.h"
+#include "system_win32.h"
 
 #define  TELOPTS
 #define  TELCMDS
@@ -1334,7 +1335,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 
   /* OK, so we have WinSock 2.0.  We need to dynamically */
   /* load ws2_32.dll and get the function pointers we need. */
-  wsock2 = LoadLibrary(TEXT("WS2_32.DLL"));
+  wsock2 = Curl_load_library(TEXT("WS2_32.DLL"));
   if(wsock2 == NULL) {
     failf(data, "failed to load WS2_32.DLL (%d)", ERRNO);
     return CURLE_FAILED_INIT;

+ 1 - 1
packages/Symbian/group/libcurl.mmp

@@ -39,7 +39,7 @@ SOURCE \
   asyn-ares.c asyn-thread.c curl_gssapi.c http_ntlm.c curl_ntlm_wb.c   \
   curl_ntlm_core.c curl_sasl.c vtls/schannel.c curl_multibyte.c        \
   vtls/darwinssl.c conncache.c curl_sasl_sspi.c smb.c curl_endian.c    \
-  curl_des.c                                                           \
+  curl_des.c system_win32.c                                            \
   vauth/vauth.c vauth/cleartext.c vauth/cram.c vauth/digest.c          \
   vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c            \
   vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c  \