Contesto
Diversi attaccanti stanno impersonando ricercatori di sicurezza informatica di una società fasulla denominata “High Sierra Cyber Security". Questi sfruttano le piattaforme Twitter e GitHub per diffondere Proof of Concept falsi riguardanti vulnerabilità zero-day presenti in software ampiamente utilizzati tra cui Microsoft Exchange, Chrome, Discord o Chromium.
Tali Proof-of-concept fraudolenti, una volta eseguiti, hanno la capacità di infettare sia i sistemi operativi Windows che Linux.
Rapporto Tecnico
I repository compromessi ospitano uno script Python denominato "poc.py", il quale svolge la funzione di downloader di malware per sistemi operativi Linux e Windows. Tale script effettua il download di un archivio ZIP da un URL esterno, in base al sistema operativo utilizzato dalla vittima, "cveslinux.zip" per utenti Linux e "cveswindows.zip" per utenti Windows.
Una volta scaricato, il malware viene salvato nelle seguenti directory di sistema:
• Windows %Temp%
• Linux /home/\
Attualmente, non è ancora stato definito il tipo specifico di malware installato, tuttavia entrambi gli eseguibili implicano l’installazione di un client TOR. In particolare, è stato identificato che nella versione per Windows vengono installati trojan progettati per esfiltrare credenziali.
Analisi del Codice “poc.py”
Il codice, di 169 righe, presenta diverse funzioni come ad esempio perform_attack, fail, try_zero_authenticate, exploit, che non vengono mai richiamate direttamente nel flusso di esecuzione principale del programma.
Questa è una tecnica che viene utilizzata dal Threat Actor per simulare una maggiore complessità di codice e creare riferimenti ad exploit e tentativi di autenticazione per ingannare la vittima.
Pertanto, il flusso principale si limita a:
• eseguire il blocco condizionale che scaricherà ed eseguirà il file malevolo a seconda che sia sistema operativo Windows o Linux.
• eseguire la funzione main() che simulerà l’inizio di una finta scansione.
Di seguito in dettaglio la parte di codice che verrà eseguita nel flusso principale:
-
Il blocco condizionale if __name==\’__main\’ : verifica se il modulo è stato eseguito come script principale, ovvero direttamente da shell di sistema.
-
All’interno di questo blocco, viene effettuato un controllo sull’ambiente operativo utilizzando os.name.
Se il valore di os.name è \’nt\’, l’ambiente operativo è Windows, altrimenti si tratta di ambiente operativo Linux. -
os.name == nt (Windows):
a. Sono definiti i valori che verranno utilizzati successivamente:
- namezip è il nome del file zip da scaricare ("cveswindows.zip")
- name è il nome della directory di destinazione ("cveswindows")
- url è l’URL da cui scaricare il file
b. Viene creato il percorso di destinazione des utilizzando os.environ[\’TMP\’] (che rappresenta la directory temporanea del sistema) e il nome del file zip.
c. Viene effettuato un controllo per verificare se il file eseguibile (name + ".exe") esiste nella cartella di destinazione. Se il file non esiste, viene eseguito il blocco condizionale interno.
d. All’interno di questo blocco, il file zip viene scaricato utilizzando urllib.request.urlretrieve(), salvato nella directory di destinazione specificata, quindi estratto utilizzando ZipFile e extractall().
e. Successivamente, viene utilizzata subprocess.Popen() per avviare l’esecuzione del file eseguibile specificato (name + ".exe") tramite il comando Popen(). Vengono anche specificati alcuni flag per controllare come viene creato il processo, ad esempio creationflags=0x00000008 per creare il processo come processo separato e subprocess.CREATE_NO_WINDOW per evitare la visualizzazione di una finestra della console.
f. Nel blocco except, viene utilizzata la clausola pass per gestire eventuali eccezioni che potrebbero verificarsi durante il processo di download, estrazione o avvio del file eseguibile. In pratica, se si verifica un’eccezione, viene ignorata e il programma continua l’esecuzione senza interrompersi.
-
os.name != nt (Linux):
a. Sono definiti i valori che verranno utilizzati successivamente:
- namezip è il nome del file zip da scaricare ("cveslinux.zip")
- name è il nome della directory di destinazione ("cveslinux")
- url è l’URL da cui scaricare il file
b. Viene creato il percorso di destinazione des utilizzando os.environ["USERNAME"] per ottenere il nome utente corrente e il percorso desiderato.
c. Viene effettuato un controllo per verificare se il file eseguibile esiste nella cartella di destinazione. Se il file non esiste, viene eseguito il blocco condizionale interno.
d. All’interno di questo blocco, il file zip viene scaricato utilizzando urllib.request.urlretrieve(), salvato nella directory di destinazione specificata, quindi estratto utilizzando ZipFile e extractall().
e. Viene ottenuto l’oggetto stat del file utilizzando os.stat() e successivamente utilizzato per applicare i permessi di esecuzione al file utilizzando os.chmod()
f. Viene avviato un nuovo processo utilizzando subprocess.Popen(), che esegue il comando /bin/bash -c con il percorso completo del file eseguibile "cveslinux" come argomento. L’opzione start_new_session=True viene utilizzata per avviare il processo in una nuova sessione.
g. L’output standard del processo viene reindirizzato a subprocess.DEVNULL (nessun output) e l’output di errore viene reindirizzato a subprocess.STDOUT (output standard).
-
Per ultimo esegue la chiamata alla funzione main:
a. Controlla il numero di argomenti passati al programma tramite sys.argv, che è una lista che contiene gli argomenti della riga di comando. Se il numero di argomenti non è compreso tra 3 e 4 (inclusi), viene stampato un messaggio di utilizzo (‘Usage: cve.py \
\ ) e un messaggio di errore (Error no –hostname or –port supplied, exiting…), quindi il programma viene terminato con sys.exit(1) per indicare un errore.b. Se il numero di argomenti è valido, la funzione prosegue. La riga [_, dc_name, dc_ip] = [\"127.0.0.1", \"who", \"wat"] assegna valori di default alle variabili dc_name e dc_ip.
c. Vengono quindi stampati i messaggi "Starting the scan…" e "Host is not vulnerable" seguiti dal valore del primo argomento passato (sys.argv[1]).
d. La riga dc_name = dc_name.rstrip(\’$\’) rimuove eventuali caratteri \’$\’ alla fine del valore di dc_name. Questa operazione può essere utile per pulire il valore e rimuovere eventuali caratteri indesiderati.
e. La variabile victim viene assegnata con il valore di dc_name.
f. Infine, viene chiamata la funzione perform_attack() con tre argomenti: \’\\\\\’ + dc_name, dc_ip e victim. Tuttavia, la chiamata a questa funzione è attualmente commentata, quindi non eseguita nel flusso del codice.