[Reference] [1]: Create process as different user with Java and Kerberos
As mentioned in the code, we need to pass hToken in the below snippets:
Advapi32.INSTANCE.ImpersonateLoggedOnUser(/* provide the security context token */)
In the below code primaryToken is just a empty object,
// create primary token by duplicating impersonation token
WinNT.HANDLEByReference primaryToken = new WinNT.HANDLEByReference();
boolean createProcessResult = Advapi32.INSTANCE.CreateProcessAsUser(
primaryToken.getValue(), /* hToken */
null, /* lpApplicationName */
command, /* lpCommandLine */
null, /* lpProcessAttributes */
null, /* lpThreadAttributes */
false, /* bInheritHandles */
WinNT.CREATE_NEW_CONSOLE | WinNT.CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
environment, /* lpEnvironment */
processDirectory, /* lpCurrentDirectory */
startupInfo, /* lpStartupInfo */
processInfo); /* lpProcessInformation */
These referenced code is stated as working solution, but mostly it has custom empty objects and other than getting token bytes from authorization Header. We haven't done anything with windowsIdentity object from security context.
Kindly anyone let me know how to get the hToken from the security context.
Enable SE_INCREASE_QUOTA_NAME Privilege -- Returns true
private void adjustProcessPrivilege() {
HANDLEByReference hToken = new HANDLEByReference();
WinNT.LUID luid = new WinNT.LUID();
Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(),
WinNT.TOKEN_ADJUST_PRIVILEGES, hToken);
Advapi32.INSTANCE.LookupPrivilegeValue("", WinNT.SE_INCREASE_QUOTA_NAME, luid);
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(1);
tp.Privileges[0] = new LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
boolean isPrivilegeAdjusted = Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tp, tp.size(), null,
new IntByReference());
System.out.println(isPrivilegeAdjusted); //Returns True
}
CreateProcessAsUserA -- Impersonation has failed
@GetMapping("createProcessAsUserNew")
public String createProcessAsUserNew() {
adjustProcessPrivilege();
HANDLEByReference phToken = new HANDLEByReference();
HANDLE processHandle = null;
HANDLE threadHandle = null;
Win32Exception err = null;
HANDLE hToken = null;
try {
// open thread or process token
threadHandle = Kernel32.INSTANCE.GetCurrentThread();
if (!Advapi32.INSTANCE.OpenThreadToken(threadHandle, WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_QUERY | WinNT.TOKEN_ASSIGN_PRIMARY, false, phToken)) {
int rc = Kernel32.INSTANCE.GetLastError();
if (rc != W32Errors.ERROR_NO_TOKEN) {
throw new Win32Exception(rc);
}
processHandle = Kernel32.INSTANCE.GetCurrentProcess();
if (!Advapi32.INSTANCE.OpenProcessToken(processHandle, WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_QUERY | WinNT.TOKEN_ASSIGN_PRIMARY, phToken)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}
}
catch (Win32Exception e) {
err = e;
throw err;
} finally {
hToken = phToken.getValue();
if (!WinBase.INVALID_HANDLE_VALUE.equals(hToken)) {
try {
Kernel32Util.closeHandle(hToken);
} catch (Win32Exception e) {
if (err == null) {
err = e;
} else {
err.addSuppressed(e);
}
}
}
if (err != null) {
throw err;
}
}
boolean isUserImpersonated = Advapi32.INSTANCE.ImpersonateLoggedOnUser(hToken); //This returns false
System.out.printf("User Impersonated:",isUserImpersonated);
// create primary token by duplicating impersonation token
WinNT.HANDLEByReference impersonateUserToken = new WinNT.HANDLEByReference();
boolean primaryTokenResult = Advapi32.INSTANCE.DuplicateTokenEx(
threadHandle, /* hExistingToken */
WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_QUERY | WinNT.TOKEN_ASSIGN_PRIMARY, /* dwDesiredAccess */
null, /* lpTokenAttributes */
WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, /* ImpersonationLevel */
WinNT.TOKEN_TYPE.TokenPrimary, /* TokenType */
impersonateUserToken);
WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
WinBase.PROCESS_INFORMATION processInfo = new WinBase.PROCESS_INFORMATION();
boolean createProcessResult = Advapi32.INSTANCE.CreateProcessAsUser(
impersonateUserToken.getValue(), /* hToken */
"C:\\Windows\\notepad.exe", /* lpApplicationName */
null, /* lpCommandLine */
null, /* lpProcessAttributes */
null, /* lpThreadAttributes */
false, /* j */
WinNT.CREATE_NEW_CONSOLE | WinNT.CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
null, /* lpEnvironment */
null, /* lpCurrentDirectory */
startupInfo, /* lpStartupInfo */
processInfo); /* lpProcessInformation */
System.out.println(createProcessResult);
return String.format("New Process created ",createProcessResult);
}
The API Documentation for
CreateProcessAsUsertells you how to get the token (bold emphasis at the end is mine):Given your focus on impersonating a client,
DuplicateTokenExlooks like precisely what you need. This is done in the post to which you linked but you only quoted the first line and skipped the next code which populates that value:As you indicate in your edit, you need to add the
SE_INCREASE_QUOTA_NAMEprivilege. However, you are not adequately checking whether that privilege was assigned. The return value fromAdjustTokenPrivilegesis not sufficient: