Mais de 15 vulnerabilidades foram encontradas no aplicativo HeyCyan Glasses
Relatório Completo de Análise de Segurança — HeyCyan Smart Glasses
Veja a pesquisa completa
Aplicativo: HeyCyan — Companheiro dos Óculos Inteligentes Glass Studio
Pacote:com.glasssutdio.wear
Versão: 1.0.103 (código 103)
SDK Mínimo: 26 (Android 8.0)
SDK Alvo: 35 (Android 15)
Data da Análise: Junho de 2026
Autor: Juan Mathews Rebello Santos
Classificação Geral de Risco: CRÍTICA
Sumário Executivo
Este relatório apresenta uma análise de segurança abrangente do aplicativo HeyCyan, companheiro dos óculos inteligentes Glass Studio. Foram identificadas 21 vulnerabilidades distribuídas em 3 Críticas, 7 Altas, 8 Médias e 3 Baixas. A investigação aprofundada revelou que o pior cenário de ataque é a cadeia de exploração remota via WebView, que combina tráfego HTTP permitido com JavaScript Bridge para permitir execução remota de código (RCE) no dispositivo.
Uma descoberta significativa desta análise aprofundada é que o sistema de criptografia do aplicativo é substancialmente mais robusto do que a análise inicial indicava. O app utiliza AndroidKeyStore com hardware seguro (TEE/SE) para gerar um par de chaves RSA-2048, que por sua vez protege uma chave AES-256-GCM, usada para criptografar as credenciais de API obtidas dinamicamente do servidor backend. As strings de algoritmos fracos (DES/ECB/MD5) encontradas no DEX pertencem a bibliotecas de terceiros (Azure SDK), não ao código do próprio aplicativo.
A vulnerabilidade mais crítica é a combinação de:
- Tráfego HTTP permitido globalmente (V1) — permite ataque MITM
- WebView com JavaScript Bridge (V3) — permite RCE via injeção de scripts
- FileProvider expondo o sistema de arquivos (V2) — permite exfiltração de dados
Esta cadeia de ataque pode ser explorada remotamente sem privilégios especiais, resultando em comprometimento total do dispositivo e dos dados do usuário.
Metodologia
- Análise Estática de APK: Extração e inspeção manual do AndroidManifest.xml binário (AXML decodificado), network_security_config.xml, provider_paths.xml
- Extração de Strings DEX: Script Python customizado para extração de strings legíveis de 4 arquivos classes.dex (~32 MB de bytecode total)
- Inspeção de Assets: Análise de 11 modelos TensorFlow Lite (~13,4 MB), 34 scripts Lua (framework VLC), arquivos de configuração
- Inventário de Bibliotecas Nativas: Catalogação de 47 bibliotecas .so (~105 MB, apenas armeabi-v7a) incluindo Agora RTC, VLC, Microsoft Cognitive Services, TensorFlow Lite, Allwinner
- Reengenharia do Sistema de Criptografia: Reconstrução da arquitetura de segurança de chaves a partir de strings DEX e referências de classes
- Mapeamento de Permissões: Revisão sistemática das 32 permissões declaradas
- Análise de Rede: Mapeamento de todos os endpoints de API e servidores backend
Índice de Vulnerabilidades
| # | Vulnerabilidade | CVSSv3.1 | Gravidade |
|---|---|---|---|
| V1 | Tráfego HTTP Cleartext Permitido Globalmente | 9.1 | Crítica |
| V2 | FileProvider com Root-Path Exposto | 8.4 | Crítica |
| V3 | WebView Inseguro com Ponte JavaScript | 8.8 | Crítica |
| V4 | NotificationListenerService Exportado | 7.1 | Alta |
| V5 | LicenseContentProvider (PairIP) Exportado | 7.5 | Alta |
| V6 | Banco SQLite sem Criptografia (Dados de Usuário) | 6.5 | Alta |
| V7 | Certificate Pinning Ausente | 7.4 | Alta |
| V8 | PendingIntents Mutáveis | 7.0 | Alta |
| V9 | SharedPreferences Legível por Outros Apps | 6.8 | Alta |
| V10 | Superfície de Ataque WebView — Cadeia RCE | 9.1 | Alta |
| V11 | Ausência de Verificação de Integridade dos Modelos TFLite | 6.5 | Média |
| V12 | Permissões Excessivas (32 no total) | 5.9 | Média |
| V13 | Componentes Exportados sem Proteção | 6.1 | Média |
| V14 | Deep Linking sem Validação | 5.3 | Média |
| V15 | Gerenciamento Inseguro de Cookies | 5.5 | Média |
| V16 | Canal de Atualização OTA/Firmware Inseguro | 6.5 | Média |
| V17 | Modelos TensorFlow Lite sem Criptografia (Roubo de IP) | 5.3 | Média |
| V18 | Vulnerabilidades em Bibliotecas Nativas (VLC, Agora) | 5.0 | Média |
| V19 | Coleta de Localização em Background | 4.0 | Baixa |
| V20 | Debug Probes em Build de Produção | 3.3 | Baixa |
| V21 | Telemetria Firebase Crashlytics | 2.1 | Baixa |
Análise Detalhada das Vulnerabilidades
🔴 V1 — Tráfego HTTP Cleartext Permitido Globalmente (Crítica)
Arquivos: AndroidManifest.xml / res/xml/network_security_config.xml
Evidência:
<application
android:usesCleartextTraffic="true"
... >
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
Impacto: Esta é a porta de entrada para a cadeia de ataque mais perigosa do aplicativo. Com usesCleartextTraffic=true e cleartextTrafficPermitted=true, QUALQUER conexão de rede pode ser realizada em HTTP puro. A confiança em certificados de usuário (certificates src="user") permite que proxies MITM (como Burp Suite ou Fiddler) sejam aceitos sem restrição.
Um atacante na mesma rede WiFi pode:
- Interceptar todo o tráfego de rede, incluindo requisições de API
- Capturar tokens de autenticação e credenciais obtidas dinamicamente
- Injeta respostas maliciosas — especialmente crítico para páginas WebView
- Substituir atualizações de firmware OTA
- Cadeia com V3: Injetar JavaScript em páginas carregadas no WebView, ativando a ponte JavaScript → Java para RCE
CVSS: 9.1 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
Correção Imediata:
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
🔴 V2 — FileProvider com Root-Path Exposto (Crítica)
Arquivo: res/xml/provider_paths.xml
Evidência:
<paths>
<root-path name="root" path="." />
<files-path name="files" path="." />
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<external-files-path name="beta_external_path" path="." />
<external-cache-path name="beta_external_files_path" path="." />
</paths>
Impacto: O FileProvider expõe TODOS os diretórios do aplicativo — e criticamente a raiz do sistema de arquivos (root-path com path="."). Isto significa que QUALQUER aplicativo no dispositivo que requisite acesso ao FileProvider pode:
- Ler o banco SQLite completo (
glass_w_database.db) com histórico de chat IA, álbuns de fotos, reuniões gravadas - Acessar SharedPreferences contendo dados criptografados (embora a chave esteja protegida pelo AndroidKeyStore, os dados cifrados ainda podem ser extraídos)
- Percorrer todo o sistema de arquivos a partir da raiz
- Extrair modelos TFLite, scripts Lua, e outros ativos do aplicativo
Agravante: O LicenseContentProvider do PairIP estende este FileProvider vulnerável e é exportado (V5).
CVSS: 8.4 (AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
Correção Imediata:
<paths>
<files-path name="shared_images" path="images/" />
<files-path name="shared_docs" path="documents/" />
<!-- JAMAIS usar root-path com path="." -->
</paths>
🔴 V3 — WebView Inseguro com Ponte JavaScript (Crítica)
Classes Identificadas:
com.glasssutdio.wear.all.view.web.WebViewPreloader— Cache de WebViews pré-carregadascom.glasssutdio.wear.setting.WebStartActivity— Activity exportada com WebViewcom.glasssutdio.wear.setting.WebNotTitleStartActivity— Activity exportada sem barra de título
Evidência (strings do DEX):
setJavaScriptEnabled(true)
addJavascriptInterface(objeto, "Android")
JavascriptInterface
setupWebView(webView)
createSafeWebView(nome) ← Nome enganoso — NÃO é seguro
preloadedWebViews.put(chave, webView)
webView.settings.allowFileAccess = true
Cadeia de Ataque Completa (RCE):
| Passo | Vulnerabilidade | Descrição |
|---|---|---|
| 1 | V1 — HTTP Cleartext | Atacante realiza MITM na rede |
| 2 | V1 — CA de usuário confiado | Proxy MITM é aceito |
| 3 | V3 — JavaScript habilitado | Páginas carregadas executam JS |
| 4 | V3 — Ponte JS | JavaScript invoca métodos Java nativos |
| 5 | V3 — file:// acesso | JS lê arquivos locais via file:///android_asset/ |
| 6 | V14 — WebViews exportados | Apps maliciosos abrem WebView com URLs manipuladas |
| 7 | V15 — Deep Links | Parâmetros de URL injetam payloads |
Resultado: Execução Remota de Código (RCE) — A anotação @JavascriptInterface expõe métodos Java que podem ser chamados do JavaScript. Com acesso file://, o atacante pode exfiltrar o banco de dados SQLite completo, SharedPreferences, e qualquer arquivo acessível. Se a ponte expuser qualquer método que acesse Context, pode ser usada para invocar intents arbitrários.
CVSS: 8.8 (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H)
Correção Imediata:
// REMOVER addJavascriptInterface completamente
// webView.removeJavascriptInterface("Android")
// Desabilitar JavaScript para páginas estáticas (guias)
webView.settings.javaScriptEnabled = false
// Desabilitar file:// e content:// access
webView.settings.allowFileAccess = false
webView.settings.allowContentAccess = false
// Validar URLs com strict allowlist
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
return !request.url.toString().startsWith("https://www.qlifesnap.com/101guide/")
}
}
// NUNCA exportar Activities com WebView
// android:exported="false"
🟠 V4 — NotificationListenerService Exportado (Alta)
Arquivo: AndroidManifest.xml
Evidência:
<service
android:name="com.glasssutdio.wear.push.service.MyNotificationService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Impacto: O NotificationListenerService está exportado. Um app malicioso com permissão do usuário pode:
- Interceptar todas as notificações de todos os apps
- Ler conteúdo de WhatsApp, Telegram, SMS, e-mails
- Capturar códigos 2FA e OTP de autenticação
- Extrair tokens de autenticação de payloads de notificação
CVSS: 7.1 (AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N)
Correção:
<service
android:name=".push.service.MyNotificationService"
android:exported="false"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
</service>
🟠 V5 — LicenseContentProvider (PairIP) Exportado (Alta)
Evidência:
com.pairip.licensecheck.LicenseContentProvider
com.glasssutdio.wear.com.pairip.licensecheck.LicenseContentProvider
com.glasssutdio.wear.MicrosoftCognitiveServicesSpeech.InternalContentProvider
Análise do Sistema PairIP:
O PairIP é um sistema de proteção de integridade de aplicativos (adquirido pelo Google) que utiliza:
- Verificação de instalação pela Play Store
- Validação de assinatura do APK
- Checksums CRC32 para detectar adulteração
- Anti-debugging (bloqueio de Frida, GDB)
- Virtualização de código (lógica crítica executa em VM bytecode customizado)
O Paradoxo de Segurança: O PairIP foi projetado para PROTEGER o aplicativo, mas seu LicenseContentProvider está exportado. Isto permite que um atacante:
- Interaja com o sistema de licenciamento via Content Provider
- Extraia dados sobre o esquema de licenciamento
- Utilize ferramentas de bypass conhecidas (patches de AndroidManifest.xml, ajustes de CRC32, hooks Frida)
CVSS: 7.5 (AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L)
Correção:
<provider
android:name="com.pairip.licensecheck.LicenseContentProvider"
android:exported="false"
android:authorities="com.glasssutdio.wear.pairip.licensecheck" />
🟠 V6 — Banco SQLite sem Criptografia (Alta)
Evidência (entidades Room do DEX):
| Entidade | Conteúdo | Sensibilidade |
|---|---|---|
AiChatEntity | Histórico de conversas com IA | Alta |
GlassAlbumEntity | Fotos e vídeos do álbum | Alta |
MeetingEntity | Reuniões gravadas (transcrições) | Alta |
MessagePushEntity | Mensagens push recebidas | Média |
TranslateEntity | Histórico de traduções | Média |
DeviceSettingEntity | Configurações do dispositivo | Média |
OtaFileEntity | Metadados de firmware OTA | Média |
Arquivo do banco: /data/data/com.glasssutdio.wear/databases/glass_w_database.db
Impacto: O banco Room armazena dados do usuário sem criptografia em repouso. Combinado com V2 (FileProvider exposto) ou acesso ADB, um atacante pode extrair todo o histórico de conversas com IA, metadados de álbuns e reuniões gravadas.
Nota: Diferente das credenciais de API (que são protegidas pelo AndroidKeyStore), os dados de usuário neste banco estão em texto puro e vulneráveis a extração.
CVSS: 6.5 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N)
Correção:
// SQLCipher para criptografia do banco Room
val passphrase = getDatabasePassphrase() // Derivada do AndroidKeyStore
val supportFactory = SupportFactory(passphrase)
val db = Room.databaseBuilder(
context,
AppDatabase::class.java,
"glass_w_database.db"
)
.openHelperFactory(supportFactory)
.build()
🟠 V7 — Certificate Pinning Ausente (Alta)
Evidência (strings DEX):
okhttp3.CertificatePinner // Classe importada
deprecated_certificatePinner // Implementação marcada como obsoleta
certificatePinner == null // Verificação opcional — provavelmente não usado
allowedGroupCiphers // Configuração TLS customizada
allowedPairwiseCiphers // Configuração TLS customizada
Impacto: Embora o OkHttp tenha suporte a Certificate Pinning, a implementação está marcada como deprecated e há verificações de nulabilidade, indicando que não está ativo. Sem pinning:
- Qualquer CA comprometida ou controlada por governo pode emitir certificados válidos para
qlifesnap.com,qcwxkjvip.com, etc. - Ataques MITM em infraestrutura de ISP, WiFi público ou proxy corporativo são viáveis
- A confiança em CAs de usuário (V1) agrava o risco
CVSS: 7.4 (AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N)
Correção:
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">qlifesnap.com</domain>
<pin-set expiration="2027-06-01">
<pin digest="SHA-256">AAAA...=</pin> <!-- Hash da chave pública -->
<pin digest="SHA-256">BBBB...=</pin> <!-- Hash de backup -->
</pin-set>
</domain-config>
</network-security-config>
🟠 V8 — PendingIntents Mutáveis (Alta)
Evidência (strings DEX):
PendingIntent.getActivity
PendingIntent.getService
PendingIntent.getBroadcast
getLaunchPendingIntent
createReminderPendingIntent
buildMediaButtonPendingIntent
getReadPendingIntent
getReplyPendingIntent
createPendingIntent
PendingIntent.FLAG_UPDATE_CURRENT ← Presente
PendingIntent.FLAG_CANCEL_CURRENT ← Presente
// FLAG_IMMUTABLE NÃO encontrado
Impacto: PendingIntents mutáveis permitem que o destinatário modifique o Intent original. Isto possibilita:
- Redirecionar ações de notificação para Activities maliciosas
- Lançar componentes arbitrários no contexto do app
- Roubar dados passados via Intent extras
No Android 12+ (SDK 31), PendingIntents devem declarar mutabilidade explicitamente. Com target SDK 35, a ausência de FLAG_IMMUTABLE cria vulnerabilidades de segurança.
CVSS: 7.0 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L)
Correção:
val pendingIntent = PendingIntent.getActivity(
context,
requestCode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
🟠 V9 — SharedPreferences Legível por Outros Apps (Alta)
Evidência (strings DEX):
publishWorldReadableSharedPreferences(nome, valor)
Descrição: O método publishWorldReadableSharedPreferences cria explicitamente arquivos SharedPreferences com modo MODE_WORLD_READABLE (depreciado desde API 17, removido na API 24+). Embora o Android 8.0+ bloqueie este modo, a presença do método indica:
- Uma decisão consciente de tornar dados acessíveis a outros apps
- Código legado que pode tentar contornar a segurança do Android
- Dados "criptografados" (encryptedApiKey, encryptedApiSecret) armazenados em SharedPreferences legíveis
Nota: Embora os dados estejam criptografados, o simples fato de estarem em um arquivo legível permite sua exfiltração via V2 (FileProvider) para ataques offline de força bruta.
CVSS: 6.8 (AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N)
Correção:
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPreferences = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
🟠 V10 — Superfície de Ataque WebView — Cadeia RCE (Alta)
Nota: Esta vulnerabilidade é um aprofundamento da V3, documentando a cadeia de ataque completa.
Cenário A: MITM em Rede WiFi → RCE
- Atacante na mesma rede WiFi que a vítima
- Tráfego HTTP é permitido (V1) — atacante realiza MITM
- Usuário carrega página de guia (ex: onboarding) no WebView
- Atacante injeta JavaScript na resposta HTTP
- JavaScript invoca métodos
@JavascriptInterfacena ponte Java - Ponte acessa
Contextpara lançar Intents arbitrários - Atacante exfiltra banco de dados, fotos, histórico de conversas
Cenário B: App Malicioso → WebView Hijack
- App malicioso no dispositivo lança
WebStartActivity(exportada — V14) - Passa URI manipulada via Intent
- WebView carrega URL controlada pelo atacante
- Ponte JavaScript permite roubo de dados
Cenário C: Deep Link → XSS → Ponte JS
- Atacante envia link malicioso via SMS/e-mail
- Usuário clica, abrindo URL no WebView
- Parâmetro
?hw=<script>...</script>injeta payload XSS - Script acessa ponte Java e executa comandos arbitrários
CVSS: 9.1 (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H)
🟡 V11 — Modelos TensorFlow Lite sem Verificação de Integridade (Média)
11 modelos TFLite encontrados em assets/:
| Modelo | Tamanho | Idioma |
|---|---|---|
english_intent_model_with_noise.tflite | 1,59 MB | Inglês |
de_intent_model_with_noise.tflite | 1,34 MB | Alemão |
es_intent_model_with_noise.tflite | 1,34 MB | Espanhol |
fr_intent_model_with_noise.tflite | 1,34 MB | Francês |
it_intent_model_with_noise.tflite | 1,34 MB | Italiano |
ko_intent_model_with_noise.tflite | 1,34 MB | Coreano |
nl_intent_model_with_noise.tflite | 1,34 MB | Holandês |
ru_intent_model_with_noise.tflite | 1,34 MB | Russo |
tflite_compatible_chinese_model.tflite | 1,34 MB | Chinês |
ja_intent_model_with_noise.tflite | 334 KB | Japonês |
reminder_intent.tflite | 150 KB | Lembretes |
artigo completo
Veja aqui:
https://github.com/azurejoga/heycyan-vulnerabilitys/