fix: verify active system session token setup

This commit is contained in:
2026-09-06 13:58:00 +00:00
parent 98070d21df
commit 6c85c8e039
@@ -649,6 +649,15 @@ func duplicateServiceTokenForSession(sessionID uint32) (winapi.Token, supervisor
return 0, supervisor.EffectiveIdentity{}, err return 0, supervisor.EffectiveIdentity{}, err
} }
defer source.Close() defer source.Close()
var restorePrivilege func()
if sessionID != 0 {
var err error
restorePrivilege, err = enableTokenPrivilege(source, "SeTcbPrivilege")
if err != nil {
return 0, supervisor.EffectiveIdentity{}, fmt.Errorf("enable SeTcbPrivilege for active session token: %w", err)
}
defer restorePrivilege()
}
var target winapi.Token var target winapi.Token
if err := winapi.DuplicateTokenEx(source, winapi.TOKEN_ALL_ACCESS, nil, winapi.SecurityImpersonation, winapi.TokenPrimary, &target); err != nil { if err := winapi.DuplicateTokenEx(source, winapi.TOKEN_ALL_ACCESS, nil, winapi.SecurityImpersonation, winapi.TokenPrimary, &target); err != nil {
return 0, supervisor.EffectiveIdentity{}, err return 0, supervisor.EffectiveIdentity{}, err
@@ -658,6 +667,16 @@ func duplicateServiceTokenForSession(sessionID uint32) (winapi.Token, supervisor
_ = target.Close() _ = target.Close()
return 0, supervisor.EffectiveIdentity{}, err return 0, supervisor.EffectiveIdentity{}, err
} }
var actualSession uint32
var returned uint32
if err := winapi.GetTokenInformation(target, winapi.TokenSessionId, (*byte)(unsafe.Pointer(&actualSession)), uint32(unsafe.Sizeof(actualSession)), &returned); err != nil {
_ = target.Close()
return 0, supervisor.EffectiveIdentity{}, fmt.Errorf("verify active SYSTEM token session: %w", err)
}
if returned != uint32(unsafe.Sizeof(actualSession)) || actualSession != sessionID {
_ = target.Close()
return 0, supervisor.EffectiveIdentity{}, errors.New("active SYSTEM token session did not read back as requested")
}
} }
user, err := target.GetTokenUser() user, err := target.GetTokenUser()
if err != nil || user.User.Sid == nil || user.User.Sid.String() != securitySystemRID { if err != nil || user.User.Sid == nil || user.User.Sid.String() != securitySystemRID {
@@ -670,6 +689,39 @@ func duplicateServiceTokenForSession(sessionID uint32) (winapi.Token, supervisor
return target, supervisor.EffectiveIdentity{Context: string(ContextLocalSystem), SessionID: sessionID, UserSID: user.User.Sid.String(), Elevated: true, Integrity: "system"}, nil return target, supervisor.EffectiveIdentity{Context: string(ContextLocalSystem), SessionID: sessionID, UserSID: user.User.Sid.String(), Elevated: true, Integrity: "system"}, nil
} }
// enableTokenPrivilege enables one privilege only for the short operation
// that needs it and returns a best-effort restoration closure. Windows may
// report ERROR_NOT_ALL_ASSIGNED even when AdjustTokenPrivileges itself
// succeeds; treat that as a hard capability failure rather than silently
// creating a Session-0 token for an active-session request.
func enableTokenPrivilege(token winapi.Token, name string) (func(), error) {
privilegeName, err := winapi.UTF16PtrFromString(name)
if err != nil {
return nil, err
}
var luid winapi.LUID
if err := winapi.LookupPrivilegeValue(nil, privilegeName, &luid); err != nil {
return nil, err
}
state := winapi.Tokenprivileges{PrivilegeCount: 1}
state.Privileges[0] = winapi.LUIDAndAttributes{Luid: luid, Attributes: winapi.SE_PRIVILEGE_ENABLED}
var previous winapi.Tokenprivileges
var returned uint32
if err := winapi.AdjustTokenPrivileges(token, false, &state, uint32(unsafe.Sizeof(state)), &previous, &returned); err != nil {
return nil, err
}
if lastErr := winapi.GetLastError(); lastErr != nil && !errors.Is(lastErr, syscall.Errno(0)) {
return nil, lastErr
}
restore := func() {
if returned == 0 {
return
}
_ = winapi.AdjustTokenPrivileges(token, false, &previous, uint32(unsafe.Sizeof(previous)), nil, nil)
}
return restore, nil
}
func logonLocalService() (winapi.Token, error) { func logonLocalService() (winapi.Token, error) {
account, _ := syscall.UTF16PtrFromString("LocalService") account, _ := syscall.UTF16PtrFromString("LocalService")
domainName, _ := syscall.UTF16PtrFromString("NT AUTHORITY") domainName, _ := syscall.UTF16PtrFromString("NT AUTHORITY")