aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service/securityapi.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-05-11 22:13:31 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-12 11:13:35 +0200
commit7fe35e8c15f4c10a5ccaeaa0864ece39469daea6 (patch)
tree72eb403c8d0ef420414e1b55501f0ebcb4afbd22 /service/securityapi.go
parentservice: run UI at high integrity (diff)
downloadwireguard-windows-7fe35e8c15f4c10a5ccaeaa0864ece39469daea6.tar.xz
wireguard-windows-7fe35e8c15f4c10a5ccaeaa0864ece39469daea6.zip
service: run UI with elevated token
There are too many attacks possible when starting this with a non-elevated token. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--service/securityapi.go184
1 files changed, 0 insertions, 184 deletions
diff --git a/service/securityapi.go b/service/securityapi.go
index cf2e597a..37713b32 100644
--- a/service/securityapi.go
+++ b/service/securityapi.go
@@ -7,10 +7,8 @@ package service
import (
"errors"
- "fmt"
"golang.org/x/sys/windows"
"runtime"
- "syscall"
"unicode/utf16"
"unsafe"
)
@@ -51,68 +49,10 @@ type wtsSessionInfo struct {
//sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
const (
- SE_KERNEL_OBJECT = 6
-
- SE_GROUP_LOGON_ID = 0xC0000000
SE_GROUP_ENABLED = 0x00000004
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010
-
- ACL_REVISION = 2
-
- PROCESS_TERMINATE = 0x0001
- PROCESS_CREATE_THREAD = 0x0002
- PROCESS_SET_SESSIONID = 0x0004
- PROCESS_VM_OPERATION = 0x0008
- PROCESS_VM_READ = 0x0010
- PROCESS_VM_WRITE = 0x0020
- PROCESS_DUP_HANDLE = 0x0040
- PROCESS_CREATE_PROCESS = 0x0080
- PROCESS_SET_QUOTA = 0x0100
- PROCESS_SET_INFORMATION = 0x0200
- PROCESS_QUERY_INFORMATION = 0x0400
- PROCESS_SUSPEND_RESUME = 0x0800
- PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
-
- OWNER_SECURITY_INFORMATION = 0x00000001
- GROUP_SECURITY_INFORMATION = 0x00000002
- DACL_SECURITY_INFORMATION = 0x00000004
- SACL_SECURITY_INFORMATION = 0x00000008
- LABEL_SECURITY_INFORMATION = 0x00000010
- ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
- SCOPE_SECURITY_INFORMATION = 0x00000040
- BACKUP_SECURITY_INFORMATION = 0x00010000
- PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
- PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
- UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
- UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
-
- AclRevisionInformation = 1
- AclSizeInformation = 2
)
-type ACL_SIZE_INFORMATION struct {
- aceCount uint32
- aclBytesInUse uint32
- aclBytesFree uint32
-}
-type ACE_HEADER struct {
- aceType byte
- aceFlags byte
- aceSize uint16
-}
-
-//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, owner *uintptr, group *uintptr, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
-//sys addAccessAllowedAce(acl *byte, aceRevision uint32, accessmask uint32, sid *windows.SID) (err error) = advapi32.AddAccessAllowedAce
-//sys setSecurityDescriptorDacl(securityDescriptor *byte, daclPresent bool, dacl *byte, defaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
-//sys setSecurityDescriptorSacl(securityDescriptor *byte, saclPresent bool, sacl *byte, defaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
-//sys getAclInformation(acl *byte, info *ACL_SIZE_INFORMATION, len uint32, infoclass uint32) (err error) = advapi32.GetAclInformation
-//sys getAce(acl *byte, index uint32, ace **ACE_HEADER) (err error) = advapi32.GetAce
-//sys addAce(acl *byte, revision uint32, index uint32, ace *ACE_HEADER, lenAce uint32) (err error) = advapi32.AddAce
-//sys initializeAcl(acl *byte, len uint32, revision uint32) (err error) = advapi32.InitializeAcl
-//sys makeAbsoluteSd(selfRelativeSecurityDescriptor uintptr, absoluteSecurityDescriptor *byte, absoluteSecurityDescriptorSize *uint32, dacl *byte, daclSize *uint32, sacl *byte, saclSize *uint32, owner *byte, ownerSize *uint32, primaryGroup *byte, primaryGroupSize *uint32) (err error) = advapi32.MakeAbsoluteSD
-//sys makeSelfRelativeSd(absoluteSecurityDescriptor *byte, relativeSecurityDescriptor *byte, relativeSecurityDescriptorSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
-//sys setTokenInformation(token windows.Token, infoClass uint32, info *byte, infoSize uint32) (err error) = advapi32.SetTokenInformation
-
//sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
//sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock
@@ -149,7 +89,6 @@ func tokenIsElevated(token windows.Token) bool {
return false
}
return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
-
}
func getElevatedToken(token windows.Token) (windows.Token, error) {
@@ -189,126 +128,3 @@ func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
runtime.KeepAlive(gs)
return isAdmin
}
-
-func sliceToSecurityAttributes(sa []byte) *syscall.SecurityAttributes {
- return &syscall.SecurityAttributes{
- Length: uint32(len(sa)),
- SecurityDescriptor: uintptr(unsafe.Pointer(&sa[0])),
- }
-}
-
-func getSecurityAttributes(mainToken windows.Token, tokenThatHasLogonSession windows.Token) ([]byte, error) {
- gs, err := tokenThatHasLogonSession.GetTokenGroups()
- if err != nil {
- return nil, err
- }
- var logonSid *windows.SID
- groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount]
- for _, g := range groups {
- if g.Attributes&SE_GROUP_LOGON_ID != 0 && g.Attributes&SE_GROUP_ENABLED != 0 {
- logonSid = g.Sid
- break
- }
- }
- if logonSid == nil {
- return nil, errors.New("Unable to find logon SID")
- }
-
- var originalSecurityDescriptor uintptr
- err = getSecurityInfo(windows.Handle(mainToken), SE_KERNEL_OBJECT, ATTRIBUTE_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION|SCOPE_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &originalSecurityDescriptor)
- if err != nil {
- return nil, err
- }
- var (
- absoluteSecurityDescriptorSize uint32
- daclSize uint32
- saclSize uint32
- ownerSize uint32
- primaryGroupSize uint32
- )
- err = makeAbsoluteSd(originalSecurityDescriptor, nil, &absoluteSecurityDescriptorSize, nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &primaryGroupSize)
- if err != windows.ERROR_INSUFFICIENT_BUFFER {
- windows.LocalFree(windows.Handle(originalSecurityDescriptor))
- return nil, fmt.Errorf("Expected insufficient buffer from MakeAbsoluteSd, but got: %v", err)
- }
- absoluteSecurityDescriptor := make([]byte, absoluteSecurityDescriptorSize)
- dacl := make([]byte, daclSize)
- sacl := make([]byte, saclSize)
- owner := make([]byte, ownerSize)
- primaryGroup := make([]byte, primaryGroupSize)
- err = makeAbsoluteSd(originalSecurityDescriptor, &absoluteSecurityDescriptor[0], &absoluteSecurityDescriptorSize, &dacl[0], &daclSize, &sacl[0], &saclSize, &owner[0], &ownerSize, &primaryGroup[0], &primaryGroupSize)
- if err != nil {
- windows.LocalFree(windows.Handle(originalSecurityDescriptor))
- return nil, err
- }
- windows.LocalFree(windows.Handle(originalSecurityDescriptor))
-
- var daclInfo ACL_SIZE_INFORMATION
- err = getAclInformation(&dacl[0], &daclInfo, uint32(unsafe.Sizeof(daclInfo)), AclSizeInformation)
- if err != nil {
- return nil, err
- }
- newDacl := make([]byte, daclInfo.aclBytesInUse*2+0x1000)
- err = initializeAcl(&newDacl[0], uint32(len(newDacl)), ACL_REVISION)
- if err != nil {
- return nil, err
- }
- var ace *ACE_HEADER
- for i := uint32(0); i < daclInfo.aceCount; i++ {
- err = getAce(&dacl[0], i, &ace)
- if err != nil {
- return nil, err
- }
- err = addAce(&newDacl[0], ACL_REVISION, ^uint32(0), ace, uint32(ace.aceSize))
- if err != nil {
- return nil, err
- }
- }
- runtime.KeepAlive(dacl)
- err = addAccessAllowedAce(&newDacl[0], ACL_REVISION, PROCESS_QUERY_LIMITED_INFORMATION, logonSid)
- if err != nil {
- return nil, err
- }
- runtime.KeepAlive(gs)
- err = setSecurityDescriptorDacl(&absoluteSecurityDescriptor[0], true, &newDacl[0], false)
- if err != nil {
- return nil, err
- }
- //TODO: This should not be required!! But right now we can't give the process the high integrity SACL, which is unfortunate. So we unset it.
- err = setSecurityDescriptorSacl(&absoluteSecurityDescriptor[0], false, nil, true)
- if err != nil {
- return nil, err
- }
- var selfRelativeSecurityDescriptorSize uint32
- err = makeSelfRelativeSd(&absoluteSecurityDescriptor[0], nil, &selfRelativeSecurityDescriptorSize)
- if err != windows.ERROR_INSUFFICIENT_BUFFER {
- return nil, fmt.Errorf("Expected insufficient buffer from MakeSelfRelativeSd, but got: %v", err)
- }
- relativeSecurityDescriptor := make([]byte, selfRelativeSecurityDescriptorSize)
- err = makeSelfRelativeSd(&absoluteSecurityDescriptor[0], &relativeSecurityDescriptor[0], &selfRelativeSecurityDescriptorSize)
- if err != nil {
- return nil, err
- }
- runtime.KeepAlive(absoluteSecurityDescriptor)
- runtime.KeepAlive(newDacl)
- runtime.KeepAlive(sacl)
- runtime.KeepAlive(owner)
- runtime.KeepAlive(primaryGroup)
-
- return relativeSecurityDescriptor, nil
-}
-
-func addElevatedIntegrityToUserToken(elevatedToken, userToken windows.Token) error {
- //TODO: We really don't want to be doing this. See the note above. We'd rather the UI process have very few permissions in its token, and do everything with its SACL. But we can't.
- var integrityLevel [0x2000]byte
- len := uint32(len(integrityLevel))
- err := windows.GetTokenInformation(elevatedToken, windows.TokenIntegrityLevel, &integrityLevel[0], len, &len)
- if err != nil {
- return err
- }
- err = setTokenInformation(userToken, windows.TokenIntegrityLevel, &integrityLevel[0], len)
- if err != nil {
- return err
- }
- return nil
-}