Manage User Rights with Group Policy

Group Policy is nothing but flexible and extremely powerful when it comes to both configuration management and installation of software.  In addition, Group Policy is one of your best tools for securing your endpoints.  You can manage anything and everything from Firewall rules, account privileges, application white-listing, etc.  You can also manage user rights as well.

Computers and Users in your environment have a lot of rights, by default, that they don’t need.  Using Group Policy, we can manage these privileges and start to lock-down our environments without making it burdensome for our end users.  One such privilege is the ability to Log on Locally.

Use Group Policy to define accounts or services that are allowed to log on locally
Use Group Policy to define accounts or services that are allowed to log on locally

By default, anyone that has the correct username and password can log on locally to a system, but do you really need to log on to a server in your datacenter using a local account?  Some of you might, in this case you should explicitly allow certain accounts to have this privilege.  Instead of using the default setting of “if you have a local account you can log in to this system”, but instead restrict this at a global level.  This ensures that your systems are properly managed and no one was being lazy or malicious by creating a one-time account they forgot about.

Use Group Policy to define accounts or services that are not allowed to log on locally
Use Group Policy to define accounts or services that are not allowed to log on locally

Let’s take the opposite approach.  Do you have systems on your network(s) that should only be logged on by specific individuals, accounts, services, etc?  Instead of relying on plainly on the security of your username and password, we should restrict this right to the specific accounts, computers, users, etc. that should have access. Only then, if they have the correct credentials are they allowed to login over the network.

Use Group Policy to allow access to computers from the network
Use Group Policy to allow access to computers from the network

By restricting this access to only the certain machines or users within a specific group, someone who has either found a set of credentials or has somehow infiltrated your network will only be able authorize a set of systems because others have been restricted.

Another example is to manage who has access to Log on Remote Desktop Services permissions.  Does everyone need to access a set of systems (this goes for both workstations and servers)?  I bet not, so why just enable RDP (Remote Desktop Protocol) for anyone who has valid credentials?  We should tightly restrict who has access to our systems, especially when using RDP.

Use Group Policy to allow or deny access to Remote Desktop Services
Use Group Policy to allow or deny access to Remote Desktop Services

For all situations regarding user rights and access to systems, we should always restrict access as much as possible.  The key is to create these restrictions without being burdensome for your end-users.  There is a fine line, but we should always attempt to be reasonable with this approach.  Some systems just shouldn’t be accessed over RDP or locally, this will be up to the discretion of your organizations risk.  Providing clear guidance and allowing your management to either enable these restrictions or to accept the risk is all that we as IT professionals can do.

 

Advertisements

Cattle vs. Unicorns

When organizations begin to think of users as cattle instead of unicorns we begin to remove their pride for, and their responsibility to, an organization.  When responsibility for their actions are only out of necessity or self-preservation then you have lost the battle, but not necessarily the war.  You can change people’s mindset but it just may take a little more effort.

I believe that people are the answer to most security problems.  Empowering people by making them part of your security team enhances their awareness and fosters a sense of shared responsibility.  Organizations that encourage (and consistently preach) a shared responsibility will have continual communication and awareness of their responsibilities in order to protect themselves and their fellow employees.  Those organizations that treat employee’s as another expense (or cattle) will push their employees away which allows them to disassociate themselves from their responsibility.  You have now created more resistance, and ultimately your security team has another force fighting against them – and not with them.

Do you really want to be another statistic?

Cattle organizations encourage people to use their creativity in an unproductive way.  The results include employees who attempt to bypass your security measures, instead of identifying and reporting potential incidents.  Most organizations have warmed up to the idea of phishing simulations (I hope your organization has) to provide an immersive and lifelike training experience.  Some cattle organizations have gone as far as to let go of employees that fail these tests.  By taking this approach, you have now forced your employees to either report everything, report nothing, or use creative ways to fight against the security team instead of for it.  Employees in a cattle organization will begin to use their creativity to bypass their training by creating Outlook rules to detect these simulations, or completely ignoring (caring) about a new face walking through the halls.  The first question that should come to your mind is, why are my employees doing this.  The second is identifying and preventing these (negative) creative ideas within your environment.

Are you a Batman Unicorn?

Unicorns are majestic and beautiful creatures.  Organizations and security teams that believe, and routinely encourage, their employees have equal (shared) responsibility for the protection of their organization, their data, and ultimately their job, will obtain an army of security agents to constantly watch for suspicious activity both digitally and physically.  Our security teams now have more actionable intelligence to do their jobs successfully.

Just imagine, if everyone (Finance, HR, System Administrators, Shipping, etc.) in your organization is encouraged to protect themselves, their fellow employees, and their organization from suspicious email, people, system configurations, and so on.  If you have worked in security for any amount of time you know that the best information about problems or incidents comes from employees.  Unicorn organizations create a culture of responsibility – a stake-hold of sorts – which enables a form of peer pressure to report and communicate any suspicious activity.  I don’t know about you, but I would rather believe in unicorns than step in cow shit.

Understanding Group Policy order

Group Policy order can be confusing. To understand how exactly Windows applies one GPO (Group Policy Object) versus another, you can use the “LSD OU” rule.

You should always ask yourself two questions when dealing with Group Policy:

  1. Where are you (local, site, domain, or organizational unit)?
  2. What are you (computer or user)?

Read More

PowerShell Phishing Response Toolkit (PPRT)

Yesterday I gave a talk at ShowMeCon in St. Louis regarding PPRT.  I also gave this talk at CircleCityCon, but had some technical issues. 🙂  I wanted to write this quick post to share out my PowerPoint Slides from this presentation.  If you have any questions about PPRT, please reach out via this blog or create an issue on my GitHub page: https://github.com/MSAdministrator/PPRT—PowerShell-Phishing-Response-Toolkit

Enjoy!

Slides: PowerShell Phishing Response Toolkit

PowerShell & Qualys: Get Asset Group Info – Part 2

Today I decided to write another post regarding PowerShell and Qualys Vulnerability Management API.  This post will focus on gathering information about your enrolled Asset Groups.   You can find the complete script on GitHub: https://github.com/MSAdministrator/POSH-Guard/blob/master/Get-QualysAssetGroupInformation

We start of by opening up PowerShell ISE and using our handy “Snippet” shortcut:

PowerShell_ISE_CTRL_+_J

We select the “Cmdlet (Advanced function) – complete” option in the “Snippet” context menu.  Once we have our advanced function template, we then proceed by entering a name for our Qualys Asset Group function.

Since we will be gathering some additional information about our Asset Groups, I am going to name my function:


function Get-QualysAssetGroupInformation

Next, we will start by filling out our “Help” info.  At this point, a lot of people skip this step; I HIGHLY recommend that you do not.  It will help you and anyone else viewing your code, understand what your intention was when writing this function.

Next, we start by looking at our advanced functions template within the body of this function.  The first thing you will see is some default parameters for [CmdletBinding].  With my function, I’m going to weed these parameters down a bit, as they are not really needed.  Your function should look something like this when complete:

function Get-QualysAssetGroupInformation
{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  HelpUri = 'https://raw.githubusercontent.com/MSAdministrator/POSH-Guard/master/Get-QualysAssetGroupInformation',
                  ConfirmImpact='Medium')]
    [Alias()]
    Param
    (
        # Param1 help description
        [parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage="Please provide a credential obejct")]
                   [ValidateNotNullOrEmpty()]
                   [System.Management.Automation.CredentialAttribute()]$credential
        ) 

    Begin
    {
    }
    Process
    {
        
    }
    End
    {
    }
}

After we have the base of this function setup and ready to go, we will start off by adding some code into our Begin block.  Remember, the Begin block will always run once for every call to the function.

	$results = @()
	$assetGroupInfo = @()
        [xml]$assetGroupInfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/asset_group_list.php" -Credential $credential

Here I am setting my $assetGroupInfo and a $results variable as empty array’s/hash-table’s. Next, I’m casting my $assetGroupInfo variable as an XML object. This ensures that we receive XML from Invoke-RestMethod Cmdlet.

If we want to make sure that any errors are caught, we should add a Try/Catch block to our Invoke-RestMethod call. Your code should look like this:

 Begin
    {
        $results = @()
        $assetGroupInfo = @()

        Try
        {
            [xml]$assetGroupInfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/asset_group_list.php" -Credential $credential
        }
        Catch
        {
            Write-Debug "Error using Invoke-RestMethod: $_"
        }
    }

Now we move to the Process block. This is where we will be parsing our data into our objects. As I mentioned above, we are wanting to gather all our Asset Groups Titles, their assigned IP Addresses, their role, and the users login ID. To do this, we must loop through each item, or branch returned by our query above. Each $item can be considered as an Asset Group. Additionally, we need to loop through each of the users assigned to that Asset Group.

Once we have that data, we want to create a Custom PSObject to hold all of this data. Your code should look like this:

Process
{
	foreach ($item in $assetGroupInfo.SelectNodes("/ASSET_GROUP_LIST/ASSET_GROUP"))
	{
		for ($u=0; $u -lt $($item.ASSIGNED_USERS.ASSIGNED_USER.LOGIN).count;$u++)
		{
			$tempAssetGroupInfo = @()
		                            
                                $props = @{
				userlogin=$($item.ASSIGNED_USERS.ASSIGNED_USER[$u].LOGIN.InnerText)
				userrole=$($item.ASSIGNED_USERS.ASSIGNED_USER[$u].ROLE.InnerText)
                                           assetgrouptitle=$($item.TITLE.InnerText)
                                           ip=$($item.SCANIPS.IP)
                                          }
		
			$tempAssetGroupInfo = New-Object PSObject -Property $props
		        
                                $results += $tempAssetGroupInfo
		}
	}
}

Now, we can either simply put the following line in our End block:

return $results

But, I actually like it to be saved into an XML file. This means that I can use this data with other functions without having to call Qualys again. To be quite frank, as you may know, Qualys is not the fastest website/service out there. Don’t get me wrong, the scanning engines are fast, but their database(s) – not so much.

To return both the object and export the results to an XML, we can just add this one line of code:

Export-Clixml -Path "$env:USERPROFILE\Desktop\QualysData\assetgroupinfo.xml" -InputObject $results

That’s it. We now have a function that can return some details about our Asset Groups within Qualys. Next time, I will focus on creating a function that gathers our enrolled IP Addresses, split’s them into a single list.

Hint: Qualys loves IP ranges (192.168.0.1-192.168.0.123) and their API calls return it the same way. 🙂