Just like any other website, phishing sites can have security vulnerabilities. But, for once, these security vulnerabilities are actually helpful for defenders: they can let us identify who has fallen victim to the phish, and sometimes even disrupt the site and prevent anyone else being phished.
Vulnerabilities are easiest to find when you've got the source code of a phishing site (the phishing "kit"), but we've analysed numerous kits and identified some trends.
One of the most common ways phishing sites collect victim's credentials is by writing them to a log file using code like this:
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$ip = getenv("REMOTE_ADDR");
$message = "\n";
$message .= "----------- | IP : $ip | -----------\n";
$message .= "EM : ".$_POST['EM']." \n";
$message .= "PS : ".$_POST['PS']."\n";
$message .= "PN : ".$_POST['PN']."\n";
$message .= "full : ".$_POST['full']." \n";
$message .= "dob : ".$_POST['dob']."\n";
$message .= "phone : ".$_POST['phone']."\n";
$message .= "ccno : ".$_POST['ccno']." \n";
$message .= "exp : ".$_POST['exp']."\n";
$message .= "cvv : ".$_POST['cvv']."\n";
$message .= "----------- | By JoCker | -----------\n";
$message .= "\n";
$file = fopen("./greyhat.txt", 'a');
fwrite($file, $message);
This takes all victim's information (email, password, credit card number, etc.) out of the request and writes it to a file named greyhat.txt
.
Later on, the phisher can access this file and get all the data that has been collected while they've been away.
But, the vast majority of phishing sites that write logs this way, fail to protect the log file from being viewed. If you know the log file name (or can guess it), as a defender you can load it in your browser and instantly see which of your users have been compromised.
Directory listing is a feature of many web servers where if you request a directory (like /css
) rather than a specific file (like /css/style.css
), a list of all the files in the folder is returned.
Normally this wouldn't be a problem: you'd expect files on a website to be public. But in phishing sites this actually leaks a lot of useful information:
login-myaccount.com/bankname
, we often find you can load login-myaccount.com
and see a folder bankname
and a bankname.zip
containing the phishing kit source code.IP addresses are commonly checked by phishing sites in an attempt to evade detection by security tools. They'll get the IP address of whoever's access the phishing site and refuse to load unless the IP address is:
However, we almost always see this code implemented incorrectly.
// Function to get the client IP address
function get_client_ip() {
$ipaddress = '';
if (getenv('HTTP_CLIENT_IP'))
$ipaddress = getenv('HTTP_CLIENT_IP');
else if(getenv('HTTP_X_FORWARDED_FOR'))
$ipaddress = getenv('HTTP_X_FORWARDED_FOR');
else if(getenv('HTTP_X_FORWARDED'))
$ipaddress = getenv('HTTP_X_FORWARDED');
else if(getenv('HTTP_FORWARDED_FOR'))
$ipaddress = getenv('HTTP_FORWARDED_FOR');
else if(getenv('HTTP_FORWARDED'))
$ipaddress = getenv('HTTP_FORWARDED');
else if(getenv('REMOTE_ADDR'))
$ipaddress = getenv('REMOTE_ADDR');
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
This is a typical function used by a phishing kit to get the user's IP address.
If tries a sequence of HTTP headers and if none of them are set finally falls back to PHP's REMOTE_ADDR
variable.
The trouble is that these HTTP headers are all untrusted!
We can set any IP we like in the X-Forwarded-For
header and the phishing kit will blindly trust it.
Why are these functions always so broken?
Phishing kit authors need their kits to work in a wide variety of setups.
Some phishers will just host their sites publicly, whereas others will put them behind services like Cloudflare in an attempt to make them harder to take down.
The phishing kit itself doesn't know whether it's behind a reverse proxy or not, and so has to trust the X-Forwarded-For
header.
Some more advanced phishing kits have admin panels that the phisher can use to monitor the status of their site (and even interact with victims currently on the site). These admins panels are usually password protected to prevent security teams snooping on them. But, the password protection is often implemented poorly.
In many cases, we've seen an admin panel structured like this:
# gateway.php
# Bounce the admin to login page if they're not authed
if(!isset($_SESSION["ok"]))
{
echo '<meta http-equiv="refresh" content="0;URL=login.php" />';
die();
}
# Switch functionality based on the request's GET parameters
if(isset($_GET["logs"]))
{
$res=file_get_contents($panel_url."/functions/logs.php");
}
# ...
The phisher thinks that their admin panel is secure because this gateway handles all the authentication and calls out to separate "functions" files for each feature.
But, the reality is we can directly request the /admin/functions/logs.php
file and completely bypass the authentication logic.
Exploiting this vulnerability does of course rely on knowing the filenames you need to directly request but, as usual, directory listing is your friend here.
Phishing sites vary in how well they're configured, so it sometimes takes some patience before you can really find all the vulnerabilities in a certain kit. This is why it's important you can distinguish between the different phishing kits you see (using our Indicator Of Kit tool can help).
Once you've identified a specific phishing kit and discovered vulnerabilities in it, you're ready to make use of them: