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. 🙂

PowerShell & Qualys: Authentication – Part 1

I always mean to post more on my blog, but as life gets in the way and work keeps me busy, I always seem to push it to the back-burner. This time, I am hoping to make it stick as a regular routine.

To kick off my new-found motivation to blog more, I am starting a series of posts surrounding PowerShell and Qualys Vulnerability Management API.

To start this off, first I’m going to share some my basic steps with regards to authentication to Qualys VM API v1. This is really basic, but I see a lot of posts around that seem to try to create some “advanced” way of authenticating to Qualys API. You don’t need to do anything fancy.

As with all scripts/modules/etc., I suggest that you get into the habit of using PowerShell ISE and it’s many great keyboard shortcuts to help you get on the right path.

First, open PowerShell ISE and enter the following keyboard shortcut:


CRT + J

Once the “Show Snippets” context menu shows up, select “Advanced Function (Complete)”. I always recommend that you start with a ‘Complete’ Advanced FUnction. This makes your script look much better, and it’s all around a good idea.

Once you have the Snippet loaded, I would begin by coming up with a name; following Microsoft’s approved Verb-Noun naming convention:

Approved Verbs – https://technet.microsoft.com/en-us/library/ms714428(v=vs.85).aspx
Get-Verb Documentation: https://technet.microsoft.com/en-us/library/hh852690.aspx

Next, start adding a “Credential” object parameter to your code. Qualys uses “Basic” authentication, so using Invoke-RestMethod in combination with a “Credential” object is extremely easy.

To capture your credentials into a Credential Object used by Invoke-RestMethod, you simply need the following before you run your function or within your function:


$cred = Get-Credential

Enter your Qualys API username and password.

*NOTE: Do not try to save this credential object to disk or to a file. It’s NOT hard to enter your username and password every time you connect to Qualys API.

Next, you should have the following code in your function:


[xml]$hostinfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/get_host_info.php?host_netbios=$netbios&general_info=1"-Credential $credential

I recommend that your $credential object should be passed into your function as a parameter. This will help when you move into more advanced interaction and multiple calls to Qualys VM API.

Now that you have your XML (Type cast) $hostinfo variable, you can then parse the data very, very, very easily.

In my next post I will share with you how to do this to gather some very important data for any Qualys Vulnerability Management Administrator.

If you have any questions, then please leave a comment.


function Test-QualysAuthentication ()
{

[cmdletbinding()]
param (
[parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
HelpMessage="Please provide a credential obejct")]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.CredentialAttribute()]$credential
)

<# .SYNOPSIS This function tests your Qualys VM API Credentials .PARAMETER Credential Specifices a set of credentials used to query the QualysGuard API .EXAMPLE C:\PS> $cred = Get-Credential
C:\PS> Test-QualysAuthentication -credential $cred

#>

[xml]$hostinfo = Invoke-RestMethod -Uri "https://qualysapi.qualys.com/msp/get_host_info.php?host_netbios=$netbios&general_info=1" -Credential $credential

return $hostinfo
}

QualysGuard: Decentralized IT & How to organize your Assets

I work for a University with a decentralized IT department: each college, division, department, etc maintains their users.  As a security department who maintains QualysGuard, we were wanting each department to scan their own assets and re-mediate all vulnerabilities found in these scans based on the following policy:

  • Level 4 and Level 5 vulnerabilities must be re-mediated within 15 days
  • Level 3 vulnerabilities must be re-mediated within 30 days
  • Level 2 vulnerabilities must be re-mediated within the next semesters
  • Level 1 vulnerabilities must be re-mediated whenever possible

WIth this policy in mind, we began rolling out our QualysGuard service using the following methods.  We would create Asset Groups for each group of servers that belong to one of the following: a department, college, division, application group, etc.  Each Asset Group would be additionally subdivided into each network core.  For example, if you have a Athletics department, they may have assets in all the different network cores (Faculty/Staff Network, Data Center, DMZ, Residential Network, etc.).  Because each of these departments will have multiple assets in multiple network cores, we relied heavily on our naming conventions.  Our naming convention is the following for Asset Groups: CAMPUS DEPT NETWORK Assets (SCANNER NAME) -> CAMPUS Athletics DC Assets (DC_SCANNER)

When dealing with QualysGuard in a decentralized IT infrastructure, your naming convention will save you!

Once you have a group of Assets in their respective Asset Groups, then we add them to their own Business Unit.  Remember that you must a Unit Manager (at least 1), and you may any number of Scanner and Reader roles.  You can additionally assign a role to specific Asset Groups within the Business Unit (or another Business Unit).

Please see the following graphic, which outlines what was previously stated:

2015-01-11 14_12_21-Business Unit Hierarchy

Remember, when you are rolling out your QualysGuard VM infrastructure you will want to plan (in great detail) your roll-out.  Creating a roll-out plan that relies on system owners to take responsibility for their own systems, instead of System Administrators and/or Security Analyst is the idea goal.  By doing this, it highlights the importance for security in your organization as well as giving everyone insight into the security posture of their organization.  Hopefully they will see QualysGuard as a tool of transparency that helps strengthen your organization vulnerability management life cycle management.

Windows Security: Patch Management Strategy

Recently, at work, I nominated myself to begin a “Windows Security” course for IT Professionals that I work with.  Being a former IT Pro, and now part of our security department as an Incident Responder, I thought I would create a course surrounding security.  So, i’m going to use my blog to layout my plans for this “Windows Security” course – which will hopefully be useful for others as well.

My first post is going to focus on “Patch Management”.  Many IT Pro’s, SysAdmins, etc. deploy assets (systems, applications, services, etc.) and join them to their domain, all while not being patched.  Having assets that are not fully patched is a major security risk for your organization.  Imagine, you have server that’s not fully patched you’ve deployed (or someone else) on a Friday afternoon and then you become busy because of another incident.  Monday comes along and your slammed again – once again you forget about this server for some period of time.  We’ve all seen this happen or know of someone who does this.

In this situation, your Patch Management strategy is of the utmost importance.  Having this server on your network is a major security risk, but not if you have a fully patched image.  Whether you are using a fat, thin, zero-touch imaging solution, you need to make sure that your images are up to date and ready to deploy.

Using Microsoft Deployment Toolkit or SCCM (System Center Configuration Manager), can solve this problem with little to no interaction needed.  I’m personally a fan of MDT (check out my walk-through) in an large, decentralized, environment.  Utilizing MDT for your servers is extremely easy and gives your “System Administrators” a flexible and reliable solution for the many configurations your environment demands.

You can also use SCCM, if your environment can justify the cost, to automate this process to a complete “Zero-Touch” solution.  My environment does not allow this because we are not a centralized IT department with a standard “image” across all departments.  Setting up SCCM is cumbersome unless you have full access to the SCCM “site server(s)”.  Never-the-less, SCCM is extremely powerful and can manage all systems (servers, workstations, etc.) in an automated way – but again, it’s pricey.

If you choose to solely use a “fat” image and decide to just use a WinPE disc or even Windows Deployment Servers (WDS), just make sure that you update your image every month or at-least quarterly – and do not, I repeat, do not, join it to your domain/network without it being fully patched.

Deploying Operating Systems is a fairly complicated affair, and we need to utilize the tools available to us – but don’t forget about our third party applications as well.  In my environment, most malware outbreaks are caused by either two types of incidents:

  • Third party products are out of date and malware droppers are taking advantage (either in advertising sites or plan malicious sites) of these exploits.
  • Phishing attempts

Maintaining our applications is also a crucial step that cannot be overlooked.  Again, you can utilize SCCM for this process (if you can justify it) or you can use additional third party products (Ninite, Secunia PSI, WSUS, etc.).  No matter what you use, you need to make sure that all of your systems are updated, and be able to report on this.

Having the ability to view your network/systems is a crucial part of a proper “Patch Management” strategy, so you need to have continual scanning on your network (with the ability to report on systems).  You can either use Nessus, SCCM, QualysGuard, etc., but no matter what, you need this data.  Again, utilize the tools you have – LEARN POWERSHELL!  PowerShell can give you crazy amounts of data – use it, love it, live it.

The last part of this discussion is about anti-virus/malware software.  Depending on the solution, your organization is using, you should be able to alert on infected systems.  If you’re using Microsoft ForeFront Endpoint Protection, then well you may not be able to (besides using PowerShell to gather the log files). It would be preferred if you have a anti-virus/malware solution that has an administrative console or the ability to run reports.

If you don’t have a A/V solution that has this capability, then you need to rely on your Windows Logs and parse them with either Splunk or LogStash or something similar.  Utilizing a system that can correlate this data for you is of immense help – especially if this repository is the same repository as your IDS/IPS logs, Windows Event Logs, etc.

Having the ability to fully patch a system before it is deployed is crucial in every environment.  One piece of malware (with a C2) can scan your entire network for a new server and then as soon as a “SysAdmin” logs in…… well, the game is over – time to rebuild.

Qualys Guard: Qualys in a University Environment

The University I work for has began using Qualys for our Enterprise Vulnerability Scanning and so far it’s been well received.  The problem is that every “College/School” maintains their own systems thus we are decentralized, which makes maintaining Reports/Scans/Maps/etc. very difficult.

Because I have not found many posts/articles focused on a decentralized environment I decided I would explain the way we are approaching this.  This is all a work in progress – if you have any questions or ideas, please get a hold of me.:)

So our basic process for setting up Qualys goes like this (overview):

  • Gather IPs to add to our Qualys subscription (we are only worrying about servers at this time)
  • Create Asset Groups (Naming Conventions: CAMPUS DEPT VLAN QUALYSCANNER#)
  • Create User that will be the Unit Manager of a Business Unit
  • Create Business Unit while creating user
  • Assign Asset Group to Business Unit
  • Setup a Scheduled Scan
  • Have the Unit Manager create scheduled reports based on Global Templates that we’ve create

Again, this is a high level overview but this is our basic process.  In future posts I will try to break down Qualys in more detail and how to manage a large diverse group of systems across a decentralized campus.