Aug 6, 2012 6:44:00 AM
Using System Center Orchestrator to Automate Security Tasks

With System Center Configuration Manager 2012, customers have the ability to use Endpoint Protection capabilities to provide anti-malware services and security to servers and clients. However, to reduce administrator touch points and mistakes, we can use the flexibility of System Center Orchestrator to augment and automate standard security processes. In this post, I will demonstrate how to create a runbook to automate the triggering of a full Endpoint Protection malwarescan in response to a malware detected alert within Configuration Manager.

In a normal operations scenario, an administrator or security specialist would receive and email alert from Configuration Manager indicating an alert from a client, and would then proceed to launch the Configuration Manager console, and initiate a full scan, as shown below:

This, of course, is dependent on the assigned person(s) monitoring their email, having access to the console, and generally caring at all, not to mention lost productivity cycles. And really, wouldn’t it be better to just automate the whole process and be done with it only alerting someone if something fails?

Configuring the Workflow

The first activity that we need to do is to map out the workflow (all code and related items will be included below).

  1. First item is to determine how to identify clients that have had a recent malware event. For our discussion, let’s assume this will run hourly, and we will check to see what happened in the last hour. The easiest way is to leverage the ConfigMgr database view named v_EP_LastMalware. Here is a full query:

[sourcecode language="sql"]
SELECT [MachineID], [LastMessageTime], [DetectionTime], [ActionTime], [DetectionSource], [PendingActions], [CleaningAction],[ExecutionStatus], [ActionSuccess], [ErrorCode]

FROM [CM_XXX].[dbo].[vEP_LastMalware]

Where DetectionTime > DATEADD(hour, -1, getutcdate())
[/sourcecode]

You will also notice that the query leverages the getutcdate. This is because the messages are timestamped in UTC time for ConfigMgr. For our benefit, we will use the following query to just return the MachineID:

[sourcecode language="sql"]
SELECT [MachineID]
FROM [CM_CS1].[dbo].[vEP_LastMalware]
Where DetectionTime > DATEADD(hour, -1, getutcdate())

[/sourcecode]

The returned MachineID is the ConfigMgr client ID that we will use to set the policy.

  1. The next activity is to map the MachineID to a computer name. You can combine the two queries, but I chose to separate them out for logging purposes, and ease of since we will need both the machineID and computer name. Here is the query for mapping the ID to the name:

[sourcecode language="sql"]
SELECT [Netbios_Name0]
FROM [CM_CS1].[dbo].[vSMS_R_System]
Where ItemKey = <em>InsertKeyHere.</em>
[/sourcecode]

  1. The third activity is to ping the computer name, and based on the results of that ping, either connect to the computer to manually initiate a full scan (using MPCMDRUN.exe) or to set a client policy.
  2. For the MPCMDRUN, we will simply start a process on the target computer. For unreachable systems, we will connect to WMI and invoke a method. I have created a custom vb.net console application to do this for me as well.
  3. And then we will do some email notifications, SCOM alerts, text file logging, etc., based on what we need as well.

And on to System Center Orchestrator!

With the workflow mapped out, here are the specifics:

  1. Query Database for EP Records: This is where the workflow will start. Add the Query Database activity, and using the following query will yield the machines that had a recent event:

[sourcecode language="sql"]
SELECT [MachineID]

FROM [CM_CS1].[dbo].[vEP_LastMalware]

Where DetectionTime &gt; DATEADD(hour, -1, getutcdate())
[/sourcecode]

You will need to configure the Query Database activity with the ConfigMgr SQL Server name, database, and optionally, a run account. For my purposes, I added the Orchestrator run account to the ConfigMgr_DViewAccess local group on the SQL Server.

  1. Add another Query Database activity to convert the ConfigMGR client ID to a computer name for future uses. If you do this, we will need to use the published data from the first query, as follows:

[sourcecode language="sql"]
SELECT [Netbios_Name0]
FROM [CM_CS1].[dbo].[vSMS_R_System]
WHERE ItemKey =
[/sourcecode]

After the ‘=’, we will need to use the published data from the first query. Use the published data as shown below:

Lastly, configure looping on the activity and place a 1 second delay between attempts. This will serve to iterate through all the returned rows.

  1. We will then add the Get Computer/IP Status to determine if the system is reachable, and if so, then we should simply run the locally available command line utility called MPCMDRUN. If not we, will use our custom application to connect to the ConfigMgr site, and use the native WMI API method for setting the policy.

Configure the Get Computer/IP Status with the computer name field with published data from the second Query Database Activity – Full line as a string with fields separated by ‘:’

  1. Add two activities for “Run Program”. Name one “Run MPCMDRUN”, and the other “Run SCCM_ClientOperation”. Link the activites to the Get Computer/IP status, and on the links, configure the link connecting to MPCMDRUN to success, and the link to the SCCM_ConsoleOperation with a failed. This will be used for our branching logic.
  1. Configure the “Run MPCMDRUN” as follows”

Mode: Program Execution

Computer: Full line as a string with fields separated by ‘:’, from the second database query.

Program Path: C:\Program Files\Microsoft Security Client\Antimalware\MpCmdRun.exe

Program parameters: -Scan 3

Run As: Use a dedicated account if need be, for administrative priviliges.

  1. Configure the Run SCCM_ConsoleOperation activity as follows:

Mode: Program Execution

Computer: localhost (or wherever the app is located at)

Program Path: C:\temp\SCCM_ClientOperations.exe

Parameters:

/sitecode:SiteCode

/siteserver:SiteServerName

/resid: Full line as a string with fields separated by ‘:’ (From the first database query)

Run As: Use an account that has administrative privileges to Configuration Manger.

 

Wrapping it up

Of course, feel free to add in Operations Manager alerting, email notifications, variables, etc., to refine and provide logging where needed. However, this should provide you with a simple use case scenario for Orchestrator, and take a few minutes to develop. This is just one example of a task, and can be extended to even include Active Directory tasks, such as forcing the primary user of the computer to change their password.

Code and Other Items

All code is my own work, and I am solely responsible, with no warranty provided.

SQL Query to find Malware Events:

[sourcecode language="sql"]
SELECT [MachineID]
,[LastMessageTime]
,[DetectionTime]
,[ActionTime]
,[DetectionSource]
,[PendingActions]
,[CleaningAction]
,[ExecutionStatus]
,[ActionSuccess]
,[ErrorCode]
FROM [CM_CS1].[dbo].[vEP_LastMalware]
WHERE DetectionTime &gt; DATEADD(hour, -1, getutcdate())
[/sourcecode]

SQL Query to map resource ID to computer name:

[sourcecode language="sql"]
SELECT [Netbios_Name0]
FROM [CM_CS1].[dbo].[vSMS_R_System]
Where ItemKey =
[/sourcecode]

SQL Query to determine client operations initiated:

[sourcecode language="sql"]
SELECT TOP [ID]
,[UniqueID]
,[Type]
,[RequestedTime]
,[SourceSite]
,[rowversion]
FROM [CM_CS1].[dbo].[ClientOperation]
[/sourcecode]

VB.Net Code for SCCM_ClientOperation.exe

I used Visual Basic 2010, and created a vb.net console application

------------------------------------------------------------

[sourcecode language="vb"]

Imports System
Imports System.Management
Module Module1
Sub Main(ByVal args() As String)
Dim strSiteCode As String = Nothing
Dim strSiteServer As String = Nothing
Dim strResID As Integer = Nothing

'valid command lines:
'/sitecode
'/siteserver
'/resid = resource ID (one at a time)

Dim s As String
For Each s In args
s.ToLower()

If s.Contains("/sitecode:") Then
Dim arrTemp() As String
arrTemp = s.Split(":")
strSiteCode = arrTemp(1)
arrTemp = Nothing
ElseIf s.Contains("/siteserver:") Then
Dim arrTemp() As String
arrTemp = s.Split(":")
strSiteServer = arrTemp(1)
arrTemp = Nothing
ElseIf s.Contains("/resid:") Then
Dim arrTemp() As String
arrTemp = s.Split(":")
strResID = arrTemp(1)
arrTemp = Nothing
End If
Next

Console.WriteLine(strSiteCode)
Console.WriteLine(strSiteServer)
Console.WriteLine(strResID)

Try

Console.WriteLine("Starting:")

Dim classInstance As New ManagementClass("\\" &amp; strSiteServer &amp; "\root\SMS\site_" &amp; strSiteCode, "SMS_ClientOperation", Nothing)

Console.WriteLine("Declaring inparams:")

' Obtain [in] parameters for the method
Dim inParams As ManagementBaseObject = classInstance.GetMethodParameters("InitiateClientOperation")

' Add the input parameters.
'inParams("TargetCollectionID") = ""
Dim arrResID() As Integer = {strResID}
inParams("TargetResourceIDs") = arrResID
inParams("Type") = 1

' Execute the method and obtain the return values.

Dim outParams As ManagementBaseObject = classInstance.InvokeMethod("InitiateClientOperation", inParams, Nothing)
Catch err As ManagementException
Console.WriteLine("An error occurred while trying to execute the WMI method: ")
End Try

End Sub
End Module

[/sourcecode]