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 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 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 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 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 logout(self, s): payload = {'action': 'logout'} r = s.post('https://qualysapi.qualys.com/api/2.0/fo/session/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): Utilities.printLog(elem.text)
def logout(self, s): payload = { 'action':'logout' } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/session/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): Utilities.printLog(elem.text)
def login(self, s, username, password): payload = { 'action':'login', 'username':username, 'password':password } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/session/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): Utilities.printLog(elem.text) Utilities.printLog("Cookie: QualysSession = " + r.cookies['QualysSession'])
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 login(self, s, username, password): payload = { 'action': 'login', 'username': username, 'password': password } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/session/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//TEXT'): Utilities.printLog(elem.text) Utilities.printLog("Cookie: QualysSession = " + r.cookies['QualysSession'])
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 launch_report(self, s, scan_ref, report_type, target_IP, report_template_id): # launching report report_ID = "" payload = { 'action':'launch', 'report_type':'Scan', 'template_id':report_template_id,#'991466', 'output_format':report_type, 'report_refs':scan_ref, 'report_title':target_IP, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/report/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//ITEM'): if (elem[0].text == 'ID'): report_ID = elem[1].text Utilities.printLog("Report ID: " + report_ID) return report_ID
def access_request_handler(): access_details = readAccessReq() # Reading the Access Request try: tree = parse('scanner_details.xml') # Reading the Scanner Details root = tree.getroot() # Access request handler for scanners # Read Nessus scanner details scanner = root.find('nessus') execute_nessus = scanner.get('enabled') if execute_nessus == '1': # print(scanner) if scanner.find('host').text is None or scanner.find('username').text is None or scanner.find('host').text is None: xml_error("Nessus data missing in scanner_details.xml") print("Nessus" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Nessus" + ": ") nessus_details = {'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text} # Scanner task calls from here Utilities.printLog("Executing Nessus tasks") nessusObj = nes.Nessus(nessus_details) # Create Nessus scanner class obj msg = nessusObj.handleAccessReq(access_details, nessus_details) # Login | Add User | Logout # Read Nexpose scanner details scanner = root.find('nexpose') execute_nexpose = scanner.get('enabled') if execute_nexpose == '1': # print(scanner) if scanner.find('host').text is None or scanner.find('username').text is None or scanner.find('host').text is None: xml_error("Nexpose data missing in scanner_details.xml") print("Nexpose" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Nexpose" + ": ") nexpose_details = {'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text} # Scanner task calls from here Utilities.printLog("Executing Nexpose tasks") nexposeObj = nex.Nexpose(nexpose_details) # Create Nexpose scanner class obj msg += "\n"+nexposeObj.handleAccessReq(access_details, nexpose_details) # Login | SaveSite | Add User | Logout # Read Qualys scanner details scanner = root.find('qualys') execute_qualys = scanner.get('enabled') if execute_qualys == '1': # print(scanner) if scanner.find('host').text is None or scanner.find('username').text is None or scanner.find('host').text is None: xml_error("Qualys data missing in scanner_details.xml") print("Qualys" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Qualys" + ": ") qualys_details = {'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text} # Scanner task calls from here Utilities.printLog("Executing Qualys tasks") qualysObj = qua.Qualys(qualys_details) # Create Qualys scanner class obj qualysObj.handleAccessReq(access_details, qualys_details) # Login | Add Asset | Add Asset Grp | Add User msg +="\nQualys\nDetails send to email." Utilities.write_to_file(msg) except Exception as e: Utilities.printException("In fun access_request_handler():"+ str(e))
def launch_report(self, s, scan_ref, report_type, target_IP, report_template_id): # launching report report_ID = "" payload = { 'action': 'launch', 'report_type': 'Scan', 'template_id': report_template_id, #'991466', 'output_format': report_type, 'report_refs': scan_ref, 'report_title': target_IP, } r = s.post('https://qualysapi.qualys.com/api/2.0/fo/report/', data=payload) xmlreturn = ET.fromstring(r.text) for elem in xmlreturn.findall('.//ITEM'): if (elem[0].text == 'ID'): report_ID = elem[1].text Utilities.printLog("Report ID: " + report_ID) return report_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 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 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 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 access_request_handler(): access_details = readAccessReq() # Reading the Access Request try: tree = parse('scanner_details.xml') # Reading the Scanner Details root = tree.getroot() # Access request handler for scanners # Read Nessus scanner details scanner = root.find('nessus') execute_nessus = scanner.get('enabled') if execute_nessus == '1': # print(scanner) if scanner.find('host').text is None or scanner.find( 'username').text is None or scanner.find( 'host').text is None: xml_error("Nessus data missing in scanner_details.xml") print("Nessus" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Nessus" + ": ") nessus_details = { 'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text } # Scanner task calls from here Utilities.printLog("Executing Nessus tasks") nessusObj = nes.Nessus( nessus_details) # Create Nessus scanner class obj msg = nessusObj.handleAccessReq( access_details, nessus_details) # Login | Add User | Logout # Read Nexpose scanner details scanner = root.find('nexpose') execute_nexpose = scanner.get('enabled') if execute_nexpose == '1': # print(scanner) if scanner.find('host').text is None or scanner.find( 'username').text is None or scanner.find( 'host').text is None: xml_error("Nexpose data missing in scanner_details.xml") print("Nexpose" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Nexpose" + ": ") nexpose_details = { 'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text } # Scanner task calls from here Utilities.printLog("Executing Nexpose tasks") nexposeObj = nex.Nexpose( nexpose_details) # Create Nexpose scanner class obj msg += "\n" + nexposeObj.handleAccessReq( access_details, nexpose_details) # Login | SaveSite | Add User | Logout # Read Qualys scanner details scanner = root.find('qualys') execute_qualys = scanner.get('enabled') if execute_qualys == '1': # print(scanner) if scanner.find('host').text is None or scanner.find( 'username').text is None or scanner.find( 'host').text is None: xml_error("Qualys data missing in scanner_details.xml") print("Qualys" + " host@:" + scanner.find('host').text) # print(scanner.find('username').text) usr_passwd = input("Please enter your password for " + " Qualys" + ": ") qualys_details = { 'uname': scanner.find('username').text, 'passwd': usr_passwd, 'host': scanner.find('host').text } # Scanner task calls from here Utilities.printLog("Executing Qualys tasks") qualysObj = qua.Qualys( qualys_details) # Create Qualys scanner class obj qualysObj.handleAccessReq( access_details, qualys_details) # Login | Add Asset | Add Asset Grp | Add User msg += "\nQualys\nDetails send to email." Utilities.write_to_file(msg) except Exception as e: Utilities.printException("In fun access_request_handler():" + str(e))