Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2021-3560 — Exploit em C para CVE-2021-3560, um desvio de autenticação no polkit permitindo que usuários não privilegiados criem uma conta privilegiada via DBus, com uma análise técnica detalhada. | Kitploit
Ferramentas/GitHubGitHub/hakivvi/cve-2021-3560
Autenticação e AutorizaçãoEscalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoTestes de PenetraçãoRed Teaming
GitHubhakivvi/cve-2021-3560

CVE-2021-3560

Exploit em C para CVE-2021-3560, um desvio de autenticação no polkit permitindo que usuários não privilegiados criem uma conta privilegiada via DBus, com uma análise técnica detalhada.

Ver Repositório
401210há 5 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2021-3560

um exploit confiável em C para CVE-2021-3560.

Resumo:

Ontem me deparei com este post no blog de Kevin Backhouse (descobridor desta vulnerabilidade), tentei os comandos bash fornecidos no post e, para minha surpresa, funcionou na minha máquina Kali Linux!

CVE-2021-3560 é uma bypass de autenticação no polkit, que permite que um usuário não privilegiado chame métodos privilegiados usando DBus. O PoC explora esse bug para chamar 2 métodos privilegiados fornecidos pelo accountsservice (CreateUser e SetPassword), o que nos permite criar um usuário privilegiado e depois definir uma senha para ele.

O polkit verifica se o chamador está autorizado a chamar tal método, fazendo isso primeiro verificando o ID de usuário do chamador; se for zero, assume-se que o chamador é root e a ação é permitida sem solicitar autenticação; caso contrário, solicita a senha do usuário.

A função polkit_system_bus_name_get_creds_sync() invoca 2 métodos para obter o UID e PID do chamador: GetConnectionUnixUser e GetConnectionUnixProcessID. O resultado dessas chamadas é escrito na struct data do tipo AsyncGetBusNameCredsData (esta struct é inicializada com 0) pela função de callback on_retrieved_unix_uid_pid(), e polkit_system_bus_name_get_creds_sync() bloqueia enquanto espera que a função de callback defina um erro ou o 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);

a função de callback on_retrieved_unix_uid_pid() é invocada após cada chamada de método para recuperar a resposta (UID e PID) ou definir um erro. Esta função chama g_dbus_connection_call_finish() para recuperar a resposta; se um erro ocorrer, então define data.caught_error como TRUE e retorna (data.uid e data.pid permanecem 0). Caso contrário, atribui o valor recuperado (UID ou PID) a data.uid ou data.pid (dependendo de qual valor foi recuperado) e retorna.

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;
	}
    }
}

Os métodos GetConnectionUnixUser e GetConnectionUnixProcessID retornarão o UID e PID se encontrados (o processo chamador ainda está conectado ao barramento), ou um erro se ocorrer um erro (por exemplo: processo chamador morto).

Uma vez que data.uid e data.pid são definidos ou data.caught_error é definido, a função polkit_system_bus_name_get_creds_sync() continua e é aqui que a vulnerabilidade existe: polkit_system_bus_name_get_creds_sync() não retorna um erro se data.caught_error está definido; em vez disso, define o valor que está em data.uid para out_uid e retorna TRUE (mesmo se data.caught_error estiver definido). out_pid é um ponteiro para uma variável guint32 passado para polkit_system_bus_name_get_creds_sync() quando chamado por 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;

exploração:

Baixar ferramenta