WikiKit AiTM Phishing Kit: Where Links Tell Lies

### #WikiKitPhishing #CredentialHarvesting #PhishingCampaigns

Summary: The WikiKit phishing kit targets various industries by using deceptive landing pages that mimic legitimate company branding to harvest user credentials. This campaign has been active since early October 2024, employing sophisticated techniques to increase user trust and engagement.

Threat Actor: Unknown | WikiKit
Victim: Various Industries | Automotive, Manufacturing, Medical, Construction, Consulting, Entertainment

Key Point :

  • WikiKit uses landing pages hosted on Jimdosite, featuring targeted company logos to deceive users.
  • Phishing emails often contain links that appear to be from legitimate services like Salesforce to increase trust.
  • The campaign employs CAPTCHA checks and JavaScript redirection to manage user interactions effectively.
  • It utilizes an anonymizing service for redirects, complicating tracking efforts.
  • Indicators of compromise include outbound connections to specific URLs associated with the phishing campaign.

TRAC Labs has recently identified a phishing kit, which we have named WikiKit because of its functionality to redirect to Wikipedia pages if the JavaScript is disabled or the phishing link is invalid.

This particular phishing campaign began in early October 2024, targeting the automotive, manufacturing, medical, construction, consulting, and entertainment industries.

What is distinctive about the WikiKit phishing campaign is its use of landing pages hosted on Jimdosite, featuring the targeted company’s logo in the background, as shown below. These pages prompt users to click on Review Document Here, which redirects them to a credential harvesting page as shown below.

Landing page

The threat actor or group initially gains unauthorized access to various corporate credentials associated with the landing pages listed in the IOC section. They then leverage the compromised user’s email account to further distribute phishing links. These emails often include an “attachment” with an embedded link. Some of these links begin with app.salesforceiq.com to give users the impression that the URL is part of a legitimate Salesforce redirect, increasing the likelihood of user trust and interaction, for example hxxps://app.salesforceiq[.]com/r?target=<redacted>&url=hxxps://<victim-lookalike-domain>.jimdosite.com. Previously, the Google Ads services were used for the redirects.

WikiKit infection chain

The victim would be presented with the landing page mentioned above. The text below is similar across all landing pages:

New PDF Document Received

You’ve (2) new PDF Documents for your review
Please sign and return

Upon clicking on Review Document Here the user is faced with Cloudflare Tursntile CAPTCHA check.

The <noscript> tag provides alternative content or behavior when the JavaScript id disabled. So, the redirection would take place.

We have analyzed a few samples, where the redirect links would be one of the following:

WikiKit is consistently using href.li anonymizing service for redirects.

Source code of /verify

Upon entering the email address, the request is sent to hxxps://yugaljeeautomotive[.]com/z/pro/mentanance/auth/rUADZcQ3GvV5Gl0r8ijP2l0EbMGF93CFwuqd54Zosi9LiJYgAQtjQfSDI4kmB7RER8PNhNEeClpv8A6z6dboxLHvHSapudmgeIsmHLzTXsq5SWuxcUr4Kqfnyoo1O7WBTk2fV9MkgPy0KwxBOXJIRo/validate to validate the email address. If the email is correct the server responds with the following:

{
"live": true,
"grablogo": "1",
"email": "email address",
"icon": "https://aadcdn.msauthimages.net/<redacted>",
"background": "https://aadcdn.msauthimages.net/<redacted>"
}

Where:

  • live — indicates whether the email provided by the user is considered valid or not (true or false).
  • grablogo — acts as a flag to determine whether dynamic branding should be applied to the phishing page (1 or 0).
  • email — represents the email address provided by the victim during the phishing process.
  • icon — a URL pointing to an image file (a logo).
  • background — a URL pointing to a background image.

After the user enters the valid credentials, it gets sent to the server:

em=email_address
pa=password

The response from the server would contain the following example:

{
"live": true,
"email": "email address",
"twofactor": true,
"role": false,
"edu": false,
"type": "business",
"twofactor_info": [
{
"method_name": "PhoneAppOTP",
"display": "",
"isDefault": true
},
{
"method_name": "PhoneAppNotification",
"display": "",
"isDefault": false
}
]
}

If a specific authentication method is not marked as the default (isDefault is false), that method is hidden from the user interface by the hideOption() function. This ensures that the user is only presented with the default method.

The code uses a few checks with regular expressions to detect if the environment or the code itself is being tampered by debugging tools, injected scripts, or instrumentation. The self-validation check and console tampering are also present:

  • const _0x55de0f = new RegExp(‘function *( *)’);
    The regex looks for function definitions in a specific format: function() { … } or function () { … } . Debugging tools sometimes introduce extra code into the environment, for example function() { debugger; }.
  • const _0x1da82d = new RegExp(‘++ *(?:[a-zA-Z_$][0–9a-zA-Z_$]*)’, ‘i’);
    This regex looks for increment operations on variable names (++variableName). Debugging tools might loop through objects or properties by incrementing variables, for example:
let counter = 0;
while (counter < 100) {
++counter;
}
  • The test method applies the two regular expressions to the result of _0x47c7e9 concatenated with strings like chain or input. If either of the checks fails, the code calls _0x47c7e9('0'), which is likely a method to disrupt or halt execution. Otherwise, it invokes _0x5e3e02(), which will continue further validation.
test method and the first two checks
  • Inside _0x5152d1(), if the input parameter _0x1001fa is of type string, it creates a new function containing an infinite loop (while (true) {}) using JavaScript’s constructor mechanism. This prevents against debuggers that may inject string-type data during runtime or tamper with the execution flow.
  function _0x5152d1(_0x1001fa) {
if (typeof _0x1001fa === 'string') {
return function (_0x1599e0) {}
.constructor('while (true) {}')
.apply('counter')
  • If _0x1001fa is not a string, the function performs a mathematical operation (_0x1001fa / _0x1001fa) to detect anomalies. Under normal circumstances, this operation should return 1 because any number divided by itself equals 1. However, if tampering has occurred or if _0x1001fa is an unexpected value (such as 0 or a non-numeric input), the result could be NaN (Not-a-Number).
{
;('' + _0x1001fa / _0x1001fa).length !== 1 || _0x1001fa % 20 === 0
? function () {
return true
}
  • _0x1001fa % 20 === 0 might also be a part of the debugger check: the condition checks whether the input value _0x1001fa is divisible by 20. If true, the script assumes the input might be part of a debugger’s repetitive loop or automated process. Debuggers sometimes loop through numbers or variables systematically to analyze program behavior.

So, the debugger statement would trigger whenever the script detects anomalies or tampering through these checks mentioned above. The debugger statement is sometimes used in scripts to frustrate analysis. For example, it can disrupt debugging by forcing the debugger to pause repeatedly.

Debugger statement
  • Function _0x2af670 manipulates the browser’s console object by iterating through common logging methods (log, warn, info, error, exception, table and trace) and replacing them with a placeholder function (no-op). This disables the ability to log messages, warnings, or errors to the console, preventing analysts from using browser developer tools to analyze the script’s behavior.

The variables such as unReq, unEm, pwdReq, unPw, unCode, unSms, and emCode in the code snippet are used to store Base64-encoded images or icons. Each represents an image displayed on the webpage under specific error conditions.

The table that describes the input validation (captures user input) and error handling.

The variables storing the base64-encoded images

WikiKit adjusts the authentication method based on the user’s configuration. Three primary methods (PhoneAppNotification, PhoneAppOTP, and OneWaySMS) refer to different authentication workflows that correspond to multi-factor authentication (MFA) mechanisms.

Each method sends specific parameters to the C2 server (auth=verify_app, auth=verify_code, or auth=verify_sms) along with other parameters like the entered email address (em) and verification code (code).

If authentication is successful, the user is redirected to outlook.office365.com/Encryption/ErrorPage.aspx?src=0&code=10&be=DM8PR09MB6088&fe=1.

The recent campaign (December 2024) has been using the same URL (yugaljeeautomotive[.]com/z/pro/mentanance/auth) for the credential harvesting page. You can view the IOCs in the Indicators of Compromise section.

Threat Hunting

  • Look for the outbound connections to remote URL containing “.jimdosite”, inspect the URL for the patterns described in this blog.
  • Look for outbound connections to outlook.office365.com/Encryption/ErrorPage.aspx?src=0&code=10&be=DM8PR09MB6088&fe=1, which indicates that the user has entered the valid credentials.
  • ANY.RUN Threat Intelligence queries:
    domainName:"yugaljeeautomotive.com" OR domainName:"app.salesforceiq.com"

For additional hunting queries please feel free to reach out to us 🙂

Indicators of Compromise

Source: https://trac-labs.com/wikikit-aitm-phishing-kit-where-links-tell-lies-abdea71ba094