O recurso de configurações de segurança de rede permite personalizar as definições de segurança de rede do seu app em um arquivo de configuração seguro e declarativo sem modificar o código do app. Essas configurações podem ser definidas para domínios específicos e para um determinado app. Os principais atributos do recurso são:
- Âncoras de confiança personalizadas:personaliza quais autoridades certificadoras (AC) são confiáveis para as conexões seguras de um app. Por exemplo, confiar em certificados autoassinados particulares ou restringir o conjunto de ACs públicas em que o app confia.
- Substituições somente de depuração:depure conexões seguras do app sem adicionar riscos à base instalada.
- Cancelamento do uso de tráfego de texto simples:protege apps contra o uso acidental de tráfego de texto simples (não criptografado).
- Transparência de certificados:restringe as conexões seguras de um app para usar certificados registrados de forma comprovada.
- Fixação de certificados:restringe a conexão segura de um app a certificados específicos.
Adicionar um arquivo de configurações de segurança de rede
O recurso de configurações de segurança de rede usa um arquivo XML em que você especifica as configurações do app. Inclua uma entrada no manifesto do app que aponte para esse arquivo. O trecho de código a seguir de um manifesto demonstra como criar essa entrada:
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> </manifest>
Personalizar CAs confiáveis
Você pode querer que seu app confie em um conjunto personalizado de ACs em vez de no padrão da plataforma. Os motivos mais comuns para isso são:
- Conectar-se a um host com uma CA personalizada, como uma CA autoassinada ou emitida internamente em uma empresa.
- Limitar o conjunto de CAs para apenas aquelas nas quais você confia em vez de todas as CAs pré-instaladas.
- Confiar em CAs adicionais não incluídas no sistema.
Por padrão, conexões seguras (que usam protocolos como TLS e HTTPS) de todos os apps confiam nas
ACs pré-instaladas do sistema, e os apps destinados ao Android 6.0 (nível 23 da API) e versões anteriores também confiam
no repositório de ACs adicionadas pelo usuário por padrão. Você pode personalizar as conexões do seu app usando
base-config (para personalização em todo o app) ou domain-config (para
personalização por domínio).
Configurar uma CA personalizada
É possível se conectar a um host que use um certificado SSL autoassinado ou a um host cujo
certificado SSL seja emitido por uma AC não pública em que você confia, como a AC interna
da sua empresa. O exemplo de código abaixo demonstra como configurar seu app para uma AC personalizada em
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
Adicione o certificado da CA autoassinada ou não pública em formato PEM ou DER em
res/raw/my_ca.
Limitar o conjunto de CAs confiáveis
Se você não quiser que seu app confie em todas as ACs em que o sistema confia, especifique um conjunto reduzido de ACs confiáveis. Isso protege o app contra certificados fraudulentos emitidos por qualquer outra CA.
A configuração para limitar o conjunto de CAs confiáveis é semelhante a
confiar em uma CA personalizada para um domínio específico, mas fornecendo várias
CAs no recurso. O exemplo de código abaixo demonstra como limitar o conjunto de ACs confiáveis do seu
app em res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
Adicione as ACs confiáveis em formato PEM ou DER em res/raw/trusted_roots. Se você usar o formato PEM, o arquivo precisa conter apenas dados PEM, sem texto extra. Você também pode fornecer vários elementos
<certificates>
em vez de apenas um.
Confiar em outras CAs
Talvez você queira que seu app confie em outras ACs em que o sistema não confia. Por exemplo, se
o sistema ainda não incluir a AC ou se ela não atender aos requisitos para inclusão no
sistema Android. É possível especificar várias fontes de certificados para uma configuração em
res/xml/network_security_config.xml usando um código como o trecho abaixo.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
Configurar CAs para depuração
Ao depurar um app conectado por HTTPS, é recomendável que você se conecte a um servidor de desenvolvimento
local que não tenha o certificado SSL do seu servidor de produção. Para fazer isso
sem modificar o código do app, você pode especificar ACs somente de depuração, que são confiáveis
somente quando
android:debuggable é
true, usando debug-overrides. Normalmente, ambientes de desenvolvimento integrado e ferramentas de build definem
essa flag automaticamente para builds que não são de lançamento.
Isso é mais seguro do que o código condicional normal porque, como medida de segurança, os repositórios de apps não aceitam apps marcados como depuráveis.
O trecho abaixo mostra como especificar ACs somente de depuração em
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
Transparência dos certificados
Observação : o suporte à transparência de certificados está disponível apenas no Android 16 (nível 36 da API).
A Transparência de certificados (CT, RFC 6962) é um padrão da Internet projetado para aumentar a segurança dos certificados digitais. Ela exige que as CAs enviem todos os certificados emitidos a um registro público que os grava, aumentando a transparência e a responsabilidade no processo de emissão de certificados.
Ao manter um registro verificável de todos os certificados, a CT dificulta significativamente a falsificação de certificados por pessoas mal-intencionadas ou a emissão por engano pelas CAs. Isso ajuda a proteger os usuários contra ataques man-in-the-middle e outras ameaças à segurança. Para mais informações, consulte a explicação em transparency.dev. Para mais informações sobre a conformidade com a CT no Android, consulte a política de CT do Android.
O comportamento padrão da transparência de certificados depende do nível da API:
- A partir do Android 17 (nível 37 da API), a transparência de certificados é ativada por padrão. Os apps podem desativar o recurso de forma global ou por domínio.
- No Android 16 (nível 36 da API), a transparência de certificados é desativada por padrão. Os apps podem ativar o recurso de forma global ou por domínio.
- No Android 15 (nível 35 da API) e versões anteriores, a transparência de certificados não está disponível.
Desativar a transparência de certificados
Observação : para o Android 16 (nível da API 36), ative a transparência de certificado definindo
<certificateTransparency enabled="true"/> (ela fica desativada por padrão).
Se você pretende que seu app se conecte a destinos sem exigir que os certificados deles sejam registrados em registros de transparência de certificados, desative a transparência de certificados.
Por exemplo, você pode querer permitir que seu app faça conexões com
secure.example.com
sem exigir transparência de certificado.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <certificateTransparency enabled="false"/> </domain-config> </network-security-config>
ClientHello criptografado
Observação : o suporte ao Encrypted Client Hello só está disponível no Android 17 (nível da API 37) e exige que a biblioteca de rede do app seja compatível com ECH. A configuração especificada aqui só vai entrar em vigor se a biblioteca de rede tiver adotado o ECH.
O Encrypted Client Hello (ECH, RFC 9849) é uma extensão do protocolo TLS projetada para aumentar a privacidade das conexões seguras. Ele criptografa as partes sensíveis do handshake inicial de TLS, principalmente o campo de indicação de nome do servidor (SNI, na sigla em inglês).
Ao criptografar o SNI, o ECH impede que intermediários de rede observem o nome de domínio específico a que o cliente está tentando se conectar. Isso ajuda a evitar que os usuários sejam impressos digitalmente ou monitorados com base nos domínios que visitam, mitigando um vazamento significativo de privacidade presente em handshakes TLS padrão.
O comportamento padrão do Encrypted Client Hello depende do nível da API:
- A partir do Android 17 (nível 37 da API), a ECH é usada no modo "oportunista" por padrão. Os apps podem desativar o recurso ou modificar o comportamento dele globalmente ou por domínio.
- No Android 16 (nível 36 da API) e versões anteriores, a ECH não está disponível.
Desativar o ClientHello criptografado
Você pode desativar o recurso a qualquer momento. Por exemplo, se você quiser desativar o ECH
ao fazer conexões apenas com disable-ech.example.com, mas manter o ECH ativado para
todos os outros domínios, use a seguinte configuração:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <domainEncryption mode="enabled"/> </base-config> <domain-config> <domain includeSubdomains="true">disable-ech.example.com</domain> <domainEncryption mode="disabled"/> </domain-config> </network-security-config>
Tráfego de texto não criptografado
Os desenvolvedores podem ativar ou desativar o tráfego de texto simples (usando o protocolo HTTP não criptografado em vez de HTTPS) para os aplicativos deles. Consulte
NetworkSecurityPolicy.isCleartextTrafficPermitted()
para mais detalhes.
O comportamento padrão do tráfego de texto simples depende do nível da API:
- Até o Android 8.1 (nível 27 da API), o suporte a texto não criptografado é ativado por padrão. Os aplicativos podem cancelar o uso de tráfego de texto simples para ter mais segurança.
- A partir do Android 9 (nível 28 da API), o suporte a texto não criptografado é desativado por padrão. Os aplicativos que exigem tráfego de texto não criptografado podem ativar o tráfego de texto não criptografado.
Cancelar uso de tráfego de texto simples
Observação : a orientação desta seção se aplica apenas aos apps destinados ao Android 8.1 (nível 27 da API) ou versões anteriores.
Se você pretende que seu app se conecte a destinos usando apenas conexões seguras, desative o suporte a tráfego de texto simples para esses destinos. Essa opção ajuda a evitar regressões acidentais em apps devido a mudanças nos URLs fornecidos por fontes externas, como servidores de back-end.
Por exemplo, você pode querer que seu app garanta que as conexões com
secure.example.com
sejam sempre realizadas por HTTPS para proteger o tráfego confidencial de redes hostis.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
Ativar o tráfego de texto não criptografado
Observação : a orientação desta seção se aplica apenas aos apps destinados ao Android 9 (nível 28 da API) ou versões mais recentes.
Se o app precisar se conectar a destinos usando tráfego de texto não criptografado (HTTP), ative o suporte a texto não criptografado para esses destinos.
Por exemplo, você pode querer permitir que seu app faça conexões não seguras com
insecure.example.com.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">insecure.example.com</domain> </domain-config> </network-security-config>
Se o app precisar ativar o tráfego de texto não criptografado para qualquer domínio, defina
cleartextTrafficPermitted="true" no base-config. Essa configuração
insegura deve ser evitada sempre que possível.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> </base-config> </network-security-config>
Fixar certificados
Normalmente, um app confia em todas as ACs pré-instaladas. Se qualquer uma dessas ACs emitir um certificado fraudulento, um invasor no caminho poderá comprometer o app. Alguns apps optam por limitar o conjunto de certificados que aceitam restringindo o conjunto de ACs ou fixando certificados.
A fixação de certificados é realizada ao fornecer um conjunto de certificados pelo hash da chave pública
(SubjectPublicKeyInfo do certificado X.509). Uma cadeia de certificados é válida somente se contiver pelo menos uma das chaves públicas fixadas.
Ao usar a fixação de certificados, é preciso sempre incluir uma chave reserva para que, se você precisar alternar para novas chaves ou mudar as ACs (ao fixar um certificado de CA ou um intermediário dela), a conectividade do seu app não seja afetada. Caso contrário, será necessário enviar uma atualização ao app para restaurar a conectividade.
Além disso, é possível definir um tempo de expiração para as fixações, para que depois disso elas não sejam mais realizadas. Isso ajuda a evitar problemas de conectividade em aplicativos que não foram atualizados. No entanto, definir um prazo de validade para fixações pode permitir que invasores ignorem seus certificados fixados.
O exemplo abaixo mostra como fixar certificados em
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </pin-set> </domain-config> </network-security-config>
Comportamento de herança de configuração
Valores não definidos em uma configuração específica são herdados. Esse comportamento permite configurações mais complexas mantendo o arquivo de configuração legível.
Por exemplo, valores não definidos em um domain-config são obtidos pelo domain-config pai, se aninhados, ou, caso contrário, pelo base-config. Valores
não definidos no base-config usam os valores padrão da plataforma.
Por exemplo, considere um caso em que todas as conexões para subdomínios de
example.com precisam usar um conjunto personalizado de CAs. Além disso, o tráfego de texto simples para
esses domínios é permitido exceto ao se conectar com secure.example.com.
Ao aninhar a configuração para secure.example.com dentro da configuração para
example.com, o trust-anchors não precisa ser duplicado.
O trecho abaixo mostra como esse aninhamento ficaria em
res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
Configuração de localhost
Em geral, não é necessário aplicar os recursos de segurança de rede para conexões localhost. Por exemplo, a transparência de certificados raramente é necessária para conexões de host local.
No Android 17 (nível 37 da API) e versões mais recentes, se nenhuma configuração tiver sido definida para localhost, uma configuração implícita será incluída. Por padrão, essa configuração faz o seguinte:
- Permite o tráfego de texto simples.
- Não aplica a transparência de certificados (CT, na sigla em inglês).
- Não aplica a fixação de certificados.
- Delega a
<base-config>para âncoras de confiança.
Uma configuração é considerada como segmentando o localhost se o domínio for:
localhostip6-localhostou-
um endereço IP numérico e
InetAddress.isLoopback()étrue(por exemplo,127.0.0.1ou[::1])
Formato do arquivo de configurações
O recurso de configurações de segurança de rede usa um formato do arquivo XML. A estrutura geral do arquivo é mostrada no exemplo de código a seguir:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
As seções a seguir descrevem a sintaxe e outros detalhes do formato do arquivo.
<network-security-config>
- pode conter:
-
0 ou 1 ou
<base-config>
Qualquer número de<domain-config>
0 ou 1 de<debug-overrides>
<base-config>
- Sintaxe:
<base-config cleartextTrafficPermitted=["true" | "false"]> ... </base-config>
- Pode conter:
-
<trust-anchors><certificateTransparency><domainEncryption> - descrição:
-
A configuração padrão usada por todas as conexões cujo destino não é coberto por um
domain-config.Qualquer valor não definido usa os valores padrão da plataforma.
A configuração padrão para apps destinados ao Android 9 (nível da API 28) e versões mais recentes é a seguinte:
<base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
A configuração padrão para apps destinados ao Android 7.0 (nível da API 24) até o Android 8.1 (nível da API 27) é a seguinte:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
A configuração padrão para apps destinados ao Android 6.0 (nível da API 23) e versões anteriores é a seguinte:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config>
<domain-config>
- Sintaxe:
-
<domain-config cleartextTrafficPermitted=["true" | "false"]> ... </domain-config>
- pode conter:
-
1 ou mais
<domain>
0 ou 1<certificateTransparency>
0 ou 1<trust-anchors>
0 ou 1<pin-set>
0 ou 1<domainEncryption>
Qualquer número de<domain-config>aninhados - descrição:
-
A configuração usada para conexões com destinos específicos, conforme definido pelos
elementos
domain.Se vários elementos
domain-configcobrirem um destino, a configuração com a regra de domínio correspondente mais específica (mais longa) será usada.
<domain>
- Sintaxe:
-
<domain includeSubdomains=["true" | "false"]>example.com</domain>
- atributos:
-
-
includeSubdomains -
Se
"true", a regra de domínio corresponderá ao domínio e a todos os subdomínios, incluindo subdomínios de subdomínios. Caso contrário, a regra se aplica apenas a correspondências exatas.
-
<certificateTransparency>
- Sintaxe:
-
<certificateTransparency enabled=["true" | "false"]/>
- descrição:
-
Se
true, o app vai usar os registros de Transparência dos certificados para validar certificados. Quando um app usa o próprio certificado (ou o armazenamento do usuário), é provável que o certificado não seja público e, portanto, não possa ser verificado usando a Transparência dos certificados. Por padrão, a verificação fica desativada nesses casos. Ainda é possível forçar a verificação usando<certificateTransparency enabled="true"/>na configuração do domínio. Para cada<domain-config>, a avaliação segue esta ordem:- Se
certificateTransparencyestiver ativada, ative a verificação. -
Se algum
<trust-anchors>for"user"ou in-line (ou seja,"@raw/cert.pem"), desative a verificação. - Caso contrário, use a configuração herdada.
- Se
<domainEncryption>
- Sintaxe:
-
<domainEncryption mode=["enabled" | "opportunistic" | "disabled"]/>
- descrição:
-
Controla o comportamento do ClientHello criptografado (ECH)
para conexões com os domínios especificados.
Observação : o elemento
domainEncryptiondepende da biblioteca de rede do app que oferece suporte à ECH. O comportamento especificado só terá efeito se a biblioteca de rede tiver adotado o ECH. Não é esperado que os apps processem as configurações de ECH por conta própria. Em vez disso, eles devem usar as bibliotecas de rede para fazer isso ao estabelecer o handshake TLS.O atributo
modepode ser um dos seguintes:enabled: aplica o ECH em uma conexão quando a configuração do ECH é fornecida ao estabelecer o handshake de TLS e ativa o ECH GREASE caso contrário.opportunistic: use o ECH em uma conexão quando a configuração do ECH for fornecida ao estabelecer o handshake de TLS. Se a conexão falhar ou a configuração não for fornecida, volte para um ClientHello TLS padrão não criptografado. Esse modo não ativa o ECH GREASE.disabled: não tente usar ECH ou ECH GREASE em nenhuma conexão.
Se não for especificado, o padrão
modeserá"opportunistic".
<debug-overrides>
- Sintaxe:
-
<debug-overrides> ... </debug-overrides> - pode conter:
-
0 ou 1
<trust-anchors> - descrição:
-
Substituições a serem aplicadas quando
android:debuggable for
"true", o que normalmente ocorre em builds que não são de lançamento gerados por IDEs e ferramentas de build. Âncoras de confiança especificadas emdebug-overridessão adicionadas a todas as outras configurações, e a fixação de certificados não é realizada quando a cadeia de certificados do servidor usa uma dessas âncoras de confiança somente de depuração. Se android:debuggable for"false", esta seção será ignorada por completo.
<trust-anchors>
- Sintaxe:
-
<trust-anchors> ... </trust-anchors>
- pode conter:
-
Qualquer número de
<certificates> - descrição:
- Conjunto de âncoras de confiança para conexões seguras.
<certificates>
- Sintaxe:
-
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
- Descrição:
- Conjunto de certificados X.509 para elementos
trust-anchors. - atributos:
-
src-
A fonte de certificados de CA. Cada certificado pode ser um dos seguintes:
- Um ID de recurso bruto que aponta para um arquivo que contém certificados X.509. Os certificados precisam ser codificados em formato DER ou PEM. No caso de certificados PEM, o arquivo não pode conter dados não PEM extras, como comentários.
"system"para os certificados de CA pré-instalados do sistema"user"para certificados de CA adicionados pelo usuário
overridePins-
Especifica se as CAs dessa fonte ignoram a fixação de certificados. Se
"true", a fixação não será realizada em cadeias de certificados que são assinados por uma das ACs dessa fonte. Isso pode ser útil para depurar CAs ou para testar ataques de interceptação no tráfego seguro do seu app.O padrão é
"false", a não ser que seja especificado em um elementodebug-overrides. Nesse caso, o padrão será"true".
<pin-set>
- Sintaxe:
-
<pin-set expiration="date"> ... </pin-set> - pode conter:
-
Qualquer número de
<pin> - descrição:
-
Um conjunto de fixações de chave pública. Para que uma conexão segura seja confiável, uma das chaves públicas na
cadeia de confiança precisa estar presente no conjunto de fixações. Consulte
<pin>para saber mais sobre o formato das fixações. - atributos:
-
-
expiration -
A data, no formato
yyyy-MM-dd, em que as fixações expiram e são desativadas. Se o atributo não for definido, as fixações não expirarão.A expiração ajuda a evitar problemas de conectividade em apps que não recebem atualizações para o conjunto de fixações, por exemplo, quando o usuário desativa as atualizações do app.
-
<pin>
- Sintaxe:
-
<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>
- atributos:
-
-
digest -
O algoritmo de resumo usado para gerar a fixação. Atualmente, só há suporte para
"SHA-256".
-