
Avviso pubblico e PoC per CVE-2026-26897 — Deep Link Bypass in EcoOnline EHS Android (com.airsweb.v10), corretto in 0.2.500
Divulgazione pubblica / advisory per CVE-2026-26897, un bypass della validazione dei deep link nell'applicazione Android EcoOnline EHS (com.airsweb.v10). Un deep link ehs-app:// appositamente creato viene riscritto in https:// e caricato direttamente nella WebView principale dell'app senza il controllo della whitelist degli host che l'app applica su ogni altro percorso di navigazione, consentendo a un aggressore remoto di visualizzare contenuti arbitrari controllati dall'aggressore all'interno dell'applicazione fiduciaria (phishing).
Divulgato in modo responsabile, riconosciuto dal fornitore e corretto nella versione 0.2.500.
com.airsweb.v10 0.2.499 (versionCode 44631)L'applicazione del fornitore è proprietaria e non viene ridistribuita in questo repository. L'analisi statica di seguito è stata eseguita sulla build identificata qui — ottenere l'APK esatto da un archivio (es. cronologia versioni APKPure) e verificarne l'hash prima di riprodurre:
| Pacchetto | com.airsweb.v10 |
| versionName / versionCode | 0.2.499 / 44631 |
EcoOnline EHS per Android è un wrapper WebView Jetpack-Compose attorno alla piattaforma web EHS. Il suo contenuto predefinito viene caricato da:
startUrl = "https://ehsmobilelanding.ecoonline.net/"
L'app esporta una singola Activity (MainActivity) che è sia il launcher che il gestore per lo schema URL personalizzato ehs-app. L'elemento <data> del intent-filter del deep link dichiara solo uno schema — nessun host e nessun percorso — quindi qualsiasi URI ehs-app://… viene instradato all'app.
Per proteggere la navigazione WebView, l'app implementa una whitelist degli host (isInternalHost) e la applica quando ripristina l'ultimo URL visitato. Tuttavia, il ramo di gestione del deep link non chiama affatto quella whitelist. Prende l'URI del deep link in arrivo, esegue una sostituzione ingenua della stringa dello schema ehs-app: → https: e chiama WebView.loadUrl() sul risultato. Un aggressore remoto può quindi creare un deep link che fa sì che l'app fiduciaria carichi un'origine https:// arbitraria.
AndroidManifest.xml (v0.2.499) — deep link esportato, solo schema<activity
android:name="com.airsweb.v10.MainActivity"
android:exported="true" ... >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="ehs-app"/> <!-- solo schema: nessun host, nessun percorso -->
</intent-filter>
</activity>
MainActivityKt.WebViewPage (decompilato, v0.2.499)// intent consegnato alla MainActivity esportata
if (intent.getScheme().equals("ehs-app")) {
WebView webView = ...;
if (webView != null) {
Uri data = intent.getData(); // URI completo ehs-app://…
String s = String.valueOf(data);
// riscrittura ingenua dello schema: "ehs-app:" -> "https:"
String url = StringsKt.replaceFirst(s, "ehs-app:", "https:", false, 4, null);
webView.loadUrl(url); // <-- NESSUN CONTROLLO isInternalHost()
}
}
La whitelist che questo ramo non applica (usata altrove nello stesso file):
private static final Regex internalDomains =
new Regex("^[-\\w]*\\.(airsweb)|(ecoonline)\\.net");
private static final List<String> excludeDomainsStartingWith =
listOf("passport", "login", "auth");
public static boolean isInternalHost(String host) {
for (String p : excludeDomainsStartingWith)
if (host.startsWith(p)) return false;
return internalDomains.containsMatchIn(host);
}
Nota secondaria: la regex
internalDomainsè essa stessa debole (alternanza interrotta + corrispondenza di sottostringhecontainsMatchIn), ma il problema principale è che il ramo deep-link non invoca maiisInternalHost.
Una PoC con registrazione dello schermo è stata prodotta il 13-01-2026 contro com.airsweb.v10 0.2.499.
ehs-app://attacker.example/login
MainActivity riscrive lo schema e la WebView carica:
https://attacker.example/login
Una dimostrazione benigna, non di raccolta del reindirizzamento è inclusa in poc/redirect-proof.html (utilizzo: poc/README.md). Dimostra che un'origine arbitraria viene caricata all'interno dell'app fiduciaria, senza input, senza cattura di credenziali e senza richieste di rete.
Nella PoC originale il ricercatore ha ospitato una pagina di destinazione benigna simile puramente per dimostrare il reindirizzamento. Questo advisory documenta la vulnerabilità a scopo difensivo / di divulgazione e intenzionalmente non contiene nessuna pagina di phishing o codice di cattura delle credenziali.
https:// arbitrari controllati dall'aggressore all'interno del contesto dell'applicazione fiduciaria.CVSS v3.1 (stima del ricercatore — finalizzare prima della pubblicazione):
AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N → 6.3 (Medio) (si può avanzare un argomento Scope:Changed, poiché il contenuto non fiduciario viene eseguito nel contesto dell'app fiduciaria).
Aggiornare a com.airsweb.v10 0.2.500 o successiva. Correzioni consigliate:
isInternalHost() (o una whitelist equivalente) agli URL dei deep link prima di loadUrl().intent-filter del deep link con un esplicito android:host/android:pathPrefix.internalDomains (ancorare completamente l'host; evitare corrispondenze di sottostringhe).Scoperto e segnalato da Ahmet Mersin — GitHub @iwallplace, HackerOne iwallplace.
| SHA-256 | e9e8a38d133cb9da9901caf03c4a7a033c75ad1f32ba0539260e47d5dd5068c0 |
| Fonte | APKPure — cronologia versioni di "EcoOnline EHS" |
| Campo | Valore |
|---|
| CVE ID | CVE-2026-26897 |
| Fornitore | EcoOnline ("EcoOnline Global") — https://www.ecoonline.com/ |
| Prodotto | EcoOnline EHS per Android (com.airsweb.v10) |
| Versione interessata | 0.2.499 (versionCode 44631) |
| Versione corretta | 0.2.500 |
| Tipo di vulnerabilità | Validazione impropria in un gestore di schema URL personalizzato (bypass deep link) → caricamento WebView non validato / reindirizzamento aperto |
| CWE | CWE-939 (Autorizzazione impropria nel gestore per schema URL personalizzato); correlata CWE-749 |
| Componente interessato | com.airsweb.v10.MainActivity (gestore deep link esportato) e il ramo deep-link in MainActivityKt.WebViewPage |
| Schema personalizzato | ehs-app:// |
| Tipo di attacco | Remoto (richiede interazione dell'utente — apertura di un link appositamente creato) |
| Impatto | Phishing / ingegneria sociale: contenuto web arbitrario controllato dall'aggressore visualizzato all'interno dell'app EcoOnline EHS fiduciaria (es. falso login), bypassando la whitelist dei domini dell'app |
| Scopritore | Ahmet Mersin |
| Data | Evento |
|---|
| 2026-01-13 | PoC registrata contro 0.2.499 |
| 2026-01-15 | Richiesta CVE inviata a MITRE (ticket scr1979357) |
| 2026-02-27 | CVE-2026-26897 assegnato da MITRE |
| prima della pubblicazione | Fornitore riconosciuto; correzione rilasciata in 0.2.500 |
| 2026-03-04 | Richiesta di pubblicazione inviata a MITRE |
| 2026-05-06 | MITRE ha richiesto un URL di divulgazione pubblica completo |
| 2026-06-03 | Advisory pubblico pubblicato (questo repository) |