A Credential Harvester that's Actually Interesting!

Philip Roberts, Cyber Security Operations Consultant | Sep 4, 2023
Sho Yamamoto, Cyber Security Operations Consultant

We’ve all seen a million of them - a fake login page that ultimately sends a victim’s inputted credentials to the threat actor. Boring. However, Fortian’s Managed Security Services Team  recently had an interesting investigation stemming from a client who had interacted with a credential harvester delivered via email. There were several more layers of intrigue to this harvester which involved the IPFS protocol, multiple obfuscated JavaScripts, an inability to detonate in sandboxes, and Telegram bots.

In this write-up, we would like to share our recent experience, detailing the initial detection, incident response process, JavaScript de-obfuscation, and how you can go about detecting and preventing these types of attacks in future.

In August 2023, Fortian’s security operations center received an alert for InterPlanetary File System (IPFS) network traffic from a client device. IPFS is designed to serve content in a decentralized manner, where files are distributed across a network of nodes. Given its decentralised nature, it is frequently leveraged by threat actors to stage malware and phishing kit infrastructure. The detection was initiated by a custom alert rule we deployed, designed to identify connections to .ipfs domains. Given the client's frequent exposure to targeted phishing campaigns and their lack of legitimate use of IPFS, this query has proven effective at detecting phishing attacks and maintains a high true positive detection rate.

Upon initial alert triage, we detected that the user's device had connected to the domain fleek.ipfs[.]io via Google Chrome. From here, proximate device activity was examined to determine what preceded this connection. Via Defender for Endpoint’s advanced hunting, a range of device activity within the 5 minutes that preceded the connection was collected for investigation.

The event that immediately stood out was a file creation event for a file named EFT_Reciept.html. This file was created from Outlook and subsequently launched in Google Chrome. Following the Chrome process creation, several outbound connections were made to the IPFS domain. An HTML file, downloaded from Outlook, which was followed by connections to an IPFS domain immediately rang alarm bells, so I requested assistance from another team member (thanks Ben Watson!) to assist with the investigation.

At this point, the HTML file proved the most likely source for the suspicious connections, so we needed to quickly establish two factors: what was the HTML file doing, and how was the HTML file delivered to the user. The file was created by Outlook, meaning it was almost certainly delivered via email. I asked Ben to investigate the email logs to confirm this delivery method, and if so to determine who sent the email and more importantly who else in the organisation had received it.

While Ben investigated the source and scope, I obtained a copy of the file via Defender for Endpoint. I copied the file onto my sandbox for analysis and started off by opening the file in Visual Studio for static analysis.

Greeted with obfuscated JavaScript strongly suggested that our culprit was found. At this point I elected to execute the file to try replicate the activity observed on the client’s device. I opened the file in Microsoft Edge and upon doing so got redirected to a legitimate support.microsoft.com website instructing me on how to fix OneDrive sync problems:

This was strange given how many factors were now pointing to this file being malicious, yet I couldn’t get the payload to detonate. From here, Sho Yamamoto stepped in to assist with de-obfuscation.

De-Obfuscating the Code

After executing the file led nowhere, we tried de-obfuscating the code to see what was happening here.

Let’s first look at the file in question:

The thing that stands out from the start is what seems to be an array of hex character strings. The astute amongst you may notice that this array acts similarly to a substitution cipher key which maps the various property names being referenced in the obfuscated code. (Many objects call in JS are just a property of the object, so it can be referenced by specifying the property key).

Knowing this, we can easily revert this into human readable code using a super advanced technique – copy pasting.

Cool, this is something we can work with. Let’s look at some of the interesting parts of the code:

  • Line 1: Retrieves a HTML attribute called “data-l” from the <html> tag on the document. This value turned out to be a Base64 string which acts as the “seed” value used to derive all other values in the next step.
  • Line 2-4: Decodes the “seed” value and replaces some value to form a URL.
  • Line 7-10: The decoded URL is used as the source of an injected <script> tag.

The decoded URL translated to (defanged) hxxps://fleek.ipfs[.]io/ipfs/bafybeigdbzrd5z56jizetdacvzwnveie4dc7edw2li5we7rlg4u52m4zim/fakeNAME33_19072023LOGS.js which is where the second JavaScript file was hosted.

At this point, we know everything the page is doing – Great. We now need to investigate this second Javascript code that’s loaded into the script tag – Boo.

Looking at this URL we are greeted by…

More obfuscated code. This one look much longer than the previous one too.

Luckily for us, the obfuscation method is the same. However, manually replacing the values isn’t possible with the sheer number of values being referenced. We could have written some script to convert this back into a valid code, but in the middle of an investigation we want something that can get the job done quickly.

What we realised early in the process was that the goal was not to create valid code. Rather, all we needed was readable code. Knowing this, we opted to convert the obfuscated code into a string and use regex to convert references to the array into a string interpolation referencing the same array index. To achieve this, we came up with the following regex:

  • Matches all reference to the hex array (_0x99e6), and groups the index value.

  • Replace the above match with the following string. Note that the $1 is a reference to the matched regex group.

The main advantage to this method was that it used the way the code was already obfuscated to our advantage. Now, we can view the code in question.

The code contains a basic phishing page designed to look like a Microsoft login page. The code is a bit too long to go over all of it, but we’ll go over some of the interesting parts of them. For the sake of readability, the following codes have been edited.

First, let’s look at the equivalent of the main function of this script. Aptly named “entry point”

Now we see something very interesting. One of the first thing this code does is call an IP information API to check whether the IP is owned by an organisation in a blacklist. If the IP is not part of the blacklist, the phishing page is loaded. Otherwise, the user is simply redirected to a Microsoft support page.

This explains why visiting the URL on our Azure based VM did not display the phishing page.

Lastly, here’s the code used to exfiltrate the phished password and username to a telegram channel.

Like the previous code, the IP information API is used to retrieve information about the user. This information is attached along with the phished details and sent to a telegram channel.

From the victim’s perspective, upon clicking the HTML file they would see the following Microsoft logon page:

The username section was prefilled based on the email address that received the phishing email that as the delivery mechanism for the html file. After entering a password, the page displays a fake server error message. In the background, this would then be sent to the Telegram bot:

Containment

While Sho de-obfuscated the code, we worked with the client to ensure the target user’s account credentials were reset and that the file was removed off the device. We also investigated the scope of the incident to ensure that no other users were victim of the same campaign. As a result, the attack failed to succeed in compromising the victim’s credentials.

Detecting similar attacks

We strongly recommend implementing detection rules to alert on IPFS network events. This can be achieved through the following means:

  1. Alerting on connections to IPFS gateways: https://ipfs.github.io/public-gateway-checker/ Most browsers do not support IPFS natively, so IPFS content is typically accessed via a gateway.
  2. Alerting on DNS requests for .IPFS domain or IPFS gateways.
  3. While less likely leveraged by threat actors in credential harvesting campaigns, it is worthwhile alerting on the IPFS daemon running on a device. This would allow the device to communicate directly via the IPFS protocol rather than via HTTP requests to an IPFS gateway.

Some of these may be more client-agnostic than others, so as always, we recommend detailed client baselining to ensure suitability.

In many organisations, it may also be worthwhile alerting on communication to Telegram APIs.

Threat hunting lines of effort

Many of the events associated with this incident may be too noisy to alert on, but threat hunts investigating a hypothetical credential harvest attack may consider:

  • Investigating users interacting with html files from unfamiliar senders. This would require dynamically baselining email senders, looking for email senders where the EnvelopeFrom domain is uncommon, then correlating the email attachments with a file creation event on endpoints. In my experience this has proven exceptionally effective in detecting credential harvesting attempts.
  • You should also consider investigating anomalous user sign ins and work backward to determine if they were the result of user interaction with a credential harvester. For example, an offshore conditional access failure preceded by the user opening a .html attachment on their device 10 minutes prior.
  • We also recommend investigating remote device fingerprinting attempts, such as connections from workstations to websites that facilitate IP, ASN, or VPN lookups. For example ipinfo[.]io

Security Recommendations

To reduce the likelihood of being impacted by this credential harvesting campaign, we recommend the following:

  1. Where possible, deploy conditional access policies which block offshore sign ins, or restrict sign ins from countries which users are never expected to operate from.
  2. Leverage Microsoft’s sign in risk level to block users from signing in when the attempt is deemed high risk.
  3. Ensure MFA is enabled and required for all users. Where possible, use MFA number matching with an authenticator over simple MFA prompts or text notifications.
  4. Conduct periodic user access reviews and conditional policy reviews to eliminate scope creep.
  5. Deploy egress network controls to block connections to IPFS domains and connections using the IPFS protocol.
  6. Assess the business need of permitting inbound emails with .html and .htm file attachments. If possible, configure a rule to quarantine any email with these attachments or only permit these attachments from approved senders. Where delivery of the attachment is necessary, you can then manually release the email from quarantine.

Indicators of Compromise

669a93c11cfd079148549743d58fc05c
MD5
Original HTML file
209.94.90.1
IP Address
IP address of IPFS node which staged the second JS file.
https://fleek.ipfs[.]io/ipfs/bafybeigdbzrd5z56jizetdacvzwnveie4dc7edw2li5we7rlg4u52m4zim/fakeNAME33_19072023LOGS.js
URL
URL of remotely hosted JS file.
https://api.telegram[.]org/bot5998110893:AAG6T2GBrNd9CPii5mQnr2oF7xf9di9Wzb0/sendMessage?chat_id=-921284909
URL
Parameterised URL communicating to Telegram bot.
CONTACT US

Speak with a Fortian Security Specialist

Request a consultation with one of our security specialists today.

Get in touch