How to create a phishing simulator with Python Django?

Django Phishing Simulator

Phishing simulators are used to run tests where deceptive emails, similar to malicious emails, are sent by an organization to their own staff to gauge their response to phishing and similar email attacks.

In this article, we will have a look at how to implement mailing functionality, send the phishing link as messages, capture agent-data, click-count and input data.

We are using the ‘django-user-agents’ package to capture agent data.

The process of creating a phishing simulator has been divided into 4 steps and will be setting up urls and views all together.

  1. Setting up a Project and an app.
  2. Setting up mailing functionality
  3. Setting up SMTP functionality
  4. Dynamic templates and fetching phishing related data.
  5. Setting up routes.

The entire source code is available in GitHub

1. Setting up a Project and an app

As a first step, we set up a django project “phishing” with the app “core”.

2. Setting up mailing functionality

a. To start with, we will create required models in core/models.py file. This is the first data model. We will save the mail related data in the Mail data Model.

  1. To start with, we will create required models in core/models.py file. Add the model given below in models.py. We will save the mail related data in the Mails model.
class Mails(models.Model):
    sender_email    = models.CharField(max_length=255, blank=True, null=True)
    sender_name     = models.CharField(max_length=255, blank=True, null=True)
    reply_to_email  = models.CharField(max_length=255, blank=True, null=True)
    reply_to_name   = models.CharField(max_length=255, blank=True, null=True)
    subject         = models.CharField(max_length=255, blank=True, null=True)
    message         = models.TextField(blank=True, null=True)
    dt_stamp        = models.DateTimeField(auto_now_add=True, blank=True, null=True)
 
    def __str__(self):
        return str(self.id)
 
    class Meta:
        verbose_name_plural = "Mail"
  1. Add the below code in the models.py. We will be saving recipient info In the Recipient data model.
class Recipient(models.Model):
    email = models.CharField(max_length=255, blank=True, null=True)
    mail  = models.ForeignKey(Mails, on_delete=models.CASCADE, related_name="recipients", blank=True, null=True)
   
    def __str__(self):
        return str(self.id)
  1. Then, add the below data model to save the phishing related data.
class PhishingData(models.Model):
    link        = models.ForeignKey(PhishingLink, on_delete=models.CASCADE)
    recipient   = models.ForeignKey(Recipient, on_delete=models.CASCADE)
    click_count = models.IntegerField(default=0)
    agent_data  = models.TextField(blank=True, null=True)
    input_data  = models.TextField(blank=True, null=True)
 
    def __str__(self):
        return str(self.id)
  1. Now let’s create a view to send mail in core/views.py
def MailView(request):
    if request.method == "POST”:
        
         sender_email    = “sender email here”
         sender_name     = “sender name here”
         reply_to_email  = “reply to email here”
         reply_to_name   = “reply to name here”
         subject         = “this is subject”
         message         = “phishing template here” 
         email_list      = [“abc@example.com”,”bcd@example.com”]
                              
          m = Mails.objects.create(sender_email=sender_email, sender_name=sender_name, subject=subject, message=valid_message) 
                 
          for i in email_list:
            msg = EmailMessage(
                          subject,
                          message,
                          from_email=sender_name+ '<'+sender_email+'>',
                          to=[i],
                          reply_to=[reply_to_name+ '<'+reply_to_email+'>'],
                          connection=backend,
                           )
            msg.content_subtype = "html"
            msg.send()
            r = Recipient.objects.create(email=i, mail=m)
            PhishingData.objects.create(link=template_url, recipient= r)
 
          return HttpResponse({"res":"Email sent successfully"})

3. Setting up SMTP functionality

After the mailing functionality is implemented, We need to set SMTP to send the mail. Add the code given below in views.py/MailView to make SMTP work.

backend = EmailBackend(host=email_host, port=email_port, username=email_host_user,
                       password=email_host_password, use_tls=email_use_tls, 
                       fail_silently=False
                      )

We will be passing the actual SMTP credentials in the above function as arguments.

4. Dynamic template and fetching phishing related data

  1. Add this in views.py/MailView to render the phishing link.
template_url = BASE_URL +/render/+ “template_name”
message = template_url
  1. Then create another view  DynamicTemplate in core/views.py.
def DynamicTemplate(request, url_slug):
  
    if request.method == 'GET':
		  # Capturing agent data using user_agent plugin.
		  adata = {}
      adata["browser"] = str(request.user_agent.browser.family) +" "+ str(request.user_agent.browser.version_string)
      adata["os"] = str(request.user_agent.os.family)+" "+str(request.user_agent.os.version_string)
 
      p_data = PhishingData.objects.filter(link=, recipient__unq_id=rpt_id)
      if len(p_data) > 0:
        p_data = p_data[0]
        p_data.click_count = p_data.click_count + 1
        if p_data != None or p_data != "":
          # Adding agent data
          p_data.agent_data = str(adata)
          p_data.save()
        return HttpResponse(template_code)
	
    if request.method == 'POST':
      p_data = PhishingData.objects.filter(link=id, recipient__unq_id=rpt_id)
			
			# Saving POST data.
      if len(p_data) > 0:
        p_data = p_data[0]
        p_data.input_data = str(request.POST.dict())
		    p_data.save()
      return httpResponse("Done")
  1.  Then, add temporary template code to render.
template_code = ”””
	<html>
        <body>
	        <h1>Test template</h1>
          <input type="text" name="name">
          <input type="submit" name="submit" value="Update SMTP">
        </body>
        </html>
              ”””
  1. Finally, your views.py file should look like this
def MailView(request):
  
  if request.method == "POST”:
     sender_email    = “sender email here”
     sender_name     = “sender name here”
     reply_to_email  = “reply to email here”
     reply_to_name   = “reply to name here”
     subject         = “this is subject”
     message         = “phishing template here” 
     email_list      = [“abc@example.com”,”bcd@example.com”]
 
    backend = EmailBackend(host=email_host, port=email_port, 
                           username=email_host_user, password=email_host_password, 
                           use_tls=email_use_tls, fail_silently=False
                          )
   
    m = Mails.objects.create(sender_email=sender_email, sender_name=sender_name, subject=subject, message=valid_message)
 
		template_url = BASE_URL +/+ “template_name”     
	  message = template_url 
                 
    for i in email_list:
        msg = EmailMessage(
            subject,
            message,
            from_email=sender_name+ '<'+sender_email+'>',
            to=[i],
           reply_to=[reply_to_name+ '<'+reply_to_email+'>'],
           connection=backend,
             )
        msg.content_subtype = "html"
        msg.send()
	      r = Recipient.objects.create(email=i, mail=m)
	      PhishingData.objects.create(link=template_url,recipient= r)
 
    return HttpResponse({"res":"Email sent successfully"})
           
  
  
def DynamicTemplate(request, url_slug):
  
    template_code = ”””
				<html>
        <body>
	        <h1>Test template</h1>
          <input type="text" name="name">
          <input type="submit" name="submit" value="Update SMTP">
        </body>
        </html>
                ”””
 
    # We will capture click-count and agent-info here.
    if request.method == 'GET':
	    # Capture agent-data
      adata = {}
      adata["browser"] = str(request.user_agent.browser.family) +" "+ str(request.user_agent.browser.version_string)
      adata["os"] = str(request.user_agent.os.family)+" "+str(request.user_agent.os.version_string)
 
      p_data = PhishingData.objects.filter(link=, recipient__unq_id=rpt_id)
        
      # Capture Click-count 
      if len(p_data) > 0:
        p_data = p_data[0]
        p_data.click_count = p_data.click_count + 1
        if p_data != None or p_data != "":
          p_data.agent_data = str(adata)
          p_data.save()
       
        return HttpResponse(temp_instance.template_code)
 
    # We will save the POST data here.
    if request.method == 'POST':  
       p_data = PhishingData.objects.filter(link=id, recipient__unq_id=rpt_id)
        if len(p_data) > 0:
          p_data = p_data[0]
          p_data.input_data = str(request.POST.dict())
		      p_data.save()
        return httpResponse("Done")

5. Setting up routes

In the phishing/urls.py, add these routes in url_patterns.

urlpatterns = [
	    # This route will redirect to the mail view.
    path('', MailView, name="mail-view"),
    # This is to render the dynamic template with the slug.
    path(render/<url_slug>/', RenderTemplate, name="render-template"),
     ]

Summary

By following the above steps you can implement the phishing simulator concept and functionality. Summarizing the overall process once again below,

1. Setting up a project and an app

We create a django project and give it the name “phishing” with the app “core”.

2. Setting up mailing functionality

We create a required model in core/models.py file, then we save our recipient info in our Recipient Data Model, and then add the given data model to save the phishing related data. Then we create it to send the mail in core/view.py.

3. Setting up SMTP Functionality

SMTP is needed to actually send the mail. We add the given code in views.py/MailView to make smtp work. Our actual smtp credentials will be passed there as arguments.

4. Dynamic template and fetching phishing related data

We need to add the given code in views.py/MailView to render the phishing link, then create another view DynamicTemplate in core/views.py, and then we add temporary template code to render.

5. Setting up Routes

In the phishing/urls.py, add the given routes in url_patterns.

About Wolfish

Wolfish is an open-source phishing simulator project developed by Wolfpack. We encourage you to browse through and contribute. Thanks! 🥂


Github repo

Demo
Username – admin
Password – 1234