Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
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
Ferramentas/GitHubGitHub/chenaotian/cve-2021-3560
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoAnálise de BináriosAprendizado e Educação
GitHubchenaotian/cve-2021-3560

CVE-2021-3560

Análise aprofundada da CVE-2021-3560, uma vulnerabilidade de escalonamento local de privilégios no Linux PolKit. Inclui análise da causa raiz, mecânica do exploit e uma demonstração da condição de corrida que leva ao acesso root.

Ver Repositório
936há 4 anosAinda não revisado

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

Análise de Elevação de Privilégio Local por Condição de Corrida no PolKit (CVE-2021-3560)

[toc]

Resumo da Vulnerabilidade

ID da vulnerabilidade: CVE-2021-3560

Pontuação da vulnerabilidade:

Produto vulnerável: linux PolKit (polkitd)

Escopo de impacto: introduzido no código-fonte 0.113; https://www.venustech.com.cn/new_type/aqtg/20210611/22788.html

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

Condições de exploração: linux local; dbus + polkitd presente

Efeito da exploração: elevação de privilégio local

Obtenção do código-fonte:

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

Configuração do Ambiente

A imagem padrão do Ubuntu ubuntu-20.04.2 já pode ser reproduzida: http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-desktop-amd64.iso

Princípio da Vulnerabilidade

Ponto Ocorrente da Vulnerabilidade

Primeiro, veja o código do problema

/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; //某些原因失败之后设置error位
    }
  else
  {
      ··· ···//执行成功的数据处理
  }
  ··· ···
}

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 被初始化为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, //回调函数
			  &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, //回调函数
			  &data);

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); //等待总线那边执行完毕,uid、pid都处理完毕或异常

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; //无论如何都是 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;
}

Na função polkit_system_bus_name_get_creds_sync, que realiza a autenticação de identidade para certas requisições (a lógica do cenário específico será detalhada posteriormente). Ela chama os métodos GetConnectionUnixUser e GetConnectionUnixProcessID através do barramento org.freedesktop.DBus. Esses métodos, fornecidos pelo barramento org.freedesktop.DBus, obtêm o PID e o UID do processo solicitante, que são passados para a função de retorno on_retrieved_unix_uid_pid para processar os dados retornados. Em seguida, o código aguarda bloqueando até que o barramento termine o processamento.

Pode-se ver na função on_retrieved_unix_uid_pid que, com base no resultado retornado pelo barramento, define se houve uma exceção (error?) e então define o sinalizador de exceção. Se a execução for bem-sucedida, retorna normalmente o UID do usuário ou o PID do processo. Mas, na função polkit_system_bus_name_get_creds_sync, após aguardar bloqueando o retorno do barramento (julgando se os sinalizadores de processamento indicam que tanto UID quanto PID foram processados ou que ocorreu uma exceção), ou seja, logicamente, o barramento pode retornar três resultados: obter UID de usuário 0 (usuário privilegiado); obter UID de usuário não zero (usuário comum); ou exceção. No entanto, no processamento posterior, não há tratamento para exceções: ele define diretamente out_uid a ser retornado para a camada superior como data.uid retornado pelo barramento e define ret como TRUE:

  while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
    g_main_context_iteration (tmp_context, TRUE); //等待总线那边执行完毕,uid、pid都处理完毕或异常

  if (out_uid)
    *out_uid = data.uid;
  if (out_pid)
    *out_pid = data.pid;
  ret = TRUE; //无论如何都是 TRUE?

Mas ignora uma situação: quando a execução no barramento DBUS resulta em exceção, a função de retorno define o sinalizador de exceção e retorna sem processar os dados data, que foi inicializado como 0. Isso faz com que posteriormente out_uid seja definido como 0, ou seja, usuário privilegiado.

Então, onde essa função problemática polkit_system_bus_name_get_creds_sync é usada?

Caminho de Gatilho

O ponto vulnerável está no processo polkitd:

polkit é um conjunto de ferramentas em nível de aplicação que, através da definição e auditoria de regras de permissão, possibilita a comunicação entre processos de diferentes prioridades: as decisões de controle são centralizadas em um framework unificado, determinando se um processo de baixa prioridade tem acesso a um processo de alta prioridade.

Resumindo, é um processo root executado em segundo plano que, por meio de comunicação entre processos, realiza um julgamento de permissão quando outros processos de baixa prioridade tentam acessar funcionalidades fornecidas por processos de alta prioridade. Como anexar um depurador a esse processo o reinicia, só podemos analisar pelo código-fonte para encontrar o caminho de gatilho da função vulnerável:

O polkitd utiliza extensivamente o framework de comunicação entre processos gio DBUS. Pode-se consultar previamente o manual e prestar atenção a algumas funções importantes.

A seguir, analisa-se o caminho de gatilho da vulnerabilidade no polkitd:

  1. Primeiro, o 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",  //注册了一个总线名称
                                      G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                                        (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
                                      on_bus_acquired, //访问该总线时的回调函数
                                      on_name_acquired,
                                      on_name_lost,
                                      NULL,
                                      NULL);
    
      g_print ("Entering main event loop\n");
      g_main_loop_run (loop); //循环启动
      ··· ···
      ··· ···
    }
    
  2. Primeiro, registra um barramento chamado org.freedesktop.PolicyKit1, e há três funções de retorno; foca principalmente em on_bus_acquired, que é chamada quando o barramento é acessado.

Baixar ferramenta