Skip to content

Network Automation

My journey with Network & Cloud Automation

Menu
  • Beginner
  • DevOps-NetDevOps
  • Network Automation
    • Docker
    • Python Libraries
      • NAPALM
      • Netmiko
      • Jinja2
      • Scrapli
      • Yang
  • Cloud Automation
    • Terraform
  • Python 🐍 Tips and Tricks
Menu
SDWAN Vulnerability scanner

Cisco SDWAN Vulnerability Scanner using Python

Posted on September 29, 2021September 28, 2021 by Gurpreet Kochar

Cisco does have a bug toolkit to programmatically fetch the vulnerability information but it doesn’t have any such API for SDWAN vulnerability information yet. So I had the option to create a web scraper to fetch that information into an excel sheet and update it automatically at a click of a button. Let’s take a look at a very straightforward code that you can modify to suit your requirements.

Cisco posts its SDWAN vulnerability information at this URL.

Intent:- Click on each URL on this web page automatically and gather the required information from each URL and dump it into an excel sheet.

STEP1:-

setup imports and write a method to fetch all URLs from cisco’s SDWAN vulnerability URL

from bs4 import BeautifulSoup
import requests
import os


URL_SDWAN = "https://www.cisco.com/c/en/us/support/routers/sd-wan/products-security-advisories-list.html"

class SDWAN_BS4:
	def __init__(self):
		self.OUTPUT = os.path.join(os.getcwd(), 'OUTPUT')
	
	def get_all_vuln_urls(self):
		all_urls = []
		r = requests.get(URL_SDWAN)
		if r.ok:
			soup = BeautifulSoup(r.text, 'lxml')
		hrefs = soup.find('div', class_="no-groups").find_all('a')
		all_urls = [f"https://www.cisco.com/{href.get('href')}" for href in hrefs]
		return all_urls

Executing the above piece of code gives us a list of all SDWAN Vulnerabilities that have been published

[
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-Fhqh8pKX.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-jOsuRJCc.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-credentials-ydYfskzZ.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-maapi-cmdinjec-znUYTuC.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdw-mpls-infodisclos-MSSRFkZq.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-vmanage-infdis-LggOP9sE.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-fuErCWwF.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdw-auth-bypass-65aYqcS2.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-vmanage-4TbynnhZ.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-dos-Ckn5cVqW.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-privesc-QVszVUPy.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-vmanageinfdis-LKrFpbv.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-vmanage-9VZO4gfU.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-arbfile-7Qhd9mCn.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-enumeration-64eNnDKy.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-xss-eN75jxtW.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-vmaninfdis3-OvdR6uu8.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-auth-bypass-Z3Zze5XC.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-cmdinj-nRHKgfHX.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-xml-ext-entity-q6Z7uVUg.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-cql-inject-c7z9QqyB.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-info-disclos-gGvm9Mfu.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-YuTVWqy.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-authorization-b-GUEpSLK.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwanvman-infodis1-YuQScHB.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdw-sqlinj-HDJUeEAX.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-vdaemon-bo-RuzzEA2.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-privesc-vman-kth3c82B.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-sigverbypass-gPYXd6Mk.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-dir-trav-Bpwc5gtm.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-pathtrav-Z5mCVsjf.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-vinfdis-MC8L58dj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-infodis-2-UPO232DG.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-cql-inject-72EhnUc.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-sqlinjm-xV8dsjq5.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-cmdinjm-9QMSmgcn.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-dosmulti-48jJuEUP.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-abyp-TnGFHrS.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-bufovulns-B5NrSHbj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-file-Y2JSRNRb.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanpt2-FqLuefsS.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmxss2-NL4KSSVR.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanxsshi-9KHEqRpM.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanxss1-XhJCymBt.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-cedge-filt-bypass-Y6wZMqm4.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-privilege-zPmMf73k.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanuafw-ZHkdGGEy.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanxss2-ugJyqxWF.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanx3-vrZbOqqD.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanx2-KpFVSUc.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vepeshlg-tJghOQcA.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vepestd-8C3J9Vc.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vsoln-arbfile-gtsEYxns.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vman-traversal-hQh24tmk.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-escalation-Jhqs5Skf.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vepescm-BjgQm4vJ.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vepegr-4xynYLUj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwan-xss-xXeLFpC3.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdbufof-h5f5VSeL.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-uabvman-SYGzt8Bv.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-clibypvman-sKcLf2L.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanrce-4jtWT28P.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdw-dos-KWOdyHnB.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdscred-HfWWfqBj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sivm-M8wugR9O.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmdirtrav-eFdAxsJg.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanxss-z7bhvHpy.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanxml-Aj4GFEKd.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmandowndir-CVGvdKM3.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmpresc-SyzcS4kC.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanage-v78FubGV.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-emvman-3y6LuTcZ.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-vmanwebid-5QWMcCvt.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200318-vmanage-cypher-inject.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwpresc-ySJGvE9.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwclici-cvrQpH9v.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sdwanbo-QKcABnS2.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200318-vmanage-xss.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200122-sdwan-cmd-inject.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200122-sdwan-sqlinj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200122-sdwan-priv-esc.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20200122-sdwan-sql-inject.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20191120-vman-csrf.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190807-sd-wan-bypass.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190619-sdwan-cmdinj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190619-sdwan-privesca.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190619-sdwan-privilescal.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190123-sdwan-escal.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190123-sdwan-unaccess.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190123-sdwan-sol-escal.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190123-sdwan-bo.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20190123-sdwan-file-write.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20181003-sd-wan-bypass.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180905-sd-wan-escalation.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180905-sd-wan-injection.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180905-sd-wan-validation.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sd-wan-bo.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sd-wan-code-ex.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sd-wan-cmd-inject.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-coinj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-cmdinj.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-fo.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-cmdnjct.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-ci.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-dos.html',
    'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-20180718-sdwan-cx.html'
]

STEP2:- Write a method to access information inside each of these URLs and gather the required information. In this case, I am going to fetch information with the below fields in a dictionary. I assume this is all we need in most of the cases when doing vulnerability assessment.

d = {
			"Advisory ID" : advisory_id,
			"URL" : url,
			"CVE" : cve,
			"First Published" : first_published,
			"Last Updated" : last_updated,
			"BUG IDs" : '\n'.join(ids).strip(),
			"BUG URL" : '\n'.join(urls).strip(),
			"CVE" : '\n'.join(cve).strip(),
			"Summary" : summary,
			"Vulnerable Products" : vuln_products,
			"Non Vulnerable" : non_vuln_products,
			"Workaround" : workaround,
			"Fixed Software" : fixed_software
		}

This method is the heart of this script and can get a little tricky. The intent here is to mimic how HTML on that webpage has stored information and extract information from HTML. If you inspect that webpage, you will find the same elements as mentioned in the below code where the information we need exists. Take some time to review especially if you are not at all familiar with web scrapping.

def get_vuln_detail(self, url):
		r = requests.get(url)
		if r.ok:
			soup = BeautifulSoup(r.text, 'lxml')

		advisory_id = soup.find('div',  id="divpubidvalue").text
		URL = url
		first_published = soup.find('div', id='ud-published').find('div', class_='divLabelContent').text.replace(u'\xa0', u' ')
		try:
			last_updated = soup.find('div', id='ud-last-updated').find('div', class_='divLabelContent').text.replace(u'\xa0', u' ')
		except Exception:
			last_updated = 'Not published'
		try:
			bugs = soup.find('span', id='fullddtscontent_content').find_all('a')
		except Exception:
			bugs = soup.find('div', class_='ddtsList').find_all('a')
		urls = [url.get('href') for url in bugs if '#' not in url.get('href')]
		ids = [url.text for url in bugs]
		try:
			cve = soup.find('span', id='fullcvecontent_content').text
			cve = cve.spit(',')
		except Exception:
			cve = soup.find('div', class_='CVEList').find_all('div', class_='inlineblock divPaddingTen')
			cve = [x.text for x in cve]
		summary = soup.find('div', id="summaryfield").text.strip()
		vuln_products = soup.find('div', id="vulnerableproducts").text.strip()
		non_vuln_products = soup.find('div', id="productsconfirmednotvulnerable").text.strip()
		workaround = soup.find('div', id='workaroundsfield').text.strip()
		fixed_software = soup.find('div', id='fixedsoftfield').text.strip()

		d = {
			"Advisory ID" : advisory_id,
			"URL" : url,
			"CVE" : cve,
			"First Published" : first_published,
			"Last Updated" : last_updated,
			"BUG IDs" : '\n'.join(ids).strip(),
			"BUG URL" : '\n'.join(urls).strip(),
			"CVE" : '\n'.join(cve).strip(),
			"Summary" : summary,
			"Vulnerable Products" : vuln_products,
			"Non Vulnerable" : non_vuln_products,
			"Workaround" : workaround,
			"Fixed Software" : fixed_software
		}

		return d

The above method gives us output in the below format

{
    'Advisory ID': 'cisco-sa-sd-wan-Fhqh8pKX',
    'URL': 'https://www.cisco.com//c/en/us/support/docs/csa/cisco-sa-sd-wan-Fhqh8pKX.html',
    'CVE': 'CVE-2021-1546',
    'First Published': '2021 September 22 16:00 GMT',
    'Last Updated': 'Not published',
    'BUG IDs': 'CSCvx79335',
    'BUG URL': 'https://bst.cloudapps.cisco.com/bugsearch/bug/CSCvx79335',
    'Summary': 'A vulnerability in the CLI of Cisco\xa0SD-WAN Software could allow an authenticated, local attacker to access sensitive information.\nThis vulnerability is due to improper protections on file 
access through the CLI. An attacker could exploit this vulnerability by running a CLI command that targets an arbitrary file on the local system. A successful exploit could allow the attacker to return portions
of an arbitrary file, possibly resulting in the disclosure of sensitive information.\nCisco\xa0has released software updates that address this vulnerability. There are no workarounds that address this 
vulnerability.\nThis advisory is available at the following link:https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-sd-wan-Fhqh8pKX',
    'Vulnerable Products': 'At the time of publication, this vulnerability affected the following Cisco\xa0products if they were running a vulnerable release of Cisco\xa0SD-WAN Software:\n\nSD-WAN vBond 
Orchestrator Software\nSD-WAN vEdge Cloud Routers\nSD-WAN vEdge Routers\nSD-WAN vManage Software\nSD-WAN vSmart Controller Software\n\nFor information about which Cisco\xa0software releases were vulnerable, see
the Fixed Software section of this advisory. See the Details section in the bug ID(s) at the top of this advisory for the most complete and current information.',
    'Non Vulnerable': 'Only products listed in the Vulnerable Products section of this advisory are known to be affected by this vulnerability.\nCisco\xa0has confirmed that this vulnerability does not affect 
Cisco\xa0IOS XE SD-WAN Software.',
    'Workaround': 'There are no workarounds that address this vulnerability.',
    'Fixed Software': 'When considering software upgrades, customers are advised to regularly consult the advisories for Cisco\xa0products, which are available from the Cisco\xa0Security Advisories page, to 
determine exposure and a complete upgrade solution.\nIn all cases, customers should ensure that the devices to be upgraded contain sufficient memory and confirm that current hardware and software configurations
will continue to be supported properly by the new release. If the information is not clear, customers are advised to contact the Cisco\xa0Technical Assistance Center (TAC) or their contracted maintenance 
providers.\nFixed Releases\nAt the time of publication, the release information in the following table(s) was accurate.\xa0See the Details section in the bug ID(s) at the top of this advisory for the most 
complete and current information.\nThe left column lists Cisco\xa0software releases, and the right column indicates whether a release was affected by the vulnerability described in this advisory and which 
release included the fix for this vulnerability.\n\n\n\nCisco\xa0SD-WAN Software Release\nFirst Fixed Release\n\n\n\n\n18.4\nMigrate to a fixed release.\n\n\n19.2\nMigrate to a fixed 
release.\n\n\n20.3\xa0\nMigrate to a fixed release.\n\n\n20.4\n20.4.2\n\n\n20.5\n20.5.2\n\n\n20.6\n20.6.1'
}

STEP3:- Create a method to write to an excel sheet. It takes in a list of data frames, output folder, and filename as an argument and writes each dataframe to a separate sheet of workbook like in this case.

	def write_to_excel(self, df_list, folder, file_name):
		save_file_name = f"{folder}/{file_name}_{datetime.now().strftime('%d-%b-%Y')}.xlsx"
		writer = pd.ExcelWriter(save_file_name, engine='xlsxwriter')
		for df, sheetname, index in df_list:
			df.to_excel(writer, sheet_name=sheetname, index=index)
		writer.save()

STEP4:- Iterate over each URL and prepare the data frames that we need to create excel sheets.

	def create_sdwan_vuln_report(self):
		all_urls = self.get_all_vuln_urls()
		self.data = [self.get_vuln_detail(url) for url in all_urls]
		df = pd.DataFrame(self.data)
		df_exploded = df.copy()
		df_exploded['BUG IDs'] = df_exploded['BUG IDs'].str.split('\n')
		df_exploded = df_exploded.explode('BUG IDs')
		df_list = [(df, 'SDWAN_VULNS', False), (df_exploded, 'RAW', False)]
		self.write_to_excel(df_list, self.OUTPUT, 'sdwan_vulnerabilities_bs4')

STEP5:- Bringing it all together

from bs4 import BeautifulSoup
import requests
import pandas as pd
import os
from datetime import datetime


URL_SDWAN = "https://www.cisco.com/c/en/us/support/routers/sd-wan/products-security-advisories-list.html"

class SDWAN_BS4:
	def __init__(self):
		self.OUTPUT = os.path.join(os.getcwd(), 'OUTPUT')
		if not os.path.exists(self.OUTPUT):
			os.mkdir(self.OUTPUT)
	
	def get_all_vuln_urls(self):
		all_urls = []
		r = requests.get(URL_SDWAN)
		if r.ok:
			soup = BeautifulSoup(r.text, 'lxml')
		hrefs = soup.find('div', class_="no-groups").find_all('a')
		all_urls = [f"https://www.cisco.com/{href.get('href')}" for href in hrefs]
		return all_urls
	
	def get_vuln_detail(self, url):
		r = requests.get(url)
		if r.ok:
			soup = BeautifulSoup(r.text, 'lxml')

		advisory_id = soup.find('div',  id="divpubidvalue").text
		URL = url
		first_published = soup.find('div', id='ud-published').find('div', class_='divLabelContent').text.replace(u'\xa0', u' ')
		try:
			last_updated = soup.find('div', id='ud-last-updated').find('div', class_='divLabelContent').text.replace(u'\xa0', u' ')
		except Exception:
			last_updated = 'Not published'
		try:
			bugs = soup.find('span', id='fullddtscontent_content').find_all('a')
		except Exception:
			bugs = soup.find('div', class_='ddtsList').find_all('a')
		urls = [url.get('href') for url in bugs if '#' not in url.get('href')]
		ids = [url.text for url in bugs]
		try:
			cve = soup.find('span', id='fullcvecontent_content').text
			cve = cve.spit(',')
		except Exception:
			cve = soup.find('div', class_='CVEList').find_all('div', class_='inlineblock divPaddingTen')
			cve = [x.text for x in cve]
		summary = soup.find('div', id="summaryfield").text.strip()
		vuln_products = soup.find('div', id="vulnerableproducts").text.strip()
		non_vuln_products = soup.find('div', id="productsconfirmednotvulnerable").text.strip()
		workaround = soup.find('div', id='workaroundsfield').text.strip()
		fixed_software = soup.find('div', id='fixedsoftfield').text.strip()

		d = {
			"Advisory ID" : advisory_id,
			"URL" : url,
			"CVE" : cve,
			"First Published" : first_published,
			"Last Updated" : last_updated,
			"BUG IDs" : '\n'.join(ids).strip(),
			"BUG URL" : '\n'.join(urls).strip(),
			"CVE" : '\n'.join(cve).strip(),
			"Summary" : summary,
			"Vulnerable Products" : vuln_products,
			"Non Vulnerable" : non_vuln_products,
			"Workaround" : workaround,
			"Fixed Software" : fixed_software
		}

		return d


	def write_to_excel(self, df_list, folder, file_name):
		save_file_name = f"{folder}/{file_name}_{datetime.now().strftime('%d-%b-%Y')}.xlsx"
		writer = pd.ExcelWriter(save_file_name, engine='xlsxwriter')
		for df, sheetname, index in df_list:
			df.to_excel(writer, sheet_name=sheetname, index=index)
		writer.save()


	def create_sdwan_vuln_report(self):
		all_urls = self.get_all_vuln_urls()
		self.data = [self.get_vuln_detail(url) for url in all_urls]
		df = pd.DataFrame(self.data)
		df_exploded = df.copy()
		df_exploded['BUG IDs'] = df_exploded['BUG IDs'].str.split('\n')
		df_exploded = df_exploded.explode('BUG IDs')
		df_list = [(df, 'SDWAN_VULNS', False), (df_exploded, 'RAW', False)]
		self.write_to_excel(df_list, self.OUTPUT, 'sdwan_vulnerabilities_bs4')


if __name__ == '__main__':
	sdwan = SDWAN_BS4()
	sdwan.create_sdwan_vuln_report()

At this point, you should have an excel sheet that looks like this ( unformatted but it does contain everything you need). Also, you could add print statements, logs, progress bars to make it more verbose at the moment, you will see nothing when it’s working. Another enhancement could be to use threads to make the script faster since there are tens of URLs we need to fetch information from. Search for multithreading and multiprocessing in the search bar on the top right for the blog about those.

sdwan_vulnerabilities_bs4_28-Sep-2021Download

You could add a couple of more methods to format the excel sheet to your desire as well. Here is my implementation of openpyxl formatting.

def _color_formatting(self, workbook):
		# Add a format. Light red fill with dark red text.
		red = workbook.add_format({'bg_color': '#FFC7CE',
									'font_color': '#9C0006'})

		# Add a format. Yellow fill with dark yellow text.
		yellow = workbook.add_format({'bg_color':   '#FFEB9C',
										'font_color': '#9C6500'})

		# Add a format. Green fill with dark green text.
		green = workbook.add_format({'bg_color': '#C6EFCE',
									'font_color': '#006100'})

		cell_format = workbook.add_format()
		cell_format.set_text_wrap()
		cell_format.set_align('center')
		cell_format.set_align('vcenter')

		header_format = workbook.add_format({
				'bold': True,
				'text_wrap': True,
				'valign': 'center',
				'align': 'vcenter',
				'fg_color': '#CC00CC',
				'font_size': 12,
				'border': 1})

		return red, yellow, green, cell_format, header_format


	def write_to_excel(self, df_list, folder, file_name):
		save_file_name = f"{folder}/{file_name}_{datetime.now().strftime('%d-%b-%Y')}.xlsx"
		writer = pd.ExcelWriter(save_file_name, engine='xlsxwriter')
		for df, sheetname, index in df_list:
			df.to_excel(writer, sheet_name=sheetname, startrow=1, header=False, index=index)  # strip default header
			workbook = writer.book
			red, yellow, green, cell_format, header_format = self._color_formatting(workbook)
			worksheet = writer.sheets[sheetname]
			worksheet.set_column('A:AC', 20, cell_format)
			
			new_cols = df.columns.values #
			if index:
				new_cols = list(df.index.names) + list(df.columns.values)
			for col_num, value in enumerate(new_cols):  # Adding custom header
				worksheet.write(0, col_num, value, header_format) # for all sheets.
			
			worksheet.set_row(0, 25)  # Set header row width
		
		writer.save()

At this point, you should have a sheet that looks like this

sdwan_vulnerabilities_bs4_28-Sep-2021-1Download

Implementing multi-threads should be relatively easy. Take a look at below search results.

https://networkautomationlane.in/?s=multithreading

Know someone who may benefit? Share this:

  • Tweet
  • Click to share on Telegram (Opens in new window) Telegram
  • Click to share on WhatsApp (Opens in new window) WhatsApp
  • Click to email a link to a friend (Opens in new window) Email
  • More
  • Click to print (Opens in new window) Print
  • Click to share on Reddit (Opens in new window) Reddit
  • Share on Tumblr
  • Pocket

Like this:

Like Loading...

Related

Leave a ReplyCancel reply

All Blog Posts
My Resume

Upcoming Posts

Sorry - nothing planned yet!

Recent Posts

  • How to backup configuration to TFTP Server using Ansible – Part II
  • How to backup network devices using Ansible – Part I
  • Netmiko SSH Proxy/JumpServer
  • A short note on SASE
  • Understanding Ansible

Recent Comments

  1. Jack on Multithreading with Python for Network Engineers
  2. LifeCanvas on [Theory] Multithreading vs Multiprocessing vs AsyncIO
  3. Jasper Horng on Netmiko SSH Proxy/JumpServer
  4. asdfasdf on Python API Using FASTAPI – UPDATE – PUT – PATCH – Part V
  5. Gurpreet Kochar on Python Scrapli AsyncIO Usage

Archives

  • September 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
Topic Request / Suggestion
Loading
© 2025 Network Automation | Powered by Minimalist Blog WordPress Theme
%d