iPhone 使用者必更新,蘋果安全性大漏洞解析

Apple 最近發佈了 iOS 7.0.6,更新內容只講了是有關 SSL 的安全性更新。乍聽之下好像不是什麼嚴重的大更新。但是在許多安全專家開始仔細研究後,發現其實 Apple 出了一個相當大的包,影響非常之大,造成的原因卻又簡單的好笑。
評論
評論

本文轉自 PTT iPhone 版 iPluto「[情報] 解析 7.0.6 更新的安全性漏洞」一文,Inside 獲作者 iPluto 授權轉載。

Apple 最近發佈了 iOS 7.0.6,更新內容只講了是有關 SSL 的安全性更新。乍聽之下好像不是什麼嚴重的大更新。

但是在許多安全專家開始仔細研究後,發現其實 Apple 出了一個相當大的包,影響非常之大,造成的原因卻又簡單的好笑。

首先我們要先了解什麼是 SSL。SSL 是網路連線的一種加密認證方式,普遍應用在各大網站的登入系統來避免 Man In The Middle 攻擊。

舉例來說,你今天想要進行網路購物,你勢必要輸入你的信用卡號碼傳給網站。所謂 Man In The Middle 攻擊,就是攻擊者假扮成你要購物的網站,從中拿走了你的信用卡資料。然後為了不讓你察覺,他當然也會把這份資料送去給真正的購物網站,拿到購物網站的回應後再傳回給你。這樣在你的眼中,你還是正常的消費,但是信用卡資料卻已經神不知鬼不覺的被盜取了。同樣的原理,你的 email 或者網路銀行的帳號密碼,都可以這樣被盜取。

所以 SSL 的存在就是為了阻止這件事情。你也許注意到許多網站在登入時你的網址都會從 http:// 變成 https://,這就表示 SSL 已經啟動。SSL 會認證跟你溝通的對象,確定對方真的是他所宣稱的網站而不是攻擊者所偽裝的。背後的原理就像是我們使用親筆簽名來確認是否為本人一樣,使用數位簽名來確認對方的身分。

那 Apple 出了什麼包呢?基本上在過去的半年多,所有 Apple 的產品,SSL 的認證機制都是壞掉的。也就是如果你使用 Apple 的產品在公開的網路環境登入任何網站,你的資料基本上相當容易被盜取。在過去幾個月也許知道這個漏洞的人不多,所以也許沒有太多的攻擊事件,但是就在幾天前漏洞曝光,利用此漏動的攻擊者將會大幅增加。

這邊有個測試網站,它會顯示你的瀏覽器是否受此漏洞影響:

https://gotofail.com

問題講完了 現在來講解決方案。iOS 的使用者,請更新到 7.0.6。已經 JB 的人,evasi0n 團隊已經更新了工具可以支援 7.0.6,只要更新 -> 重新 JB-> 重新裝回所有 tweak,或者可以直接到 Cydia 安裝 SSLPatch 這個 tweak。

MacOSX 的使用者... 很抱歉 Apple 還沒有出更新檔... 所以現在盡量避免使用公共無線網路登入任何網站 (特別是跟金錢相關的)... 等到 Apple 有更新檔請第一時間更新。(有個非官方的更新,但是不推薦)Update: Apple 已釋出 10.9.2 的 OSX 更新。(編按:按此 閱讀蘋果網站公佈的更新教學)

好,現在來講講到底是什麼原因造成這種大漏洞的。說來好笑,只是因為某份程式碼多了一行...

在 C 語言裡面,判斷是是這樣寫的:

if (條件)
{
條件成立要做的事情;
條件成立要做的另一件事情;

}

但是 C 又有另一個設計,就是如果要做的事情可以一行寫完,那可以不用寫那兩個 {},你可以寫成這樣:

if (條件)
一行就可以做完的事情;

但是如果你這樣寫,就要特別小心,像以下這種狀況:

if (條件)
第一件事情;
第二件事情;

這種狀況乍看之下跟前面的例子一樣,實際上只有第一件事情是條件符合才會執行,第二件事情是無論如何都會被執行... 因為只有 if 下面那行才跟條件判斷有關係...

這就是 Apple 出的包,以下是它的程式碼:

static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext ctx, bool isRsa,
SSLBuffer signedParams,
uint8_t
signature, UInt16
signatureLen)
{
...

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; <---- DANGER
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
goto fail;

err = sslRawVerify(ctx,
ctx->peerPubKey,
dataToSign,
dataToSignLen,
signature,
signatureLen);
...
fail:
SSLFreeBuffer(&signedHashes);
SSLFreeBuffer(&hashCtx);
return err;

}

這段程式碼就是 SSL 在認證簽名用的,整個函數會檢查簽名是否為真然後回傳檢查結果,傳回 0 就是正確,傳回非 0 就是錯誤。本來這段程式碼是沒有問題的,每個判斷式會檢查一樣東西,認證成功會檢查下一樣東西,認證不成功會跳到最下面的 3 行程式碼,此時 err 應該不會是 0,所以整個函數回傳非 0 的值,認證失敗。

問題是某處連續出現的兩個 goto fail,只有第一個跟它上面的 if 有關,會考慮條件判斷。後面那個 goto fail 不管怎麼樣都會被執行到!!!也就是認證到一半就跳到下面那三行程式碼,此時 err 當然是 0,函數回傳了 0,直接宣布認證通過...

對,錯誤就是這麼簡單,多了一行 goto fail,可以影響全世界不知道多少的用戶,讓整個 SSL 認證機制完全無效,寫程式真的不能不小心啊…

最後, 請記得更新你的系統。隨著 Apple 發表這個更新檔並且被挖出了相關漏洞資訊,攻擊者會增加的非常快速。

網友於推文中質疑蘋果應不致犯這種低級錯誤,作者 iPluto 補充回覆:

網路上的東西是不該隨便相信沒有錯。

來,首先看 Apple 的公告:
http://support.apple.com/kb/HT6147?viewlocale=en_US&locale=en_US

這邊提到漏洞編號是 CVE-2014-1266。

於是接著查到這邊:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-1266&cid=1

表示漏洞存在於 libsecurity_ssl/lib/sslKeyExchange.c,最後是 Apple 自己放上去的程式碼:
http://tinyurl.com/phzhghu
裡面就有上面提到的漏洞。

然後有人針對這段程式碼的錯誤自行做了一個 Patch,在 這裡 可以找到

實測結果 patch 後真的有效 (前面有漏洞測試網站),所以應該是這個錯誤無誤。

最後,加密認證很多程式碼都是公開的,例如 OpenSSL,程式碼公開不代表安全性有問題 (其實公開的反而安全 大家會幫忙找漏洞),加密認證的重點在你有攻擊者所不知道的 key。