' Copyright 2003-2015 Opmantek Limited (www.opmantek.com)
'
' ALL CODE MODIFICATIONS MUST BE SENT TO CODE@OPMANTEK.COM
'
' This file is part of Open-AudIT.
'
' Open-AudIT is free software: you can redistribute it and/or modify
' it under the terms of the GNU Affero General Public License as published
' by the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' Open-AudIT is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU Affero General Public License for more details.
'
' You should have received a copy of the GNU Affero General Public License
' along with Open-AudIT (most likely in a file named LICENSE).
' If not, see
'
' For further information on Open-AudIT or for a license other than AGPL please see
' www.opmantek.com or email contact@opmantek.com
'
' *****************************************************************************
' @package Open-AudIT
' @author Mark Unwin
' @version 1.8.2
' @copyright Copyright (c) 2014, Opmantek
' @license http://www.gnu.org/licenses/agpl-3.0.html aGPL v3
Option Explicit
dim log_entry, error_returned, error_description, exit_status, command, timestamp, exit_text, objExecObject, line, line_split, result_file, help
' TODO -
' log each non responding IP - option
' debugging values
' 0 = no debug
' 1 = basic debug
' 2 = verbose debug
dim create_file : create_file = "y"
dim debugging : debugging = "2"
dim echo_output : echo_output = "y"
dim log_no_response : log_no_response = "n"
dim org_id : org_id = ""
dim submit_online : submit_online = "n"
dim subnet_range : subnet_range = ""
dim subnet_timestamp : subnet_timestamp = ""
dim syslog : syslog = "y"
dim url : url = "http://localhost/open-audit/index.php/discovery/process_subnet"
dim objHTTP
dim sequential : sequential = "n"
' below we take any command line arguements
' to override the variables above, simply include them on the command line like submit_online=n
' NOTE - argurments are case sensitive
dim objArgs, strArg, varArray
Set objArgs = WScript.Arguments
for each strArg in objArgs
if instr(strArg, "=") then
varArray = split(strArg, "=")
select case varArray(0)
case "create_file"
create_file = varArray(1)
case "debugging"
debugging = varArray(1)
case "echo_output"
echo_output = varArray(1)
case "help"
help = varArray(1)
case "log_no_response"
log_no_response = varArray(1)
case "org_id"
org_id = varArray(1)
case "submit_online"
submit_online = varArray(1)
case "subnet_range"
subnet_range = varArray(1)
case "subnet_timestamp"
subnet_timestamp = varArray(1)
case "syslog"
syslog = varArray(1)
case "url"
url = varArray(1)
case "sequential"
sequential = varArray(1)
end select
else
if (strArg = "/?" or strArg = "/help") then
help = "y"
end if
end if
next
if (help = "y") then
wscript.echo "------------------------------"
wscript.echo "Open-AudIT Subnet Audit Script"
wscript.echo "(c) Opmantek, 2014. "
wscript.echo "------------------------------"
wscript.echo "This script should be used on a Windows based computer to discover hosts in a subnet."
wscript.echo "It will run nmap against the target subnet and submit the result."
wscript.echo "This script is designed to be called by the Open-AudIT web GUI, not run directly from the command line."
wscript.echo ""
wscript.echo "Valid command line options are below (items containing * are the defaults) and should take the format name=value (eg: debugging=1)."
wscript.echo ""
wscript.echo " create_file"
wscript.echo " y - Create an XML file containing the result."
wscript.echo " *n - Do not create an XML result file."
wscript.echo ""
wscript.echo " debugging"
wscript.echo " 0 - No output."
wscript.echo " 1 - Minimal Output."
wscript.echo " *2 - Verbose output."
wscript.echo ""
wscript.echo " echo_output"
wscript.echo " *n - Do not echo the result to the screen."
wscript.echo " y - Echo the result to the screen."
wscript.echo ""
wscript.echo " /? or help=y"
wscript.echo " y - Display this help output."
wscript.echo " *n - Do not display this output."
wscript.echo ""
wscript.echo " log_no_response"
wscript.echo " *n - Do not submit a result if there is no device attached to the given ip address."
wscript.echo " y - Submit a result even if nothing is found."
wscript.echo ""
wscript.echo " org_id"
wscript.echo " - The org_id (an integer) taken from Open-AudIT. If set all devices found will be associated to that Organisation."
wscript.echo ""
wscript.echo " sequential"
wscript.echo " *n - When we run this script, post each device result and wait for a response before continuing to the next device."
wscript.echo " Y - Post each device result and continue on processing the next device without waiting for a response from the Open-AudIT server."
wscript.echo ""
wscript.echo " submit_online"
wscript.echo " *y - Submit the audit result to the Open-AudIT server."
wscript.echo " n - Don't submit the audit result."
wscript.echo ""
wscript.echo " subnet_range"
wscript.echo " - The subnet in to audit."
wscript.echo ""
wscript.echo " subnet_timestamp"
wscript.echo " - Set by the web GUI. Not used on the command line."
wscript.echo ""
wscript.echo " syslog"
wscript.echo " *y - Log the script details to the Open-AudIT log file."
wscript.echo " n - Do not log to the Open-AudIT log file."
wscript.echo ""
wscript.echo " url"
wscript.echo " *http://localhost/open-audit/index.php/discovery/process_subnet - The http url of the Open-AudIT Server used to submit the result to."
wscript.quit
end if
' leave the below settings
const HKEY_CLASSES_ROOT = &H80000000
const HKEY_CURRENT_USER = &H80000001
const HKEY_LOCAL_MACHINE = &H80000002
const HKEY_USERS = &H80000003
const FOR_APPENDING = 8
const ads_scope_subtree = 2
dim strComputer : strComputer = "."
dim count : count = 0
dim system_timestamp : system_timestamp = Year(Now()) & "-" & Right("0" & Month(Now()),2) & "-" & Right("0" & Day(Now()),2) & " " & Right("0" & Hour(Now()),2) & ":" & Right("0" & Minute(Now()),2) & ":" & Right("0" & Second(Now()),2)
dim objWMIService : set objWMIService = GetObject("winmgmts:root\cimv2")
dim objWMIService2 : set objWMIService2 = GetObject("winmgmts:root\WMI")
dim objShell : set objShell = CreateObject("wscript.shell")
dim objFSO : set objFSO = CreateObject("Scripting.FileSystemObject")
dim wshNetwork : set wshNetwork = WScript.CreateObject( "WScript.Network" )
dim system_hostname : system_hostname = wshNetwork.ComputerName
dim user : user = wshNetwork.UserName
dim objlocalwmiservice : set objlocalwmiservice = getobject("winmgmts:root\cimv2")
dim colItems : set colitems = objlocalwmiservice.execquery("select * from win32_process",,48)
dim objitem, current_pid
for each objitem in colitems
if instr (objitem.commandline, wscript.scriptname) <> 0 then
current_pid = objitem.processid
end if
next
' enumerate all the ip addresses so we can determine if we are running against localhost
dim local_net : local_net = ""
dim net_mac_address : net_mac_address = ""
set colItems = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration WHERE IPEnabled = True ",,32)
error_returned = Err.Number : if (error_returned <> 0 and debugging > "0") then wscript.echo check_wbem_error(error_returned) & " local (Win32_NetworkAdapterConfiguration) 2" end if
for each objItem in colItems
net_mac_address = objItem.MACAddress
if net_mac_address > "" then
for i = LBound(objItem.IPAddress) to UBound(objItem.IPAddress)
local_net = local_net & " " & objItem.IPAddress(i) & " "
next
end if
next
local_net = local_net & " " & system_hostname & " "
if debugging > 0 then wscript.echo "Log Level: " & debugging & vbcrlf end if
dim nmap_path : nmap_path = ""
if (instr(lcase(objShell.ExpandEnvironmentStrings( "PATH=%PATH%" )), "\nmap")) then
' nmap is installed, proceed.
nmap_path = "nmap"
else
'nmap not in path - check a couple of default folders.
nmap_path = "c:\Program Files\Nmap\nmap.exe"
if (objFSO.FileExists(nmap_path)) then
' found it
else
nmap_path = ""
end if
if (nmap_path = "") then
nmap_path = "C:\Program Files (x86)\Nmap\nmap.exe"
if (objFSO.FileExists(nmap_path)) then
' found it
else
nmap_path = ""
end if
end if
if (nmap_path = "") then
log_entry = "Nmap not found, aborting."
write_log()
wscript.quit 1
end if
end if
log_entry = "Discovery for " & subnet_range & " submitted at " & subnet_timestamp & " starting"
write_log()
if debugging > "0" then wscript.echo "My PID: " & current_pid
if debugging > "0" then wscript.echo "Scanning Subnet: " & subnet_range
if debugging > "0" then wscript.echo "URL: " & url
exit_status = "y"
command = nmap_path & " -v -sP -PE -PP -n " & subnet_range
execute_command()
dim hosts
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
line_split = split(line)
if (instr(lcase(line), "scan report for")) then
if (instr(lcase(line), "[host down]")) then
if (log_no_response = "y") then
log_entry = "Non responsive ip address " & line_split(4)
write_log
end if
else
hosts = hosts & " " & line_split(4)
end if
end if
Loop
hosts = trim(hosts)
dim hosts_in_subnet : hosts_in_subnet = split(hosts)
dim host
for each host in hosts_in_subnet
if debugging > "0" then wscript.echo "Scanning Host: " & host end if
log_entry = "Scanning ip address " & host
write_log()
dim mac_address : mac_address = ""
dim manufacturer : manufacturer = ""
dim description : description = ""
dim os_group : os_group = ""
dim os_family : os_family = ""
dim os_name : os_name = ""
dim i
dim result : result = ""
exit_status = "y"
command = nmap_path & " -vv -n -O --host-timeout 90 -PN " & host
execute_command()
Do Until objExecObject.Status = 0
WScript.Sleep 100
Loop
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "mac address:") then
i = split(line, " ")
mac_address = i(2)
manufacturer = i(3)
i = ""
i = split(line, "(")
manufacturer = replace(i(1), ")", "")
manufacturer = trim(manufacturer)
end if
if instr(lcase(line), "device type:") then
i = split(line, ":")
if instr(line, "|") then
' could be one of multiple - insert it as the description
description = trim(i(1))
else
description = ""
end if
end if
if instr(lcase(line), "running:") then
i = split(line, ":")
os_name = i(1)
os_name = replace(os_name, ")", "")
os_name = replace(os_name, "(", "")
os_name = trim(os_name)
if (instr(lcase(line), "cisco ios")) then
os_group = "Cisco"
os_family="Cisco IOS"
end if
if (instr(lcase(line), "windows")) then
os_group = "Windows"
if (instr(lcase(line), "vista")) then os_family = "Windows Vista" end if
if (instr(lcase(line), "7")) then os_family = "Windows 7" end if
if (instr(lcase(line), "8")) then os_family = "Windows 8" end if
if (instr(lcase(line), "2003")) then os_family = "Windows 2003" end if
if (instr(lcase(line), "2008")) then os_family = "Windows 2008" end if
if (instr(lcase(line), "2012")) then os_family = "Windows 2012" end if
end if
if (instr(lcase(line), "irix")) then
os_group = "IRIX"
end if
if (instr(lcase(line), "openbsd")) then
os_group = "BSD"
os_family = "Open BSD"
end if
if (instr(lcase(line), "freebsd")) then
os_group = "BSD"
os_family = "Free BSD"
end if
if (instr(lcase(line), "netbsd")) then
os_group = "BSD"
os_family = "Net BSD"
end if
if (instr(lcase(line), "sunos")) then
os_group = "SunOS"
end if
if (instr(lcase(line), "solaris")) then
os_group = "Solaris"
end if
if (instr(lcase(line), "linux")) then
os_group = "Linux"
end if
if (instr(lcase(line), "vmware")) then
os_group = "VMware"
os_family = "VMware ESXi"
end if
if (instr(lcase(line), "apple mac os x")) then
os_group="Apple"
os_family="Apple OSX"
end if
end if
if instr(lcase(line), "running (just guessing):") and os_name = "" then
i = split(line, ":")
os_name = i(1)
os_name = replace(os_name, ")", "")
os_name = replace(os_name, "(", "")
os_name = trim(os_name)
end if
if instr(lcase(line), "aggressive os guesses:") and os_name = "" then
i = split(line, ":")
os_name = i(1)
os_name = replace(os_name, ")", "")
os_name = replace(os_name, "(", "")
os_name = trim(os_name)
if description = "" then
description = os_name
end if
end if
if instr(lcase(line), "os details:") and os_name = "" then
i = split(line, ":")
os_name = i(1)
os_name = replace(os_name, ")", "")
os_name = replace(os_name, "(", "")
os_name = trim(os_name)
end if
Loop
' test for SNMP
dim snmp_status : snmp_status = "false"
exit_status = "n"
command = nmap_path & " -n -sU -p161 " & host
execute_command
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "161/udp open") then
snmp_status = "true"
end if
Loop
' test for SSH
dim ssh_status : ssh_status = "false"
exit_status = "n"
command = nmap_path & " -n -p22 " & host
execute_command()
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "22/tcp open") then
ssh_status = "true"
end if
Loop
' test for WMI
dim wmi_status : wmi_status = "false"
exit_status = "n"
command = nmap_path & " -n -p135 " & host
execute_command()
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "135/tcp open") then
wmi_status = "true"
end if
Loop
' test for webserver on port 80
dim p80_status : p80_status = "false"
exit_status = "n"
command = nmap_path & " -n -p80 " & host
execute_command()
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "80/tcp open") then
p80_status = "true"
end if
Loop
' test for webserver on port 443
dim p443_status : p443_status = "false"
exit_status = "n"
command = nmap_path & " -n -p443 " & host
execute_command()
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "443/tcp open") then
p443_status = "true"
end if
Loop
' test for telnet
dim tel_status : tel_status = "false"
exit_status = "n"
command = nmap_path & " -n -p23 " & host
execute_command()
Do Until objExecObject.StdOut.AtEndOfStream
line = objExecObject.StdOut.ReadLine
if instr(lcase(line), "23/tcp open") then
tel_status = "true"
end if
Loop
' special case of determining WMI on localhost on Windows
if (instr(local_net, host & " ") > 0) then
wmi_status = "true"
end if
result = " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " unknown" & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result_file = result_file & result
if submit_online = "y" then
log_entry = "Submitting discovery subnet scan result for " & host
write_log()
result = "" & vbcrlf & result & ""
Err.clear
on error resume next
Set objHTTP = WScript.CreateObject("MSXML2.ServerXMLHTTP.3.0")
objHTTP.setTimeouts 5000, 5000, 5000, 120000
objHTTP.SetOption 2, 13056 ' Ignore all SSL errors
if sequential = "n" then
objHTTP.Open "POST", url, False ' wait for a response before continuing
else
objHTTP.Open "POST", url, True ' do not wait for a respone before continuing
end if
objHTTP.setRequestHeader "Content-Type","application/x-www-form-urlencoded"
objHTTP.Send "form_details=" + result + vbcrlf
on error goto 0
if (error_returned <> 0) then
log_entry = "Result send for " & host & " failed"
write_log
else
log_entry = "Result send for " & host & " succeeded"
write_log
end if
if debugging > 1 and sequential = "n" then
wscript.echo
wscript.echo "Response"
wscript.echo "--------"
wscript.echo objHTTP.ResponseText
end if
end if
next
result = " " & vbcrlf
result = result & " " & vbcrlf
result = result & " " & vbcrlf
result = result & " y" & vbcrlf
result = result & " "
result_file = result_file & result
result_file = "" & vbcrlf & result_file & vbcrlf & ""
if echo_output = "y" then
wscript.echo result_file
end if
if create_file = "y" then
if debugging > "0" then wscript.echo "Creating output File" end if
' Write the results to a file
dim file_timestamp
file_timestamp = Right("0" & Year(Now()),2) & _
Right("0" & Month(Now()),2) & _
Right("0" & Day(Now()),2) & _
Right("0" & Hour(Now()),2) & _
Right("0" & Minute(Now()),2) & _
Right("0" & Second(Now()),2)
dim OutputFile : OutputFile = "subnet-" & subnet_range & "-" & file_timestamp & ".xml"
OutputFile = replace(OutputFile, "/", "-")
if debugging > "0" then wscript.echo "Output file: " & OutputFile end if
Err.clear
on error resume next
dim objFileToWrite
Set objFileToWrite = CreateObject("Scripting.FileSystemObject").OpenTextFile(OutputFile,2,true)
objFileToWrite.WriteLine(result_file)
objFileToWrite.Close
Set objFileToWrite = Nothing
error_returned = Err.Number
error_description = Err.Description
on error goto 0
if (error_returned <> 0) then
if debugging > "0" then wscript.echo "Problem writing to file." end if
if debugging > "0" then wscript.echo "Error Number:" & error_returned end if
if debugging > "0" then wscript.echo "Error Description:" & error_description end if
log_entry = "Failed to create output file named " & OutputFile & " for " & subnet_range & " submitted at " & subnet_timestamp
write_log
else
if debugging > "0" then wscript.echo "Output file created." end if
log_entry = "Output file named " & OutputFile & " created for " & subnet_range & " submitted at " & subnet_timestamp
write_log
end if
end if
if submit_online = "y" then
result = "" & vbcrlf & result & ""
Err.clear
on error resume next
Set objHTTP = WScript.CreateObject("MSXML2.ServerXMLHTTP.3.0")
objHTTP.setTimeouts 5000, 5000, 5000, 120000
objHTTP.SetOption 2, 13056 ' Ignore all SSL errors
objHTTP.Open "POST", url, FALSE ' as at 1.8.2, wait for the output
'objHTTP.Open "POST", url, TRUE
objHTTP.setRequestHeader "Content-Type","application/x-www-form-urlencoded"
' reverted the below (changed in 1/8/2 and back in 1.8.4) to send the final subnet
' finished result instead of the entire result file
'objHTTP.Send "form_details=" + result_file + vbcrlf
objHTTP.Send "form_details=" + result + vbcrlf
on error goto 0
if (error_returned <> 0) then
if debugging > "0" then wscript.echo "Result complete send failed for " & subnet_range & " submitted at " & subnet_timestamp end if
log_entry = "Result send failed for " & subnet_range & " submitted at " & subnet_timestamp
write_log
if (not isempty(objHTTP.ResponseText) and objHTTP.ResponseText > "" and debugging > "1") then
wscript.echo objHTTP.ResponseText
end if
else
if debugging > "0" then wscript.echo "Result complete send succeeded for " & subnet_range & " submitted at " & subnet_timestamp end if
log_entry = "Result send successful for " & subnet_range & " submitted at " & subnet_timestamp
write_log
if (not isempty(objHTTP.ResponseText) and objHTTP.ResponseText > "" and debugging > "2") then
wscript.echo objHTTP.ResponseText
end if
end if
end if
log_entry = "Discovery for " & subnet_range & " submitted at " & subnet_timestamp & " completed"
write_log()
function get_timestamp()
get_timestamp = monthname(month(now()), True) & " " & Right("0" & Day(Now()),2) & " " & Right("0" & Hour(Now()),2) & ":" & Right("0" & Minute(Now()),2) & ":" & Right("0" & Second(Now()),2)
end function
function write_log()
timestamp = get_timestamp()
if debugging > 1 then
wscript.echo "Writing Log (if required): " & timestamp & " " & system_hostname & " " & current_pid & " S:discover_subnet U:" & user & " " & log_entry & vbcrlf
end if
if syslog = "y" then
on error resume next
dim objTS
set objTS = objFSO.OpenTextFile("c:\xampplite\open-audit\other\log_system.log", FOR_APPENDING, True)
error_returned = Err.Number
error_description = Err.Description
on error goto 0
if (error_returned <> 0) then
if debugging > "0" then wscript.echo "Problem opening log file." end if
if debugging > "0" then wscript.echo "Error Number:" & error_returned end if
if debugging > "0" then wscript.echo "Error Description:" & error_description end if
Err.Clear
else
log_entry = timestamp & " " & system_hostname & " " & current_pid & " U:" & user & " S:discover_subnet M:" & log_entry & vbcrlf
objTS.Write log_entry
objTS.Close
Set objTS = Nothing
end if
end if
end function
function execute_command()
if debugging > 1 then wscript.echo "Executing: " & command end if
on error resume next
set objExecObject = objShell.Exec(command)
Do Until objExecObject.Status = 0
WScript.Sleep 1000
Loop
error_returned = Err.Number
error_description = Err.Description
on error goto 0
if (error_returned <> 0) then
if debugging > "0" then wscript.echo "Discovery command failed (" & command & "). Error Number: " & error_returned & " Error Description: " & error_description end if
'if syslog = "y" then
if exit_status = "y" then
exit_text = " Aborting script."
else
exit_text = ""
end if
timestamp = get_timestamp()
log_entry = timestamp & " " & system_hostname & " " & current_pid & " Discovery command failed (" & command & ")." & exit_text & vbcrlf
write_log()
'end if
Err.Clear
if exit_status = "y" then
wscript.quit 1
end if
end if
end function