Detecting Device Tampering Using SafetyNet In Android

Posted By : Pushpandra Kumar | 30-Apr-2018

Today, I will discuss device tampering and why it is important. How we can check whether our device tampered or not.
So, let's first understand what actually is device tampering. Device Tampering is interfering with device's software or hardware. A tampered device is called in Tampered State. Tampered State can include a 'rooted device', 'device affected by malware' or 'device being monitored by some malicious piece of code'. A tampered state can have many definitions. A rooted device is a device in which a user gained root access via unlocking bootloader and modifying the system files. Tampering a device compromises user's security and privacy. Some app developers don't allow their applications to be run these tampered devices to avoid security risk. They use Google's Tampered detection tool called as SafetyNet to detect device tampering.  It is the CTS compatibility status of a device that Google provides to requesting app as its opinion regarding CTS. CTS stands for Compatibility Test Suite which a device should pass before including Google Play Services. We cannot consider CTS compatible device vulnerability free device as it just checks if the device's expected normal state has tampered or not. 

 

Steps to Use SateyNet Attestation/ Test :
1. Make a call to SafetyNetApi.attest(). This function connects to Google's servers by using GoogleApiClient.
2. Your request should include nonce to prevent replay attacks.
3. A JSON response is sent by Google with attestation result in JSON Web Signature(JWS) format (a signed JSON object) with "ctsProfileMatch" :true|flase.
4. Fields of JSON object need to be verified manually by the developer. By making another API call, the signature of response can also be verified by Google.

 

Code: 

// We need different nonce for every request, Note : this is an example only, its not the secure way. Generate nonce securely 
// Generating nonce
String nonceData = "Safety Net Sample: " + System.currentTimeMillis();
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] bytes = new byte[24];
mRandom.nextBytes(bytes);
try {
		byteStream.write(bytes);
        byteStream.write(nonceData.getBytes());
    } catch (IOException e) {
        return null;
    }
byte[] nonce = byteStream.toByteArray();
/*
     Call the SafetyNet API asynchronously.
     The result is returned through the success or failure listeners.
     First, get a SafetyNetClient for the foreground Activity.
     Next, make the call to the attestation API. The API key is specified in the gradle build
     configuration and read from the gradle.properties file.
*/
// Note : Implement your own Success and Failure listeners. This is just a sample code for reference
SafetyNetClient client = SafetyNet.getClient(getActivity());
Task task = client.attest(nonce, BuildConfig.API_KEY);
task.addOnSuccessListener(getActivity(), mSuccessListener)
.addOnFailureListener(getActivity(), mFailureListener);

Hope you enjoyed my post, In Next post, I will discuss how SafetyNet Works behind the scenes.  

About Author

Author Image
Pushpandra Kumar

Pushpender has experience in Core Java, C & C++. His hobbies are learning new technologies and listening music.

Request for Proposal

Name is required

Comment is required

Sending message..