0

I found code on project imas to calculate the integrity of an app and have the problem that I can not set the sha256_placeholder so that the comparison at the end passes. With every run it seems that the calculated hash is different. Do you see how to fix this?

My approach would be to check the integrity with an import of an array of possible app sizes and hashes from my backend and compare it to the calculated app size and hash.

Here is my code:

#import <Foundation/Foundation.h>
#import "IntegrityCheck.h"
#import <CommonCrypto/CommonDigest.h>

unsigned char sha256_placeholder[] =
{ 0x16, 0x13, 0x13, 0x19, 0x14, 0x48, 0xbe, 0xd2, 0x9d, 0x3d, 0x27, 0x45, 0x0b, 0x86, 0x51, 0xde, 0x58, 0x6d,0x39, 0xb2};

unsigned char file_size_placeholder[] = { 0x80, 0x04, 0x67, 0x02 };

NSData *get_sha256() {
   return  [NSData dataWithBytes:sha256_placeholder length:32];
}


NSData *get_fileSize() {
   return[NSData dataWithBytes:file_size_placeholder  length:8];
}

#ifdef FAIL
    NSString *AppName = @"MyAppiOS_fail";
#else
     NSString *AppName = @"MyAppiOS";
#endif

int doAppIntegrity() {

    int ret = 0;

    //** read my APPS executable
    NSFileHandle      *inFile;
    NSFileManager     *fileMgr;
    NSString          *filePath;

    fileMgr = [NSFileManager defaultManager];

    //** open and read APP file into a data block
    filePath = [[NSBundle mainBundle] pathForResource:AppName ofType:0 ];

    if ( [fileMgr fileExistsAtPath:filePath] == NO ) {
        NSLog(@"File does not exist!");
        ret = -1;
    }

    //** FILE SIZE
    inFile = [NSFileHandle fileHandleForReadingAtPath: filePath];
    NSData *plain_txt = [ inFile readDataToEndOfFile];
    unsigned int app_file_size = (CC_LONG)[plain_txt length];
    NSLog(@"AS-IS - APP file size: %d", app_file_size);
    [inFile closeFile];

    //** SHA256bit HASH
    unsigned char hash[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256([plain_txt bytes], (CC_LONG)[plain_txt length], hash);
    NSData *app_sig = [NSData dataWithBytes:hash length:CC_SHA1_DIGEST_LENGTH];
    NSLog(@"AS-IS - sha_hash_val 20 bytes: %@", app_sig);
    NSLog(@"app_sig_len:%lu", (unsigned long)[app_sig length]);


    NSData *trusted_app_sig = [NSData dataWithBytes:sha256_placeholder length:CC_SHA1_DIGEST_LENGTH];
    NSLog(@"trusted app sig:%@", trusted_app_sig);
    NSLog(@"trusted app sig len:%lu", (unsigned long)[trusted_app_sig length]);

    NSData *trusted_app_size_data = [NSData dataWithBytes:file_size_placeholder length:4];
    unsigned int trusted_app_size;
    [trusted_app_size_data getBytes:&trusted_app_size length:sizeof(trusted_app_size)];

    NSLog(@"trusted app size hex:%@", trusted_app_size_data);
    NSLog(@"trusted app size:%d", trusted_app_size);

    // compare computed sha hash to passed in value
    if (8004672 != app_file_size) {
        NSLog(@"App Integrity FAIL - file size MISMATCH");
        ret = -1;
    }

    else {
        NSLog(@"App Integrity PASS - file size MATCH");
    }
    if ([trusted_app_sig isEqualToData:app_sig]){
        NSLog(@"App Integrity PASS - signature MATCH");
    }
    else {
        NSLog(@"App Integrity FAIL - signature MISMATCH");
        ret = -1;
    }

    return ret;
}
netshark1000
  • 7,245
  • 9
  • 59
  • 116
  • There is no reliable way to do this. If it existed, then Apple would use that technique to prevent jailbreaks in the first place. With obfuscation and hardening techniques you can keep somewhat ahead of attackers, but it will require ongoing updates as your techniques are broken. For more see https://stackoverflow.com/questions/9448632/best-practices-for-ios-applications-security/9448821#9448821, https://stackoverflow.com/questions/9181186/secure-https-encryption-for-iphone-app-to-webpage – Rob Napier Sep 30 '19 at 18:18

1 Answers1

0

I found code on project imas to calculate the integrity of an app and have the problem that I can not set the sha256_placeholder so that the comparison at the end passes. With every run it seems that the calculated hash is different. Do you see how to fix this?

While I cannot help you with validating your code I can alert you for the fact that this approach is easily bypassed by hooking an instrumentation framework, like Frida or xPosed, into the call to doAppIntegrity(), and then change its return value to be always a valid integrity check.

Frida

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

xPosed

Xposed is a framework for modules that can change the behavior of the system and apps without touching any APKs. That's great because it means that modules can work for different versions and even ROMs without any changes (as long as the original code was not changed too much). It's also easy to undo.

Just to have a notion of the power of instrumentation frameworks, you can watch this video to see how xPosed is being used to bypass certificate pinning during run-time.

So what I want to convey here is that any decisions you make in the client side can be bypassed by using the already mentioned instrumentation frameworks, but if you really want to know if your mobile app have been modified or not, you need to make that decision outside the device. In an high level overview you will need to have an external server that challenges the mobile app to determine its integrity, and not use the result of this integrity check directly on the mobile app, because you know, instrumentation frameworks can hook on the code that uses the integrity check result to decide if it can present or not some content, and modify it to always show the content. This means that the API server must be one that will use the integrity check result to decide to send or not the content to the mobile app. This concept have a name, Mobile App Attestation.

Before I dive into the Mobile APP Attestation concept I would like to first clear a misconception about WHO and WHAT is accessing an API server.

The Difference Between WHO and WHAT is Accessing the API Server

To better understand the differences between the WHO and the WHAT are accessing an API server, let’s use this picture:

Man in the Middle Attack

The Intended Communication Channel represents the mobile app being used as you expected, by a legit user without any malicious intentions, using an untampered version of the mobile app, and communicating directly with the API server without being man in the middle attacked.

The actual channel may represent several different scenarios, like a legit user with malicious intentions that may be using a repackaged version of the mobile app, a hacker using the genuine version of the mobile app, while man in the middle attacking it, to understand how the communication between the mobile app and the API server is being done in order to be able to automate attacks against your API. Many other scenarios are possible, but we will not enumerate each one here.

I hope that by now you may already have a clue why the WHO and the WHAT are not the same, but if not it will become clear in a moment.

The WHO is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

OAUTH

Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.

OpenID Connect

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

While user authentication may let the API server know WHO is using the API, it cannot guarantee that the requests have originated from WHAT you expect, the original version of the mobile app.

Now we need a way to identify WHAT is calling the API server, and here things become more tricky than most developers may think. The WHAT is the thing making the request to the API server. Is it really a genuine instance of the mobile app, or is a bot, an automated script or an attacker manually poking around with the API server, using a tool like Postman?

For your surprise you may end up discovering that It can be one of the legit users using a repackaged version of the mobile app or an automated script that is trying to gamify and take advantage of the service provided by the application.

Well, to identify the WHAT, developers tend to resort to an API key that usually they hard-code in the code of their mobile app. Some developers go the extra mile and compute the key at run-time in the mobile app, thus it becomes a runtime secret as opposed to the former approach when a static secret is embedded in the code.

Mobile App Attestation

The role of a Mobile App Attestation solution is to detect at run-time that your mobile app was not tampered with, is not running in a rooted device, not being instrumented by a framework like xPosed or Frida, not being MitM attacked, and this is achieved by running an SDK in the background. The service running in the cloud will challenge the app, and based on the responses it will attest the integrity of the mobile app and device is running on, thus the SDK will never be responsible for any decisions.

On successful attestation of the mobile app integrity a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud are aware. In the case of failure on the mobile app attestation the JWT token is signed with a secret that the API server does not know.

Now the App must sent with every API call the JWT token in the headers of the request. This will allow the API server to only serve requests when it can verify the signature and expiration time in the JWT token and refuse them when it fails the verification.

Once the secret used by the Mobile App Attestation service is not known by the mobile app, is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.

Summary

While in app integrity checks can be used to male it hard for an attacker to mount an attack in the device, they are not harder to bypass, even for script kids or seasonal attackers.

A best approach is to make the mobile app integrity checks decisions outside of the device, and at same time let the API server know them in order it can decide when to provide or not the content to the mobile app, because decisions made on the client side, aka the mobile app, can always be bypassed with instrumentation frameworks.

In the end, the solution to use in order to protect your mobile app and API server must be chosen in accordance with the value of what you are trying to protect and the legal requirements for that type of data, like the GDPR regulations in Europe.

Do you want to go the Extra Mile?

OWASP Mobile Security Project - Top 10 risks

The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

Community
  • 1
  • 1
Exadra37
  • 11,244
  • 3
  • 43
  • 57
  • "The role of a Mobile App Attestation solution is to guarantee at run-time that your mobile app was not tampered with." This isn't possible. I assume you mean "…is to provide some assurance through hardening techniques that is regularly updated every time it's broken that your mobile app has likely not been tampered with." – Rob Napier Sep 30 '19 at 13:36
  • Without some explanation of how this is technically achieved, this answer currently reads a just marketing material for Approov. The details about JWT gloss over the entire problem: the attestation itself, which is not a fully solvable problem in the way this answer implies. – Rob Napier Sep 30 '19 at 13:38
  • You also appear to have copy and pasted the same (apparently marketing) material on at least 7 answers. If the same answer applies, then vote to close as duplicate. Do not keep posting the same marketing material for Approov as answers. – Rob Napier Sep 30 '19 at 13:44
  • My answers try to have as much as educational content as possible and yes I link to some blog posts in Approov or links elsewhere, but I am not directly promoting the company with links to the site or to subscribe the services. And yes my answers are mostly on mobile and API security(sometimes on Docker) and I try to educated as much as I can the developers for their misconception on the WHO vs the WHAT. Mention and links to the Approov blog post removed. – Exadra37 Sep 30 '19 at 14:32
  • Understood, and the very beginning of your answer is quite good (and it does not qualify as spam). But by the time you get to "Mobile App Attestation," your answer becomes misleading (you give the impression that this is a solvable problem, when it is at best a mitigable problem if you constantly update your solution as attackers break it), and at the end it becomes pure marketing copy with "Do you want to go the Extra Mile?" In any case, you should be voting to mark these duplicate, not posting the same answer repeatedly. – Rob Napier Sep 30 '19 at 14:36
  • By "it does not qualify as spam," I mean the whole post, not just the first part. I don't believe this is spam, and I haven't flagged it as spam. I think your answers are in good faith and you're trying to help folks. The answer just has the problems I've discussed, and shouldn't be repeated on multiple questions. – Rob Napier Sep 30 '19 at 14:40
  • The Going the Extra Mile is linking to OWASP Top 10 mobile risks https://www.owasp.org/index.php/OWASP_Mobile_Security_Project#Top_Ten_Mobile_Risks, and I like to add it in all my answers about mobile security, because I thinks is important to spread the word about this awesome work. Do you interpret this as pure marketing? – Exadra37 Sep 30 '19 at 14:42
  • Addressed your feedback about the use of the word "guarantee" and replaced it with "detect". – Exadra37 Sep 30 '19 at 14:49