Best Place to Store Included AWS Credentials in an iOS Application - ios

I plan on using the AWS SDK for iOS for an upcoming project. I need to store credentials for AWS with the packed application. Where is the most secure place to place them? I know that storing them in a pList would be a bad idea. Is it better to just 'hard-code' it into a class that will be compiled? Is there any risk there?

I believe that completely hiding the credentials is theoretically impossible. That is, if your compiled code can read them, then in theory so can anyone with access to the compiled code. But imperfect security is still worth something. I'd guess that most attackers would just look through the binary for strings that look like secret keys, and not go to the trouble of decompiling the code and trying to interpret how it works, so one way to hide the credentials would be to store them in an encoded form, then decode them as needed. This way the decoding algorithm becomes your key, and an attacker would have to find and understand it to extract your credentials.
Here's a fairly simple way to do it using a random XOR mask. Replace the following bogus password with yours, and remember to keep the NULL terminator (\0) in place. Compile and run this code as a standalone program:
#include <stdio.h>
#define PAD_LENGTH 32
int main() {
int i;
char c;
// start with the password
char password[PAD_LENGTH] = "My AWS Password\0";
// make a random pad to encrypt it
printf("PAD:\n{");
char pad[PAD_LENGTH];
for (i = 0; i < PAD_LENGTH; i++) {
c = arc4random() & 0xFF;
pad[i] = c;
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
// make an encrypted version of the password
printf("KEY:\n{");
for (i = 0; i < PAD_LENGTH; i++) {
c = pad[i] ^ password[i];
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
return(0);
}
Then copy the generated pad and key into code like this (which will actually get included with your app):
#define PAD_LENGTH 32
char pad[PAD_LENGTH] = {0x83,0x26,0x8a,0x8b,0xee,0xab,0x6,0xed,0x2e,0x99,0xff,0x23,0x7f,0xef,0xc8,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
char key[PAD_LENGTH] = {0xce,0x5f,0xaa,0xca,0xb9,0xf8,0x26,0xbd,0x4f,0xea,0x8c,0x54,0x10,0x9d,0xac,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
for (int i = 0; i < PAD_LENGTH; i++) {
key[i] = key[i] ^ pad[i];
}
NSString *password = [NSString stringWithCString:key encoding:NSASCIIStringEncoding];
Since this is on a public forum, you might want to change a few things, like making the pads a different length, splitting them up and rejoining them with code, reordering them, etc. You could also store the pad and key in distant parts of the code. A truly skilled and dedicated attacker is going to be able to find your password no matter what, but the basic idea is that most people scanning the binary for a password will not find it as such.

Have you looked at the Data Protection API?
What are the new "iOS data protection APIs"?
There are various options depending on your security needs.
This question may help also.
Data Protection on iOS
The video from a conference this year was useful.
http://developer.apple.com/videos/wwdc/2010

you should use AWS Identity and Access Management (IAM): http://aws.amazon.com/iam/
you can find more information about AWS Credential Management in Mobile Applications on http://aws.amazon.com/articles/4611615499399490

Related

How to avoid hardcoding keys for encryption (Objective C)?

In my Objective C code, I have a consumer key and secret hardcoded in my code to be used in SHA-1 encryption. What I would like to know is whether I could avoid hardcoding to improve security. I have found the following so far,
Finding 1
https://www.owasp.org/index.php/Technical_Risks_of_Reverse_Engineering_and_Unauthorized_Code_Modification#Cryptographic_Key_Replacement
Steps explained are as follows,
Damage static keys that are declared in source code. Such keys should be damaged while on disk to prevent an adversary from analyzing and intercepting the original key;
Next, the application should repair the key just before the code requiring the key uses it;
Immediately before use of the key, the application should perform a checksum of the key’s value to verify that the non-damaged key matches the value that the code declares at build time; and
Finally, the application should immediately re-damage the key in memory after the application has finished using it for that particular call.
Finding 2
https://github.com/UrbanApps/UAObfuscatedString
Can somebody help me please?
Sample code:
+ (NSString *) getOauthHeaderForRequestString:(NSString *)requestString {
NSString *oauthConsumerKey = #"<consumer key which I want avoid hardcoding>";
NSString *oauthConsumerSecret = #"<consumer secret which I want to avoid hardcoding>";
NSString *oauthSignatureMethod = #"HMAC-SHA1";
NSString *oauthVersion = #"1.0";
NSString *oauthNonce = [self generateNonce];
NSString *oauthtimestamp = [NSString stringWithFormat:#"%d", (int)[[NSDate date] timeIntervalSince1970]];
NSArray * params = [NSArray arrayWithObjects:
[NSString stringWithFormat:#"%#%%3D%#", #"oauth_consumer_key", oauthConsumerKey],
[NSString stringWithFormat:#"%#%%3D%#", #"oauth_nonce", oauthNonce],
[NSString stringWithFormat:#"%#%%3D%#", #"oauth_signature_method", oauthSignatureMethod],
[NSString stringWithFormat:#"%#%%3D%#", #"oauth_timestamp", oauthtimestamp],
[NSString stringWithFormat:#"%#%%3D%#", #"oauth_version", oauthVersion],
[NSString stringWithFormat:#"%#%%3D%#", #"request", [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]],
nil];
params = [params sortedArrayUsingSelector:#selector(compare:)];
NSString *parameters = [params componentsJoinedByString:#"%26"];
NSString *postURL = #"<my post url>";
NSArray * baseComponents = [NSArray arrayWithObjects:
#"POST",
[self encodeString:postURL],
parameters,
nil];
NSString * baseString = [baseComponents componentsJoinedByString:#"&"];
NSArray *signingKeyComponents = [NSArray arrayWithObjects:oauthConsumerSecret, #"", nil];
NSString *signingKey = [signingKeyComponents componentsJoinedByString:#"&"];
NSData *signingKeyData = [signingKey dataUsingEncoding:NSUTF8StringEncoding];
NSData *baseData = [baseString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[20] = {0};
CCHmac(kCCHmacAlgSHA1, signingKeyData.bytes, signingKeyData.length, baseData.bytes, baseData.length, digest);
NSData *signatureData = [NSData dataWithBytes:digest length:20];
NSString *oauthSignature = [self base64forData:signatureData];
// final request build
NSString *oauthHeader = #"OAuth ";
oauthHeader = [oauthHeader stringByAppendingFormat:#"oauth_consumer_key=\"%#\"",oauthConsumerKey];
oauthHeader = [oauthHeader stringByAppendingFormat:#",oauth_nonce=\"%#\"",oauthNonce];
oauthHeader = [oauthHeader stringByAppendingFormat:#",oauth_signature=\"%#\"",[self encodeString:oauthSignature]];
oauthHeader = [oauthHeader stringByAppendingFormat:#",oauth_signature_method=\"%#\"",oauthSignatureMethod];
oauthHeader = [oauthHeader stringByAppendingFormat:#",oauth_timestamp=\"%#\"",oauthtimestamp];
oauthHeader = [oauthHeader stringByAppendingFormat:#",oauth_version=\"1.0\""];
return oauthHeader;
}
I've written about the challenges of solving this problem before, but I wanted to demonstrate a little bit using your UAObfuscatedString idea, since I think this is the kind of solution most people are looking for, but is worse than nothing. It's important to note: I'm not particularly good at this. I'm not a seasoned reverse engineer and commercial systems are way beyond my skillset. I'm just a guy with Hopper and literally five minutes of reverse engineering work (I ran a timer; 5:35s, including upgrading Hopper because I hadn't run it in a few months).
So, I wrote an iOS program with UAObfuscatedString. I used Swift because Swift is generally a little harder to reverse engineer than ObjC. ObjC is a reverse engineer's dream.
let identifier = "c".o.m.dot.u.r.b.a.n.a.p.p.s.dot.e.x.a.m.p.l.e
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
print(identifier)
return true
}
I then archived it, so it's optimized code, etc. etc. just like you'd send to the App Store. I then loaded it up in to Hopper and looked at the app delegate's init. That's where constants are initialized, based on the assumption that most people stick this stuff in their app delegate. Obviously if I see a class named KeyStorage or SecretStuffHelper, I'd look there first....
void * -[_TtC13ObfuscateTest11AppDelegate init](void * self, void * _cmd) {
*(r31 + 0xffffffffffffffe0) = r20;
*(0xfffffffffffffff0 + r31) = r19;
*(r31 + 0xfffffffffffffff0) = r29;
*(r31 + 0x0) = r30;
r0 = sub_100005e14();
return r0;
}
Hmm, it calls this anonymous function sub_100005e14(). Let's see what that does.
...
0000000100005e38 adr x0, #0x100006859 ; "c"
...
0000000100005e48 bl imp___stubs___T0SS18UAObfuscatedStringE1oSSfg
...
0000000100005e50 bl imp___stubs___T0SS18UAObfuscatedStringE1mSSfg
...
0000000100005e74 bl imp___stubs___T0SS18UAObfuscatedStringE3dotSSfg
...
0000000100005e98 bl imp___stubs___T0SS18UAObfuscatedStringE1uSSfg
...
0000000100005ebc bl imp___stubs___T0SS18UAObfuscatedStringE1rSSfg
...
0000000100005ee0 bl imp___stubs___T0SS18UAObfuscatedStringE1bSSfg
...
0000000100005f04 bl imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
0000000100005f28 bl imp___stubs___T0SS18UAObfuscatedStringE1nSSfg
...
0000000100005f4c bl imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
0000000100005f70 bl imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
0000000100005f94 bl imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
0000000100005fb8 bl imp___stubs___T0SS18UAObfuscatedStringE1sSSfg
...
0000000100005fdc bl imp___stubs___T0SS18UAObfuscatedStringE3dotSSfg
...
0000000100006000 bl imp___stubs___T0SS18UAObfuscatedStringE1eSSfg
...
0000000100006024 bl imp___stubs___T0SS18UAObfuscatedStringE1xSSfg
...
0000000100006048 bl imp___stubs___T0SS18UAObfuscatedStringE1aSSfg
...
000000010000606c bl imp___stubs___T0SS18UAObfuscatedStringE1mSSfg
...
0000000100006090 bl imp___stubs___T0SS18UAObfuscatedStringE1pSSfg
...
00000001000060b4 bl imp___stubs___T0SS18UAObfuscatedStringE1lSSfg
...
00000001000060d8 bl imp___stubs___T0SS18UAObfuscatedStringE1eSSfg
I'm not sure why the Swift demangler isn't working here, but anyway, we can easily see the pattern:
_T0SS18UAObfuscatedStringE1oSSfg => o
_T0SS18UAObfuscatedStringE1mSSfg => m
_T0SS18UAObfuscatedStringE3dotSSfg => dot => .
_T0SS18UAObfuscatedStringE1uSSfg => u
...
Realizing there are these USObfuscatedString methods, I search for that and find everywhere in the app that uses obfuscated strings. If I was willing to up my game a little and spend a day or so playing with it, I could probably write a tool to automatically extract every UAObfuscatedString just using otool and the binary.
And this is the deep lesson. You've just labeled all the strings you want to hide. Once I realize that UAObfuscatedString is a thing, you just made it easier for me to find your sensitive information. It is literally worse than nothing. Your only hope here is that the attacker doesn't know this exists. That's the problem with obfuscation, and what separates obfuscation from security.
I want also to emphasize that I spent 5 minutes and 35 seconds attacking this program. Yes, I knew basically what kind of thing I was looking for, but I also have no skills at this. If UAObfuscatedString were to become popular, I assure you that the auto-detect/de-obfuscate tool would become part of every script-kiddie's toolbox ("script-kiddie" is what security folks call attackers who do not know what they're doing, and just use automated tools that others have written).
The lesson here is that if you want to obfuscate, you're better off making up some random approach yourself. It won't be effective, but it probably won't be actively harmful to your goal in the way that most FOSS solutions are. "Free and open source" can be very good for security, but are the worst possible thing for obscurity.
If hiding information is really important to your business plan and you can't change your business plan, then you should expect to spend a lot of money on this problem and hire a team of people dedicated to constantly evolving your obfuscation system to keep ahead of attackers who will adapt to whatever you build.
So I recommend use yours second finding
https://github.com/UrbanApps/UAObfuscatedString
and add the regenerated strings to the keychain at the first application launch
so all methods could use values from keychain later in you code.
also I recommend build a singleton that will provide access to such values too keep all in one for time you want to change or update this solution
In general I wrote may api keys just inline in code, sometime declare them split it into two parts for safety. I am using a brain factor;)
let's say you API key xxx-xxxx-xxxx
I code the string xxx-xxxx-xFFF which as you see has same length as right key, somewhere in other method I cut las FFF and append right xxx postfix.
If you have a paranoia you could do it in different classes that defined in same file for convenience but stays alphabetically different places like AStoredKeys TheRightPostfixes that somehow hides your approach from disassemblers.
Honestly there is not much you can do. Literals are probably the best choice, but consider that you really don't know who will have a device and what they are doing with it. It's safe to assume that any talented engineer will be able to get to the keys and code on the device. Even if you protect your keys, there are apps, like screen scrapers and other things than can really get information. Obfuscation is not a good long term practice and good engineers can figure their way around this... it just slows them down. You do have control over your server, so focus on keeping that solid.
In general instead of thinking of securing your keys, think more about limiting information and access.
In regards to data, minimize private data to be received. For example, credit card numbers are never displayed and only the last 4 digits are stored. Or in the case of a banking app, only account balances are displayed, and they also offer two factor authentication (with an image for example). If a device is compromised, while it would suck to have a person's balance known, it's not the end of the world.
This also tends to be good corporate practice as it keeps you safe from any allegations. A person can't allege that information was compromised if you don't have it in the first place.
With access, limit what an app is capable of doing. Firewall it in a sense. Or provide other authentication steps, like SMS verification, two factor authentication. You can also let the server do the secure tasks for you. In the case of banking again, instead of allowing unlimited transfers, limit the number of transfers or the amount. Limit the accounts to which it can be transferred.
You could keep the password separately, in a file on an encrypted disc, or encrypted USB stick. Your code would just retrieve the appropriate file from secure storage. All an attacker would see in your code is the name of the password file.
If that is not practical, then you could XOR encrypt the password in your code. Your application will contain text strings like: "Please enter your password." That doesn't look like a key, but you could use that string as the XOR key to encrypt/decrypt the password. This is more vulnerable as an attacker would see the XOR key you are using in your code and be able to decrypt for herself.
Whatever method you use, do remember to overwrite the variable that holds the actual password before it goes out of scope.

Detect if Cycript/Substrate or gdb is attached to an iOS app's process?

I am building an iOS app that transmits sensitive data to my server, and I'm signing my API requests as an additional measure. I want to make reverse engineering as hard as possible, and having used Cycript to find signing keys of some real-world apps, I know it's not hard to find these keys by attaching to a process. I am absolutely aware that if someone is really skilled and tries hard enough, they eventually will exploit, but I'm trying to make it as hard as possible, while still being convenient for myself and users.
I can check for jailbroken status and take additional measures, or I can do SSL pinning, but both are still easy to bypass by attaching to the process and modifying the memory.
Is there any way to detect if something (whether it be Cycript, gdb, or any similar tool that can be used for cracking the process) is attached to the process, while not being rejected from App Store?
EDIT: This is not a duplicate of Detecting if iOS app is run in debugger. That question is more related to outputting and it checks an output stream to identify if there's an output stream attached to a logger, while my question is not related to that (and that check doesn't cover my condition).
gdb detection is doable via the linked stackoverflow question - it uses the kstat to determine if the process is being debugged. This will detect if a debugger is currently attached to the process.
There is also a piece of code - Using the Macro SEC_IS_BEING_DEBUGGED_RETURN_NIL in iOS app - which allows you to throw in a macro that performs the debugger attached check in a variety of locations in your code (it's C/Objective-C).
As for detecting Cycript, when it is run against a process, it injects a dylib into the process to deal with communications between the cycript command line and the process - the library has part of the name looking like cynject. That name doesn't look similar to any libraries that are present on a typical iOS app. This should be detectable with a little loop like (C):
BOOL hasCynject() {
int max = _dyld_image_count();
for (int i = 0; i < max; i++) {
const char *name = _dyld_get_image_name(i);
if (name != NULL) {
if (strstr(name, "cynject") == 0) return YES;
}
}
}
Again, giving it a better name than this would be advisable, as well as obfuscating the string that you're testing.
These are only approaches that can be taken - unfortunately these would only protect you in some ways at run-time, if someone chooses to point IDA or some other disassembler at it then you would not be protected.
The reason that the check for debugger is implemented as a macro is that you would be placing the code in a variety of places in the code, and as a result someone trying to fix it would have to patch the app in a variety of places.
Based on #petesh's answer, I found the below code achieved what I wanted on a jailbroken phone with Cycript. The existence of printf strings is gold to a reverse engineer, so this code is only suitable for demo / crack-me apps.
#include <stdio.h>
#include <string.h>
#include <mach-o/dyld.h>
int main ()
{
int max = _dyld_image_count();
for (int i = 0; i < max; i++) {
const char *name = _dyld_get_image_name(i);
const char needle[11] = "libcycript";
char *ret;
if ((ret = strstr(name, needle)) != NULL){
printf("%s\nThe substring is: %s\n", name, ret);
}
}
return 0;
}
As far as I know, Cycript process injection is made possible by debug symbols. So, if you strip out debug symbols for the App Store release (the default build setting for the Release configuration), that would help.
Another action you could take, which would have no impact on the usability of the App, would be to use an obfuscator. However, this would render any crash reports useless, since you wouldn't be able to make sense of the symbols, even if the crash report was symbolicated.

PRNG in iOS KeyChain

My boss is asking me, which PRGN (Pseudo Random Number Generator) is using our iOS App for encrypting and decrypting data.
We are using the native KeyChain services for storing the data and I don't know what to answer since we are using the KeyChainItemWrapper for accessing the single items i.e. password, ports, etc. in our App and there is not too much reference about this.
I already debugged the app to see if I find something but I couldn't find something yet.
Any help would be appreciated,
thanks
If you need random bytes as opposed to a a random number:
randomBytes: returns count random bytes in *bytes, allocated by the caller.
Returns 0 on success or -1 if something went wrong, check errno to find out the real error.
#import <Security/Security.h>
+ (NSData *)randomBytes:(size_t)count
{
NSMutableData *data = [NSMutableData dataWithLength:count];
SecRandomCopyBytes( kSecRandomDefault,
data.length,
data.mutableBytes);
return data;
}
Be sure to add the Security framework.

iOS: Storing Non-User password

I need to store third-party username/password in my iOS application, what is the best and most secure way to do this? When my app first runs, it will need to talk to Google's Picasa to download private pictures to use for the app. To talk to Picasa, I have to provide my username/password and storing in the code is not secure at all.
I've search the web, I see Keychain came up a lot, but how exactly do I pre-load my password into keychain?
Is there a configuration file in xCode somewhere to store passwords needed for web-services?
Thanks
Think that you need to store the password in encrypted form. Pick some encrypting algorithm, generate the encrypted details. And in code have some method to decrypt it when needed.
You just don't want someone who would read your code as plain text to see the password.
Think that something as simple as splitting the password into separate strings and later joining them could be enough.
Here for example You have encrypted in code "My1Password":
#define R1 #"My"
#define R2 #"Password"
+ (NSString *)generatePass{ return [NSString stringWithFormat:#"%#%#%#, R1, #(1), R2]; }
This is a response to krzysztof above:
I'm in a catch-22 situation here as I can't seem to grasp the concept of feeding the password as parameter to another function. Aside from avoid others reading the source code in plain text, can't hackers obtain the binary file and reverse engineer to read the password in the source code (R1 & R2 in this case)???
Back to encryption, lets take the following line of code which Encrypt/Decrypt data:
NSData *encryptedImage = [RNEncryptor encryptData:imageData withSettings:kRNCryptorAES256Settings password:#"A_SECRET_PASSWORD" error:nil];
NSData *decryptedData = [RNDecryptor decryptData:data withSettings:kRNCryptorAES256Settings password:#"A_SECRET_PASSWORD" error:nil];
This is where I'm stuck... where do I store A_SECRET_PASSWORD?

What is the correct way to clear sensitive data from memory in iOS?

I want to clear sensitive data from memory in my iOS app.
In Windows I used to use SecureZeroMemory. Now, in iOS, I use plain old memset, but I'm a little worried the compiler might optimize it:
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/771-BSI.html
code snippet:
NSData *someSensitiveData;
memset((void *)someSensitiveData.bytes, 0, someSensitiveData.length);
Paraphrasing 771-BSI (link see OP):
A way to avoid having the memset call optimized out by the compiler is to access the buffer again after the memset call in a way that would force the compiler not to optimize the location. This can be achieved by
*(volatile char*)buffer = *(volatile char*)buffer;
after the memset() call.
In fact, you could write a secure_memset() function
void* secure_memset(void *v, int c, size_t n) {
volatile char *p = v;
while (n--) *p++ = c;
return v;
}
(Code taken from 771-BSI. Thanks to Daniel Trebbien for pointing out for a possible defect of the previous code proposal.)
Why does volatile prevent optimization? See https://stackoverflow.com/a/3604588/220060
UPDATE Please also read Sensitive Data In Memory because if you have an adversary on your iOS system, your are already more or less screwed even before he tries to read that memory. In a summary SecureZeroMemory() or secure_memset() do not really help.
The problem is NSData is immutable and you do not have control over what happens. If the buffer is controlled by you, you could use dataWithBytesNoCopy:length: and NSData will act as a wrapper. When finished you could memset your buffer.

Resources