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
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
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()
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!
The techniques presented in this series of article and the framework itself should not be used without proper consent or authorization.
This Project is Open-Source and is available at this page: https://github.com/Balzu/PyPhish