如何避免硬编码加密密钥(目标C)? [英] How to avoid hardcoding keys for encryption (Objective C)?

查看:344
本文介绍了如何避免硬编码加密密钥(目标C)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Objective C代码中,我的代码中有一个消费者密钥和密码,用于SHA-1加密。我想知道的是我是否可以避免硬编码来提高安全性。到目前为止我找到了以下内容,

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,

查找1
https://www.owasp.org/index.php/Technical_Risks_of_Reverse_Engineering_and_Unauthorized_Code_Modification#Cryptographic_Key_Replacement
步骤说明如下,

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,


  1. 损坏源代码中声明的静态密钥。这些密钥在磁盘上应该被损坏,以防止对手分析和拦截原始密钥;

  1. 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.

查找2
https://github.com/UrbanApps/UAObfuscatedString

有人可以帮助我吗?

示例代码:

+ (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;
}


推荐答案

我写过< a href =https://stackoverflow.com/questions/9401315/ios-5-how-to-encrypt-property-list-in-the-bundle>解决此问题的挑战,但是我想用你的 UAObfuscatedString 想法进行一些演示,因为我认为这是大多数人都在寻找的解决方案,但是比没什么好。重要的是要注意:我并不是特别擅长这一点。我不是一名经验丰富的逆向工程师,商业系统超出了我的技能水平。我只是一个有 Hopper 的人,还有五分钟的逆向工程(我跑了一个计时器; 5:35s ,包括升级Hopper,因为我几个月没有运行它。)

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).

所以,我用 UAObfuscatedString写了一个iOS程序。我使用Swift是因为Swift通常比ObjC更难逆向工程。 ObjC是逆向工程师的梦想。

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
}

然后我将其存档,所以它是优化的代码等等,就像你发送到App Store一样。然后我将其加载到Hopper并查看应用程序委托的 init 。这是常量初始化的地方,基于大多数人将这些东西粘贴在他们的app委托中的假设。显然,如果我看到一个名为 KeyStorage SecretStuffHelper 的类,我会先看一下....

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;
}

嗯,它调用这个匿名函数 sub_100005e14() 。让我们看看它是做什么的。

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

我不确定为什么Swift会消失r在这里不起作用,但无论如何,我们可以很容易地看到模式:

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
...

实现这些 USObfuscatedString 方法,我搜索它并在应用程序中找到使用混淆字符串的所有地方。如果我愿意花一点时间玩我的游戏并花一天时间玩它,我可能会编写一个工具来自动提取每个 UAObfuscatedString 只需使用 otool 和二进制文件。

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.

这是深刻的教训。您刚刚标记了要隐藏的所有字符串。一旦我意识到 UAObfuscatedString 是一件事,你就让我更容易让我找到你的敏感信息。它实际上比没有任何东西更糟糕。你唯一的希望是攻击者不知道这存在。这就是混淆的问题,以及混淆与安全的区别。

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.

我还要强调我花了5分35秒攻击这个程序。是的,我基本上知道我在寻找什么样的东西,但我也没有这方面的技能。如果 UAObfuscatedString 变得流行,我向你保证自动检测/去混淆工具将成为每个script-kiddie工具箱的一部分(script-kiddie是什么安全人员称攻击者不知道他们在做什么,只使用其他人编写的自动化工具。

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).

这里的教训是,如果你想混淆,你最好自己制定一些随机的方法。它不会有效,但它可能不会像大多数FOSS解决方案那样对您的目标产生积极影响。 免费和开源对安全性非常有利,但对于默默无闻是最糟糕的事情。

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.

这篇关于如何避免硬编码加密密钥(目标C)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆