O recurso de configurações de segurança de rede permite que os apps personalizem essas configurações em um arquivo declarativo e seguro sem modificar o código do app. Essas configurações podem ser definidas para domínios específicos e para um app específico. Os principais recursos são:
- Âncoras de confiança personalizadas: personalize quais autoridades de certificação (CA, na sigla em inglês) são confiáveis para as conexões seguras de um app. Por exemplo, confiar em certificados autoassinados privados ou restringir o conjunto de CAs públicas em que o app confia.
- Substituições somente de depuração: depure conexões seguras do app, sem adicionar riscos à base instalada.
- Cancelar uso de tráfego de texto simples: proteja apps contra o uso acidental de tráfego de texto simples.
- Fixar certificados: restrinja 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 são especificadas as configurações do seu aplicativo. É necessário incluir uma entrada no manifesto do seu app para apontar para esse arquivo. Este trecho de código 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
Um app pode querer confiar em um conjunto personalizado de CAs em vez de no padrão da plataforma. Os motivos mais comuns para isso são:
- Conectar-se a um host com uma autoridade de certificação personalizada, como uma CA autoassinada ou emitida internamente em uma empresa.
- Limitar o conjunto de CAs para apenas aquelas em que você confia, em vez de todas as CAs pré-instaladas.
- Confiar em outras CAs 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 CAs pré-instaladas do sistema, e os apps destinados ao Android 6.0 (nível de API 23) e versões anteriores também confiam no repositório de CAs adicionadas pelo usuário por padrão. Um aplicativo pode personalizar as próprias conexões usando base-config
(para personalização em todo o aplicativo) ou domain-config
(para personalização por domínio).
Configurar uma CA personalizada
Suponhamos que você queira se conectar a um host que use um certificado SSL autoassinado ou a um host cujo certificado SSL foi emitido por uma CA não pública na qual confia, como a CA interna da sua empresa.
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
Um app que não queira confiar em todas as CAs em que o sistema confia pode especificar o próprio conjunto limitado de CAs 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.
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 CAs confiáveis em formato PEM ou DER em res/raw/trusted_roots
.
Ao usar o formato PEM, o arquivo precisa conter somente dados PEM, sem texto extra. Você também pode fornecer vários elementos <certificates>
em vez de um.
Confiar em outras CAs
Um app pode querer confiar em CAs em que o sistema não confia. Isso pode ocorrer se o sistema ainda não incluiu a CA ou se a CA não atender aos requisitos de inclusão no sistema Android. O app pode fazer isso ao especificar várias fontes de certificados para uma configuração.
res/xml/network_security_config.xml
:
<?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 CAs somente de depuração que sejam confiáveis somente quando o android:debuggable for true
, usando debug-overrides
. Normalmente, IDEs e ferramentas de compilação definem essa sinalização 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 do app não aceitam apps marcados como depuráveis.
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>
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 de API 27) ou versões anteriores. A partir do Android 9 (nível de API 28), a compatibilidade com texto simples é desativada por padrão.
Apps que pretendem se conectar a destinos usando apenas conexões seguras podem cancelar o uso de texto simples de suporte (usando o protocolo HTTP não criptografado em vez de HTTPS) para esses destinos. Essa opção ajuda a evitar regressões acidentais em apps devido a alterações nos URLs fornecidos por fontes externas, como servidores back-end.
Consulte NetworkSecurityPolicy.isCleartextTrafficPermitted()
para mais detalhes.
Por exemplo, é recomendável que o app garanta que todas as conexões com secure.example.com
sejam sempre realizadas por HTTPS para proteger o tráfego confidencial de redes hostis.
res/xml/network_security_config.xml
:
<?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>
Fixar certificados
Normalmente, um app confia em todas as CAs pré-instaladas. Se qualquer uma dessas CAs emitir um certificado fraudulento, o app correrá o risco de sofrer ataques de interceptação ("man-in-the-middle"). Alguns apps optam por limitar o conjunto de certificados que aceitam restringindo o conjunto de CAs 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 de backup para que, se você for forçado a alternar para novas chaves ou alterar as CAs (ao fixar um certificado de CA ou um intermediário dessa CA), 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, após o qual elas não sejam mais realizadas. Isso ajuda a evitar problemas de conectividade em apps que não foram atualizados. No entanto, definir um tempo de expiração para fixações pode fazer com que elas sejam ignoradas.
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.
Se um valor não for definido em uma entrada específica, o valor da entrada mais genérica será usado. 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 no qual todas as conexões para subdomínios de example.com
precisem 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.
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>
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 desse arquivo é mostrada no seguinte exemplo de código:
<?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>
- 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 de API 28) e versões posteriores é 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 de API 24) até o Android 8.1 (nível de 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 de 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<trust-anchors>
0 ou 1<pin-set>
Qualquer número de<domain-config>
aninhado - Descrição
- A configuração usada para conexões com destinos específicos, conforme é definido pelos elementos
domain
.Observe que, se vários elementos
domain-config
cobrirem 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.
-
- Descrição:
<debug-overrides>
- sintaxe:
-
<debug-overrides> ... </debug-overrides>
- Pode conter:
-
0 ou 1
<trust-anchors>
- Descrição:
-
Modificações a serem aplicadas quando android:debuggable for
"true"
, o que normalmente ocorre em builds de não lançamento gerados por IDEs e ferramentas de compilação. Âncoras de confiança especificadas emdebug-overrides
são adicionadas a todas as demais 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 é realizada em cadeias de certificados que são assinados por uma das CAs 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
, na qual 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"
.
-
Outros recursos
Para mais informações sobre configurações de segurança de rede, consulte os recursos a seguir.