Back to Windows Service Security Descriptors Project
' Author: Cameron L. Wilson (thepip3r)
' Date: 9/25/2011
' Description: Track vulnerable services on Windows systems
' References:
' - Win32_ACE: http://msdn.microsoft.com/en-us/library/aa394063.aspx
' - Win32_SecurityDescriptor: http://msdn.microsoft.com/en-us/library/aa394402.aspx
' - Win32_Service: http://msdn.microsoft.com/en-us/library/aa394418(v=VS.85).aspx
' ****************************************************************************************************************************************
' Begin: Create Custom WMI Namespace/Class
' ****************************************************************************************************************************************
Const wbemCimtypeSint16 = 2
Const wbemCimtypeSint32 = 3
Const wbemCimtypeReal32 = 4
Const wbemCimtypeReal64 = 5
Const wbemCimtypeString = 8
Const wbemCimtypeBoolean = 11
Const wbemCimtypeObject = 13
Const wbemCimtypeSint8 = 16
Const wbemCimtypeUint8 = 17
Const wbemCimtypeUint16 = 18
Const wbemCimtypeUint32 = 19
Const wbemCimtypeSint64 = 20
Const wbemCimtypeUint64 = 21
Const wbemCimtypeDateTime = 101
Const wbemCimtypeReference = 102
Const wbemCimtypeChar16 = 103
Set objLocator = CreateObject("WbemScripting.sWbemLocator")
Set objSvc = objLocator.ConnectServer(".", "root")
Set objNamespace = objSvc.Get("__namespace")
Set objCustomNameSpace = objNamespace.SpawnInstance_
objCustomNamespace.name = "custom" ' Create the "Custom" namespace
objCustomNamespace.Put_()
Set objWMI = GetObject("winmgmts:root\custom")
Set objClass = objWMI.Get()
strClass = "ServiceVulnerabilities"
' Look for existing custom classes on this host and wipe them out if they exist
On Error Resume Next
Set objServiceVulnerabilities = objWMI.Get(strClass)
If Err.Number = 0 Then
objServiceVulnerabilities.Delete_
End If
On Error Goto 0
' Create the custom class with all of its properties
objClass.Path_.Class = strClass
objClass.Properties_.add "ServiceID", wbemCimtypeUint32
objClass.Properties_("ServiceID").Qualifiers_.add "key", true
objClass.Properties_.add "ServiceName", wbemCimtypeString
objClass.Properties_.add "ServiceDisplayName", wbemCimtypeString
objClass.Properties_.add "Trustee", wbemCimtypeString
objClass.Properties_.add "AccessMask", wbemCimtypeUint32
objClass.Properties_.add "AceType", wbemCimtypeUint32
objClass.Properties_.add "AceFlags", wbemCimtypeUint32
objClass.Put_()
' Apply a pre-defined security string to the new namespace/class
strSD = "1,0,4,128,148,0,0,0,164,0,0,0,0,0,0,0,20,0,0,0,2,0,128,0,4,0,0,0,0,18,24,0,63,0,6,0,1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0,0,18,20,0,19,0,0,0,1,1,0,0,0,0,0,5,20,0,0,0,0,18,20,0,19,0,0,0,1,1,0,0,0,0,0,5,19,0,0,0,0,18,20,0,19,0,0,0,1,1,0,0,0,0,0,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0,1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0"
arrSD = Split(strSD,",")
Set objSS = objWMI.Get("__SystemSecurity=@")
objSS.SetSD(arrSD)
' ****************************************************************************************************************************************
' End: Create Custom WMI Namespace/Class
' ****************************************************************************************************************************************
' ****************************************************************************************************************************************
' Begin: Query Service Security Descriptors for User-Defined Criteria
' ****************************************************************************************************************************************
Const SE_DACL_PRESENT = &h4
Const ACCESS_ALLOWED_ACE_TYPE = &h0
Const ACCESS_DENIED_ACE_TYPE = &h1
strExclusions = "BUILTIN\Administrators, NT SERVICE\TrustedInstaller, NT AUTHORITY\SYSTEM, NT SERVICE\IPBusEnum, BUILTIN\Domain Administrators"
arrExclusions = Split(strExclusions, ",")
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate, (Security)}!\\" & strComputer & "\root\cimv2")
Set colServices = objWMIService.ExecQuery("Select * from Win32_Service")
Set objData = objWMI.Get(strClass)
Set objInstance = objData.SpawnInstance_
y = 0
For Each objService in colServices
WScript.Echo objService.Name
iReturn = objService.GetSecurityDescriptor( objSD )
If ( iReturn <> 0 ) Then
WScript.Echo "Could not get security descriptor: " & iReturn
End If
' Extract the security descriptor flags
intControlFlags = objSD.ControlFlags
If intControlFlags AND SE_DACL_PRESENT Then
WScript.Echo " Control Flags:" & vbTab & intControlFlags
' Get the ACE entries from security descriptor
colACEs = objSD.DACL
For Each objACE in colACEs
strTrustee = objACE.Trustee.Domain & "\" & objACE.Trustee.Name
If Trim(strTrustee) = "\" Then
strTrustee = objACE.Trustee.SIDString
End If
' Make sure the ACEType is an "allow", make sure the accessmask gives the group some kind of "write" permissions, and the trustee group isn't predefined as "good"
If objACE.AceType = ACCESS_ALLOWED_ACE_TYPE And objACE.AccessMask >= 262144 And Not InArray(arrExclusions, strTrustee) Then
' Get all the trustees and determine which have access to the service
strTrustees = strTrustees & strTrustee & vbCrLf
strAccessMasks = strAccessMasks & objACE.AccessMask & vbCrLf
strAceFlags = strAceFlags & objACE.AceFlags & vbCrLf
strAceTypes = strAceTypes & objACE.AceType & vbCrLf
WScript.Echo " Trustee:" & vbTab & strTrustee
WScript.Echo " Trustee SID:" & vbTab & objACE.Trustee.SIDString
WScript.Echo " Trustee SIDLength:" & vbTab & objACE.Trustee.SIDLength
WScript.Echo " Trustee SID:"
For Each strSIDpart in objACE.Trustee.SID
strSID = strSID & strSIDPart
Next
WScript.Echo " " & vbTab & strSID
WScript.Echo " Access Mask:" & vbTab & objACE.AccessMask
WScript.Echo " Ace Flags:" & vbTab & objACE.AceFlags
WScript.Echo " Ace Types:" & vbTab & objACE.AceType
ElseIf objACE.AceType = ACCESS_DENIED_ACE_TYPE Then
' Don't care about Denies
End If
Next
If strTrustees <> "" Then
WScript.Echo " Class Index:" & vbTab & y
arrTrustees = Split(strTrustees, vbCrLf)
arrAccessMasks = Split(strAccessMasks, vbCrLf)
arrAceFlags = Split(strAceFlags, vbCrLf)
arrAceTypes = Split(strAceTypes, vbCrLf)
' Loop through the found ACE entries and write those to our custom class
For x=0 to (Ubound(arrTrustees)-1)
objInstance.ServiceID = y
objInstance.ServiceName = objService.Name
objInstance.ServiceDisplayName = objService.DisplayName
objInstance.Trustee = arrTrustees(x)
objInstance.AccessMask = arrAccessMasks(x)
objInstance.AceType = arrAceTypes(x)
objInstance.AceFlags = arrAceFlags(x)
objInstance.Put_()
y = y + 1
Next
strTrustees = ""
strAccessMasks = ""
strAceFlags = ""
strAceTypes = ""
End If
Else
' No DACL found; we don't care about the security descriptor.
WScript.Echo " Control Flags(F):" & vbTab & intControlFlags
End If
Next
' ****************************************************************************************************************************************
' End: Query Service Security Descriptors for User-Defined Criteria
' ****************************************************************************************************************************************
' Checks for the existence of a string in an array
Function InArray(arrName, strValue)
For Each strItem in arrName
If Trim(LCase(strItem)) = Trim(LCase(CStr(strValue))) Then
InArray = TRUE
Exit Function
End If
Next
InArray = FALSE
End Function