Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2021-3560 — Analisi approfondita di CVE-2021-3560, una vulnerabilità di escalation dei privilegi locali in Linux PolKit. Include l'analisi della causa principale, le meccaniche dell'exploit e una dimostrazione della condizione di gara che porta all'accesso root. | Kitploit
Strumenti/GitHubGitHub/chenaotian/cve-2021-3560
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitAnalisi di BinariApprendimento e Formazione
GitHubchenaotian/cve-2021-3560

CVE-2021-3560

Analisi approfondita di CVE-2021-3560, una vulnerabilità di escalation dei privilegi locali in Linux PolKit. Include l'analisi della causa principale, le meccaniche dell'exploit e una dimostrazione della condizione di gara che porta all'accesso root.

Vedi Repository
9364 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Analisi di elevazione dei privilegi locali tramite condition race CVE-2021-3560 PolKit

[toc]

Riepilogo della vulnerabilità

ID vulnerabilità: CVE-2021-3560

Punteggio vulnerabilità:

Prodotto vulnerabile: linux PolKit (polkitd)

Versione interessata: introdotta nel codice sorgente 0.113; https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

  • RHEL 8
  • Fedora 21 e versioni successive
  • Debian testing (“bullseye”)
  • Ubuntu 20.04

Condizioni di sfruttamento: linux locale; dbus + polkitd presenti

Effetto dello sfruttamento: elevazione dei privilegi locali

Ottenere il codice sorgente:

  • polkit-0.113: https://launchpad.net/debian/+source/policykit-1/0.113-5
  • accountsservice: apt source accountsservice
  • dbus: apt source dbus

Allestimento dell'ambiente

L'immagine predefinita di ubuntu-20.04.2 può essere riprodotta: http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

Principio della vulnerabilità

Punto di innesco della vulnerabilità

Prima esaminiamo il codice problematico

/polkit-0.113/src/polkit/polkitsystembusname.c : 388 : polkit_system_bus_name_get_creds_sync

static void
on_retrieved_unix_uid_pid (GObject              *src,
			   GAsyncResult         *res,
			   gpointer              user_data)
{
  AsyncGetBusNameCredsData *data = user_data;
  GVariant *v;

  v = g_dbus_connection_call_finish ((GDBusConnection*)src, res,
				     data->caught_error ? NULL : data->error);
  if (!v)
    {
      data->caught_error = TRUE; // imposta il flag di errore dopo un fallimento per qualche motivo
    }
  else
  {
      ··· ···// elaborazione dei dati in caso di successo
  }
  ··· ···
}

static gboolean
polkit_system_bus_name_get_creds_sync (PolkitSystemBusName           *system_bus_name,
				       guint32                       *out_uid,
				       guint32                       *out_pid,
				       GCancellable                  *cancellable,
				       GError                       **error)
{
  gboolean ret = FALSE;
  AsyncGetBusNameCredsData data = { 0, }; // data viene inizializzato a 0
  ··· ···
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixUser",      /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, // callback
			  &data);
  g_dbus_connection_call (connection,
			  "org.freedesktop.DBus",       /* name */
			  "/org/freedesktop/DBus",      /* object path */
			  "org.freedesktop.DBus",       /* interface name */
			  "GetConnectionUnixProcessID", /* method */
			  g_variant_new ("(s)", system_bus_name->name),
			  G_VARIANT_TYPE ("(u)"),
			  G_DBUS_CALL_FLAGS_NONE,
			  -1,
			  cancellable,
			  on_retrieved_unix_uid_pid, // callback
			  &data);

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); // aspetta che il bus termini l'esecuzione, uid e pid siano stati elaborati o che si sia verificato un errore

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; // indipendentemente da tutto, TRUE?
 out:
  if (tmp_context)
    {
      g_main_context_pop_thread_default (tmp_context);
      g_main_context_unref (tmp_context);
    }
  if (connection != NULL)
    g_object_unref (connection);
  return ret;
}

Nella funzione polkit_system_bus_name_get_creds_sync, essa autentica l'identità per certe richieste (la logica specifica verrà dettagliata in seguito). Chiama prima GetConnectionUnixUser e poi GetConnectionUnixProcessID tramite il bus org.freedesktop.DBus. Questi due metodi sono forniti dal bus org.freedesktop.DBus e servono per ottenere il PID e l'UID del processo richiedente. I risultati vengono passati alla funzione callback on_retrieved_unix_uid_pid per l'elaborazione. Quindi la funzione si blocca in attesa che il bus termini l'esecuzione.

Nella funzione on_retrieved_unix_uid_pid si può vedere che, in base al risultato restituito dal bus, imposta se si è verificato un errore (error?) e imposta il flag di errore; se l'esecuzione ha successo, restituisce correttamente l'UID utente o il PID del processo. Ma nella funzione polkit_system_bus_name_get_creds_sync, dopo aver atteso il risultato dal bus (il criterio per considerare completata l'elaborazione è che sia UID che PID siano stati elaborati o che si sia verificato un errore). In altre parole, logicamente ci sono tre possibili risultati dal bus: ottenere UID utente 0 (utente privilegiato); ottenere UID utente diverso da 0 (utente normale); errore. Tuttavia, nell'elaborazione successiva, non viene gestito l'errore: il out_uid da restituire al livello superiore viene impostato direttamente al data.uid restituito dal bus, e ret viene impostato a TRUE:

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); // aspetta che il bus termini l'esecuzione, uid e pid siano stati elaborati o che si sia verificato un errore

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; // indipendentemente da tutto, TRUE?

Ma viene trascurato un caso: se il bus DBUS restituisce un errore, la callback imposta il flag di errore e ritorna senza elaborare i dati data, che però sono inizializzati a 0. Ciò fa sì che successivamente out_uid venga impostato a 0, cioè utente privilegiato.

Allora, dove viene utilizzata la funzione difettosa polkit_system_bus_name_get_creds_sync?

Percorso di innesco

Il processo in cui si trova il punto di vulnerabilità è il processo polkitd:

polkit è un set di strumenti a livello applicativo che, mediante la definizione e la verifica di regole di autorizzazione, realizza la comunicazione tra processi con priorità diverse: le decisioni di controllo sono concentrate in un quadro unificato, determinando se un processo a bassa priorità ha diritto di accesso a un processo ad alta priorità.

In breve, è un processo root in esecuzione in background che, tramite comunicazione interprocesso, decide l'autorizzazione quando un processo a bassi privilegi tenta di accedere alle funzionalità fornite da un processo ad alti privilegi. Poiché questo processo si riavvia se si tenta di collegarlo con gdb, possiamo analizzarlo solo a livello di codice sorgente per trovare il percorso di innesco della funzione vulnerabile:

polkitd utilizza ampiamente il framework di comunicazione interprocesso gio DBUS. È possibile consultare il manuale per conoscere in anticipo alcune funzioni importanti.

Ora analizziamo il percorso di innesco della vulnerabilità in polkitd:

  1. Prima di tutto, il main:

    polkit-0.113\src\polkitbackend\polkitd.c : 155 : main

    int
    main (int    argc,
          char **argv)
    {
      ··· ···
      ··· ···
    
      loop = g_main_loop_new (NULL, FALSE);
    
      sigint_id = g_unix_signal_add (SIGINT,
                                     on_sigint,
                                     NULL);
    
      name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
                                      "org.freedesktop.PolicyKit1",  // registra un nome di bus
                                      G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                                        (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
                                      on_bus_acquired, // callback quando si accede al bus
                                      on_name_acquired,
                                      on_name_lost,
                                      NULL,
                                      NULL);
    
Scarica lo strumento