Creating a Phishing Framework in Python part 1 : creating HTML emails

In this tutorial I will show you how it is possible to design and send simple HTML emails in Python. This knowledge will be useful to create the phishing framework, where the HTML code will be replaced to spoof a legitimate organization.


testbed nmap
Introduction

Both common criminals and Advances Persistent Threats (APT) use phishing emails to steal users credentials or to get initial foothold into target organizations. Especially in the latter case, emails are targeted to very specific people (spear Phishing) and are built very well, closely resembling the emails of the spoofed organizations.
In this article, we will learn to code HTML email in Python, a key feature that attackers can use to make their scam emails look like legitimate ones. To illustrate the concept, we will build emails with simple HTML tables, which will be filled with vulnerabilities from CISA's Known Exploited Vulnerabilities Catalog (https://www.cisa.gov/known-exploited-vulnerabilities-catalog). While the effort in this video is on actually coding a script to send HTML emails programmatically with Python, and not in the HTML per se, in a second article we will go on and substitute the HTML inside the script with actual HTML code that resembles a legitimate website. This trick will allow us to possibly fool our victim into believing that the email comes from a trusted source. This is a common trick carried out by APTs, so it is interesting to understand how they can do that.

Parsing CSV data

CSV (Comma Separated Value) is a common format used to share information organized in a table fashion, where rows are separated by newlines and columns are separated by commas. It is a format generally provided when you export data, and it is indeed it is possible to open .csv files with Excel and then instruct the program to properly arrange data in table format, in order to use all the functions provided by Excel.

For this reason it is useful to know how to manipulate data in csv format, and for this reason I decided to take as example the CISA'S Known Exploited Vulnerabilities Catalog in order to demonstrate the point.
You can follow the steps on the video, basically you simply have to go to the page holding the catalog (https://www.cisa.gov/known-exploited-vulnerabilities-catalog), and then click on Download CSV version.

At the beginning of the script, you need to import the module to work with csv: import csv.
Then we define a function to parse the csv file. We define the csv reader and set the comma as delimiter. Then, we iterate on each line (for vuln in vulns), discarding the first line that holds only column names. For each line we extract the meaningful information and at the end we return the full list of vulnerabilities that have been added after the threshold date that can be provided as parameter.

def parse_vulnerabilities_csv(after_date="1970-01-01", filename="known_exploited_vulnerabilities.csv"):
	""" 
	Takes the vulnerabilities in the csv file {filename} and returns 
	a list with all the vulnerabilities disclosed after {after_date}
	"""
	vulnerabilities = []
	date_threshold = datetime.strptime(after_date, '%Y-%m-%d')
	with open (filename, 'r') as csvfile:
		vulns = csv.reader(csvfile, delimiter=',')
		for vuln in vulns: 
			if vuln[0] == 'cveID': continue #skip first title row
			date_added = datetime.strptime(vuln[4], '%Y-%m-%d')
			if (date_added >= date_threshold):
				cve = vuln[0]
				vendor = vuln[1]
				product = vuln[2]
				vname = vuln[3]
				action = vuln[6]
				ddate = vuln[7]
				v = {
					'CVE': cve, 
					'Vendor' : vendor, 
					'Product':product, 
					'VName':vname, 
					'Action':action, 
					'DDate':ddate
				}
				vulnerabilities.append(v)
	return vulnerabilities



Sending HTML emails

Once the csv file containing the vulnerabilities has been correctly parsed and the vulnerabilities have been inserted into a list , it is time to organize them in an HTML table for cool visualization and send them via email.
In order to do that, we will need to add the following imports at the beginning of the script:


import csv, datetime, smtplib, getpass
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

The following function is responsible for creating and delivering the HTML emails.
At the beginning, we define the parameters inherent to the email, such as sender, receivers, and subject. Note that we use the class MIMEMultipart: this allows us to provide a double version of the email, both HTML and plain-text. In case our target's mail agent does not support HTML email, or HTML emails have been disabled, we can still deliver a textual email. In that case, we could simply insert a link towards a malicious website and try to induce the user to click on it, maybe with an url that can make the user believe it is actually a legitimate website (typosquatting). However, in this case we skip this part as our scope is on HTML email, and only show a textual message if HTML emails are not supported.
Then, it is time to build the HTML message. It will be a standard Python string, which will hold all the tags needed to create a valid HTML code. Here I don't report all the HTML, I encourage you to look at the script on GitHub, however the thing to note is that we have a valid HTML, thats also carries CSS style directives inside the tag. The instead contains the actual table: the content of the table, i.e. the vulnerabilities, are added dinamically to the string by scanning the vulnerabilities list that we created in the previous function.

Then we add these two parts, the html and the textual one, to the message and send it using the SMTP (Simple Mail Transfer Protocol), specifying the fully qualified domain name and the port of our SMTP server. Then we identify ourself to the server with a EHLO command, encrypt the communication with the STARTTLS command, we carry out the login providing email and password and finally we send the emails.


def send_emails(sender, receivers, subject, vulnerabilities, sender_psw):
    """ Sends the emails to the proper receivers """
    sender_email = sender
    receivers_email = receivers  
    message = MIMEMultipart("alternative")
    message["Subject"] = subject
    message["From"] = sender_email 
    message["To"] = ", ".join(receivers_email)

    # Create the plain-text and HTML version of your message
    text = """\
        Plain text. If you are seeing this message, it means that HTML emails are not supported.
    """
    
    html = """\
    <html>
    	<head>
	 -- snip -- 
	</head>
	<body>
	 -- snip -- 
	</body>
    </html>
    """

    # Turn these into plain/html MIMEText objects
    part1 = MIMEText(text, "plain")
    part2 = MIMEText(html, "html")

    # Add HTML/plain-text parts to MIMEMultipart message
    # The email client will try to render the last part first
    message.attach(part1)
    message.attach(part2)

    # Send email
    with smtplib.SMTP('smtp.email.com', 587) as server: #replace with address of SMTP server
        server.ehlo()
        server.starttls()
        server.login(sender_email, sender_psw)
        try:
            server.sendmail(sender_email, receivers_email, message.as_string()        )
        finally:
            server.quit()

Result

The HTML email is correctly built and delivered! At this point we just need to copy the HTML code from some legitimate organization (Linkedin, Twitter, Facebook, Google or any organization that could make our phishing attempt attractive), which can be easily done by just registrating to such services in order to get the email template, substitute it to our HTML code inserting the link to our Command and Control server, and deliver the email!

csv vulnerability python email

Notice

The techniques presented in this series of article and the framework itself should not be used without proper consent or authorization.


Download

This Project is Open-Source and is available at this page: https://github.com/Balzu/PyPhish


Video