I am working with PowerShell constrained endpoints. I have an endpoint that runs as a specific user as it needs to reach out to make calls to another service on another system. Virtual accounts and gMSAs will not work with this other service so it must be a regular user account.
I would like to be able to record the connection's client IP address in the logs. In the past I have used the following:
$script:EndpointClientIp = Get-WSManInstance Shell -Enumerate | Where-Object { $_.ProcessId -eq $script:EndpointProcessId } | Select-Object -ExpandProperty ClientIP
However, the above Get-WSManInstance command only works if the user is an admin. In these new JEA endpoints I am trying to avoid giving the run-as user admin privileges.
Is there a way to acquire this IP address without being an admin on the system? Perhaps there is a way to modify the WSMan permissions to allow this user account to access that portion of the WSMan config? If so, what else would it gain access to that I would want to consider? If not through the WSMan, is there another way to tie the IP address of an incoming connection to the process ID of the app allowing the connection (again, without admin privileges)?
This is a Windows Server 2019 box.
Related
I have a need to monitor what applications and process are using a given port for example a query of Active Directory for login by an application.
So what I want to do is:
Application sends login credentials to AD.
I want to see this request on the computer making the request, identify the the PID, record it with timestamp .. and if possible get the result of that query as successful or not.
Example of output:
ApplicationBahBlah_PID, 10:38:01:1234 , (Failed)
ApplicationBahBlah_PID, 10:42:21:9734 , (Success)
I have looked here Using /proc/<pid>, how can I identify a network port number's application?
But that is for Linux and also not C#
I want to write a function in a windows service application to remove a given computer name from Active Directory.
The Windows service is running on a machine which is domain-joined to the DC. Currently I have logged in to this machine with domain admin account.
The Windows service is running under the security context of "NT AUTHORITY/SYSTEM" and this should not be changed, as there shouldn't be any user interaction after installing the application, meaning that admin shouldn't enter their credentials in services.
When I run the application with my newly added code to delete the computer account, it doesn't work. However, when I change the logon info on the Windows Service and update that with domain admin credentials, it's able to successfully remove the computer account from AD.
Below is [a shortened version of] the function used to delete computer accounts.
Is there any way I can modify the code to be able to remove Computer Accounts using the same security context (NT AUTHORITY/SYSTEM)?
private void DeleteComputerAccount(string CompName, DirectoryEntry DirEntry)
{
try
{
//Delete computer account
DirectorySearcher search = new DirectorySearcher(DirEntry, "(name=" + CompName + ")");
SearchResult res = search.FindOne();
res.GetDirectoryEntry().DeleteTree();
}
catch (Exception)
{
Throw();
}
}
Where DeleteComputerAccount is called:
DirectoryEntry dirEntry = new DirectoryEntry("LDAP://domain.contoso.com");
string compName = "MyWorkstation01";
DeleteComputerAccount(compName, dirEntry);
When a service runs as local system, it will access the network (and thus AD) in the security context of the host's computer account. You can delegate the computer account (or better, a group which the computer is a member of) the ability to delete objects from AD. This link has accurate advice on how to complete that task - http://sigkillit.com/2013/06/12/delegate-adddelete-computer-objects-in-ad/
While not what you asked, a couple other things stand out to me:
You're not filtering your search very well. You might get something other than what you want back. I'd suggest a filter like this instead: (&(objectClass=computer)(sAMAccountName=<PCName>$))
Local system is a lot of access. Could you run this as network service instead?
I manage a terminal server in our production environment that serves many different machines that connect under the same generic ID. Using the Cassia library, I am easily able to capture everything I need to know about the remote connections programmatically, but I am as of yet stumped as to how I need to go about applying the printer change to that user. My distinguishing criteria will be the name of the PC that s/he is connecting from. There are 4 machines in particular that I am interested in, and the rest will be ignored.
In a nutshell, I need to capture when these particular PCs log on, and set a default printer for them for the remainder of their session.
At a local level, it is no challenge to change a default printer programmatically. I seem to be struggling with changing the default printer for a user's session on a remote terminal server from another utility server.
The easiest way to do this is create a script that is set to run on login and set the printer via a WMI to Win32_Printer.SetDefaultPrinter.
Here is a example of how to do it in a simple 3 line powershell script
$Printers = Get-WmiObject -Class Win32_Printer
$Printer = $Printers | Where{$_.Name -eq 'Name Of Printer To Use'}
$Printer.SetDefaultPrinter()
Save that in a .ps1 file and set the terminal server policies to run the script on login.
If you don't want to use a fixed name in the script it is easily modifiable to query some other external source, just replace 'Name Of Printer To Use' with a variable that holds the name you want to connect to.
The SetDefaultPrinter method is supported on Windows Vista/Server 2003 and up.
This sets the default printer for the current user on a Terminal server.
$strPrinter = "\\ITPG-FP01\Kyocera A4 ZW"
$printer = Get-WmiObject -Class Win32_Printer | Where-Object { $_.Name -eq $strPrinter }
if ($printer) {
$deviceId = $printer.DeviceID
$network = New-Object -ComObject WScript.Network
$network.SetDefaultPrinter($deviceId)
}
I want to check some Windows services status on different remote servers like this:
ServiceController sc = new ServiceController("MyWindowsService", "COMPUTER_NAME");
var status = sc.Status
But I don't (and can't) have Administrator privileges on those servers.
What right should I be asking for to check the status ?
I don't wanna be able to restart them either, I need Read access only,
The application isn't running on the same machine.
Non-admin users can connect to the Service Control Manager remotely, provided they have the "Access this computer from the network" user right. By default this right is granted to all users.
Access to individual services is controlled by the ACL on each service. You must already know the service name, because a non-admin user cannot enumerate services remotely.
The default security descriptor for a service is as follows:
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
You can determine the security descriptor for a service using the sc sdshow command. The string format is described in Security Descriptor Definition Language on MSDN.
OK, let's expand out that security descriptor string. This is a bit tricky because the mapping between the SDDL permissions and equivalent security manager permissions does not appear to be well documented in MSDN or in the SDK headers; luckily, Wayne Martin has already done the heavy lifting for us and posted the results in the blog entry Service Control Manager Security for non-admins.
D: - this part is the DACL, the permissions on the service.
Since all the entries are allow entries, the order isn't significant; I'll list them from least to most privilege for convenience.
(A;;CCLCSWLOCRRC;;;IU) - allow the interactive user the following rights:
CC - SERVICE_QUERY_CONFIG (the right to query the service configuration)
LC - SERVICE_QUERY_STATUS (the right to query the service status)
SW - SERVICE_ENUMERATE_DEPENDENTS (the right to see service dependencies)
LO - SERVICE_INTERROGATE (the right to send SERVICE_CONTROL_INTERROGATE)
CR - SERVICE_USER_DEFINED_CONTROL (the right to send a user defined control)
RC - READ_CONTROL (the right to see the permissions)
(A;;CCLCSWLOCRRC;;;SU) - allow services the following rights:
same as for the interactive user
(A;;CCLCSWRPWPDTLOCRRC;;;SY) - allow local system the following rights:
same as for the interactive user, plus:
RP - SERVICE_START (the right to start the service)
WP - SERVICE_STOP (the right to stop the service)
DT - SERVICE_PAUSE_CONTINUE (the right to send pause and continue requests)
(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) - allow the Administrators group:
same as for local system, plus:
DC - SERVICE_CHANGE_CONFIG (the right to reconfigure the service)
SD - DELETE (the right to delete the service)
WD - WRITE_DAC (permission to change the permissions)
WO - WRITE_OWNER (permission to take ownership)
The second part of the security descriptor string (S:(...)) is the SACL, which controls what auditing is done. We're not interested in that at the moment.
You will notice that there are no allow permissions applicable to non-administrative remote users. To give remote access to a particular user, add an allow ACE for that user with the same permissions as the interactive user.
If this is your own service, you can change the permissions when the service is installed using the SetServiceObjectSecurity function. You could also write a program using this function to change the permissions on an existing service.
Alternatively, you can use sc sdset at the command line to set the permissions for an existing service based on a SDDL string. You will first need to look up the SID string for the user; in a domain, you can do this using Active Directory Users and Computers. The SID string can be seen via the Attribute Editor tab, in the objectSid attribute. (Unfortunately you can't copy and paste that way. Suggestions for more convenient methods of looking up a user's SID are welcomed.)
If the SID string were S-1-5-21-131085535662-8349591032-725385543-5981, for example, the command line would be
sc sdset myservice D:(A;;CCLCSWLOCRRC;;;S-1-5-21-131085535662-8349591032-725385543-5981)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)
(You do not need to specify the SACL; if absent, the existing SACL will be retained.)
I need to know how to get the name and domain of the primary user of a computer, remotely. I define the primary user preferably as the user logged on most times, or longest time over a period. Alternatively, if this is impossible, as the user currently/last logged on.
Currently, i scan an Active Directoy for all computer objects in an OU. I then loop though them, and try to get the name of the user using WMI.
I look in Win32_ComputerSystem to see if UserName returns a value. If this is not the case, i look in Win32_LogonSession and get the username for all LogonTypes that equal 2 or 10. If this returns none, or multiple values, i discard the result and look in Win32_Process for all non-system processes and define the primary user as the user with most processes running.
There are several problems with my approach:
Win32_ComputerSystem - UserName is often null.
Win32_LogonSession often return multiple or no values. There can be only 1 primary user.
Looking in Win32_Process is kinda ridiculous, since this will only return me the user with most processes, most likely not the primary user.
If no user is currently logged on, looking in Win32_Process returns no value and none of the 3 steps might return a value.
My 3 approaches might get me the current user. Does anyone know of a way to get the primary user? Or at least a better way to get the current. Not necessarily using WMI.
Thanks
If you have administrator privileges on the remote computer and sharing access
you can use Computer Management and select to
connect to other computer and see what users and groups are on that computer.
Or you can use TS Remote Administration or Remote Desktop if the remote computer has that capability.
Use psexec.exe (www.sysinternals.com) to run commands on a remote pc:
psexec \\pc1 net user | find /i "Steve"
psexec \\pc1 c:\tool\psloggedon | find /i "Steve"
1) Find if John Black has an account on PC1.
2) Find if he is currently logged on.
Use psloggedon.exe that uis is another SysInternals tool.
Check this also: http://www.wisesoft.co.uk/scripts/vbscript_display_username_of_user_on_a_remote_computer.aspx
Also if you want to find the User Name of the currently logged user on a remote computer using the remote computer IP then Go to the command line an type nbtstat -A <IP of remote computer> This will return all of the NetBIOS names registered on the computer, one of which is the username.