Almost 2 years ago I was asked to create a simple script that would monitor if a set of ports were open or closed. Then if the ports were open provide points for them that would add up for a team score. This script was used for the LDSBC High School Cyber Defense competition to determine if a team had maintained there systems online as they protected them from a red team and hardened them. Here is what I created located on my github.
I was asked for the same script that I used 2 years ago and found out they have used it a couple of times since that time. The below script is a much improved scoring engine which the LDSBC is going to use in the High School Cyber Defense competition coming up December 7th.
After running the script I found the following use for it. I have been in situations where a system administrator or myself has turned off a monitoring system like Nagios due to the amount of alarms that are firing during an outage. The below script could be used during a timeframe like that to monitor systems that you are working to fix or verify they are working as you are in the middle of an outage.
The script is built to allow you to launch it, configure teams or vlans. Then after configuring notes about a team or a vlan, configure the IPs and ports you would like monitored. After launching it provides a status every 10 minutes of the IPs and ports that are UP or DOWN. The score could be evaluated as the consistency of a system being up. An audit log is also generated that could be viewed to determine the UP or DOWN time of systems.
Currently it is tuned to allow up to 6 teams/vlans with up-to 20 IPs/Ports per team or a total of 120 IPs/Ports to be monitored within a 10 minute period of time. This also saves a file that could be restored every 10 minutes during the monitoring process. This script also allows you to save a configuration that you create.
#!/usr/bin/python3
# Created Nov. 30, 2018
# Updated Dec. 11, 2018
import socket
import datetime
import time
class Teams:
def __init__(self):
self.teamName = []
def addTeam(self, name):
self.teamName.append(name)
return self
class Team:
def __init__(self, name, description, location, score):
self.name = name
self.description = description
self.location = location
self.score = int(score)
class Ports:
def __init__(self):
self.monitoredPorts = []
def addPort(self, portInfo):
self.monitoredPorts.append(portInfo)
return self
class Port:
def __init__(self, teamName, ip, port, description):
self.teamName = teamName
self.ip = ip
self.port = port
self.description = description
def modifyPort(poInfo, teInfo):
while True:
print('')
print('')
print('')
print('Port Modification')
print('***************************************************************************************')
tInfo = "Name:" + str(teInfo.name)
tInfo += "\tDesc: " + str(teInfo.description)
tInfo += "\tLocation: " + str(teInfo.location)
tInfo += "\tScore: " + str(teInfo.score)
print(tInfo)
print("")
pInfo = "Port Desc:" + str(poInfo.description)
pInfo += "\tIP:" + str(poInfo.ip)
pInfo += "\tPort:" + str(poInfo.port)
print('***************************************************************************************')
print("")
print("D. Modify IP/Port Description")
print("I. Modify IP")
print("P. Modify Port")
print("")
print("R. Refresh")
print("Q. Quit to IP/Port Setup")
print("")
selectMod = input("> ")
if selectMod == 'D' or selectPort == 'd':
newDesc = input("Change IP/Port description to: ")
poInfo.description = newDesc.strip().replace('\n','').replace('\r','')
elif selectMod == 'I' or selectMod == 'i':
newIP = input("Change IP to: ")
poInfo.ip = newIP.strip().replace('\n','').replace('\r','')
elif selectMod == 'P' or selectMod == 'p':
newPort = input("Change Port to: ")
poInfo.port = int(newPort.strip().replace('\n','').replace('\r',''))
elif selectPort == 'Q' or selectPort == 'q':
return
else:
continue
return
def setPorts(teamInfo, nPorts):
while True:
print('')
print('')
print('')
print('IP/Port Setup')
print('***************************************************************************************')
tInfo = "Name:" + str(teamInfo.name)
tInfo += "\tDesc: " + str(teamInfo.description)
tInfo += "\tLocation: " + str(teamInfo.location)
tInfo += "\tScore: " + str(teamInfo.score)
print(tInfo)
print('***************************************************************************************')
portNumber = 1
portNumberSet = []
for port in nPorts.monitoredPorts:
if port.teamName == teamInfo.name:
# Check if IP is in correct format
# Check if Port is in correct format
print(str(portNumber) + ". " + str(port.description) + "\t\tIP:" + str(port.ip) + "\t\tPort:" + str(port.port))
portNumberSet.append(portNumber)
portNumber += 1
if len(nPorts.monitoredPorts) == 0:
print("No ports have been configured.")
if len(nPorts.monitoredPorts) > 0:
print("** To modify a monitored port above select the number in the front.")
print("")
print('A. Add Port')
print('')
print('N. Modify Team Name')
print('D. Modify Team Description')
print('L. Modify Team Location')
print('S. Modify Team Score')
print('')
print('Q. Quit to Main')
print
selectPort = input('> ')
try:
numbPort = int(selectPort)
if len(nPorts.monitoredPorts) >= numbPort and numbPort in portNumberSet:
modifyPort(nPorts.monitoredPorts[numb-1], teamInfo)
except:
if selectPort == 'A' or selectPort == 'a':
portDescription = input("Input Description of Monitored Port: ")
portDescription = portDescription.strip().replace('\n','').replace('\r','')
portIP = input("Input IP to Monitor for " + str(teamInfo.name) + ": ")
portIP = portIP.strip().replace('\n','').replace('\r','')
portPort = input("Input Port to Monitor: ")
portPort = int(portPort.strip().replace('\n','').replace('\r',''))
nPorts.addPort(Port(teamInfo.name, portIP, portPort, portDescription))
elif selectPort == 'N' or selectPort == 'n':
newName = input("Change team name to: ")
newName = newName.strip().replace('\n','').replace('\r','')
teamInfo.name = newName
elif selectPort == 'D' or selectPort == 'd':
newDesc = input("Change team description to: ")
newDesc = newDesc.strip().replace('\n','').replace('\r','')
teamInfo.description = newDesc
elif selectPort == 'L' or selectPort == 'l':
newLoc = input("Change team location to: ")
newLoc = newLoc.strip().replace('\n','').replace('\r','')
teamInfo.location = newLoc
elif selectPort == 'S' or selectPort == 's':
newScore = input("Change team score from " + str(teamInfo.score) + " to: ")
newScore = newScore.strip().replace('\n','').replace('\r','')
teamInfo.score = int(newScore)
elif selectPort == 'Q' or selectPort == 'q':
main()
else:
continue
return
def saveTeam(nTeams, nPorts):
print('')
fileName = input('Input file to save to, contents will be overwritten (i.e. savedTeam.txt): ')
fileName = fileName.strip().replace('\n','').replace('\r','')
if len(fileName) < 4:
print('Invalid file name, using savedTeam.txt')
fileName = 'savedTeam.txt'
f = open(fileName, 'w')
for team in nTeams.teamName:
outputTeam = "TEAM" + "|" + str(team.name) + "|" + str(team.description) + "|" + str(team.location) + "|" + str(team.score) + "\r\n"
f.write(outputTeam)
for port in nPorts.monitoredPorts:
outputPort = "PORT" + "|" + str(port.teamName) + "|" + str(port.ip) + "|" + str(port.port) + "|" + str(port.description) + "\r\n"
f.write(outputPort)
f.close()
return
def saveTeamMonitoring(nTeams, nPorts):
now = datetime.datetime.now()
timeInfo = now.strftime("_%m_%d_%YT%H_%M")
fileName = 'monitoringSaveTeam' + timeInfo + '.txt'
f = open(fileName, 'w')
for team in nTeams.teamName:
outputTeam = "TEAM" + "|" + str(team.name) + "|" + str(team.description) + "|" + str(team.location) + "|" + str(team.score) + "\r\n"
f.write(outputTeam)
for port in nPorts.monitoredPorts:
outputPort = "PORT" + "|" + str(port.teamName) + "|" + str(port.ip) + "|" + str(port.port) + "|" + str(port.description) + "\r\n"
f.write(outputPort)
f.close()
print('Saved current team information to the file "' + fileName + '"')
print('If you stop the program you can restore this file with the scores at this point-in-time.')
return
def loadTeam(nTeams, nPorts):
print('')
fileName = input('Input file name to load: ')
fileName = fileName.strip().replace('\n','').replace('\r','')
if len(fileName) < 4:
print('Invalid file name, trying savedTeam.txt')
fileName = 'savedTeam.txt'
try:
f = open(fileName, 'r')
for line in f:
column = line.split('|')
if column[0] == 'TEAM':
nTeams.addTeam(Team(column[1], column[2], column[3], column[4].strip()))
elif column[0] == 'PORT':
nPorts.addPort(Port(column[1], column[2], column[3], column[4].strip()))
else:
print('Invalid line format found in ' + fileName + '. You will need to manually correct it.')
f.close()
print("")
print("** Note: The score was loaded with the restored information...")
print("")
except:
print("")
print('Sorry either the file does not exist or problems loading the file exist.')
print("")
return
def monitorMode(currentTeams, currentPorts):
while True:
print('')
print('')
print('')
print('Monitoring Mode - Will cylcle through all ports every 10 minutes...')
print('**Note: If the cycle time is greater than 600 seconds not enough time is allowed.')
print('***************************************************************************************')
print('Current Team Scores')
for team in currentTeams.teamName:
teamInfo = str(team.name)
teamInfo += "\tDesc: " + str(team.description)
teamInfo += "\tLocation: " + str(team.location)
teamInfo += "\tScore: " + str(team.score)
print(teamInfo)
print('***************************************************************************************')
fAudit = open('auditLog.txt', 'a')
timeSleep = 0
totalSleep = 0
beforeCycle = time.time()
for port in currentPorts.monitoredPorts:
ip = port.ip
currentPort = int(port.port)
beforeDate = datetime.datetime.now()
beforeConnection = time.time()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
result = s.connect_ex((ip,currentPort))
s.close()
if result == 0:
for team in currentTeams.teamName:
if team.name == port.teamName:
# For each successful connection it provides 5 points
team.score = team.score + 5
teamScore = team.score
infoAudit = port.teamName + "|"
infoAudit += port.ip + "|"
infoAudit += str(port.port) + "|"
infoAudit += "UP|"
infoAudit += beforeDate.strftime("%m-%d-%Y %H:%M:%S") + "|"
infoAudit += str(teamScore)
print(infoAudit)
infoAudit += "\r\n"
fAudit.write(infoAudit)
else:
infoAudit = port.teamName + "|"
infoAudit += port.ip + "|"
infoAudit += str(port.port) + "|"
infoAudit += "DOWN|"
infoAudit += beforeDate.strftime("%m-%d-%Y %H:%M:%S") + "|"
infoAudit += "|"
print(infoAudit)
infoAudit += "\r\n"
fAudit.write(infoAudit)
afterConnection = time.time()
# Sleep for a total of 5 seconds per connection whether failed or successful
timeSleep = 5 - (afterConnection - beforeConnection)
#print("Time Elapsed: " + str(timeSleep))
time.sleep(timeSleep)
totalSleep += 5
fAudit.close()
print("")
saveTeamMonitoring(currentTeams, currentPorts)
# Setup to monitor all connections every 10 minutes (6 teams 20 ports = 120 ports * 5 seconds = 600 seconds)
# 3 hours / 10 minutes = 18 cycles
afterCycle = time.time()
totalCycle = afterCycle - beforeCycle
print("")
print("Cycle took " + str(totalCycle) + " seconds.")
totalTimeSleep = 600 - (afterCycle - beforeCycle)
print("Sleeping for " + str(totalTimeSleep) + " seconds until the next cycle.")
time.sleep(totalTimeSleep)
totalSleep = 0
return
def main(newTeams, newPorts):
while True:
print('')
print('')
print('')
print('Main Menu')
print('***************************************************************************************')
teamNumber = 1
for team in newTeams.teamName:
portCount = 0
for port in newPorts.monitoredPorts:
if port.teamName == team.name:
portCount += 1
teamInfo = str(teamNumber) + ". "
teamInfo += str(team.name)
teamInfo += "\tDesc: " + str(team.description)
teamInfo += "\tLocation: " + str(team.location)
teamInfo += "\tPorts Configured: " + str(portCount)
teamInfo += "\tScore: " + str(team.score)
print(teamInfo)
teamNumber += 1
if len(newTeams.teamName) == 0:
print("No teams have been configured.")
if len(newTeams.teamName) > 0:
print("** To modify a team select the number in the front.")
print('')
print('A. Add Team')
print('L. Load Team Info from File')
print('S. Save Team Info to File')
print('')
print('Type "Monitor" to enter monitoring mode based on the configuration above')
print('')
print('R. Refresh')
print('Q. Quit')
print("")
selection = input('> ')
try:
numb = int(selection)
if len(newTeams.teamName) >= numb:
setPorts(newTeams.teamName[numb-1], newPorts)
except:
if selection == 'A' or selection == 'a':
teamName = input("Input team name: ")
teamDescription = input("Input team description: ")
teamLocation = input("Input team location: ")
newTeams.addTeam(Team(teamName, teamDescription, teamLocation, 0))
elif selection == 'L' or selection == 'l':
loadTeam(newTeams, newPorts)
elif selection == 'S' or selection == 's':
saveTeam(newTeams, newPorts)
elif selection == 'Q' or selection == 'q':
exit()
elif selection == 'monitor' or selection == 'Monitor' or selection == 'MONITOR':
monitorMode(newTeams, newPorts)
else:
continue
return
listTeams = Teams()
listPorts = Ports()
main(listTeams, listPorts)
No comments:
Post a Comment