The following scripts and information can be used to audit Administrator privileges on local servers in Windows domain and non-Domain environments. These scripts require sufficient privileges on each of the servers to be audited.
Helpful ways of manipulating data in Excel
http://support.microsoft.com/kb/213889
Perform a FIND from the RIGHT hand side in Excel:
=IFERROR(RIGHT(E113406,LEN(E113406)-FIND("^^^^^",SUBSTITUTE(E113406,":","^^^^^",LEN(E113406)-LEN(SUBSTITUTE(E113406,":",""))))),E113406)
Remove the extra domain name "\" that the non-WMI audit of local servers currently puts even though it is returninig a local group.
=IFERROR(IF(FIND("\",SUBSTITUTE(B31876,"\","b",1))>0,RIGHT(B31876,LEN(B31876)-FIND("\",SUBSTITUTE(B31876,"\","b",2))),"False"),B31876)
Showing posts with label local administrators group. Show all posts
Showing posts with label local administrators group. Show all posts
Monday, March 14, 2011
Tuesday, February 15, 2011
VBScript: Extract members of local Administrators group from SYDI-Server output
Sydi-Server is a great VBS tool that can extract local group memberships into an XML output. Unfortunately this is not always the greatest format to work with.
This VBScript can be pointed to a directory containing the SYDI-Server XML files and it will extract all members of the local Administrators groups into a CSV format.
Here is the script:
Dim xmlDoc, objNodeList, plot, nodeBook
Set objRegEx = CreateObject("VBScript.RegExp")
' =======================================================
' Set up files to be written and read
' =======================================================
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim fso, logFile, dataFile, x, y
Set fso = CreateObject("Scripting.FileSystemObject")
Set dataFile = fso.CreateTextFile("Windows_Groups.txt", True) 'Output information from commands
Set logFile = fso.CreateTextFile("SessionLog.txt", True) 'Verbose Logging
If Err.Number <> 0 Then
wscript.echo "CRASH: Cannot open file for reading: Servers.txt. " & Err.Number & " " & Err.Description
wscript.quit
End If
' =======================================================
' Browse for folder containing XML files
' =======================================================
Const WINDOW_HANDLE = 0
Const BIF_EDITBOX = &H10
Const BIF_NONEWFOLDER = &H0200
Const BIF_RETURNONLYFSDIRS = &H1
Set objShell = CreateObject("Shell.Application")
Set wshShell = CreateObject("WScript.Shell")
'**Browse For Folder To Be Processed
strPrompt = "Please select the folder to process."
intOptions = BIF_RETURNONLYFSDIRS + BIF_NONEWFOLDER + BIF_EDITBOX
strTargetPath = "C:\"
strFolderPath = Browse4Folder(strPrompt, intOptions, strTargetPath)
Set objFolder = fso.GetFolder(strFolderPath)
Set objColFiles = objFolder.Files
For Each file In objColFiles
' Check if we are looking at an XML file
If UCASE(RIGHT(file.Name,3)) <> "XML" Then
logFile.WriteLine("WRN: Filename " & file.Name & " does not appear to be an XML file.")
Else
'perform the work
' =======================================================
' Browse each XML file for groups and memberships
' =======================================================
serverXMLSource=file.Name
fullServerXMLSource=objFolder&"\"&serverXMLSource
' msgbox fullServerXMLSource
serverName=LEFT(serverXMLSource,INSTR(serverXMLSource,".")-1)
logFile.WriteLine("INFO: Now processing server: " & serverXMLSource)
Set xmlDoc = CreateObject("Msxml2.DOMDocument")
xmlDoc.async=false
'xmlDoc.validateOnParse = false
xmlDoc.load(fullServerXMLSource)
if (xmlDoc.parseError.errorCode <> 0) Then
Dim myErr
Set myErr = xmlDoc.parseError
logFile.WriteLine("ERR: " & myErr.reason & ", " & myErr.srcText & ", " & myErr.line & ".")
'Msgbox ("Error: " & myErr.reason)
'Msgbox ("Error text: " & myErr.srcText)
'Msgbox ("Error line: " & myErr.line)
Else
' msgbox xmlDoc.xml
' Set elemList = xmlDoc.DocumentElement
' Set nodeList = elemList.SelectNodes("localgroups")
' for each item in nodeList
' msgbox "This is: " & item.xml
' Next
Set objChildNodes = xmlDoc.documentElement.childNodes
i = 0
childNodeNumber=0
For EAch strNode in objChildnodes
If strNode.NodeName = "localgroups" Then
childNodeNumber = i
'msgbox "Node : " & strNode.xml
End if
i=i+1
Next
If childNodeNumber = 0 Then
logFile.WriteLine("WRN: " & serverName & ": Unable to find a 'localgroups' element in " & serverXMLSource & ".")
End If
Set objLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes
j = 0
For each strNode in objLowerChildNodes
If strNode.NodeName = "group" Then
groupName = objLowerChildNodes.item(j).GetAttribute("name")
if isNull(groupname) Then
'No point looking for members as we cannot even find a name of a group
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group")
Else
'We can look for the next childnodes to find the members
'We will echo the group name to the output so that it appears even if empty.
if GroupName <> "Administrators" Then
dataFile.WriteLine(serverName & ",," & GroupName & ",No")
End If
Set objEvenLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes.item(j).ChildNodes
k = 0
For each strLowerNode in objEvenLowerChildNodes
If strLowerNode.Nodename = "member" Then
memberName = objEvenLowerChildNodes.item(k).GetAttribute("name")
if isNull(memberName) Then
'Unable to find the name of a member
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group member")
else
'We have the name of the group member
' ===========================================
' This is where we do our data manipulation
' And write it out to a file in the format:
' servername, membername, groupname, hpa, accountcode
' ============================================
' If HPA then test for Account Code
If GroupName = "Administrators" Then
hpa = "Yes"
' Allow to search for 9 consecutive digits
objRegEx.Global = false
objRegEx.Pattern = "\d{9}"
Set checkMatches = objRegEx.Execute(memberName)
'if checkMatches.Count> 0 Then
' For Each banana in checkMatches
' wscript.echo checkMatches.Count & " " & banana.Value
' Next
'End if
' - Test for JPicard or GISAdmin or 'break fix' accounts(5)
if INSTR(UCASE(memberName),"JPICARD") > 0 Then
accountCode = "5"
Elseif INSTR(UCASE(memberName),"GISADMIN") > 0 Then
accountCode = "5"
' Test for shared accounts (2)
Elseif INSTR(UCASE(memberName),"ADMIN") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\SSO") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\REDPLANET") > 0 Then
accountCode = "2"
' Test for adm accounts (?)
Elseif INSTR(UCASE(memberName),"\ADM-") > 0 Then
accountCode = "1"
' Test for \[1...9][0...9] (1)
Elseif checkMatches.Count > 0 Then
accountCode = "1"
' Test for \CEF_ \CMF_ _G_ Domain Admins and other groups (G)
Elseif INSTR(UCASE(memberName),"\CEF") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\CMF_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"_G_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"DOMAIN ADMINS") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\HP-OVE-GROUP") > 0 Then
accountCode = "G"
' Test for RRabling and personal SAM accounts (4)
Elseif INSTR(UCASE(memberName),"RRABLING") > 0 Then
accountCode = "1"
' Test for \IUSR ftpuser perfmon taskschedule and other service/app accounts(6)
Elseif INSTR(UCASE(memberName),"\IUSR") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"FTPUSER") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"PERFMON") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"TASKSCHEDULE") > 0 Then
accountCode = "6"
Else
accountCode = "3"
End If
Else
hpa = "No"
End If
dataFile.WriteLine(serverName & "," & memberName & "," & GroupName & "," & hpa & "," & accountCode)
end if
else
' It was not an element named 'member' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'member' should have been returned however the element" &_
"returned was: " & memberName)
end if
k = k + 1
Next
End If
Else
'It was not a element named 'group' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'group' should have been returned hpwever the element" &_
"returned was: " & groupName)
End If
j = j + 1
Next
end if
End If
Next
' =======================================================
' Function for browsing for folders
' =======================================================
'**Browse4Folder Function
Function Browse4Folder(strPrompt, intOptions, strRoot)
Dim objFolder, objFolderItem
On Error Resume Next
Set objFolder = objShell.BrowseForFolder(0, strPrompt, intOptions, strRoot)
If (objFolder Is Nothing) Then
Wscript.Quit
End If
Set objFolderItem = objFolder.Self
Browse4Folder = objFolderItem.Path
Set objFolderItem = Nothing
Set objFolder = Nothing
End Function
This VBScript can be pointed to a directory containing the SYDI-Server XML files and it will extract all members of the local Administrators groups into a CSV format.
Here is the script:
Dim xmlDoc, objNodeList, plot, nodeBook
Set objRegEx = CreateObject("VBScript.RegExp")
' =======================================================
' Set up files to be written and read
' =======================================================
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim fso, logFile, dataFile, x, y
Set fso = CreateObject("Scripting.FileSystemObject")
Set dataFile = fso.CreateTextFile("Windows_Groups.txt", True) 'Output information from commands
Set logFile = fso.CreateTextFile("SessionLog.txt", True) 'Verbose Logging
If Err.Number <> 0 Then
wscript.echo "CRASH: Cannot open file for reading: Servers.txt. " & Err.Number & " " & Err.Description
wscript.quit
End If
' =======================================================
' Browse for folder containing XML files
' =======================================================
Const WINDOW_HANDLE = 0
Const BIF_EDITBOX = &H10
Const BIF_NONEWFOLDER = &H0200
Const BIF_RETURNONLYFSDIRS = &H1
Set objShell = CreateObject("Shell.Application")
Set wshShell = CreateObject("WScript.Shell")
'**Browse For Folder To Be Processed
strPrompt = "Please select the folder to process."
intOptions = BIF_RETURNONLYFSDIRS + BIF_NONEWFOLDER + BIF_EDITBOX
strTargetPath = "C:\"
strFolderPath = Browse4Folder(strPrompt, intOptions, strTargetPath)
Set objFolder = fso.GetFolder(strFolderPath)
Set objColFiles = objFolder.Files
For Each file In objColFiles
' Check if we are looking at an XML file
If UCASE(RIGHT(file.Name,3)) <> "XML" Then
logFile.WriteLine("WRN: Filename " & file.Name & " does not appear to be an XML file.")
Else
'perform the work
' =======================================================
' Browse each XML file for groups and memberships
' =======================================================
serverXMLSource=file.Name
fullServerXMLSource=objFolder&"\"&serverXMLSource
' msgbox fullServerXMLSource
serverName=LEFT(serverXMLSource,INSTR(serverXMLSource,".")-1)
logFile.WriteLine("INFO: Now processing server: " & serverXMLSource)
Set xmlDoc = CreateObject("Msxml2.DOMDocument")
xmlDoc.async=false
'xmlDoc.validateOnParse = false
xmlDoc.load(fullServerXMLSource)
if (xmlDoc.parseError.errorCode <> 0) Then
Dim myErr
Set myErr = xmlDoc.parseError
logFile.WriteLine("ERR: " & myErr.reason & ", " & myErr.srcText & ", " & myErr.line & ".")
'Msgbox ("Error: " & myErr.reason)
'Msgbox ("Error text: " & myErr.srcText)
'Msgbox ("Error line: " & myErr.line)
Else
' msgbox xmlDoc.xml
' Set elemList = xmlDoc.DocumentElement
' Set nodeList = elemList.SelectNodes("localgroups")
' for each item in nodeList
' msgbox "This is: " & item.xml
' Next
Set objChildNodes = xmlDoc.documentElement.childNodes
i = 0
childNodeNumber=0
For EAch strNode in objChildnodes
If strNode.NodeName = "localgroups" Then
childNodeNumber = i
'msgbox "Node : " & strNode.xml
End if
i=i+1
Next
If childNodeNumber = 0 Then
logFile.WriteLine("WRN: " & serverName & ": Unable to find a 'localgroups' element in " & serverXMLSource & ".")
End If
Set objLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes
j = 0
For each strNode in objLowerChildNodes
If strNode.NodeName = "group" Then
groupName = objLowerChildNodes.item(j).GetAttribute("name")
if isNull(groupname) Then
'No point looking for members as we cannot even find a name of a group
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group")
Else
'We can look for the next childnodes to find the members
'We will echo the group name to the output so that it appears even if empty.
if GroupName <> "Administrators" Then
dataFile.WriteLine(serverName & ",," & GroupName & ",No")
End If
Set objEvenLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes.item(j).ChildNodes
k = 0
For each strLowerNode in objEvenLowerChildNodes
If strLowerNode.Nodename = "member" Then
memberName = objEvenLowerChildNodes.item(k).GetAttribute("name")
if isNull(memberName) Then
'Unable to find the name of a member
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group member")
else
'We have the name of the group member
' ===========================================
' This is where we do our data manipulation
' And write it out to a file in the format:
' servername, membername, groupname, hpa, accountcode
' ============================================
' If HPA then test for Account Code
If GroupName = "Administrators" Then
hpa = "Yes"
' Allow to search for 9 consecutive digits
objRegEx.Global = false
objRegEx.Pattern = "\d{9}"
Set checkMatches = objRegEx.Execute(memberName)
'if checkMatches.Count> 0 Then
' For Each banana in checkMatches
' wscript.echo checkMatches.Count & " " & banana.Value
' Next
'End if
' - Test for JPicard or GISAdmin or 'break fix' accounts(5)
if INSTR(UCASE(memberName),"JPICARD") > 0 Then
accountCode = "5"
Elseif INSTR(UCASE(memberName),"GISADMIN") > 0 Then
accountCode = "5"
' Test for shared accounts (2)
Elseif INSTR(UCASE(memberName),"ADMIN") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\SSO") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\REDPLANET") > 0 Then
accountCode = "2"
' Test for adm accounts (?)
Elseif INSTR(UCASE(memberName),"\ADM-") > 0 Then
accountCode = "1"
' Test for \[1...9][0...9] (1)
Elseif checkMatches.Count > 0 Then
accountCode = "1"
' Test for \CEF_ \CMF_ _G_ Domain Admins and other groups (G)
Elseif INSTR(UCASE(memberName),"\CEF") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\CMF_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"_G_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"DOMAIN ADMINS") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\HP-OVE-GROUP") > 0 Then
accountCode = "G"
' Test for RRabling and personal SAM accounts (4)
Elseif INSTR(UCASE(memberName),"RRABLING") > 0 Then
accountCode = "1"
' Test for \IUSR ftpuser perfmon taskschedule and other service/app accounts(6)
Elseif INSTR(UCASE(memberName),"\IUSR") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"FTPUSER") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"PERFMON") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"TASKSCHEDULE") > 0 Then
accountCode = "6"
Else
accountCode = "3"
End If
Else
hpa = "No"
End If
dataFile.WriteLine(serverName & "," & memberName & "," & GroupName & "," & hpa & "," & accountCode)
end if
else
' It was not an element named 'member' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'member' should have been returned however the element" &_
"returned was: " & memberName)
end if
k = k + 1
Next
End If
Else
'It was not a element named 'group' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'group' should have been returned hpwever the element" &_
"returned was: " & groupName)
End If
j = j + 1
Next
end if
End If
Next
' =======================================================
' Function for browsing for folders
' =======================================================
'**Browse4Folder Function
Function Browse4Folder(strPrompt, intOptions, strRoot)
Dim objFolder, objFolderItem
On Error Resume Next
Set objFolder = objShell.BrowseForFolder(0, strPrompt, intOptions, strRoot)
If (objFolder Is Nothing) Then
Wscript.Quit
End If
Set objFolderItem = objFolder.Self
Browse4Folder = objFolderItem.Path
Set objFolderItem = Nothing
Set objFolder = Nothing
End Function
Labels:
CSV,
HPA,
local administrators group,
SYDI,
SYDI-Server,
VBScript,
XML
Powershell: Write out local Administrators group membership to CSV
This powershell script will query a CSV containing a single list of servers to determine the membership of the local Administrators group. This script could be used to assist in determining HPA (Highly Privileged Access) accounts in a company.
While SYDI-Server can perform this task, some servers do not allow remote WMI connections. This script uses the same remote management interface as Computer Management to connect to the server. For this reason it could be used in conjunction with SYDI-Server to hit both WMI and non-WMI servers.
If your logged in account does not have access to the server being queried then you can try to net use \\server\IPC$ user:server\username * prior to running the command. The command should then use these impersonated credentials to connect.
This script only outputs the direct members of the local Administrators group. A second script is on this site which can be executed following this script to expand out the AD group memberships as well.
Here is the script.
cls
$csvfile = Import-Csv BadServer.csv
'"Server","Username","Type"' | Out-File -filepath "Users.csv"
foreach($line in $csvfile)
{
$strcomputer = $line.server
$computer = [ADSI]("WinNT://" + $strcomputer + ",computer")
#uncomment the following lines if you need to get all groups from the computer
# $computer.psbase.children | Where-Object{ $_.psbase.schemaClassName -eq 'group'} | foreach {
# '"' +$strcomputer + '","' + $_.name + '"' | Out-File -filepath "Groups.csv" -append
# #Write-Host $_.name
# }
$group = $computer.psbase.children.find("Administrators")
$members = $group.psbase.invoke("Members")
foreach( $member in $members)
{
#Write-Host $member.GetType().GetFields()
$compname = $member.GetType().InvokeMember("AdsPath", 'GetProperty', $null,$member, $null)
$strname = $compname.Remove(0,8).Replace("/","\")
'"' +$strcomputer + '","' + $strname+ '","' + $member.GetType().InvokeMember("Class", 'GetProperty', $null,$member, $null) + '"' | Out-File -filepath "Users.csv" -append
}
$members = $null
$group = $null
$computer = $null
}
Write-Host "done"
start .
While SYDI-Server can perform this task, some servers do not allow remote WMI connections. This script uses the same remote management interface as Computer Management to connect to the server. For this reason it could be used in conjunction with SYDI-Server to hit both WMI and non-WMI servers.
If your logged in account does not have access to the server being queried then you can try to net use \\server\IPC$ user:server\username * prior to running the command. The command should then use these impersonated credentials to connect.
This script only outputs the direct members of the local Administrators group. A second script is on this site which can be executed following this script to expand out the AD group memberships as well.
Here is the script.
cls
$csvfile = Import-Csv BadServer.csv
'"Server","Username","Type"' | Out-File -filepath "Users.csv"
foreach($line in $csvfile)
{
$strcomputer = $line.server
$computer = [ADSI]("WinNT://" + $strcomputer + ",computer")
#uncomment the following lines if you need to get all groups from the computer
# $computer.psbase.children | Where-Object{ $_.psbase.schemaClassName -eq 'group'} | foreach {
# '"' +$strcomputer + '","' + $_.name + '"' | Out-File -filepath "Groups.csv" -append
# #Write-Host $_.name
# }
$group = $computer.psbase.children.find("Administrators")
$members = $group.psbase.invoke("Members")
foreach( $member in $members)
{
#Write-Host $member.GetType().GetFields()
$compname = $member.GetType().InvokeMember("AdsPath", 'GetProperty', $null,$member, $null)
$strname = $compname.Remove(0,8).Replace("/","\")
'"' +$strcomputer + '","' + $strname+ '","' + $member.GetType().InvokeMember("Class", 'GetProperty', $null,$member, $null) + '"' | Out-File -filepath "Users.csv" -append
}
$members = $null
$group = $null
$computer = $null
}
Write-Host "done"
start .
Labels:
HPA,
local administrators group,
powershell,
security
Subscribe to:
Posts (Atom)