Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

Securing Communications on Android

$
0
0

With all the recent data breaches, privacy has become an important topic. Almost every app communicates over the network, so it's important to consider the security of user information. In this post, you'll learn the current best practices for securing the communications of your Android app.

Use HTTPS

As you are developing your app, it's best practice to limit your network requests to ones that are essential. For the essential ones, make sure that they're made over HTTPS instead of HTTP. HTTPS is a protocol that encrypts traffic so that it can't easily be intercepted by eavesdroppers. The good thing about Android is that migrating is as simple as changing the URL from http to https .

URL url = new URL("https://example.com");
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url.openConnection();
httpsURLConnection.connect();

In fact, Android N and higher versions can enforce HTTPS using Android’s Network Security Configuration .

In Android Studio, select the app/res/xml directory for your project. Create the xml directory if it doesn't already exist. Select it and click File > New File . Call it network_security_config.xml . The format for the file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">example.com</domain>
</domain-config>
</network-security-config>

To tell Android to use this file, add the name of the file to the application tag in the AndroidManifest.xml file:

<application android:networkSecurityConfig="@xml/network_security_config" Update Crypto Providers

The HTTPS protocol has been exploited several times over the years. When security researchers report vulnerabilities, the defects are often patched. Applying the patches ensures that your app's network connections are using the most updated industry standard protocols. The most recent versions of the protocols contain fewer weaknesses than the previous ones.

To update the crypto providers , you will need to include Google Play Services. In your module file of build.gradle, add the following line to the dependencies section:

implementation 'com.google.android.gms:play-services-safetynet:15.0.1'

The SafetyNet services API has many more features, including the Safe Browsing API that checks URLs to see if they have been marked as a known threat, and a reCAPTCHA API to protect your app from spammers and other malicious traffic.

After you sync Gradle, you can call the ProviderInstaller 's installIfNeededAsync method:

public class MainActivity extends Activity implements ProviderInstaller.ProviderInstallListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ProviderInstaller.installIfNeededAsync(this, this);
}
}

The onProviderInstalled() method is called when the provider is successfully updated, or already up to date. Otherwise, onProviderInstallFailed(int errorCode, Intent recoveryIntent) is called.

Certificate and Public Key Pinning

When you make an HTTPS connection to a server, a digital certificate is presented by the server and validated by Android to make sure the connection is secure. The certificate may be signed with a certificate from an intermediate certificate authority. This certificate used by the intermediate authority might in turn be signed by another intermediate authority, and so on, which is trustworthy as long as the last certificate is signed by a root certificate authority that is already trusted by Android OS.

If any of the certificates in the chain of trust are not valid, then the connection is not secure. While this is a good system, it's not foolproof. It's possible for an attacker to instruct Android OS to accept custom certificates. Interception proxies can possess a certificate that is trusted, and if the device is controlled by a company, the company may have configured the device to accept its own certificate. These scenarios allow for a “man in the middle” attack, allowing the HTTPS traffic to be decrypted and read.

Certificate pinning comes to the rescue by checking the server's certificate that is presented against a copy of the expected certificate. This prevents connections from being made when the certificate is different from the expected one.

In order to implement pinning on Android N and higher, you need to add a hash (called pins) of the certificate into the network_security_config.xml file. Here is an example implementation:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">duckduckgo.com</domain>
<pin-set>
<pin digest="SHA-256">lFL47+i9MZkLqDTjnbPTx2GZbGmRfvF3GkEh+J+1F3g=</pin>
<pin digest="SHA-256">w9MWhhnFZDSPWTFBjaoeGuClsrCs7Z70lG7YNlo8t+s=</pin>
</pin-set>
</domain-config>
</network-security-config>

To find the pins for a specific site, you can go to SSL Labs , enter the site, and click Submit . Or, if you're developing an app for a company, you can ask the company for it.

Note: If you need to support devices running an OS version older thanAndroid N, you can use the TrustKit library. It utilizes the Network Security Configuration file in exactly the same way.

Sanitization and Validation

With all of the protections so far, your connections should be quite secure. Even so, don't forget about regular programming validation. Blindly trusting data received from the network is not safe. A good programming practice is “design by contract”, where the inputs and outputs of your methods satisfy a contract that defines specific interface expectations.

For example, if your server is expecting a string of 48 characters or less, make sure that the interface will only return up to and including 48 characters.

if (editText.getText().toString().length() <= 48)
{
; //return something...
}
else
{
; //return default or error
}

If you're only expecting numbers from the server, your inputs should check for this. While this helps to prevent innocent errors, it also reduces the likelihood of injection and memory corruption attacks. This is especially true when that data gets passed to NDK or JNI ―native C and C++ code.

The same is true for sending data to the server. Don't blindly send out data, especially if it's user-generate

Viewing all articles
Browse latest Browse all 12749

Trending Articles