def addUser(self, access_req): # print("addUser Module") usrLst = access_req['userList'] for user in usrLst: usrSaveRequest = Element('UserSaveRequest', attrib={'session-id': self.session_id}) userinfo = user.split(',') # uname,name,email pswd = Utilities.gen_code() usrConfig_elem = SubElement(usrSaveRequest, 'UserConfig', attrib={'id': '-1', 'role-name': 'user', 'authsrcid': '-1', 'enabled': '1', 'name': userinfo[0], 'fullname': userinfo[1], 'email': userinfo[2], 'password': pswd}) sites_elem = SubElement(usrConfig_elem, 'UserSite') site_elem = SubElement(sites_elem, 'site', attrib={'id': self.site_id}) site_elem.text = access_req['site_name'] xmlTree = ElementTree(usrSaveRequest) f = BytesIO() xmlTree.write(f, encoding='utf-8', xml_declaration=True) # required so that xml declarations will come up in generated XML usrSaveReqXML = f.getvalue().decode("utf-8") # converts bytes to string # print(usrSaveReqXML) responseXML = self.makeRequest(self.reqURL, usrSaveReqXML, self.headers) # print(responseXML) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() addUserReq = root.get('success') if (addUserReq == "1"): Utilities.printSuccess("Created user: "******"Nexpose\nUsername:"******"\nPassword:"******"User creation failed: " + msg) return False
def addSite(self, access_req): # print("TestModule:SiteManagement") siteSaveRequest = Element('SiteSaveRequest', attrib={'session-id': self.session_id}) # print(access_req['site_name']) # Site element have 'S' in caps !!--lost a day on this !! site_elem = SubElement(siteSaveRequest, 'Site', attrib={'name': access_req['site_name'], 'id': '-1'}) host_elem = SubElement(site_elem, 'Hosts') for ip in access_req['ip'].split(','): range_elem = SubElement(host_elem, 'range', attrib={'from': ip, 'to': ''}) scanConfig_elem = SubElement(site_elem, 'ScanConfig', attrib={'name': 'Full audit', 'templateID': 'full-audit'}) xmlTree = ElementTree(siteSaveRequest) f = BytesIO() xmlTree.write(f, encoding='utf-8', xml_declaration=True) # required so that xml declarations will come up in generated XML saveSiteReqXML = f.getvalue().decode("utf-8") # converts bytes to string # print(saveSiteReqXML) responseXML = self.makeRequest(self.reqURL, saveSiteReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() addSiteResponse = root.get('success') if (addSiteResponse == "1"): self.site_id = root.get('site-id') Utilities.printSuccess("Created site with site-id: " + self.site_id) return True else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Site creation failed: " + msg) return False
def add_asset_grp(self, access_req): scanner_id = self.get_scanners() self.url = self.qualys_host + "/api/2.0/fo/asset/group/" if scanner_id is not None: params = { 'action': 'add', 'ips': access_req['ip'], 'title': access_req['site_name'], 'appliance_ids': scanner_id } # print(self.url) response_asset_grp_add = self.makeRequest(params) # print(response_asset_grp_add.content) responseXML = response_asset_grp_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RESPONSE') asset_status = asset_response.find('TEXT').text if asset_status == "Asset Group successfully added.": Utilities.printSuccess("Asset group added to Qualys Scanner") return True else: Utilities.printError("Asset group addition Failure: " + asset_status) Utilities.printLog("Skipping remaning Qualys tasks..") return False else: Utilities.printError( "Asset Group adition Failure: Scanner id not found") return False
def login_nexpose(self, scanner_info): # API v1.1 Login and get the session here max_login_try_limit = 2 while True: if self.login_try == 0: xmlReq = Element('LoginRequest', attrib={'user-id': scanner_info['uname'], 'password': scanner_info['passwd']}) elif self.login_try > 0 and self.login_try < max_login_try_limit: usr_name = input("Please enter your username for " + " Nexpose" + ": ") usr_passwd = input("Please enter your password for " + " Nexpose" + ": ") xmlReq = Element('LoginRequest', attrib={'user-id': usr_name, 'password': usr_passwd}) else: Utilities.printError("Nexpose login attemts exceded maximum limit, skipping Nexpose tasks..") return False xmlReq = Element('LoginRequest', attrib={'user-id': scanner_info['uname'], 'password': scanner_info['passwd']}) xmlTree = ElementTree(xmlReq) f = BytesIO() xmlTree.write(f, encoding='utf-8', xml_declaration=True) # required so that xml declarations will come up in generated XML loginReqXML = f.getvalue().decode("utf-8") # converts bytes to string # print(self.loginReqXML) responseXML = self.makeRequest(self.reqURL, loginReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() loginResponse = root.get('success') if (loginResponse == "1"): self.session_id = root.get('session-id') Utilities.printSuccess("Logged in to Nexpose Scanner") return True else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Login Failure: " + msg) self.login_try += 1
def add_user(self, access_req): self.url = self.qualys_host + "/msp/user.php" usrLst = access_req['userList'] for user in usrLst: userinfo = user.split(',') # uname,name,email pswd = userinfo[0] + '!vul5c4p1' parms = {'action': 'add', 'user_role': 'scanner', 'business_unit': 'Unassigned', 'asset_groups': access_req['site_name'], 'first_name': userinfo[1].split(' ')[0], 'last_name': userinfo[1].split(' ')[1], 'title': 'Scanner User', 'phone': '0000000000', 'email': userinfo[2], 'address1': '3401 Hillview Ave', 'city': 'Palo Alto', 'country': 'United States of America', 'state': 'California', 'zip_code': '94304', 'send_email': '1'} response_user_add = self.makeRequest(parms) # print(response_user_add.content) responseXML = response_user_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RETURN') user_add_status = asset_response.get('status') user_add_status_msg = asset_response.find('MESSAGE').text # print(user_add_status + user_add_status_msg) if user_add_status == "SUCCESS": Utilities.printSuccess( user_add_status_msg +" for " + userinfo[1]) return True else: Utilities.printError("User addition Failure: " + user_add_status_msg) return False
def download_report(self, s, report_ID, target_IP): # downloading the reports ts = time.time() dt = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%dT%H%M%S') #file format: report folder, IP, date-time stamp filename = "qualys_scan_report_" + target_IP + "_" + dt + ".pdf" payload = { 'action': 'fetch', 'id': report_ID, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/report/', data=payload, stream=True) if r.status_code == 200: with open(filename, 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) Utilities.printLog("report downloaded") else: Utilities.printError( "report failed to download with status code: " + r1.status_code) #this is another way to save report #if the above method fails to save report correctly, use the below method '''
def launch_scan(self, s, target_IP, scan_option_id): # launching the scan scan_ref = "" payload = { 'action':'launch', 'ip':target_IP, 'iscanner_name':'is_vmwar_as', 'option_id':scan_option_id, #'797901', 'scan_title':target_IP, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/scan/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//ITEM'): if (elem[0].text == 'REFERENCE'): scan_ref = elem[1].text for elem in xmlreturn.findall('.//TEXT'): if "none of the specified IPs are eligible" in elem.text: Utilities.printError("You do not have permissions to run scans on IP " + target_IP) else: Utilities.printLog(elem.text) if "scan" in scan_ref: Utilities.printLog("Scan Reference Number: " + scan_ref) else: scan_ref = "SCAN_NOT_STARTED" return scan_ref
def launch_scan(self, s, target_IP, scan_option_id): # launching the scan scan_ref = "" payload = { 'action': 'launch', 'ip': target_IP, 'iscanner_name': 'is_vmwar_as', 'option_id': scan_option_id, #'797901', 'scan_title': target_IP, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/scan/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//ITEM'): if (elem[0].text == 'REFERENCE'): scan_ref = elem[1].text for elem in xmlreturn.findall('.//TEXT'): if "none of the specified IPs are eligible" in elem.text: Utilities.printError( "You do not have permissions to run scans on IP " + target_IP) else: Utilities.printLog(elem.text) if "scan" in scan_ref: Utilities.printLog("Scan Reference Number: " + scan_ref) else: scan_ref = "SCAN_NOT_STARTED" return scan_ref
def login_nexpose(self, scanner_info): # API v1.1 Login and get the session here max_login_try_limit = 2 while True: if self.login_try == 0: xmlReq = Element('LoginRequest', attrib={ 'user-id': scanner_info['uname'], 'password': scanner_info['passwd'] }) elif self.login_try > 0 and self.login_try < max_login_try_limit: usr_name = input("Please enter your username for " + " Nexpose" + ": ") usr_passwd = input("Please enter your password for " + " Nexpose" + ": ") xmlReq = Element('LoginRequest', attrib={ 'user-id': usr_name, 'password': usr_passwd }) else: Utilities.printError( "Nexpose login attemts exceded maximum limit, skipping Nexpose tasks.." ) return False xmlReq = Element('LoginRequest', attrib={ 'user-id': scanner_info['uname'], 'password': scanner_info['passwd'] }) xmlTree = ElementTree(xmlReq) f = BytesIO() xmlTree.write( f, encoding='utf-8', xml_declaration=True ) # required so that xml declarations will come up in generated XML loginReqXML = f.getvalue().decode( "utf-8") # converts bytes to string # print(self.loginReqXML) responseXML = self.makeRequest(self.reqURL, loginReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() loginResponse = root.get('success') if (loginResponse == "1"): self.session_id = root.get('session-id') Utilities.printSuccess("Logged in to Nexpose Scanner") return True else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Login Failure: " + msg) self.login_try += 1
def setup_auth(self, s, target_IP, username, password, title): #set up host authentication status = "Success" payload = { 'action': 'create', 'title': title + '_' + target_IP, 'ips': target_IP, 'username': username, 'password': password, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): if "action has invalid value" in elem.text: Utilities.printError( "You do not have permissions do add authentication records" ) else: Utilities.printSuccess("Authentication Record " + elem.text) if "existing scan auth record has the specified title" in elem.text: #delete the auth record payload = {'action': 'list', 'title': target_IP} r = s.post( 'https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//AUTH_UNIX'): title_id = elem[0].text payload = { 'action': 'delete', 'ids': title_id, } r = s.post( 'https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): status = elem.text Utilities.printLog("Authentication Record " + status) self.setup_auth(s, target_IP, username, password, title) elif "one or more of the specified IPs" in elem.text: #delete the auth record status = "Failure" Utilities.printError( "---\nPlease note:\nIP exists in another authentication record\nQualys doesn't support multiple authentication record of same type for any IP\nPlease delete the existing authentication record manually to proceed.\n---" ) return status
def handleAccessReq(self, access_req, scanner_info): user_add_status = False # print("TestMofule") if self.login_nexpose(scanner_info): addSiteStatus = self.addSite(access_req) if addSiteStatus: user_add_status = self.addUser(access_req) else: Utilities.printError("Site creation failed, aborting user creation..") self.logoutOperation() if user_add_status: return self.msg else: return "Nexpose user creation failed"
def addUser(self, access_req): # print("addUser Module") usrLst = access_req['userList'] for user in usrLst: usrSaveRequest = Element('UserSaveRequest', attrib={'session-id': self.session_id}) userinfo = user.split(',') # uname,name,email pswd = Utilities.gen_code() usrConfig_elem = SubElement(usrSaveRequest, 'UserConfig', attrib={ 'id': '-1', 'role-name': 'user', 'authsrcid': '-1', 'enabled': '1', 'name': userinfo[0], 'fullname': userinfo[1], 'email': userinfo[2], 'password': pswd }) sites_elem = SubElement(usrConfig_elem, 'UserSite') site_elem = SubElement(sites_elem, 'site', attrib={'id': self.site_id}) site_elem.text = access_req['site_name'] xmlTree = ElementTree(usrSaveRequest) f = BytesIO() xmlTree.write( f, encoding='utf-8', xml_declaration=True ) # required so that xml declarations will come up in generated XML usrSaveReqXML = f.getvalue().decode( "utf-8") # converts bytes to string # print(usrSaveReqXML) responseXML = self.makeRequest(self.reqURL, usrSaveReqXML, self.headers) # print(responseXML) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() addUserReq = root.get('success') if (addUserReq == "1"): Utilities.printSuccess("Created user: "******"Nexpose\nUsername:"******"\nPassword:"******"User creation failed: " + msg) return False
def login_nessus(self, scanner_info): sessionreqURL = self.nessus_host + "/session" max_login_try_limit = 2 while True: if self.login_try == 0: payload = {'username': scanner_info['uname'], 'password': scanner_info['passwd']} elif self.login_try > 0 and self.login_try < max_login_try_limit: usr_name = input("Please enter your username for " + " Nessus" + ": ") usr_passwd = input("Please enter your password for " + " Nessus" + ": ") payload = {'username': usr_name, 'password': usr_passwd} else: Utilities.printError("Nessus login attemts exceded maximum limit, skipping Nessus tasks..") return False response = self.makeRequest(sessionreqURL, json.dumps(payload), self.headers) json_rep = json.loads(response.decode("utf-8")) # convert to string then convert to json # print(json_rep) if self.status_code == 200: self.session_token = json_rep['token'] self.headers.update({'X-Cookie': 'token=' + self.session_token}) # session token added to HTTP header # print(self.headers) Utilities.printSuccess("Logged in to Nessus Scanner") return True elif self.status_code == 400: Utilities.printError("Login Failure: username format is not valid") self.login_try += 1 elif self.status_code == 401: Utilities.printError("Login Failure: username or password is invalid") self.login_try += 1 elif self.status_code == 500: Utilities.printError("Login Failure: too many users are connected") self.login_try += 1
def addSite(self, access_req): # print("TestModule:SiteManagement") siteSaveRequest = Element('SiteSaveRequest', attrib={'session-id': self.session_id}) # print(access_req['site_name']) # Site element have 'S' in caps !!--lost a day on this !! site_elem = SubElement(siteSaveRequest, 'Site', attrib={ 'name': access_req['site_name'], 'id': '-1' }) host_elem = SubElement(site_elem, 'Hosts') for ip in access_req['ip'].split(','): range_elem = SubElement(host_elem, 'range', attrib={ 'from': ip, 'to': '' }) scanConfig_elem = SubElement(site_elem, 'ScanConfig', attrib={ 'name': 'Full audit', 'templateID': 'full-audit' }) xmlTree = ElementTree(siteSaveRequest) f = BytesIO() xmlTree.write( f, encoding='utf-8', xml_declaration=True ) # required so that xml declarations will come up in generated XML saveSiteReqXML = f.getvalue().decode( "utf-8") # converts bytes to string # print(saveSiteReqXML) responseXML = self.makeRequest(self.reqURL, saveSiteReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() addSiteResponse = root.get('success') if (addSiteResponse == "1"): self.site_id = root.get('site-id') Utilities.printSuccess("Created site with site-id: " + self.site_id) return True else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Site creation failed: " + msg) return False
def handleAccessReq(self, access_req, scanner_info): user_add_status = False # print("TestMofule") if self.login_nexpose(scanner_info): addSiteStatus = self.addSite(access_req) if addSiteStatus: user_add_status = self.addUser(access_req) else: Utilities.printError( "Site creation failed, aborting user creation..") self.logoutOperation() if user_add_status: return self.msg else: return "Nexpose user creation failed"
def add_IP(self, s, target_IP): #set up host authentication payload = { 'action':'add', 'ips':target_IP, 'enable_vm':1, 'enable_pc':0, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/asset/ip/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): if "action has invalid value" in elem.text: Utilities.printError("You do not have permissions do add IP(s)") else: Utilities.printSuccess(elem.text)
def setup_auth(self, s, target_IP, username, password, title): #set up host authentication status = "Success" payload = { 'action':'create', 'title':title+'_'+target_IP, 'ips':target_IP, 'username':username, 'password':password, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): if "action has invalid value" in elem.text: Utilities.printError("You do not have permissions do add authentication records") else: Utilities.printSuccess("Authentication Record " + elem.text) if "existing scan auth record has the specified title" in elem.text: #delete the auth record payload = { 'action':'list', 'title':target_IP } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//AUTH_UNIX'): title_id = elem[0].text payload = { 'action':'delete', 'ids':title_id, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/auth/unix/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): status = elem.text Utilities.printLog("Authentication Record " + status) self.setup_auth(s, target_IP, username, password, title) elif "one or more of the specified IPs" in elem.text: #delete the auth record status = "Failure" Utilities.printError("---\nPlease note:\nIP exists in another authentication record\nQualys doesn't support multiple authentication record of same type for any IP\nPlease delete the existing authentication record manually to proceed.\n---") return status
def add_IP(self, s, target_IP): #set up host authentication payload = { 'action': 'add', 'ips': target_IP, 'enable_vm': 1, 'enable_pc': 0, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/asset/ip/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): if "action has invalid value" in elem.text: Utilities.printError( "You do not have permissions do add IP(s)") else: Utilities.printSuccess(elem.text)
def get_scanners(self): self.url = self.qualys_host + "/api/2.0/fo/appliance/" parms = {'action': 'list'} response_get_scanners = self.makeRequest(parms) # print(response_get_scanners.content) responseXML = response_get_scanners.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() if root.find('RESPONSE') is not None: response = root.find('RESPONSE') if response.find('APPLIANCE_LIST') is not None: appliance_list = response.find('APPLIANCE_LIST') appliance = appliance_list.findall('APPLIANCE') # we take only the first appliance, coz no multiple appliance nw. appliance_id = appliance[0].find('ID').text if response.find('TEXT') is not None: # Error condition Utilities.printError("Failure to get the scanner list: "+ response.find('TEXT').text) appliance_id = None # print(appliance_id) return appliance_id
def add_user(self, access_req): self.url = self.qualys_host + "/msp/user.php" usrLst = access_req['userList'] for user in usrLst: userinfo = user.split(',') # uname,name,email pswd = userinfo[0] + '!vul5c4p1' parms = { 'action': 'add', 'user_role': 'scanner', 'business_unit': 'Unassigned', 'asset_groups': access_req['site_name'], 'first_name': userinfo[1].split(' ')[0], 'last_name': userinfo[1].split(' ')[1], 'title': 'Scanner User', 'phone': '0000000000', 'email': userinfo[2], 'address1': '3401 Hillview Ave', 'city': 'Palo Alto', 'country': 'United States of America', 'state': 'California', 'zip_code': '94304', 'send_email': '1' } response_user_add = self.makeRequest(parms) # print(response_user_add.content) responseXML = response_user_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RETURN') user_add_status = asset_response.get('status') user_add_status_msg = asset_response.find('MESSAGE').text # print(user_add_status + user_add_status_msg) if user_add_status == "SUCCESS": Utilities.printSuccess(user_add_status_msg + " for " + userinfo[1]) return True else: Utilities.printError("User addition Failure: " + user_add_status_msg) return False
def logoutOperation(self): xmlReq = Element('LogoutRequest', attrib={'session-id': self.session_id}) xmlTree = ElementTree(xmlReq) f = BytesIO() xmlTree.write(f, encoding='utf-8', xml_declaration=True) # required so that xml declarations will come up in generated XML logoutReqXML = f.getvalue().decode("utf-8") # converts bytes to string # print(logoutReqXML) responseXML = self.makeRequest(self.reqURL, logoutReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() logoutResponse = root.get('success') if (logoutResponse == "1"): self.session_id = root.get('session-id') Utilities.printSuccess("Logged out of Nexpose Scanner") else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Logout Failure: " + msg)
def add_asset(self, access_req): self.url = self.qualys_host + "/api/2.0/fo/asset/ip/" params = {'action': 'add', 'ips': access_req['ip'], 'enable_vm': '1'} max_login_try_limit = 2 while True: # Login check done here, if it fails here then rest all task is skipped if (self.login_try > 0) and (self.login_try < max_login_try_limit): self.uname = input("Please enter your username for " + " Qualys" + ": ") self.passwd = input("Please enter your password for " + " Qualys" + ": ") elif self.login_try >= max_login_try_limit: Utilities.printError("Qualys login attemts exceded maximum limit, skipping Qualys tasks..") return False response_aasset_add = self.makeRequest(params) # print(response_aasset_add.content) responseXML = response_aasset_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RESPONSE') asset_status = asset_response.find('TEXT').text if asset_status == "IPs successfully added to Vulnerability Management": Utilities.printSuccess("Asset added to Qualys Scanner") return True elif asset_status == "Bad Login/Password": Utilities.printError("Qualys login failed..") self.login_try += 1 else: Utilities.printError("Asset adition Failure: " + asset_status) Utilities.printLog("Skipping remaning Qualys tasks..") return False
def create_user(self, access_req): try: # Create User create_user_URL = self.nessus_host + "/users" usrLst = access_req['userList'] for user in usrLst: userinfo = user.split(',') # uname,name,email pswd = Utilities.gen_code() payload = {'username': userinfo[0], 'password': pswd, 'permissions': '32', 'name': userinfo[1], 'email': userinfo[2], 'type': 'local'} response = self.makeRequest(create_user_URL, json.dumps(payload), self.headers) json_rep = json.loads(response.decode("utf-8")) # print(json_rep) if self.status_code == 200: Utilities.printSuccess("Created user: "******"Nessus\nUsername:"******"\nPassword:"******"User creation Failure: Invalid field request") return False if self.status_code == 403: Utilities.printError("User creation Failure: No permission to create a user") return False if self.status_code == 409: Utilities.printError("User creation Failure: Duplicate username") return False except Exception as e: Utilities.printException(str(e))
def add_asset(self, access_req): self.url = self.qualys_host + "/api/2.0/fo/asset/ip/" params = {'action': 'add', 'ips': access_req['ip'], 'enable_vm': '1'} max_login_try_limit = 2 while True: # Login check done here, if it fails here then rest all task is skipped if (self.login_try > 0) and (self.login_try < max_login_try_limit): self.uname = input("Please enter your username for " + " Qualys" + ": ") self.passwd = input("Please enter your password for " + " Qualys" + ": ") elif self.login_try >= max_login_try_limit: Utilities.printError( "Qualys login attemts exceded maximum limit, skipping Qualys tasks.." ) return False response_aasset_add = self.makeRequest(params) # print(response_aasset_add.content) responseXML = response_aasset_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RESPONSE') asset_status = asset_response.find('TEXT').text if asset_status == "IPs successfully added to Vulnerability Management": Utilities.printSuccess("Asset added to Qualys Scanner") return True elif asset_status == "Bad Login/Password": Utilities.printError("Qualys login failed..") self.login_try += 1 else: Utilities.printError("Asset adition Failure: " + asset_status) Utilities.printLog("Skipping remaning Qualys tasks..") return False
def check_scan(self, s, scan_ref): # checks the status of the scan state = "Default" payload = { 'action':'list', 'scan_ref':scan_ref, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/scan/', data=payload) xmlreturn = ET.fromstring(r.text) code = xmlreturn.find('.//CODE') status = xmlreturn.find('.//STATUS') text = xmlreturn.find('.//TEXT') if status != None: state = status[0].text if code != None: if text != None: Utilities.printError("Error Text: " + text.text) Utilities.printLog("Scan status: " + state) return state
def quick_scan(self, s, target_IP, username, password, title, scan_option_id, report_template_id): Utilities.printLog("Quick Scan: " + target_IP) #add IPs self.add_IP(s, target_IP) #add authentication record status = self.setup_auth(s, target_IP, username, password, title).lower() if status == "failure": return #start the scan scan_ref = self.launch_scan(s, target_IP, scan_option_id) if scan_ref == "SCAN_NOT_STARTED": Utilities.printError("Scan has not started for IP: " + target_IP) return #check the scan status after every 100 seconds #add a new if statement for various check_scan return value that is discovered while 1: #waiting for 5 mins = 300 time.sleep(300) status = self.check_scan(s, scan_ref).lower() if status == "finished": break elif status == "queued" or status == "loading" or status == "running": continue else: return #generate report after scan has completed report_type = 'pdf' report_ID = self.launch_report(s, scan_ref, report_type, target_IP, report_template_id) #waiting for report generation; then download report time.sleep(25) self.download_report(s, report_ID, target_IP)
def logoutOperation(self): xmlReq = Element('LogoutRequest', attrib={'session-id': self.session_id}) xmlTree = ElementTree(xmlReq) f = BytesIO() xmlTree.write( f, encoding='utf-8', xml_declaration=True ) # required so that xml declarations will come up in generated XML logoutReqXML = f.getvalue().decode("utf-8") # converts bytes to string # print(logoutReqXML) responseXML = self.makeRequest(self.reqURL, logoutReqXML, self.headers) tree = ElementTree(fromstring(responseXML)) root = tree.getroot() logoutResponse = root.get('success') if (logoutResponse == "1"): self.session_id = root.get('session-id') Utilities.printSuccess("Logged out of Nexpose Scanner") else: fa = root.find('Failure') ex = fa.find('Exception') msg = ex.find('message').text Utilities.printError("Logout Failure: " + msg)
def get_scanners(self): self.url = self.qualys_host + "/api/2.0/fo/appliance/" parms = {'action': 'list'} response_get_scanners = self.makeRequest(parms) # print(response_get_scanners.content) responseXML = response_get_scanners.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() if root.find('RESPONSE') is not None: response = root.find('RESPONSE') if response.find('APPLIANCE_LIST') is not None: appliance_list = response.find('APPLIANCE_LIST') appliance = appliance_list.findall( 'APPLIANCE' ) # we take only the first appliance, coz no multiple appliance nw. appliance_id = appliance[0].find('ID').text if response.find('TEXT') is not None: # Error condition Utilities.printError("Failure to get the scanner list: " + response.find('TEXT').text) appliance_id = None # print(appliance_id) return appliance_id
def check_scan(self, s, scan_ref): # checks the status of the scan state = "Default" payload = { 'action': 'list', 'scan_ref': scan_ref, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/scan/', data=payload) xmlreturn = ET.fromstring(r.text) code = xmlreturn.find('.//CODE') status = xmlreturn.find('.//STATUS') text = xmlreturn.find('.//TEXT') if status != None: state = status[0].text if code != None: if text != None: Utilities.printError("Error Text: " + text.text) Utilities.printLog("Scan status: " + state) return state
def add_asset_grp(self, access_req): scanner_id = self.get_scanners() self.url = self.qualys_host + "/api/2.0/fo/asset/group/" if scanner_id is not None: params = {'action': 'add', 'ips': access_req['ip'], 'title': access_req['site_name'], 'appliance_ids':scanner_id} # print(self.url) response_asset_grp_add = self.makeRequest(params) # print(response_asset_grp_add.content) responseXML = response_asset_grp_add.content tree = ElementTree(fromstring(responseXML)) root = tree.getroot() asset_response = root.find('RESPONSE') asset_status = asset_response.find('TEXT').text if asset_status == "Asset Group successfully added.": Utilities.printSuccess("Asset group added to Qualys Scanner") return True else: Utilities.printError("Asset group addition Failure: " + asset_status) Utilities.printLog("Skipping remaning Qualys tasks..") return False else: Utilities.printError("Asset Group adition Failure: Scanner id not found") return False
def download_report(self, s, report_ID, target_IP): # downloading the reports ts = time.time() dt = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%dT%H%M%S') #file format: report folder, IP, date-time stamp filename = "qualys_scan_report_"+target_IP+"_"+dt+".pdf" payload = { 'action':'fetch', 'id':report_ID, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/report/', data=payload, stream=True) if r.status_code == 200: with open(filename, 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) Utilities.printLog("report downloaded") else: Utilities.printError("report failed to download with status code: " + r1.status_code) #this is another way to save report #if the above method fails to save report correctly, use the below method '''
def login_nessus(self, scanner_info): sessionreqURL = self.nessus_host + "/session" max_login_try_limit = 2 while True: if self.login_try == 0: payload = { 'username': scanner_info['uname'], 'password': scanner_info['passwd'] } elif self.login_try > 0 and self.login_try < max_login_try_limit: usr_name = input("Please enter your username for " + " Nessus" + ": ") usr_passwd = input("Please enter your password for " + " Nessus" + ": ") payload = {'username': usr_name, 'password': usr_passwd} else: Utilities.printError( "Nessus login attemts exceded maximum limit, skipping Nessus tasks.." ) return False response = self.makeRequest(sessionreqURL, json.dumps(payload), self.headers) json_rep = json.loads(response.decode( "utf-8")) # convert to string then convert to json # print(json_rep) if self.status_code == 200: self.session_token = json_rep['token'] self.headers.update({ 'X-Cookie': 'token=' + self.session_token }) # session token added to HTTP header # print(self.headers) Utilities.printSuccess("Logged in to Nessus Scanner") return True elif self.status_code == 400: Utilities.printError( "Login Failure: username format is not valid") self.login_try += 1 elif self.status_code == 401: Utilities.printError( "Login Failure: username or password is invalid") self.login_try += 1 elif self.status_code == 500: Utilities.printError( "Login Failure: too many users are connected") self.login_try += 1
def create_user(self, access_req): try: # Create User create_user_URL = self.nessus_host + "/users" usrLst = access_req['userList'] for user in usrLst: userinfo = user.split(',') # uname,name,email pswd = Utilities.gen_code() payload = { 'username': userinfo[0], 'password': pswd, 'permissions': '32', 'name': userinfo[1], 'email': userinfo[2], 'type': 'local' } response = self.makeRequest(create_user_URL, json.dumps(payload), self.headers) json_rep = json.loads(response.decode("utf-8")) # print(json_rep) if self.status_code == 200: Utilities.printSuccess("Created user: "******"Nessus\nUsername:"******"\nPassword:"******"User creation Failure: Invalid field request") return False if self.status_code == 403: Utilities.printError( "User creation Failure: No permission to create a user" ) return False if self.status_code == 409: Utilities.printError( "User creation Failure: Duplicate username") return False except Exception as e: Utilities.printException(str(e))
def xml_error(msg): Utilities.printError(msg) raise SystemExit