Teach a man to phish

Teach a man to phish
Photo by Robson Hatsukami Morgan / Unsplash

Disclaimer: Please don't do this. This is for entertainment purposes only.

Why

This summer a family member of mine was hit with a series of phishing attacks. They fell for it. Nothing against them, the internet can be very confusing and deceptive. Anyone can get targeted by these and fall for it. But the repercussions were tough. Google accounts compromised, files stolen, etc.

In light of this I wondered how difficult it would be to set up a phishing scheme of my own. Especially after the advent of somewhat useful LLM's, I feel like I always hear that these attacks are "so easy these days" and that "anyone can set up these schemes" but how true is this?

I would pose my self as a solid middle of the road developer. I've done some open source work, a little back end-here, a little front-end there, but I'm not a professional or anything. So I guess we shall find out how difficult this truly is when armed with trusty Google Gemini in hand.

How

Okay I'm going to reiterate. Please don't do this! This is meant for educational and entertainment purposes only! If you actually phish somebody you could be in serious trouble. Spend your time on something more useful (like learning how to do a back flip).

Step 1: Back-end

So for any interactive website you need some sort of back-end. There will be two main components of this setup, the web server that serves the web page and the REST API that receives and writes down the valuable log in info.

For this project I decided to use Go as my language of choice. Go isn't necessarily the coolest language to code in anymore. But, it's easy to write and has built in HTTP libraries making creating an API really really easy and fast. So where to start?

First, I prompted Gemini for a basic web-server that can host a directory full of html files. I modified it a bit, but this is what I got. Because Go is a wonderful language for web-servers, this is literally all the code I need to host the html contents:

package main
  
import (
	"net/http"
)

func main() {
	http.Handle("/", http.FileServer(http.Dir("./website-static")))
	http.ListenAndServe(":6868", nil)
}

Second, I have to build the method that will accept a JSON POST with the forum contents (in this case a "forum" is a body of data that contains the user name and password). Gemini also was able to build the majority of this and I just tweaked paths.This takes a bit more effort so I'll break it down into parts.

To represent the forum JSON response as a struct ("data structure" in coding lingo):

type ForumEntry struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

Then I need a function to accept the forum info and break down the JSON POST into a usable variable in memory:

func handleForum(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	body, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Failed to read request body", http.StatusInternalServerError)
		return
	}

	var entry ForumEntry
	if err := json.Unmarshal(body, &entry); err != nil {
		http.Error(w, "Failed to parse JSON", http.StatusBadRequest)
		return
	}

	if err := writeToFile(entry); err != nil {
		http.Error(w, "Failed to write to file", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
	fmt.Fprintln(w, "Entry submitted successfully")
}

And finally a function to take this forum entry and write it to disk so I can come back later and see what information has been sent to the server:

func writeToFile(entry ForumEntry) error {
	file, err := os.OpenFile("forum_entries.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer file.Close()

	data, err := json.Marshal(entry)
	if err != nil {
		return err
	}

	if _, err := file.WriteString(string(data) + "\n"); err != nil {
		return err
	}

	return nil
}

And like that you have a functional web-server that can serve the malicious site, accept information, and persist it to disk. This was... unsettlingly easy. With the help of Gemini I was able to write and test this in under half an hour. Granted, anyone with coding experience would be able to whip this up in no time, but it is uncomfortable that with the help of a LLM it may actually take less time to write this back-end than install Go in the first place.

Step 2: Front-end

So we have a back-end, but that's not particularly useful if there is nothing for the user to look at on the site. You would be hard-pressed to dupe a normie to the point where they'll cURL their login info to you :p

First, lets make the web-page. So I tried to give a screenshot of the Instagram login page to Gemini but... well... it's real bad:

Terrible Gemini Instagram Login Page

LLM's are still just horrendous at the whole visual thing... yeah I'm just had to make it myself. After refreshing myself with basic CSS syntax and rules I was able to whip up this:

Custom Instagram login page

If you look closely, or click on any of the links it's pretty obvious this page is fake. But the idea of a phishing scam is to catch someone off guard, not to be fully realistic. So this is close enough. This probably took me about an hour and would take someone inexperienced a day of tinkering. I also added some basic logic to the forum so when you enter a username and password it sends the data to the back-end I previously built, and then redirects to Instagram's actual login page to attempt to shed suspicion off the poorly made website.

Step 3: Email

Next, the fake email had to be made. The styling and layout are extremely similar to the web-page, so I'll gloss over how I actually made it and just display the result:

fake email

The email came out even better than the website IMO. If I got that there is a chance I'd fall for it. There is more to this section, like finding an email provider, setting up a email with a domain, figuring out how to send html formatted emails, and all that. But all of that is pretty dry and I don't actually want anyone following this article to do this so I'll leave it to the imagination.

Aftermath

Once I finished all this, I set my web-server up on auth.instagram.jptr.tech. It's not the best domain, but I figured it looks almost right if you squint. Also while I found this entertaining, I really didn't want to spend the money to actually make it realistic thus I just used a domain I had laying around.

I set up the domain, spun up the web-server, and... immediately got flagged.

I was kinda shocked it got flagged so fast. The craziest thing is that Google Safe Browsing flagged this when the site only ever got viewed a single time via Firefox. So what happened here?My best guess is that the domain itself was the issue. Putting both instagram and auth in a unaffiliated random domain really should raise some red flags. And in this case it literally did!

My domain ended up getting put on hold at the highest level (not even by my registrar, but by the people that own the .tech TLD). Getting it back took a couple days and filling out some paperwork that pretty much boils down to "I swear I'm not the bad guy." My VPS that I hosted this on also got suspended, but the lovely lads over at GreenCloudVPS got me back up and running in no time (love those guys). Granted, it would totally have been fair if either of these providers just didn't give me my domain and server back, but they are both chill so thankfully they did (I will not be doing this kind of shenanigans in the future!). As of the time of writing, everything is back and working again.

Conclusions

In the modern world filled with LLM's and endless resources on web infrastructure, creating a phishing setup really is quite easy. For someone like me with experience, they could probably have the whole thing set up in a matter of hours. For someone with less experience, maybe a couple of days if they're persistent and willing to learn. That is... not a good thing.

On the (kind of?) upside though, it seems like the big tech companies are leveraging their power, taking this thread somewhat seriously, and automatically blocking fishy (excuse the pun) sites. It does make me a little uncomfortable that just a few companies (Google and Cloudflare namely) have such control over the internet. But oh well, that is life.

Stay safe out there!