在開發藍象安全雲的過程中,我們學習了iOS的生物驗證登錄技術(包括Touch ID 和 Face ID)。然後對比了一些常用的App的指紋登錄功能,發現很多並沒有充分利用iOS的安全能力。跟大家分享一下相關的知識,也希望我們使用的App也能夠越來越安全。

登錄驗證

為什麼要登錄驗證

早期的互聯網服務大多是沒有登錄的,主要是靜態內容,大家瀏覽。後來有一些簡單的論壇,聊天室等動態服務,這個時候就需要密碼進行身份認證了。再後來登錄作為身份驗證的方式就廣泛應用到很多很多互聯網服務了。

密碼登錄的安全問題

然而登錄要做到安全非常不容易。賬號密碼一旦落入他人之手,就可能泄露所有信息,甚至被用來詐騙。密碼登錄的安全問題有哪些呢?

1. 使用HTTP登錄驗證,而不是HTTPS

很多知名的大公司,包括前些年QQ也採用這種方式登錄,自己設計了方法來加密用戶輸入的密碼,通過HTTP方式提交到伺服器驗證,後來也放棄了。

一定要使用HTTPS驗證用戶名和密碼

一定要使用HTTPS驗證用戶名和密碼

一定要使用HTTPS驗證用戶名和密碼

2. 使用HTTPS登錄驗證,但是登錄頁面本身是HTTP

有些技術人員認為只要登錄驗證使用HTTPS,保證用戶名密碼不會泄露就安全了,登錄框用HTTP也可以,還可以節省伺服器資源,畢竟HTTPS握手很耗CPU。

這是一個很常見的錯誤,因為HTTP不安全,伺服器通過HTTP發送給用戶的網頁,很容易被嵌入JS代碼。大家對運營商嵌入網頁的廣告一點都不陌生吧,如果用戶使用了不安全的無線路由器,或者沒有密碼保護的免費Wi-Fi,試想一下,如果被嵌入惡意JS代碼,那輸入的用戶名密碼就暴露了!暴露了!暴露了!

來源 news.ifeng.com/a/201707

一定要使用HTTPS展示登錄框

一定要使用HTTPS展示登錄框

一定要使用HTTPS展示登錄框

誰認識YY,搜狐負責登錄的技術同學,麻煩轉發給他們看看,謝謝!

3. 用戶名不存在

有的網站登錄失敗是因為用戶名不存在,會返回一個用戶名不存在的提示消息,而不是像上面搜狐的錯誤那樣子。有什麼問題嗎?

是的,如果一個網站會返回 用戶名不存在 的錯誤消息,而用戶名存在,但是密碼錯誤,會提示另外一個消息,那麼就給了大壞蛋一個信息,用戶名是存在的,接下來就只需要破解密碼了。要知道在今天這個信息泄露泛濫的世界裡,我們的手機號、email地址基本上沒有任何祕密而言了。

4. 明文保存密碼

用戶註冊的密碼怎麼保存呢?直接放進資料庫唄。很多沒有經驗的程序員開發網站往往會不假思索的把用戶信息一起保存到資料庫,驗證的時候來一句SQL,搞定!

SELECT EXISTS (
SELECT * FROM login_details WHERE username = ? AND password = ?
)

好簡單!也好不安全!

明文保存密碼意味著開發人員,或者運維人員,甚至是公司其他工作人員可以直接讀取用戶密碼!!!

意味著,一旦發生數據泄漏,大壞蛋就知道了很多人的密碼!!!

還意味著,很多重複使用密碼的用戶,在很多其他平臺的賬號也暴露了!!!

5. Hash保存密碼

既然不能明文保存密碼,那就使用Hash函數加密保存密碼唄。Hash函數可是單向的,就不信大壞蛋可以把密碼還原出來。

這個,還真可以!

Hash密碼是可逆的

Hash密碼是可逆的

Hash密碼是可逆的

是的,你沒有看錯,Hash密碼是可逆的,雖然安全的Hash演算法是不可逆的。

這是因為對同一個密碼,用同一個Hash演算法,比如MD5, SHA1,計算出來的結果總是一樣的,你可以看看mysql.users表裡面,相同的密碼是不是都一樣的?:)

這個世界上,就是有一些人喫飽了沒事幹,就在那裡計算所有的密碼Hash,而且還公開給人們下載。截至目前,9位以內所有字母數字組合的密碼都被計算出來了,總共也就1TB的數據,隨便一塊硬碟就存下來了。你的密碼有幾位呢?

這麼大的數據量,要通過Hash值反查密碼也不容易吧?在彩虹表面前,這都不是事兒。

6. 多重混合Hash密碼

一次Hash不行,那就多來幾次吧,混起來Hash。是不是想到了很多這樣的騷操作?

  • md5(sha1(password))
  • sha1(sha1(password))
  • md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))

這也不安全,事實上多重混合Hash通常會降低安全性。比如MD5已經被證明不安全了,SHA1相對來說要安全一些,組合使用反而降低了SHA1的安全能力。

7. 保存密碼的正確姿勢

所以呢?保存密碼的正確姿勢是怎樣的?

先把密碼醃製起來,然後再用Hash加密,直接上代碼,

let salt = someRandomByteslet saltedPassword = salt + passwordlet hash = SHA256(saltedPassword)
save(salt, hash)

先生成隨機的salt,然後計算salt+password的Hash,最後保存salt和hash值。是的,salt是明文保存的,和hash保存在一起。

驗證用戶密碼的時候,先把salt讀出來,同樣的方式計算hash,再和資料庫中保存的hash對比。

是不是就天下太平了?還是有兩個坑,

  1. 使用固定的salt在程序裡面寫死一個隨機數當作salt,以後都直接用省去了讀資料庫的麻煩,好輕鬆!But, But 這樣子就起不到加鹽的作用了。一個用戶固定一個salt?安全起見,每次用戶重置密碼,應該重新生成salt。
  2. 使用太短的salt打個比方,如果salt只有1bit,那麼計算出來的hash就只有2個可能的值,2bit就有4個可能的值,salt越短,計算出來的hash空間就越小,也就起不到很好的保護作用。

    彩虹表都已經計算到10位密碼了,salt建議至少128bit,256bit更好。

    那是不是1024更好呢?沒有必要,因為SHA256的hash值也只有256bit,並不會增加hash值的空間。salt不需要比hash值更長。

8. 再安全一點點

如果不介意驗證密碼的時候多消耗一些CPU的話,可以把普通的Hash函數換成非常耗時的Hash演算法,比如PDKDF2, bcrypt等,這樣攻擊成本也會變得很高。

9. 撞庫怎麼辦?弱密碼怎麼辦?

來源 thesun.co.uk/tech/79784

應對撞庫業界通用的做法是採用雙因素驗證,例如簡訊驗證碼、郵箱驗證碼,TOTP(基於時間的一次性密碼)等。當然針對性的攻擊,手機號克隆,破解郵箱等也時有發生,TOTP也無法防止內鬼和黑客拖庫。釣魚攻擊被證明能夠攻破google的防護。

密碼不是唯一的登錄驗證方式

長期以來,互聯網服務基本上都採用密碼登錄驗證方案。眾所周知,密碼並不是安全的驗證方案。然鵝,很多人不知道的是,密碼也不是唯一的驗證方案。

公鑰登錄驗證

後臺開發人員登錄伺服器通常都使用SSH密鑰登錄,Github用戶也有不少使用SSH密鑰更新代碼,非常方便安全。

你家Linux伺服器還在用密碼登錄?趕緊換SSH密鑰登錄。我在之前公司就直接關閉了Linux伺服器上的密碼驗證,只能使用密鑰。

來源 blog.csdn.net/u01111832

簡單來說,其原理是利用了公鑰演算法的特點,

  1. 先把用戶的公鑰放在伺服器上
  2. 登錄時,使用私鑰加密(或者簽名)一段隨機數據
  3. 伺服器使用用戶的公鑰解密(或者驗證簽名),對比解密結果是否正確。

公鑰驗證相比密碼驗證以及TOTP等有巨大的優勢,資料庫即使被內鬼或者大壞蛋拖庫了,也只能夠獲得用戶的公鑰。而使用公鑰只能夠驗證用戶,而不能偽裝用戶登錄。更無法通過獲取到的公鑰去撞庫攻擊其他平臺。

iOS App 登錄驗證

iPhone最大的優勢之一就是安全性,App沙盒機制保證了內部存儲的數據也是安全的。

來源 cse.wustl.edu/~jain/cse

所以不少App開發者直接使用 UserDefaults 把用戶密碼明文保存在 Preferences plist中,也有簡單寫文件保存的。

這裡有兩個安全問題需要注意,

  1. iPhone/iOS相對安全,但並不是一定永遠安全。不少用戶還在使用幾年前的系統,這些舊系統可能有不少安全漏洞,可能導致數據泄露。當年蘋果不配合FBI,後來FBI破解恐怖分子的iPhone 5C手機,就是利用了iOS9上面的一個漏洞。
  2. iOS App存儲的文件默認會自動通過iCloud備份。iCloud的安全性一直不算很好,當年大表姐就深受其害,今年又出了支付寶盜刷事故。所以敏感文件一定要通過 isExcludedFromBackup 禁止備份。

美麗的大表姐

iOS保存密碼的正確姿勢

如果一定要保存密碼之類的敏感信息,應該使用iOS的 Keychain Services 服務來保存。iOS的 Keychain Services 並不是iCloud keychain,前者是給開發者存儲App重要數據的服務,默認並不適用iCloud同步,後者是iCloud給用戶提供的一個功能。這兩個東西命名很糟糕,很容易混淆。

有點像SQL,需要先創建一個Query,再調用 API 操作,使用起來不算很複雜,Ctrl-C, Ctrl-V

static let server = "www.example.com"let account = credentials.usernamelet password = credentials.password.data(using: String.Encoding.utf8)!var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
kSecAttrAccount as String: account,
kSecAttrServer as String: server,
kSecValueData as String: password]let status = SecItemAdd(query as CFDictionary, nil)guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }

iOS 生物驗證登錄

終於到主題了

早在2013年推出的iPhone 5S就支持了指紋支付,將生物驗證的安全性提升了一大步。

蘋果官方提供的iPhone安全架構,

當用戶通過Touch ID 或者 Face ID 的驗證時,Touch ID掃描用戶的指紋,提取出指紋特徵點的圖片數據,發送給直接 Secure Enclave 驗證,並不經過iOS操作系統, Secure Enclave 返回驗證結果,再通過iOS通知給App。整個過程指紋數據都不會經過iOS操作系統,而是通過硬體線路直接連接到 Secure Enclave,App就更不可能獲取到指紋數據了,非常安全。Face ID也是類似的原理,不同之處是掃描用戶頭像的3D數據。

另外,iPhone為了提升安全性,在出廠時指紋感測器晶元會和iPhone內部的安全晶元進行密鑰配對,保證即使替換了指紋感測器晶元也無法獲取到訪問 Secure Enclave 中的數據的許可權。這就是某些二手iPhone不能夠使用指紋識別的原因,因為替換的Home鍵無法和原裝的 Secure Enclave 配對。

生物驗證登錄原理

iOS 的 Secure Enclave 能夠安全的創建密鑰對,並使用私鑰對數據進行簽名。Secure Enclave創建的私鑰只保存在其內部,不允許任何程序讀出來。

那麼我們要怎樣使用iOS的硬體公鑰功能實現安全的登錄呢?

  1. 註冊流程,

sequenceDiagram

participant User
participant App
participant SecureEnclave
participant Server

App ->> SecureEnclave: SecKeyCreateRandomKey
SecureEnclave ->> User: Request authorize?
User ->> SecureEnclave: Authorized
SecureEnclave ->> App: PrivateKeyRef
App ->> SecureEnclave: SecKeyCopyPublicKey
SecureEnclave ->> App: PublicKey
App ->> Server: Send(PublicKey)
note right of Server: save PublicKey

sign-up.png

App使用 Secure Enclave 創建密鑰對時,會提示用戶授權,用戶只需要通過Touch ID或者Face ID驗證就好了。然後再把公鑰發送給伺服器保存下來。但是私鑰是保存在 Secure Enclave 內部的,App無法獲取。

  1. 登錄流程

sequenceDiagram

participant User
participant App
participant SecureEnclave
participant Server

User ->> App: Sign in
note over App: Prepare U(user info)
App ->> SecureEnclave: SecKeyCreateSignature
SecureEnclave ->> User: Request authorize?
User ->> SecureEnclave: Authorized
SecureEnclave ->> App: S(signature)
App ->> Server: Send(U, S)
note over Server: verify(PublicKey,U,S)
Server ->> App: Success

登錄也很簡單,用戶點擊登錄後,App請求 Secure Enclave 簽名,iOS會提示用戶授權,授權後會返回給App簽名,再把簽名和登錄信息一起發給伺服器驗證。

生物驗證登錄更安全

如果App充分利用了iOS生物驗證的安全能力,在用戶登錄時,使用 Secure Enclave私鑰簽名,發送給伺服器驗證,安全性比 Keychain Services 保存密碼更高。使用 Secure Enclave 私鑰簽名技術,私鑰只會保存在 Secure Enclave 內部,App,iOS系統都無法讀取。也就是說,即使App有漏洞,甚至iOS的沙盒被攻破了,大壞蛋還是無法獲取到私鑰偽裝用戶登錄。

相對而言,使用 Keychain Services 保存密碼,如果App/iOS被攻破了,大壞蛋就可能獲取到用戶密碼,從而偽裝用戶登錄。

看到過一些App有啟用指紋登錄的功能,但是啟用時都沒有提示用戶進行指紋驗證,直接就啟用了,顯然並沒有用上iPhone強大的硬體簽名能力。

Secure Enclave 的安全性

Secure Enclave 是非常安全的技術,可能是目前最安全的技術設計了,但並非絕對安全。

事實上,蘋果保留了從 Secure Enclave 讀取數據的能力,蘋果還可以通過系統更新來修改 Secure Enclave 中的系統。

發個硬廣

藍色空間努力把用戶的數據控制權還給用戶,出品的藍象安全雲無需註冊,無需密碼,由用戶保管加密密鑰,密鑰與手機設備綁定,安全可靠。

現已在蘋果應用商店上架,定價¥25獲得300GB/月,目前可以免費試用,歡迎大家下載嘗鮮。

itunes.apple.com/app/ap

參考

  • crackstation.net/hashin
  • en.wikipedia.org/wiki/M
  • en.wikipedia.org/wiki/C
  • en.wikipedia.org/wiki/S
  • en.wikipedia.org/wiki/S
  • project-rainbowcrack.com
  • support.apple.com/en-us
  • support.apple.com/en-us
  • developer.apple.com/sec
  • developer.apple.com/doc
  • developer.apple.com/lib
  • developer.apple.com/doc

*本文首發微信號藍象安全雲


推薦閱讀:
相關文章