]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Move SID-getting code into a separate function so it can be shared by
authorOwen Dunn <owen@greenend.org.uk>
Sun, 22 Nov 2015 12:04:04 +0000 (12:04 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 29 Feb 2016 19:59:33 +0000 (19:59 +0000)
make_private_security_descriptor and a new function protectprocess().

protectprocess() opens the running PuTTY process and adjusts the
Everyone and user access control entries in its ACL to deny a
selection of permissions which malicious processes running as the same
user could use to hijack PuTTY.

(cherry picked from commit aba7234bc167c8c056a9ea4f939a6dcda10e84f3)

windows/winsecur.c

index df93a74c5baa4954ecabdb669200f7e8e7af0718..6e4bd7d4c2fe54e3cbf237c32ed3a2e7e101ac3c 100644 (file)
 #define WINSECUR_GLOBAL
 #include "winsecur.h"
 
+/* Initialised once, then kept around to reuse forever */
+static PSID worldsid, networksid, usersid;
+
+
 int got_advapi(void)
 {
     static int attempted = FALSE;
@@ -99,32 +103,17 @@ PSID get_user_sid(void)
     return ret;
 }
 
-int make_private_security_descriptor(DWORD permissions,
-                                     PSECURITY_DESCRIPTOR *psd,
-                                     PACL *acl,
-                                     char **error)
+int getsids(char *error)
 {
     SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
     SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
-    EXPLICIT_ACCESS ea[3];
-    int acl_err;
-    int ret = FALSE;
+    int ret;
 
-    /* Initialised once, then kept around to reuse forever */
-    static PSID worldsid, networksid, usersid;
-
-    *psd = NULL;
-    *acl = NULL;
-    *error = NULL;
-
-    if (!got_advapi()) {
-        *error = dupprintf("unable to load advapi32.dll");
-        goto cleanup;
-    }
+    error=NULL;
 
     if (!usersid) {
         if ((usersid = get_user_sid()) == NULL) {
-            *error = dupprintf("unable to construct SID for current user: %s",
+            error = dupprintf("unable to construct SID for current user: %s",
                                win_strerror(GetLastError()));
             goto cleanup;
         }
@@ -133,7 +122,7 @@ int make_private_security_descriptor(DWORD permissions,
     if (!worldsid) {
         if (!AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID,
                                       0, 0, 0, 0, 0, 0, 0, &worldsid)) {
-            *error = dupprintf("unable to construct SID for world: %s",
+            error = dupprintf("unable to construct SID for world: %s",
                                win_strerror(GetLastError()));
             goto cleanup;
         }
@@ -142,13 +131,43 @@ int make_private_security_descriptor(DWORD permissions,
     if (!networksid) {
         if (!AllocateAndInitializeSid(&nt_auth, 1, SECURITY_NETWORK_RID,
                                       0, 0, 0, 0, 0, 0, 0, &networksid)) {
-            *error = dupprintf("unable to construct SID for "
+            error = dupprintf("unable to construct SID for "
                                "local same-user access only: %s",
                                win_strerror(GetLastError()));
             goto cleanup;
         }
     }
 
+    ret=TRUE;
+
+ cleanup:
+    if (ret) {
+      sfree(error);
+      error = NULL;
+    }
+    return ret;
+}
+  
+
+int make_private_security_descriptor(DWORD permissions,
+                                     PSECURITY_DESCRIPTOR *psd,
+                                     PACL *acl,
+                                     char **error)
+{
+    SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
+    SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
+    EXPLICIT_ACCESS ea[3];
+    int acl_err;
+    int ret = FALSE;
+
+
+    *psd = NULL;
+    *acl = NULL;
+    *error = NULL;
+
+    if (!getsids(*error))
+      goto cleanup;
+
     memset(ea, 0, sizeof(ea));
     ea[0].grfAccessPermissions = permissions;
     ea[0].grfAccessMode = REVOKE_ACCESS;
@@ -218,4 +237,74 @@ int make_private_security_descriptor(DWORD permissions,
     return ret;
 }
 
+int protectprocess(char *error)
+{
+    SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
+    SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
+    EXPLICIT_ACCESS ea[2];
+    int acl_err;
+    int ret=FALSE;
+    PACL acl = NULL;
+
+    static const nastyace=WRITE_DAC | WRITE_OWNER |
+       PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
+       PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION |
+       PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
+       PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
+       PROCESS_SUSPEND_RESUME;
+
+    if (!getsids(error))
+       goto cleanup;
+
+    memset(ea, 0, sizeof(ea));
+
+    /* Everyone: deny */
+    ea[0].grfAccessPermissions = nastyace;
+    ea[0].grfAccessMode = DENY_ACCESS;
+    ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
+    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
+    ea[0].Trustee.ptstrName = (LPTSTR)worldsid;
+
+    /* User: user ace */
+    ea[1].grfAccessPermissions = ~nastyace & 0x1fff;
+    ea[1].grfAccessMode = GRANT_ACCESS;
+    ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
+    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
+    ea[1].Trustee.ptstrName = (LPTSTR)usersid;
+
+    acl_err = p_SetEntriesInAclA(2, ea, NULL, &acl);
+
+    if (acl_err != ERROR_SUCCESS || acl == NULL) {
+       error = dupprintf("unable to construct ACL: %s",
+                         win_strerror(acl_err));
+        goto cleanup;
+    }
+
+    if (ERROR_SUCCESS !=
+       SetSecurityInfo(
+                       GetCurrentProcess(),
+                       SE_KERNEL_OBJECT,
+                       OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+                       usersid,
+                       NULL,
+                       acl,
+                       NULL
+                       )) {
+       error=dupprintf("Unable to set process ACL: %s",
+                       win_strerror(GetLastError()));
+       goto cleanup;
+    }
+                     
+
+    ret=TRUE;
+    
+  cleanup:
+    if (!ret) {
+        if (acl) {
+            LocalFree(acl);
+            acl = NULL;
+        }
+    }
+    return ret;
+}  
 #endif /* !defined NO_SECURITY */