2017-06-22 304 views
2

在我的Objective C代碼中,我的代碼中有一個使用者密鑰和密碼,用於SHA-1加密。我想知道的是我是否可以避免硬編碼來提高安全性。我發現有以下幾種到目前爲止,如何避免硬編碼加密密鑰(目標C)?

找到1 https://www.owasp.org/index.php/Technical_Risks_of_Reverse_Engineering_and_Unauthorized_Code_Modification#Cryptographic_Key_Replacement 步驟如下解釋,

  1. 損害了在源代碼中聲明的靜態密鑰。磁盤上的這些密鑰應該被破壞,以防止對手分析和攔截原始密鑰;

  2. 接下來,應用程序應在需要密鑰的代碼使用之前修復密鑰;

  3. 緊接在使用密鑰之前,應用程序應執行密鑰值的校驗和以驗證未損壞的密鑰與代碼在構建時聲明的值相匹配;和

  4. 最後,應用程序應該立即重新損壞內存中的密鑰後,應用程序已完成使用它的特定呼叫。

找到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; 
} 
+1

你是什麼意思「破壞」一個關鍵?假設密鑰是一個字符串:如何「損害」一個字符串? – Sajjon

+1

如果您正在尋找一種在iOS應用程序中安全存儲密鑰(例如字符串)的方法,則應將其存儲在「KeyChain」中。請參閱https://www.raywenderlich.com/92667/securing-ios-data-keychain-touch-id-1password或者可能是開源框架:https://github.com/kishikawakatsumi/KeychainAccess – Sajjon

+1

,你應該清楚你究竟在試圖抵禦自己的攻擊,你害怕什麼類型的攻擊。 – luk2302

回答

4

我寫過關於the challenges of solving this problem before的文章,但我想用UAObfuscatedString這個想法來展示一點點,因爲我認爲這是大多數人都在尋找的解決方案,但比沒有更糟。重要的是要注意:我並不擅長這一點。我不是一個經驗豐富的逆向工程師,商業系統遠遠超出了我的技能。我只是一個擁有Hopper的人,並且真正進行了5分鐘的逆向工程(我跑了一個計時器; 5:35s,包括升級Hopper,因爲我沒有在幾個月內運行它)。

所以,我寫了一個iOS程序UAObfuscatedString。我使用Swift是因爲Swift通常比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。這就是常量初始化的地方,這是基於大多數人將這些東西放在他們的應用代理中的假設。顯然,如果我看到一個名爲KeyStorageSecretStuffHelper類,我想看看那裏第一次....

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()。讓我們看看那是什麼。

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

我不知道爲什麼斯威夫特demangler不在這裏工作,但無論如何,我們可以很容易地看到這個模式:

_T0SS18UAObfuscatedStringE1oSSfg => o 
_T0SS18UAObfuscatedStringE1mSSfg => m 
_T0SS18UAObfuscatedStringE3dotSSfg => dot => . 
_T0SS18UAObfuscatedStringE1uSSfg => u 
... 

意識到有這些USObfuscatedString方法,我尋找的是並在使用混淆字符串的應用中查找無處不在。如果我願意提升我的遊戲並花一天左右的時間玩它,我可能會編寫一個工具來自動提取每個UAObfuscatedString,只需使用otool和二進制。

這是深刻的教訓。你剛剛標記了你想隱藏的所有字符串。一旦我意識到UAObfuscatedString是一件事情,你只是讓它更容易爲我找到你的敏感信息。這實際上比沒有更糟糕。你唯一的希望就是攻擊者不知道這存在。這就是混淆的問題,以及將混淆與安全隔離的問題。

我還想強調,我花了5分35秒攻擊這個程序。是的,我基本知道我在找什麼樣的東西,但我也沒有這方面的技能。如果UAObfuscatedString成爲流行,我向你保證,自動檢測/去混淆工具將成爲每個腳本 - 小孩的工具箱的一部分(「script-kiddie」是安全人員稱不知道他們在做什麼的攻擊者,並使用其他人編寫的自動化工具)。

這裏的一個教訓是,如果你想混淆,你最好自己編寫一些隨機的方法。它不會有效,但它可能不會以大多數FOSS解決方案的方式對您的目標產生積極的危害。 「自由和開放源代碼」對於安全性來說可能非常好,但是對於默默無聞的最糟糕的事情。

如果隱藏信息對您的業務計劃非常重要,並且您無法更改您的業務計劃,那麼您應該期望在此問題上花費大量資金並聘請一個專門致力於不斷改進您的混淆系統的人員團隊保持領先攻擊者的位置,這些攻擊者將適應你的任何構建。

+1

「我使用Swift是因爲Swift通常比ObjC更難於進行反向工程「。你能解釋一下這是怎麼回事?我想詳細瞭解。就我所知,Swift和Objective C使用相同的運行時。 – ViruMax

+3

@virumax Swift具有廣泛的靜態分派功能,可以內聯函數,然後根據這些事情執行優化。這使得得到的Swift與原始代碼相比與Objective-C的關係要少得多,而Objective-C無法跨消息傳遞進行優化(objc_msgSend)。 objc_msg發送調用遍及編譯的Objc必然會告訴你方法的名字。這在優化的Swift代碼中通常不可用。雖然Swift *可以使用ObjC運行時,但它並不需要,許多Swift也不需要。在這方面,Swift更接近於C++。 –

+0

我並不是說Swift對逆向工程來說特別困難。但Objective-C是一種逆向工程師對於本地編譯語言的夢想。 –

1

因此,我建議用你的第二個發現

https://github.com/UrbanApps/UAObfuscatedString

和再生的串在第一應用程序啓動

添加到鑰匙扣

所以所有的方法都可以稍後在代碼中使用鑰匙串中的值。 另外我建議建立一個單身人士,將提供訪問這些值也保持在一個時間你想改變或更新這個解決方案

在一般情況下,我寫了可能api鍵只是內聯在代碼中,有時聲明他們分裂它分爲兩部分以確保安全。我正在使用腦因子;)

讓我們說你的API密鑰xxx-xxxx-xxxx 我編碼的字符串xxx-xxxx-xFFF,正如你所看到的,它的長度與右鍵相同,在其他方法中我切斷了las FFF並追加右邊的xxx後綴。

如果你有偏執狂,你可以在不同的類中定義同一個文件,但爲了方便起見,它們保持按字母順序排列的不同位置,比如AStoredKeys TheRightPostfixes以某種方式隱藏了反彙編器的方法。

+0

您試圖通過存儲在鑰匙串中實現的任何其他級別的安全性?你的方法和UAObfuscatedString都會在部分代碼中仍然有字符串值(儘管很難破解)。 –

+1

'UAObfuscatedString'比這個例子更糟糕。它實際上發光了您想要隱藏的數據,同時不提供任何保護。你的分裂方法要好得多,儘管我可能會以不同的方式做幾件事情。使用原始字節而不是字符串(字符串很容易在二進制文件中找到)。將它分割成錯誤的長度(或填充錯誤的長度),以便搜索「正確長度的東西」不起作用。並將其與其他一些隨機數據進行異或運算,以便實際字節不會出現在二進制文件中。我的方式也沒有效果,但至少會嘗試。 –

+1

(我們的兩種方法都是OWASP提到的「損害」的正確版本,並且通常是在不聘用專門團隊的情況下可以做到的最好的版本。) –

-1

您可以分別將密碼保存在加密光盤上的文件或加密的USB記憶棒上。您的代碼只會從安全存儲中檢索相應的文件。攻擊者會在你的代碼中看到密碼文件的名稱。

如果這樣做不可行,那麼你可以在代碼中對密碼進行XOR加密。您的應用程序將包含以下文本字符串:「請輸入您的密碼。」這看起來不像一個密鑰,但是你可以使用該字符串作爲XOR密鑰來加密/解密密碼。由於攻擊者會看到您在代碼中使用的XOR密鑰並能夠爲自己解密,因此這更容易受到攻擊。

無論使用什麼方法,都要記得在超出範圍之前覆蓋保存實際密碼的變量。