
CVE-2026-12960 - Esportazione impropria dei componenti dell'applicazione Android nell'app ASUS Router (com.asus.aihome). PoC, APK dell'exploit, video e report del fornitore. Corretto nella versione 1.0.0.9.74.
Esportazione impropria dei componenti dell'app Android ASUS Router
Un componente incluso nell'app Android ASUS Router (com.asus.aihome) era dichiarato
android:exported="true" senza android:permission. Qualsiasi altra app sullo stesso
dispositivo, senza alcuna autorizzazione, poteva inviargli un Intent appositamente
predisposto e far aprire all'app ASUS Router un URI controllato dall'attaccante per
conto dell'utente.
Segnalato ad ASUS il 2026-03-17. Corretto da ASUS e pubblicato come CVE-2026-12960 il 2026-07-03.
Scoperto e segnalato da Sedric Louissaint di Show Up Show Out Security.
| CVE | CVE-2026-12960 |
| Prodotto | App ASUS Router per Android (com.asus.aihome) |
| Versioni vulnerabili | ≤ 1.0.0.9.71 |
| Corretto nella versione | 1.0.0.9.74 |
| Debolezza | CWE-926: Esportazione impropria dei componenti dell'applicazione Android |
| CVSS 4.0 | 6.0 Medio CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:N/SA:N |
| CNA | ASUS |
| Avviso del fornitore | https://www.asus.com/security-advisory/ |
| Testato su | com.asus.aihome 1.0.0.9.71 (Google Play), emulatore Android 11 |
L'app include l'SDK Baidu Push, che dichiara:
<service
android:name="com.baidu.android.pushservice.CommandService"
android:exported="true" />
Nessun attributo android:permission: il controllo degli accessi a livello di
componente di Android non viene quindi mai eseguito. Qualsiasi app installata può
chiamare startService() su di esso.
CommandService.onStartCommand() legge un PublicMsg Parcelable dall'extra
public_msg dell'Intent in arrivo e lo passa a handlePrivateNotification(), che
dirama sul campo mOpenType fornito dall'attaccante:
mOpenType | Comportamento |
|---|---|
1 | startActivity(ACTION_VIEW, Uri.parse(mUrl)) con l'mUrl dell'attaccante |
Né il mittente né il payload vengono validati. Poiché l'activity risultante viene avviata dall'UID e dal processo dell'app ASUS stessa, qualsiasi cosa appaia sullo schermo sembra provenire dalla fidata app di gestione del router che l'utente ha appena aperto.
In pratica, nulla di tutto ciò è specifico di Baidu: l'SDK fornisce il componente esportato, l'app ospitante lo eredita e l'identità dell'app ospitante è ciò che viene presa in prestito.
PublicMsg Parcelable che corrisponde alla
disposizione dei campi del target.mOpenType = 1 e mUrl su un URI controllato dall'attaccante.CommandService. Nessuna autorizzazione richiesta, nessuna
SecurityException.onStartCommand() → handlePrivateNotification().startActivity(ACTION_VIEW, Uri.parse(mUrl)) viene attivata dal processo
dell'app ASUS.L'ordine dei campi di PublicMsg, ricostruito da writeToParcel nello smali
decompilato e reimplementato in poc/PublicMsg.java:
String mMsgId, mAppId, mTitle, mDescription, mUrl, mPkgName
int mPkgVercode, mNotificationBuilder, mNotificationBasicStyle
int mOpenType, mUserConfirm
String mCustomContent, mPkgContent
int mAdvertiseStyle
String mAdvertiseSmallIconUrl, mAdvertiseLargeIconUrl, mAdvertiseClickUrl,
mAdvertiseBigPictureUrl, mAdvertiseBigPictureClickUrl, mAdvertiseDownloadClickUrl
Sbaglia l'ordine e la Parcel viene de-marshallata in dati spazzatura. Azzeccalo e il servizio accetta il messaggio come se fosse stato inviato dalla stessa infrastruttura push di Baidu.
Sei schemi URI, un servizio esportato, zero autorizzazioni:
media/poc_commandservice.mp4 è la registrazione
completa di 31 secondi: build, installazione, attivazione e l'emulatore che reagisce
a ciascun payload a turno.
| Attacco 1: pagina di phishing | Attacco 2: compositore SMS | Attacco 3: dialer | Autorizzazioni dell'app PoC |
|---|---|---|---|
![]() |
Quell'ultimo screenshot è l'intera argomentazione. Nessuna autorizzazione richiesta. L'app che ha appena eseguito sei azioni tramite l'app ASUS Router non ha chiesto nulla all'utente.
Richiede ADB, un JDK e gli strumenti di build dell'Android SDK (aapt2, d8/dx,
zipalign, apksigner) oltre a platforms;android-30.
./poc/poc_commandservice_exploit.sh <device_serial>
Lo script esegue tre fasi:
CommandService da
com.android.shell e segnala se qualcuna viene rifiutata. Un servizio protetto da
autorizzazione genera una SecurityException in questo punto. Questo ha accettato
tutte e tre.exploit_commandservice.apk e
lo installa. Una copia precompilata è in poc/ se preferisci saltare
questo passaggio.Output della fase 1 su un dispositivo vulnerabile:
[ACCESS] passthrough.notification.CLICK → service accepted intent
[ACCESS] privatenotification.CLICK → service accepted intent
[ACCESS] privatenotification.DELETE → service accepted intent
Phase 1 result: 3/3 actions accepted without permission check
E il ServiceRecord da dumpsys activity services, che registra il chiamante:
intent={act=com.baidu.android.pushservice.action.privatenotification.CLICK
cmp=com.asus.aihome/com.baidu.android.pushservice.CommandService}
recentCallingPackage=com.android.shell
startRequested=true callStart=true
Fase 3, da una vera app non privilegiata anziché dalla shell:
W PoCExploit: [OK] attack1_url_open → com.asus.aihome/com.baidu.android.pushservice.CommandService
W PoCExploit: [OK] attack2_sms_compose → ...
(all 6 succeed)
startService() ha restituito il ComponentName del target invece di null e non è
stata lanciata alcuna SecurityException. Android ha risolto l'Intent e lo ha
consegnato.
poc/
poc_commandservice_exploit.sh Automated three-phase reproduction script
ExploitCommandService.java PoC activity + broadcast receiver source
PublicMsg.java Parcelable matching the target's field layout
AndroidManifest_PoC.xml PoC manifest (note: no <uses-permission>)
exploit_commandservice.apk Prebuilt PoC, debug-signed, zero permissions
media/
poc_commandservice.mp4 Full PoC recording
attack1-browser.jpg Stills pulled from the recording
attack2-sms.jpg
attack3-dialer.jpg
poc-app-no-permissions.jpg
vendor/
asus-security-advisory-submission.pdf The report as filed with ASUS
L'URL in uscita del PoC è un sottodominio Burp Collaborator usato per confermare che la navigazione sia avvenuta davvero. È morto da tempo. Sostituiscilo con il tuo se stai riproducendo l'attacco.
Per il fornitore, la correzione è un attributo:
<service
android:name="com.baidu.android.pushservice.CommandService"
android:exported="false" />
Oppure, se il componente deve davvero essere raggiungibile dall'esterno, proteggilo
con un'autorizzazione a livello di protezione signature e valida il PublicMsg
deserializzato prima di agire su di esso. ASUS ha distribuito la correzione nella
1.0.0.9.74.
Per gli utenti: aggiornate l'app ASUS Router a 1.0.0.9.74 o successiva.
Per chiunque altro distribuisca app Android: verificate cosa esportano i vostri SDK di
terze parti. Eseguite aapt dump xmltree base.apk AndroidManifest.xml sulla vostra
build di rilascio e leggete ogni exported="true" presente al suo interno. Il
manifest che distribuite è la somma di tutti i manifest che avete unito, e ne siete
responsabili al 100%.
| Data | Evento |
|---|---|
| 2026-03-17 | Segnalato ad ASUS con APK PoC, script automatizzato e video |
| 2026-06-23 | CVE-2026-12960 riservata da ASUS in qualità di CNA |
| 2026-07-03 | CVE pubblicata; correzione disponibile nella 1.0.0.9.74 |
| 2026-07-25 | Write-up pubblico e PoC rilasciati |
Pubblicato dopo la divulgazione coordinata e la correzione da parte del fornitore, per uso difensivo ed educativo. Il PoC ha come target una versione già corretta e non fa altro che aprire URI. Non eseguirlo su dispositivi che non possiedi o per i quali non hai un'autorizzazione scritta al test.
2 | Intent.parseUri(mPkgContent, 0) poi startActivity() / sendBroadcast() |
| # | Scheme | Risultato |
|---|
| 1 | https: | Il browser apre una pagina di phishing controllata dall'attaccante |
| 2 | sms: | Compositore SMS precompilato con un messaggio di ingegneria sociale |
| 3 | tel: | Dialer precompilato con un numero controllato dall'attaccante |
| 4 | mailto: | Compositore email precompilato per esfiltrare credenziali |
| 5 | market: | Reindirizzamento al Play Store per l'installazione di malware |
| 6 | geo: | Reindirizzamento in Maps a un falso centro assistenza |
![]() |
![]() |
![]() |