Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
Invia
StrumentiBlog
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 — Exploit in C per CVE-2021-3560, un bypass dell'autenticazione in polkit che consente a utenti non privilegiati di creare un account privilegiato tramite DBus, con un'analisi tecnica dettagliata. | Kitploit
Strumenti/GitHubGitHub/hakivvi/cve-2021-3560
Autenticazione e AutorizzazioneEscalation di PrivilegiAnalisi delle VulnerabilitàExploitPenetration TestingRed Teaming
GitHubhakivvi/cve-2021-3560

CVE-2021-3560

Exploit in C per CVE-2021-3560, un bypass dell'autenticazione in polkit che consente a utenti non privilegiati di creare un account privilegiato tramite DBus, con un'analisi tecnica dettagliata.

Vedi Repository
4012105 anni faRevisionato da Kitploit

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

CVE-2021-3560

un exploit affidabile basato su C per CVE-2021-3560.

Sommario:

Ieri mi sono imbattuto in questo post del blog di Kevin Backhouse (lo scopritore di questa vulnerabilità), ho provato i comandi bash forniti nel post e, con mia sorpresa, ha funzionato sulla mia macchina Kali Linux!

CVE-2021-3560 è un bypass dell'autenticazione su polkit, che consente a un utente non privilegiato di chiamare metodi privilegiati tramite DBus. La PoC sfrutta questo bug per chiamare 2 metodi privilegiati forniti da accountsservice (CreateUser e SetPassword), permettendoci di creare un utente privilegiato e poi impostarne una password.

polkit verifica se il chiamante è autorizzato a invocare tale metodo; lo fa controllando prima l'user id del chiamante: se è zero, il chiamante è considerato root e l'azione è consentita senza richiedere l'autenticazione; altrimenti viene chiesta la password dell'utente.

La funzione polkit_system_bus_name_get_creds_sync() invoca 2 metodi per ottenere UID e PID del chiamante, GetConnectionUnixUser e GetConnectionUnixProcessID. Il risultato di queste chiamate viene scritto nella struct data di tipo AsyncGetBusNameCredsData (questa struct è inizializzata a 0) dalla funzione di callback on_retrieved_unix_uid_pid(), e polkit_system_bus_name_get_creds_sync() rimane in attesa che la funzione di callback imposti un errore oppure UID e PID.

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, }; // intialize to 0
  GDBusConnection *connection = NULL;
  GMainContext *tmp_context = NULL;

  connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
  if (connection == NULL)
    goto out;

  data.error = error;

  tmp_context = g_main_context_new ();
  g_main_context_push_thread_default (tmp_context);

  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 funtion
			  &data); // data is passed to the callback function along with the reply from the method
  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 funtion
			  &data); // data is passed to the callback function along with the reply from the method

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error)) // block while on_retrieved_unix_uid_pid() is not called yet
    g_main_context_iteration (tmp_context, TRUE);

La funzione di callback on_retrieved_unix_uid_pid() viene invocata dopo ogni chiamata di metodo per recuperare la risposta (UID e PID) o impostare un errore; questa funzione chiama g_dbus_connection_call_finish() per recuperare la risposta. Se si verifica un errore, imposta data.caught_error a TRUE e ritorna (data.uid e data.pid restano ancora 0). Altrimenti assegna il valore recuperato (UID o PID) a data.uid o data.pid (a seconda del valore recuperato) e poi ritorna.

static void
on_retrieved_unix_uid_pid (GObject              *src, // connection
			   GAsyncResult         *res, // Async result object
			   gpointer              user_data) // data paramter passed from previous function
{
  AsyncGetBusNameCredsData *data = user_data;
  GVariant *v;

  v = g_dbus_connection_call_finish ((GDBusConnection*)src, res,
				     data->caught_error ? NULL : data->error); // finish and get the reply
  if (!v) // error ??
    {
      data->caught_error = TRUE;
    }
  else
    {
      guint32 value;
      g_variant_get (v, "(u)", &value); // unpack the reply, get UINT32 (u)
      g_variant_unref (v);
      if (!data->retrieved_uid) // GetConnectionUnixUser method
	{
	  data->retrieved_uid = TRUE;
	  data->uid = value;
	}
      else
	{
	  g_assert (!data->retrieved_pid); // GetConnectionUnixProcessID method
	  data->retrieved_pid = TRUE;
	  data->pid = value;
	}
    }
}

I metodi GetConnectionUnixUser e GetConnectionUnixProcessID restituiscono l'UID e il PID se li trovano (il processo chiamante è ancora connesso al bus), oppure un errore se si è verificato un errore (ad es.: processo chiamante terminato).

Quando data.uid e data.pid vengono impostati, oppure viene impostato data.caught_error, la funzione polkit_system_bus_name_get_creds_sync() prosegue: è qui che risiede la vulnerabilità. polkit_system_bus_name_get_creds_sync() non restituisce un errore se data.caught_error è impostato; al contrario, assegna a out_uid qualunque valore sia in data.uid e restituisce TRUE (anche se data.caught_error è impostato). out_pid è un puntatore a una variabile guint32 passata a polkit_system_bus_name_get_creds_sync() quando viene chiamata da polkit_system_bus_name_get_user_sync():

static gboolean
polkit_system_bus_name_get_creds_sync (PolkitSystemBusName           *system_bus_name,
				       guint32                       *out_uid, // pointer
				       guint32                       *out_pid, // NULL
				       GCancellable                  *cancellable,
				       GError                       **error)
{

  [snip]
  
  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error)) // wait for the callback function to handle reply
    g_main_context_iteration (tmp_context, TRUE);

  if (out_uid) // TRUE
    *out_uid = data.uid; // set it even if there is an error [!]
  if (out_pid) // FALSE
    *out_pid = data.pid; // set it even if there is an error [!]
  ret = TRUE; // return TRUE even if there is an error [!]
 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;

sfruttamento:

Scarica lo strumento