2014.06.10 15:00

Apple出包,你的SSL加密是否安全?SSL原理解析,從密碼學看加密技術的安全性

ADVERTISEMENT

正當iDevice使用者期待iOS 7.1版更新檔釋出之際,Apple卻悄悄釋出7.0.6版更新檔,更讓人意外的是被視為已淘汰產品的iPhone 3GS以及第四世代iPod touch,也獲得6.1.6版更新,難道這不尋常的舉動背底有什麼陰謀嗎?

不是陰謀,只是亡羊補牢

眾所期待的iOS 7.1版具有許多改變,包括使用者介面的改變、攝影時依光源狀況自動開啟HDR,甚至是適用於行車時的車用模式等新功能功能。相較之下7.0.6與6.1.6版的更新履歷只有1個項目,「此安全性更新提供了SSL連線驗證的修復」。

對於使用者而言,無論從版本號的推進,或是更新內容的豐富度來看,這個更新的重要性似乎比不上7.1版,但事實上這個更新檔影響至關重大。由於Apple在SSL連線驗證過程的程式碼上犯下了嚴重的錯誤,導致SSL驗證形同虛設,讓使用者無從得知SSL加密連線是否真的經過驗證,以致於讓通信安全暴露於極大的風險之下,使用者甚至可能在看似安全的SSL加密連線過程中,無意將信用卡資訊等機密資料外洩。

此外,Apple的電腦端作業系統也受同樣的問題影響,所幸Apple也在事發幾天後釋出OSX 10.9.2版更新檔來修正此問題。由於這個安全性問題不容小覷,因此筆者建議所有OSX與iOS的使用者,務必檢查作業系統版本並進行更新。

ADVERTISEMENT

▲iOS 7.0.6版的更新內容只有1項,雖然看似單薄,不過卻可以稱得上是iOS最重要的更新之一。 

7.0.6補強安全性,但不封鎖越獄

由於Apple在iOS 7.0.6版更新中只針對SSL連線驗證問題進行修正,並沒有修補越獄所使用的漏洞,因此在iOS 7.0.6版更新檔釋出的1天之內,知名越獄團隊evad3rs馬上就更新越獄工具evasi0n7,能夠替安裝7.0.6版韌體的iDevice進行越獄。

ADVERTISEMENT

由於Apple已在於2月初釋出的iOS 7.1 Beta5版更新中修補越獄所使用的漏洞,因此沒有修補7.0.6版的原因,不可能是不知道漏洞在哪裡。筆者推測除了因為要在第一時間修正SSL連線驗證問題,可能受限於時間因素放棄修補漏洞之外,另一個可能的原因是Apple長久以來對越獄抱持著「不戰、不合」的態度,與其逼迫越獄使用者放棄7.0.6版韌體,不如採取較為寬鬆的政策讓使用者有機會修正漏洞。

▲evad3rs的成員包括pimskeks、planetbeing、pod2g、MuscleNerd等駭客,旗下evasi0n7為目前唯一公開且支援iOS 7的越獄工具。

ADVERTISEMENT

Apple出包Google補刀

由於Apple自行公開部分程式原始碼,所以我們都可以看到這段出錯的程式碼,在問題爆發後,任職於Google負擔SSL相關工作的Adam Langley很快地分析了Apple的程式碼的問題所在,並於其部落格刊載說明。筆者於下方節錄部分程式碼進行解說,詳細的完整程式碼可參考延伸閱讀中的連結。

為了讓讀者瞭解該程式的錯誤,筆者先簡單地說明一下C語言的語法,以這行程式碼為例

if ((err = SSLFreeBuffer(&hashCtx)) != 0)

ADVERTISEMENT

        goto fail;

它是條if判斷式,如果if後方括號中的條件成立,則執行下一行的指令,而函式SSLFreeBuffer(&hashCtx)則是SSL驗證過程中的其中1項,該驗證程式碼寫在其他位置,當程式執行至此就會調用該函式進行運算。

多一行程式導致失效

該判斷式中的變數err記錄著驗證狀態。而err會存入函式的運算結果,當err等於0時,由於條件不成立,所以程式會跳過下一行的指令,若當err不等於0時,條件成立,程式就執行goto fail;指令,並跳往fail:,執行fail:下方的指令。

依照一般人對於數字代表意義的直覺來看,很容易先入為主地認為應該以0代表驗證失敗,並以1代表驗證成功,但是在上述程式碼中,可以看到以0代表驗證成功,或許會讓讀者產生疑惑。

其實這個問題很簡單,由於驗證成功的情況只有1種,而驗證失敗的情況可能有百百種,所以當驗證失敗時,函式可能回傳各種不等於0的錯誤代碼,以利進行診斷,所以才會以0代表驗證成功,非0代表驗證失敗。

驗證一半就算通過

接下來讀者可以看到下方節錄程式碼中的第五個if判斷式,其後方有2行goto fail;,這將造成嚴重的安全性漏洞。當程式運算完SSLHashSHA1.update的結果時,若err值不等於0,則程式會跳到fail:後方,並執行SSLFreeBuffer(&signedHashes)與SSLFreeBuffer(&hashCtx)等2個函式(其功能應該是清空2組變數的緩衝區),接下來回傳err,由於這時候err值不等於0,所以驗證過不會通過,不會發生安全性問題。

但是若在第五個if判斷式中通過驗證,此時err值等於0,因此下一行指令將被跳過(第一行goto fail;),並執行第二行goto fail;,在清空緩衝區後,將等於0的err回傳給程式。此時即使夾在第五個if判斷式與fail:之間的驗證程序沒有被執行,程式也會認為SSL驗證無誤,造成安全漏洞。

▲讀者可以透過https://gotofail.com網站,檢測自己的電腦是否曝露於上述資安風險之下。

對於不想升級到iOS 7.0.6版且已越獄的使用者,可以在Cydia中安中裝SSLPatch來修正這個問題。

▲筆者以iOS 6.1.2版並安裝SSLPatch進行測試,結果顯示對於gotofail攻擊為安全狀態。

延伸閱讀網址

Adam Langley部落格

https://www.imperialviolet.org

Apple問題專文

https://www.imperialviolet.org/2014/02/22/applebug.html

Apple公開的相關程式碼

出問題的程式碼(節錄)

    hashOut.data = hashes + SSL_MD5_DIGEST_LEN;

    hashOut.length = SSL_SHA1_DIGEST_LEN;

    if ((err = SSLFreeBuffer(&hashCtx)) != 0)

        goto fail;

 

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0)

        goto fail;

    if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0)

        goto fail;

    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)

        goto fail;

    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)

        goto fail;

        goto fail;

    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)

        goto fail;

 

    err = sslRawVerify(ctx,

                       ctx->peerPubKey,

                       dataToSign,              /* plaintext */

                       dataToSignLen,           /* plaintext length */

                       signature,

                       signatureLen);

    if(err) {

        sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify "

                    "returned %d\n", (int)err);

        goto fail;

    }

 

fail:

    SSLFreeBuffer(&signedHashes);

    SSLFreeBuffer(&hashCtx);

    return err;

 

SSL原理:透過驗證、加密確保安全

既然從前段文章中可以看到這次SSL出包的問題,在於Apple撰寫的程式碼存在bug,並不是SSL機制有問題,但讀者不免會對SSL的運作原理及安全性有所疑問,筆者在此就講述SSL的運作原理,讓讀者對這個行之有年的安全機制有更深一層的認識。

SSL、TLS同根生

SSL的全名是Secure Sockets Layer,由曾風光一時的瀏覽器公司Netscape開發,其1.0版並未公開釋出,第一個公開版本為1995年問市的2.0版,不過由於2.0版有些許安全性缺陷,因此隔年Netscape就推出SSL 3.0。

IETF(Internet Engineering Task Force,網際網路工程任務組)在1999年制定RFC2246,並將其稱為TLS(Transport Layer Security),將其視為SSL的升級版,並於2006與2008年推出TLS 1.1與1.2版。

根據Trustworthy Internet Movement於2014年3月4日提供的數據,在他們統計的網站中,最普遍被支援的規範為SSL 3.0,其比例高達99.4%,次高比例為TLS 1.0的97.7%,支援TLS 1.2的網站只有30.2%。

ADVERTISEMENT