Sintesi
Slow Pisces (alias Jade Sleet, TraderTraitor, PUKCHONG) è un gruppo di minacce sponsorizzato dallo Stato nordcoreano che si concentra principalmente sulla generazione di entrate per il regime della Repubblica Democratica Popolare di Corea, in genere prendendo di mira grandi organizzazioni nel settore delle criptovalute. Questo articolo analizza la loro campagna che riteniamo sia collegata alle recenti furti di criptovalute.
In questa campagna, Slow Pisces ha contattato gli sviluppatori di criptovalute su LinkedIn, fingendosi potenziali datori di lavoro e inviando malware camuffati da challenges/sfide di programmazione o codifica. Queste sfide richiedono agli sviluppatori di mandare in esecuzione un progetto compromesso, infettando i loro sistemi con malware che abbiamo chiamato RN Loader e RN Stealer.
Il gruppo avrebbe rubato oltre 1 miliardo di dollari dal settore delle criptovalute nel 2023. Per farlo ha utilizzato vari metodi, tra cui applicazioni di trading false, malware distribuito tramite Node Package Manager (NPM) e compromissioni della catena di approvvigionamento.
Nel dicembre 2024, l'FBI ha attribuito a Slow Pisces il furto di 308 milioni di dollari da una società di criptovalute con sede in Giappone. Più recentemente, il gruppo è balzato agli onori della cronaca per il suo presunto coinvolgimento nel furto di 1,5 miliardi di dollari da una borsa di criptovalute di Dubai.
Abbiamo condiviso la nostra intelligence sulle minacce con gli analisti di GitHub e LinkedIn per eliminare gli account e i repository interessati.
In risposta hanno fornito la seguente dichiarazione:
GitHub e LinkedIn hanno rimosso questi account dannosi per aver violato i rispettivi termini di servizio. In tutti i nostri prodotti utilizziamo una tecnologia automatizzata, combinata con team di esperti di indagini e segnalazioni dei membri, per combattere i malintenzionati e applicare i termini di servizio. Continuiamo a evolvere e migliorare i nostri processi e incoraggiamo i nostri clienti e membri a segnalare qualsiasi attività sospetta..
Informazioni aggiuntive
- Gli utenti di GitHub possono trovare maggiori informazioni nelle nostre pagine sulle Politiche d'uso accettabili e sulla segnalazione di abusi e spam.
- Gli utenti di LinkedIn possono saperne di più su come identificare e segnalare gli abusi qui: Riconoscere e segnalare spam, contenuti inappropriati e abusivi | Guida di LinkedIn.
Questo rapporto descrive in dettaglio come Slow Pisces nasconde il malware all'interno delle sue sfide di codifica e descrive i successivi strumenti del gruppo, con l'obiettivo di fornire all'industria in generale una migliore comprensione di questa minaccia
I clienti di Palo Alto Networks sono più protetti dalle minacce discusse in questo articolo grazie ai nostri abbonamenti Next-Generation Firewall con Advanced URL Filtering e Advanced DNS Security.
Se pensate di essere stati compromessi o se avete una questione urgente, contattate il team di risposta agli incidenti dell'Unit 42.
Argomenti correlati a Unit 42 | Cryptocurrency, DPRK |
Analisi tecnica
La nostra visibilità di questa campagna segue a grandi linee tre fasi, illustrate di seguito nella Figura 1.

Fase 1 - Esche in PDF
Slow Pisces ha iniziato impersonando i reclutatori su LinkedIn e contattando i potenziali bersagli, inviando loro un PDF benigno con una descrizione del lavoro, come mostrato nella Figura 2. Se i potenziali bersagli si candidavano, ricevevano una sfida di programmazione composta da diversi compiti delineati in un foglio di domande.

Abbiamo osservato Slow Pisces spacciarsi per diverse organizzazioni con queste esche, principalmente nel settore delle criptovalute. I fogli di domande includono compiti generici di sviluppo software e una sfida di codifica "progetto reale", che rimanda a un repository GitHub mostrato nella Figura 3 qui sotto.

Fase 2 - Repository GitHub
Slow Pisces ha presentato agli obiettivi le cosiddette sfide di codifica come progetti da repository di codice su GitHub. I repository contenevano codice adattato da progetti open-source, comprese applicazioni per la visualizzazione e l'analisi:
- Dati del mercato azionario
- Statistiche dei campionati di calcio europei
- Dati meteo
- Prezzi delle criptovalute
Il gruppo ha utilizzato principalmente progetti in Python o JavaScript, probabilmente a seconda che l'obiettivo si candidasse per un ruolo di sviluppo front-end o back-end. In questa campagna abbiamo visto anche repository basati su Java, anche se erano molto meno comuni, con solo due casi che impersonavano un'applicazione di criptovaluta chiamata jCoin.
Questa scarsità suggerisce che gli aggressori potrebbero aver creato repository su richiesta, in base al linguaggio di programmazione preferito dall'obiettivo. Di conseguenza, il gruppo ha utilizzato più frequentemente i linguaggi più popolari nel settore delle criptovalute, come JavaScript e Python. Allo stesso modo, potrebbero esistere archivi non scoperti anche per altri linguaggi di programmazione.
Fase 3a - Repository Python
Alla fine del 2024, il gruppo ha utilizzato un progetto illustrato nella Figura 4, intitolato "Stocks Pattern Analyzer", adattato da un archivio legittimo.

La maggior parte del codice presente nel repository è benigno. Quando gli obiettivi tentano di eseguire il progetto secondo il foglio delle domande, i dati vengono recuperati da tre posizioni remote:
- hxxps://en.wikipedia[.]org/wiki/Lista_delle_aziende_S%26P_500_aziende
- hxxps://it.wikipedia[.]org/wiki/Currency_pair
- hxxps://en.stockslab[.]org/symbols/sp500
Due degli URL prelevano i dati da Wikipedia. Il terzo URL utilizza un dominio controllato da Slow Pisces. Questo schema - l'utilizzo di più fonti di dati, la maggior parte legittime ma una malevola - è comune nei repository Python del gruppo.
Il server di comando e controllo (C2) dannoso è configurato per imitare il formato delle fonti legittime. In questo caso, utilizza il sottodominio .en e il dominio di primo livello (TLD) .org, come vediamo per il dominio legittimo di Wikipedia.
Deserializzazione di YAML
Slow Pisces potrebbe semplicemente inserire il malware direttamente nel repository o eseguire il codice dal server C2 utilizzando le funzioni eval o exec integrate in Python. Tuttavia, queste tecniche sono facilmente rilevabili, sia con l'ispezione manuale che con le soluzioni antivirus.
Invece, Slow Pisces si assicura innanzitutto che il server C2 risponda con dati applicativi validi. Ad esempio, il repository di cui sopra si aspetta un elenco di simboli delle società S&P 500. L'URL C2 risponde inizialmente con questi dati in un elenco formato JSON. L'URL C2 risponde inizialmente con questi dati in un elenco formattato in JSON.
Gli attori di minacce inviano un payload dannoso solo a obiettivi convalidati, probabilmente in base all'indirizzo IP, alla geolocalizzazione, all'ora e alle intestazioni delle richieste HTTP. Concentrarsi su individui contattati tramite LinkedIn, rispetto a campagne di phishing di ampia portata, permette al gruppo di controllare strettamente le fasi successive della campagna e di consegnare i payload solo alle vittime previste.
Per evitare le sospette funzioni eval ed exec, Slow Pisces utilizza la deserializzazione YAML per eseguire il proprio payload, come mostrato nella Figura 5.

Questo codice recupera i dati dal server C2 tramite HTTPS e controlla l'intestazione Content-Type della risposta. Se l'intestazione indica dati JSON (application/json), il codice analizza e restituisce il JSON all'applicazione.
Se la risposta indica dati YAML (application/yaml), il codice utilizza la funzione yaml.load() della libreria PyYAML per analizzare i dati. Questa funzione è intrinsecamente non sicura e la documentazione di PyYAML raccomanda esplicitamente yaml.safe_load() per input non attendibili.
YAML è tipicamente usato per i file di configurazione, come l'esempio mostrato di seguito:
1 2 3 4 5 6 7 8 9 |
username: slow password: pisces api: key: supersecret url: example.com |
Tuttavia, yaml.load() può serializzare e deserializzare oggetti Python arbitrari, non solo dati YAML validi. Ad esempio, il seguente codice Python stampa i numeri 0-4:
1 |
range(0, 5) |
Se questo codice fosse serializzato usando yaml.dump() diventerebbe il seguente:
1 2 3 4 5 6 7 |
!!python/object/apply:builtins.range - 0 - 5 - 1 |
Infine, quando questi dati vengono passati a yaml.load(), viene eseguito il codice originale: range(0, 5).
Questo evidenzia un potenziale punto di rilevamento, poiché i payload per il repository Python, e il malware che utilizza la deserializzazione YAML in generale, contengono !!python/object/apply:builtins se il payload utilizza una funzione Python integrata.
I seguenti stadi della Tabella 1 risiedono principalmente in memoria e generalmente non hanno alcuna impronta su disco. Per aiutare la comunità nel rilevamento e nella consapevolezza, abbiamo caricato questi payload su VirusTotal. Il payload di deserializzazione YAML esegue un malware che abbiamo chiamato RN Loader e RN Stealer in base al formato del token C2 che abbiamo osservato in RN Stealer, descritto nelle sezioni successive.
Fase | Hash SHA256 |
Payload di deserializzazione YAML | 47e997b85ed3f51d2b1d37a6a61ae72185d9ceaf519e2fdb53bf7e761b7bc08f |
RN Loader | 937c533bddb8bbcd908b62f2bf48e5bc11160505df20fea91d9600d999eafa79 |
RN Stealer | e89bf606fbed8f68127934758726bbb5e68e751427f3bcad3ddf883cb2b50fc7 |
Tabella 1. Payloads del repository Python.
Il payload di deserializzazione YAML di Slow Pisces inizia con la creazione della cartella Public nella home directory della vittima e la creazione di un nuovo file in tale directory denominato __init__.py. I dati Base64 incorporati vengono decodificati e scritti in questo file, che contiene la fase successiva dell'infezione (RN Loader), che viene quindi eseguita.
Caricatore RN
Questo nuovo file creato per RN Loader in ~/Public/__init__.py si cancella dopo l'esecuzione, assicurando che esista solo in memoria. Invia informazioni di base sulla macchina vittima e sul sistema operativo tramite HTTPS allo stesso C2 all'indirizzo it.stockslab[.]org, seguito da un ciclo di comandi con le seguenti opzioni riportate nella Tabella 2.
Codice | Descrizione |
0 | Sleep for 20 seconds |
1 | Decodifica in base64 il contenuto inviato e lo salva nel file init.dll per Windows o init per tutti gli altri sistemi operativi.
Imposta una variabile d'ambiente X_DATABASE_NAME su una stringa vuota. Carica ed esegue la DLL scaricata utilizzando ctypes.cdll.LoadLibrary. |
2 | Decodifica in base64 il contenuto inviato e lo esegue utilizzando l'exec integrato in Python. |
3 | Decodifica in base64 il contenuto inviato e un parametro. Il contenuto viene salvato nel file dockerd, mentre il parametro viene salvato come docker-init.
dockerd viene quindi eseguito in un nuovo processo, con docker-init fornito come argomento della riga di comando. |
9 | Termina l'esecuzione. |
Tabella 2. Tabella dei comandi di RN Loader.
I payload del ciclo di comandi della Tabella 2 che utilizza le opzioni 1 e 3 sono attualmente sconosciuti e sono probabilmente innescati da condizioni specifiche. Tuttavia, abbiamo recuperato un infostealer basato su Python fornito dall'opzione 2 e abbiamo identificato questo malware come RN Stealer.
RN Stealer
RN Stealer genera innanzitutto un ID vittima casuale, successivamente utilizzato come cookie in tutte le comunicazioni con il server C2. Quindi richiede al server una chiave XOR per crittografare i dati esfiltrati.
La comunicazione con il server C2 avviene tramite HTTPS, utilizzando token codificati Base64 per identificare i tipi di richiesta e risposta. Il payload analizzato include quattro tipi di token:
- R0 - chiave XOR richiedente
- R64 - esfiltrazione di dati
- R128 - esfiltrazione di dati compressi
- R256 - infostealer completo
Il formato di questi tipi di token - la lettera R seguita da un numero intero N - ci ha portato a dare un nome a questo payload. Chiamiamo il payload RN Stealer e lo stadio precedente RN Loader.
Abbiamo recuperato lo script di questo campione RN Stealer da un sistema macOS. Pertanto, gli autori delle minacce hanno adattato questo campione per rubare informazioni specifiche ai dispositivi macOS, tra cui:
- Informazioni di base sulla vittima: Nome utente, nome macchina e architettura
- Applicazioni installate
- L'elenco delle directory e il contenuto di primo livello della home directory della vittima.
- Il file login.keychain-db che memorizza le credenziali salvate nei sistemi macOS
- Chiavi SSH memorizzate
- File di configurazione per AWS, Kubernetes e Google Cloud
I dati raccolti da RN Stealer determinano probabilmente se è necessario un accesso persistente. Se è così, possiamo dedurre i seguenti passaggi per questa catena di infezione di Python:
- Il server C2 controlla le vittime del beaconing in base a criteri sconosciuti. Le vittime valide ricevono un payload di deserializzazione YAML. Le vittime non valide ricevono dati JSON benigni.
- Il payload di deserializzazione stabilisce un ciclo di comando con il server C2, esfiltra le informazioni di base della vittima e consegna un infostealer Python personalizzato tramite il codice di opzione 2 nella Tabella 2.
- L'infostealer raccoglie informazioni più dettagliate sulle vittime, che gli aggressori hanno probabilmente utilizzato per determinare se avevano bisogno di un accesso continuo.
- Se è richiesto l'accesso continuo, il server C2 invia un carico utile tramite i codici di opzione 1 o 3.
- Se l'accesso non è più necessario, il codice opzione 9 termina l'esecuzione del malware, eliminando ogni accesso poiché il payload risiede esclusivamente in memoria.
Fase 3b - Repository JavaScript
Se le vittime prese di mira hanno fatto domanda per un ruolo JavaScript, potrebbero invece imbattersi in un progetto "Cryptocurrency Dashboard", simile all'esempio della Figura 6 qui sotto.

Questa applicazione contiene un file .env con l'origine dati C2 e legittima:
- PORTA=3000
- COINGECKO_API_URL=hxxps://api.coingecko[.]com/api/v3
- JQUERY_API_URL=hxxps://update.jquerycloud[.]io/api/v1
Il valore COINGECKO_API_URL viene utilizzato per recuperare i dati per la Cryptocurrency Dashboard, mentre il valore JQUERY_API_URL rappresenta un server C2 controllato da Slow Pisces. Analogamente al repository Python, il server C2 JavaScript consegna i payload solo agli obiettivi convalidati, altrimenti risponde con un numero di versione.
Il repository utilizza lo strumento di template Embedded JavaScript (EJS), passando le risposte dal server C2 alla funzione ejs.render(), mostrata di seguito nella Figura 7.

Come l'uso di yaml.load(), questa è un'altra tecnica utilizzata da Slow Pisces per nascondere l'esecuzione di codice arbitrario dai suoi server C2, e questo metodo è forse evidente solo quando si visualizza un payload valido.
La funzione di rendering di EJS accetta vari parametri, uno dei quali è chiamato view options. All'interno di questo parametro, è possibile fornire codice JavaScript arbitrario ed eseguirlo tramite il tasto escapeFunction.
Un ricercatore taiwanese, conosciuto con il nome di Huli, ha discusso i dettagli tecnici di come questo porta all'esecuzione di codice arbitrario in un post su CTF. Tuttavia, possiamo capire a sufficienza che un payload strutturato come quello mostrato nella Figura 8 porterà all'esecuzione del codice contenuto in escapeFunction quando viene passato a ejs.render().

Purtroppo non siamo riusciti a recuperare l'intera parte di questo payload. Possiamo solo ipotizzare che venga creata una nuova directory .jql sotto la home directory dell'utente, dove viene scaricato un file chiamato helper.js, contenente dati codificati in Base64.
Infrastrutture
La timeline riportata nella Figura 9 illustra in dettaglio l'infrastruttura C2 utilizzata in questa campagna dal febbraio 2024 al febbraio 2025, raggruppata in base al tipo di repository utilizzato (JavaScript o Python).

Come accennato in precedenza, i domini dell'infrastruttura di questa campagna possono imitare il formato delle fonti legittime utilizzate al loro fianco, utilizzando spesso sottodomini come api o cdn. Abbiamo scoperto infrastrutture associate a questa campagna fino al momento di questo articolo.
Conclusione
Questo rapporto ha riguardato la campagna più recente di Slow Pisces, che si è spacciata per reclutatori su LinkedIn per colpire gli sviluppatori del settore delle criptovalute con sfide di codifica dannose. Sebbene non siamo riusciti a recuperare l'intera catena di attacco per i repository JavaScript, la versione Python della campagna ha fornito due nuovi payload che abbiamo chiamato RN Loader e RN Stealer.
L'utilizzo di LinkedIn e GitHub in questo modo non è unico. Diversi gruppi affiliati alla RPDC hanno usato tattiche simili, come Alluring Pisces e Contagious Interview.
Questi gruppi non presentano sovrapposizioni operative. Tuttavia, è degno di nota il fatto che queste campagne utilizzino vettori di infezione iniziale simili.
Slow Pisces si distingue dalle campagne dei suoi colleghi per la sicurezza operativa. La consegna dei carichi utili in ogni fase è fortemente sorvegliata ed esiste solo in memoria. E gli strumenti del gruppo per le fasi successive vengono distribuiti solo quando necessario.
In particolare, il gruppo ha utilizzato due tecniche per nascondere la funzionalità:
- Deserializzazione di YAML
- EJS escapeFunction
Entrambe queste tecniche ostacolano notevolmente l'analisi, il rilevamento e la caccia. Allo stesso modo, gli sviluppatori relativamente nuovi o inesperti nel settore delle criptovalute avrebbero difficoltà a identificare questi repository come dannosi.
Sulla base delle segnalazioni pubbliche di rapine di criptovalute, questa campagna sembra avere molto successo e probabilmente persisterà nel 2025. Sebbene questo articolo abbia evidenziato due potenziali opportunità di rilevamento per la deserializzazione YAML e i payload EJS escapeFunction, la mitigazione più efficace rimane la rigorosa segregazione dei dispositivi aziendali e personali. Questo aiuta a prevenire la compromissione dei sistemi aziendali da parte di campagne mirate di social engineering.
Protezione e mitigazione di Palo Alto Networks
I clienti di Palo Alto Networks sono più protetti dalle minacce di cui sopra grazie ai seguenti prodotti:
Se pensate di essere stati compromessi o avete una questione urgente, contattate il team di risposta agli incidenti dell'Unit 42 o chiamate:
- Nord America: Numero verde: +1 (866) 486-4842 (866.4.UNIT42)
- REGNO UNITO: +44.20.3743.3660
- Europa e Medio Oriente: +31.20.299.3130
- Asia: +65.6983.8730
- Giappone: +81.50.1790.0200
- Australia: +61.2.4062.7950
- India: 00080005045107
Palo Alto Networks ha condiviso questi risultati con i membri della Cyber Threat Alliance (CTA). I membri della CTA utilizzano queste informazioni per distribuire rapidamente le protezioni ai loro clienti e per distruggere sistematicamente i criminali informatici. Per saperne di più sulla Cyber Threat Alliance.
Indicatori di compromissione
Dominio | Indirizzo IP | Visto per la prima volta | Ultimo visto | Repository |
getstockprice[.]com | 70.34.245[.]118 | 2025-02-03 | 2025-02-20 | Python |
cdn[.]clubinfo[.]io | 5.206.227[.]51 | 2025-01-21 | 2025-02-19 | Python |
getstockprice[.]info | 131.226.2[.]120 | 2025-01-21 | 2025-01-23 | Python |
api[.]stockinfo[.]io | 136.244.93[.]248 | 2024-10-30 | 2024-11-11 | Python |
cdn[.]logoeye[.]net | 54.39.83[.]151 | 2024-10-29 | 2024-11-03 | Python |
en[.]wfinance[.]org | 195.133.26[.]32 | 2024-10-12 | 2024-11-01 | Python |
en[.]stocksindex[.]org | 185.236.231[.]224 | 2024-09-11 | 2024-10-04 | Python |
cdn[.]jqueryversion[.]net | 194.11.226[.]16 | 2024-08-23 | 2024-09-23 | JavaScript |
en[.]stockslab[.]org | 91.103.140[.]191 | 2024-08-19 | 2024-09-12 | Python |
update[.]jquerycloud[.]io | 192.236.199[.]57 | 2024-07-03 | 2024-08-22 | JavaScript |
cdn[.]soccerlab[.]io | 146.70.124[.]70 | 2024-08-07 | 2024-08-21 | Python |
api[.]coinpricehub[.]io | 45.141.58[.]40 | 2024-05-06 | 2024-08-06 | Java |
cdn[.]leaguehub[.]net | 5.133.9[.]252 | 2024-07-15 | 2024-07-21 | Python |
cdn[.]clublogos[.]io | 146.19.173[.]29 | 2024-06-24 | 2024-07-12 | Python |
api[.]jquery-release[.]com | 146.70.125[.]120 | 2024-06-10 | 2024-06-28 | JavaScript |
cdn[.]logosports[.]net | 185.62.58[.]74 | 2024-05-08 | 2024-06-23 | Python |
skypredict[.]org | 80.82.77[.]80 | 2024-05-06 | 2024-06-16 | JavaScript |
api[.]bitzone[.]io | 192.248.145[.]210 | 2024-04-25 | 2024-05-13 | Python |
weatherdatahub[.]org | 194.15.112[.]200 | 2024-04-05 | 2024-05-03 | JavaScript |
api[.]ethzone[.]io | 91.234.199[.]90 | 2024-04-16 | 2024-04-24 | Python |
api[.]fivebit[.]io | 185.216.144[.]41 | 2024-04-08 | 2024-04-14 | Python |
blockprices[.]io | 91.193.18[.]201 | 2024-03-15 | 2024-04-09 | JavaScript |
api[.]coinhar[.]io | 185.62.58[.]122 | 2024-03-26 | 2024-04-09 | Python |
mavenradar[.]com | 23.254.230[.]253 | 2024-02-21 | 2024-03-26 | JavaScript |
indobit[.]io | 146.70.88[.]126 | 2024-03-19 | 2024-03-20 | Python |
api[.]thaibit[.]io | 79.137.248[.]193 | 2024-03-07 | 2024-03-09 | Python |
chainanalyser[.]com | 38.180.62[.]135 | 2024-02-23 | 2024-03-06 | JavaScript |
Risorse aggiuntive
- La Corea del Nord responsabile dell'hacking di Bybit da 1,5 miliardi di dollari - Internet Crime Complaint Center (IC3)
- L'FBI, il DC3 e l'NPA hanno identificato gli attori informatici nordcoreani, rintracciati come TraderTraitor, responsabili del furto di 308 milioni di dollari da Bitcoin.DMM.com - FBI
- Allarme sicurezza: una campagna di social engineering prende di mira i dipendenti del settore tecnologico - GitHub Blog
- La Corea del Nord sfrutta un fornitore SaaS in un attacco mirato alla catena di approvvigionamento - Mandiant, Google Cloud