Jump to content

MetaMSP

Members
  • Content Count

    36
  • Joined

  • Last visited

  • Days Won

    4

MetaMSP last won the day on May 13

MetaMSP had the most liked content!

Community Reputation

21 Excellent

1 Follower

My Information

  • Agent Count
    15000+

Converted

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. For later reference, here's another approach, modified from https://www.pdq.com/blog/modifying-the-registry-users-powershell/ $RegKey = 'Software\Microsoft\Office\16.0\Common\Identity' $RegValue ='EnableADAL' $PatternSID = 'S-1-5-21-\d+-\d+\-\d+\-\d+$' ##################################################################### $ProfileList = gp 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*' | Where-Object {$_.PSChildName -match $PatternSID} | Select @{name="SID";expression={$_.PSChildName}}, @{name="UserHive";expression={"$($_.ProfileImagePath)\ntuser.dat"}}, @{name="Username";expression={$_.ProfileImagePath -replace '^(.*[\\\/])', ''}} $LoadedHives = gci Registry::HKEY_USERS | ? {$_.PSChildname -match $PatternSID} | Select @{name="SID";expression={$_.PSChildName}} $UnloadedHives = Compare-Object $ProfileList.SID $LoadedHives.SID | Select @{name="SID";expression={$_.InputObject}}, UserHive, Username Foreach ($item in $ProfileList) { If ($item.SID -in $UnloadedHives.SID) { "Hive for SID " + $item.SID + " loading..." reg load HKU\$($Item.SID) $($Item.UserHive) | Out-Null } Else { "Hive for SID " + $item.SID + " already loaded!" } ##################################################################### "User: {0} `r`n" -f $($item.Username) | Write-Host If (Test-Path -Path registry::HKEY_USERS\$($Item.SID)\$($RegKey)) { Get-ItemProperty -Path registry::HKEY_USERS\$($Item.SID)\$($RegKey) | Foreach {"{0} {1}: {2} {3}" -f " ", $RegValue, $($_.$RegValue), "`r`n`r`n" | Write-Host} } Else { "Registry key not found!" } ##################################################################### IF ($item.SID -in $UnloadedHives.SID) { [gc]::Collect() reg unload HKU\$($Item.SID) | Out-Null } }
  2. It seems to be that deploying something to all HKEY_USERS is something that there is a lot of hubbub about but nothing directly lift-and-shiftable into Automate, except for DarrenWhite99's glorious REG-MULTI batch (!!), which can be found at https://www.mspgeek.com/topic/3528-how-would-i-run-a-script-once-user-logs-into-a-computer/?tab=comments#comment-21905 -- There has to be a better way to do this through something modern, like PowerShell, right? Nope. See sentence 1 - everything Google has found for me has been lacking, so here we go... The inherent challenge is this: Automate Agent runs as LOCAL SYSTEM, thus in the context of user SID S-1-5-18. Any commands run through Automate (that are not otherwise specified) run under the context of the Automate Agent, thus limiting the usefulness of any bare user profile command or applet. Using Group Policy Preferences (ref: https://www.grouppolicy.biz/2010/03/what-are-group-policy-preferences/) assumes the existence of Group Policy, thus assuming that an endpoint is a domain member, which is not applicable in all use cases nor is easily manageable via Automate. Some user profiles may never interactively log in to a given device, thus limiting the usefulness of Microsoft Active Setup (ref: https://en.wikipedia.org/wiki/Active_Setup). Let's start with dumping the subkeys from HKEY_USERS. PowerShell has a registry key provider (ref: https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/About/about_Registry_Provider)... surely we can use that to enumerate HKEY_USERS, right? So, the built-in registry key provider is only aware of HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER... you can't get there from here. However, PoSh allows us to extend its functionality by directly referencing .Net classes. Let me repeat that: we can reference and use native .Net Framework classes directly in PowerShell. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators calls this the static member operator: Well, now that's interesting, isn't it? Google-fu yields https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.registrykey as the .Net encapsulation of a registry key. Looking through the methods, we find the RegistryKey.OpenRemoteBaseKey(RegistryHive, String) method. All we need to do is pass it the desired hive (https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.registryhive) and the target computer name... let's see what happens! $targetComputer = $env:COMPUTERNAME; $availableProfiles = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::Users, $targetComputer).GetSubkeyNames(); $availableProfiles; *** Sanitized Output *** .DEFAULT S-1-5-19 S-1-5-20 S-1-5-21-ddddddddd-dddddddddd-dddddddddd-dddd S-1-5-21-ddddddddd-dddddddddd-dddddddddd-dddd_Classes S-1-5-18 Hey, now we're getting somewhere! That output looks an awful lot like RegEdit: Now let's add the ability to target certain subsets of HKU based off of the well-known SIDs (https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems) themselves, and also remove the _Classes subkeys from our target list (ref: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables) (ref: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_foreach) (ref: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_switch😞 [string]$targetComputer = $env:COMPUTERNAME; [bool]$targetDefaultUser = $true; [bool]$targetLocalSystem = $true; [bool]$targetLocalService = $true; [bool]$targetNetworkService = $true; [bool]$targetOtherSIDs = $true; [array]$profilesAvailable = $null; [array]$profilesTargeted = $null; $profilesAvailable = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::Users, $targetComputer).GetSubkeyNames(); foreach ($profile in $profilesAvailable) { switch ($profile) { '.DEFAULT' { if ($targetDefaultUser) n { $profilesTargeted += $profile; }; break; }; 'S-1-5-18' { if ($targetLocalSystem) { $profilesTargeted += $profile; }; break; }; 'S-1-5-19' { if ($targetLocalService) { $profilesTargeted += $profile; }; break; }; 'S-1-5-20' { if ($targetNetworkService) { $profilesTargeted += $profile; }; break; }; default { if ($targetOtherSIDs) { try { $candidateSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $profile; if ($candidateSID.IsAccountSid()) { $profilesTargeted += $profile; }; } catch {}; } } } } $profilesTargeted; *** Sanitized Output *** .DEFAULT S-1-5-19 S-1-5-20 S-1-5-21-ddddddddd-dddddddddd-dddddddddd-1001 S-1-5-18 Fantastic - we now have a list of HKU subkeys for processing! We're done, right? ... ... ... Of course not! Now we need to actually do something with those key paths. Let's change our concatenation statements to include the HKEY_USERS hive prefix, change a couple variable names for self-documentation's sake, and see how we can use the generated path to call out to a heavy lifter: [string]$targetComputer = $env:COMPUTERNAME; [string]$targetSubkey = '\Control Panel\International'; [bool]$targetDefaultUser = $true; [bool]$targetLocalSystem = $true; [bool]$targetLocalService = $true; [bool]$targetNetworkService = $true; [bool]$targetOtherSIDs = $true; [array]$profilesAvailable = $null; [string]$candidateProfile = $null; [array]$HKUsTargeted = $null; [string]$enumeratedHKUPath = $null; $profilesAvailable = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::Users, $targetComputer).GetSubkeyNames(); foreach ($candidateProfile in $profilesAvailable) { switch ($candidateProfile) { '.DEFAULT' { if ($targetDefaultUser) { $HKUsTargeted += 'HKEY_USERS\' + $candidateProfile; }; break; }; 'S-1-5-18' { if ($targetLocalSystem) { $HKUsTargeted += 'HKEY_USERS\' + $candidateProfile; }; break; }; 'S-1-5-19' { if ($targetLocalService) { $HKUsTargeted += 'HKEY_USERS\' + $candidateProfile; }; break; }; 'S-1-5-20' { if ($targetNetworkService) { $HKUsTargeted += 'HKEY_USERS\' + $candidateProfile; }; break; }; default { if ($targetOtherSIDs) { try { $candidateSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $candidateProfile; if ($candidateSID.IsAccountSid()) { $HKUsTargeted += 'HKEY_USERS\' + $candidateProfile; }; } catch {}; } } } } foreach ($enumeratedHKUPath in $HKUsTargeted) { REG QUERY ($enumeratedHKUPath+$targetSubkey) /v "LocaleName" | ? {$_.trim() -ne "" } } *** Sanitized Output *** HKEY_USERS\.DEFAULT\Control Panel\International LocaleName REG_SZ en-US HKEY_USERS\S-1-5-19\Control Panel\International LocaleName REG_SZ en-US HKEY_USERS\S-1-5-20\Control Panel\International LocaleName REG_SZ en-US HKEY_USERS\S-1-5-21-ddddddddd-dddddddddd-dddddddddd-1001\Control Panel\International LocaleName REG_SZ en-US HKEY_USERS\S-1-5-18\Control Panel\International LocaleName REG_SZ en-US Hopefully this saves others some time; I know it will save me some to have a template to refer back to each time I need to do something for all HKEY_CURRENT_USERS on a machine again Regards, Ryan
  3. Hosted suffers from the same gotchas that any shared infrastructure does - unless your environment is perfectly configured, it can end up being severely underpowered for the load upon it... and ConnectWise likes to charge for upsells. Access to the LTShare is hindered due to intermittently available WebDAV access that also needs to have a password reset every 30 days, as the password expires after 30 and no option to change that - however, as scripts tend to now be wrappers for github- or other cloud-hosted payloads, this has less of an effect than it once did. Going hosted also ties you to ConnectWise SLAs, which are a slight bit lacking lately with respect to server-downs. That said, the Cloud team has saved my bacon a few times as they do keep regular, automated backups and have good security-minded engineers feeding coal to the boilers - getting to them can be a challenge sometimes. Finally, data access - hosted means you get to sip from the silo of data; on-prem lets you hook turbopumps to the database if needed. Ultimately, IMHO if you have the resources (both hardware and wetware) to properly manage and maintain the infrastructure, on-prem gives you an Infinity Gauntlet to wield. Go hosted if you're a 1- to -5 man shop and need some time before you have the proper resources to dedicate to running your own in-house Mjolnir.
  4. MetaMSP

    nmap

    Portscan make benefit glorious nation of Kazakhstan?
  5. You'll want the amazing work from Darren White at: Good luck!
  6. Ping me in Slack about this, I'll be happy to help.
  7. You DID backup the table before modifying it, right? 🤣 I think you can bring them back by forcing a "Reload Solution Center Client" from the menu on the home screen of the Solution Center itself; that forces a rescan of all objects in the environment.
  8. Groups are exactly the preferred, best-practice tool to accomplish your desired results. Groups not only can apply monitors, but also schedule scripts, apply templates, and many other things. They are the central cog around which all other Automate modules rotate. The learning curve for Automate is steep and time-dependent. If you are under the gun, I highly suggest engaging an experienced consultant to get you up and running quickly. CW has consulting and training departments, and there are a number of independent consultants that can work with you (disclaimer: I am one). Good luck and welcome aboard - don't be afraid to dive in, the water's fine
  9. https://github.com/ManagedITStack/labtech_decode_scriptxml
  10. I had problems running the extension installer against anything older than Control v6.9.
  11. We warned ya lol - but good writeup! Hope everything you have to submit doesn't get closed as environmental though
  12. That's how important it is; it's worth repeating.
  13. Huntress Labs' recording of the CISA Awareness Briefing on Chinese Malicious Cyber Activity, which details a state-sponsored threat to MSPs specifically, and also makes mitigation recommendations: https://huntress-public.s3.amazonaws.com/DHS_China_Webinar.mp4
  14. Going to try and inject a bit more activity in this thread, although what I am doing is merely documenting what others have suggested so far: DO ensure that robots.txt is properly set on your Automate server. If you can Google your automate server's hostname and get a result, this is BROKEN and should be fixed ASAP. DON'T publish your Automate server's FQDN. This includes linking to it from your company's website. That's like a flashing signpost that says "THIS WAY TO HACK ME!" DON'T allow customers downstream access to your Automate server. This exponentially increases your attack surface area as every customer must then be as secure as you must. DO enable multifactor authentication / MFA / 2FA on All The Things. Seriously. Single factor (username/password) authentication is not sufficient in 2019. DON'T share credentials except in cases of absolute necessity (one login is available ONLY and you can't afford a single point of failure if that one person that knows it disappears). DO disable AND REMOVE and unused or unneeded plugins from your Automate environment. Each is another potential attack vector that you are eliminating by removing. DON'T expose port 3306 to your external network interface / the Internet. This is MySQL's default port and is yet another attack vector that you can easily eliminate. More to follow as it is suggested.
  15. A few suggestions from a self-education and awareness aspect: Have a look at https://www.sans.org/reading-room/whitepapers/compliance/compliance-primer-professionals-33538 - it's nearly 10 years old but is still a good overview of still-applicable regulations and standards. Better yet, register at https://www.sans.org [free] and get access to behind-the-authwall whitepapers similar (and often more recent) than the above. Head over to https://www.us-cert.gov/ncas/alerts and sign up to get regular emails or subscribe to the RSS feed to stay current with impactful vulnerabilities. Layer, layer, layer. No mitigation measure is 100% effective, and to quote @DarrenWhite99: That said, however, if we work together as a community to harden the platforms and tools we use as a group, we might just make Automate less of a target overall.
×
×
  • Create New...