轉載自 https://abcdabcd987.com/qrcode-login/
昨天在知乎上看到了一個問題微信淘寶設計掃碼登錄的理由是什么,犧牲人性化來加強安全性?,本以為這是一個送分題,可是點開一看,竟然我仰慕的高票答主回答並沒有給出我期望的回答,還有許多我關注的大大們點了贊。再一看,下面一排都在無腦噴阿里和騰訊,一點都沒有認真答題的意思,氣得我一個個點了反對+沒有幫助。終於看到了一個@陳裕皓 寫的正常的答案,幾乎感動得我熱淚盈眶。其實我覺得他基本上把我能說的話都說了,不過我還是看熱鬧不嫌事大,再插一腳進來科普科普吧。
嫌太長不想看的直接翻到最后的“總結”部分吧。
登入網站是如何工作的?
先科普一下最簡單的登入一個網站的過程是怎樣的吧。
- 當你的瀏覽器第一次訪問一個網站的時候,這個網站會分配給你一個會話(Session)。
- 會話的信息都是存在服務器上的,也就是服務器有個自己的小本子記錄了會話的信息。
- 服務器會把
session_id
返回給你的瀏覽器 - 之后每一次你訪問這個網站的任何頁面,你的瀏覽器都會把這個
session_id
發給服務器 - 服務器根據這個
session_id
就可以分辨不同的會話,同時,前面說了,也只有服務器自己知道和這個會話相關的任何信息
- 在還未登入的時候,服務器看到你這個
session_id
對應的會話里面寫着“還沒有登入”,於是就給你展示了游客的內容。 - 你進入了網站的登入界面,填寫了賬號密碼,點擊登入。
- 你的瀏覽器把你的賬號密碼發送到了服務器。
- 服務器從數據庫里面查了查,發現你的賬號密碼是匹配的。於是服務器給
session_id
對應的會話設置了新的信息,比如“已登入、用戶ID……” - 之后你再訪問這個網站,你的瀏覽器還是把同樣的
session_id
發給服務器。服務器查一查自己的小本子,發現噢這個會話已經登入了,並且用戶ID是多少多少。於是就把屬於這個用戶(也就是你)的信息展示給你。
這里順帶提一下,session_id
在瀏覽器這里的具體表現形式就是 Cookie 里的一個鍵值對。
掃碼登入是如何工作的?
回顧一下,其實站在用戶瀏覽器這邊,基本上沒什么事情好做。每次都只是拿着第一次訪問服務器的時候服務器分配的 session_id
傻乎乎地去戳服務器,然后把服務器返回的信息呈現給用戶。而服務器這邊,每次都是根據會話信息的不同來決定返回什么內容給瀏覽器。
所以說,重點在於讓服務器把會話信息改成已登入的信息。你想要讓服務器把你的會話信息改掉,你總不能空口無憑吧?不然你不就可以進入任何人的淘寶了嗎。在前面的例子里面,讓服務器相信你就是用戶本身的方法就是驗證你的賬號密碼。掃碼登入其實就是換了一種讓服務器相信你確實就是你的方式。
作為一個(自稱)全棧工程師,掃碼登入是怎么工作的還是很容易想到的:
- 用戶打開登入頁面的時候,他的瀏覽器與服務器產生了一個會話。服務器分配給他一個
login_token
並記下它對應的會話session_id
,這個login_token
會作為某個驗證登入的網址qr_verify_url
的一個參數。讓用戶輸入一大串網址太麻煩了,於是服務器把qr_verify_url
這個網址用二維碼包裝一下呈現給用戶。 - 用戶用已經登入了的該網站自家的手機APP掃描二維碼,得到一個
qr_verify_url
。- 這里要注意的是,掃描這個二維碼的軟件不能是隨隨便便的APP,必須是這個網站自家的APP。
- 強調自家手機APP已經登入,說明手機APP上有一個服務器頒發的
app_token
。
- 手機APP彈出提示,告訴用戶這是一個登入請求,如果確認是本人的操作,那么點擊登入按鈕。
- 點擊了登入按鈕之后,手機APP訪問拿着
login_token
和app_token
這兩個令牌去訪問qr_verify_url
。 - 服務器收到了請求,發現
app_token
和login_token
都是有效的,於是找到login_token
對應的session_id
。接下來的步驟就和正常登入一樣了,往這個session_id
對應的會話里面寫信息,比如說:登入成功、用戶ID…… - 用戶的瀏覽器在這整個過程期間其實都在不斷詢問服務器:我這個會話
session_id
登入成功了嗎?沒有的話,就等一會兒再問一次。一旦服務器告訴它,登入成功了,瀏覽器就跳轉到別的頁面,結束了登入流程。 - 這個時候因為服務器已經給會話
session_id
設置了相應的信息,所以服務器知道用戶已經登入了,於是返回給用戶的頁面都是登入后的結果。
舉個例子
以登入淘寶為例。在登入界面看到了一個大大的二維碼。
我們先不着急用手機淘寶掃它,我們先用在線二維碼閱讀器看看這個二維碼里面寫着什么。
可以看到這是一個短鏈接。我們繼續看看這個短鏈接里面是什么內容。
里面的“目標地址”就是前面說的 qr_verify_url
。紅色框出來的就是 login_token
。值得注意的是,這個 login_token
和我們瀏覽器中的 login_token
是相同的。順帶提一下 session_id
就是訪問服務器的時候那一大串的 Cookie 里面的一部分。
現在讓我們用手機掃一掃二維碼。掃描完了之后會有安全提示。點擊確認登入,然后我們就開心地登入了。
引入新的隱患?
知道了這個登入的流程,我們不妨站在攻擊者的角度考慮一下有沒有什么空子可以鑽。在這里,我想說明的是,就算沒有提升安全性,掃碼登入相比起傳統密碼登入也沒有引入新的安全隱患。
替換二維碼(中間人攻擊)
- 攻擊者用自己的瀏覽器訪問登入頁面,得到一個二維碼
- 攻擊者用某種方法劫持用戶流量,當用戶打開登入頁面時,將二維碼替換成自己的二維碼
- 用戶掃描二維碼,並且用戶並不知道這個二維碼不是服務器給的而是攻擊者替換過的,於是點了確認登入
- 攻擊者成功登入
這是最容易想到的攻擊方式。不過這種攻擊方式放在今天,尤其是大網站的情況下,幾乎不可能發生。現在大網站的登入頁面基本上都采用了 https
協議,相比起普通的 http
協議,https
流量都是加密的。並且以現在計算機乃至超級計算機的算力,想要破解是幾乎不可能的。
也就是說,黑客完全不知道你訪問了登入頁面,更不用說在登入頁面上做手腳了。這條路行不通。
替換二維碼(惡意瀏覽器插件或者病毒)
- 用戶不小心安裝了惡意的瀏覽器插件或者中了病毒
- 登入頁面的二維碼在本地被替換為攻擊者的二維碼
- 中招
這個方法可行。但是,這並不是把密碼登入換成掃碼登入帶來的問題。用密碼登入同樣也會遇到這樣的問題:病毒可以把登入頁面替換成攻擊者的釣魚網站,或者直接把用戶密碼發送給攻擊者……
二維碼公開地顯示在屏幕上被別人掃走
(黑人問號臉???)那不是你就登入了攻擊者的賬號嗎,你不虧啊,而且為啥攻擊者要送呢?
主動跳進坑里
- 攻擊者在朋友圈貼了一個二維碼
- 你掃描,強行忽略“請確認是本人登入”的字樣,看到那個大大的按鈕就是很想按下去
- 中招
你硬要把錢塞給我,我也沒法不要呀 ╮(╯_╰)╭
另外,從技術上來說,也是困難的。像淘寶的登入二維碼過期速度飛快,似乎一分鍾就過期了(我前面幾張圖截圖慢了點,於是二維碼過期 token 對不上了,只好再全部重新截圖一次)。那么問題來了,這個攻擊者人氣得多高才能在發完朋友圈的一分鍾之內立馬有人掃碼登入呢?
手機丟了被別人撿走
所以說攻擊者撿到了你的手機之后,打開淘寶登入頁面,心想“哈哈哈,我不用密碼就能登入了。”於是在你的手機上打開了手機淘寶,掃碼登入……
(黑人問號臉???)攻擊者為啥不直接用你的手機淘寶啊?這並不是把密碼登入換成掃碼登入帶來的問題,本來手機丟了之后就會有很直接的安全問題,還輪不到掃描登入來背鍋。
掃碼進入惡意網站
- 攻擊者制作一個誘人的廣告或者(克服重重困難)以某種方式替換了登入二維碼,指向某惡意網站
- 掃碼中招
你掃了碼,然后發現沒有一個讓你點擊“確認登入”的地方,你還會繼續嗎?
就算攻擊者做了一個長得一模一樣的惡意網站,騙你點擊“確認登入”。可是手機淘寶發現這個網站不是來自 taobao.com
,於是就不會把手機上的 app_token
發出去。所以攻擊者什么都得不到。
掃碼下載病毒
- 攻擊者制作一個誘人的廣告或者(克服重重困難)以某種方式替換了登入二維碼,指向某惡意軟件下載地址
- 掃碼中招
這個是掃碼本身的問題,不是掃碼登入帶來的。掃碼登入的時候彈出了一個下載,你不會覺得很奇怪嗎?怎么還會繼續下載、運行病毒呢?
破解手機APP
- 攻擊者通過某種方式進入了你的手機(可能是遠程地),破解了手機淘寶
- 找到了手機淘寶保存在本地的
app_token
- 拿着
app_token
偽裝是你本人操作,發送登入確認信息
對攻擊者來說,這里變數非常多,這三點都是很困難的。
- 在不接觸你的手機的情況下要進入你的手機、然后獲得非常高的權限,這很困難。
- 數據加密。要找到正確的解密方式需要一番波折。
- 發送給服務器的信息可能非常多,即還需要搞定別的驗證信息。
而且這些問題都是手機APP原先就可能存在的安全隱患,和掃碼登入無關。
掃碼登入帶來的些許好處
避免密碼泄露
在不考慮電腦中毒的情況下,輸入密碼也有可能被攻擊者肉眼看到或者拍攝到。而掃碼登入,盡管二維碼是公開的,但只有你自己用手機APP掃描才有用。
原先的核心驗證信息是賬號密碼,是暴露在外界的。現在的核心驗證信息變成了手機里的 app_token
,而這是外界看不到的,只有手機APP自己知道。就這點來說,安全性確實提高了。
用專用令牌替換通用令牌
許多人都會用同樣的密碼登入不同的網站,這樣一旦任何一個網站被攻破,攻擊者拿到了你的密碼,他就可以嘗試並成功登入其他網站。
而掃碼登入的話,就算攻擊者拿到了 app_token
,也找到了偽造請求的正確方法,他也只能登入一個網站,對其他網站束手無策。
用短期令牌替換長期令牌
用戶名密碼可以看成是過期時間無窮或者非常大的令牌(畢竟修改密碼的頻率很低,甚至大多數人是不會去修改密碼的)。掃碼登入的二維碼有效期非常短(比如一分鍾)。手機APP上的 app_token
也可以設計成快速過期(比如半個月不打開手機APP則失效),也可以吊銷(“刪除該設備”)。
短期令牌總是不比長期令牌糟糕的。
便捷性
很多人其實是記不住自己的密碼的,每次登入總要試個半天,或者有的人密碼很復雜然后打字又慢,這個時候掃一掃就能登入難道不是很誘人的選擇嗎?
理想很豐滿
現實卻很骨感。上面說了這么多的好(或者說起碼不差),這都是建立在一些前提上的,一旦這些前提不滿足,攻擊者就能從很多角度攻擊。
沒有完全強制 HTTPS
舉幾個例子:
- 攻擊者迫使用戶使用 HTTP 進行連接
- CDN 部署有問題,導致 HTTPS 降級,二維碼被替換
- 服務器沒有使用 HSTS,允許夾雜 HTTP 協議的內容,攻擊者趁機在 HTTP 訪問的 Javascript 腳本中插入惡意代碼
程序邏輯漏洞
舉幾個例子:
- 手機APP沒有驗證頁面來自自家服務器,就把
app_token
發了出去 - 手機APP沒有強制使用 HTTPS 連接自家服務器
- 二維碼過期時間過長
用戶自身素質問題
舉幾個例子:
- 容易使得自己的電腦/手機中毒
- 輕易被攻擊者引導
- 掃碼自動下載並運行了病毒的安裝程序,竟然還主動點擊“安裝”
- 不看提示,無腦點擊,主動把自己賣了
總結
在我看來,掃碼登入比起密碼登入並沒有引入新的安全隱患,甚至從側面提高了一定的安全性。但是這需要廠商、用戶共同努力。廠商不能犯低級錯誤,用戶要提高自身素質。這難嗎?
盡管大家非常喜歡抨擊BAT,但是還是要相信大廠的安全人員還是不會犯低級錯誤的。
用戶方面,只要廠商把自己的事情做好了,用戶的素質並需要多高。另外,隨着這些科技不斷深入日常生活,用戶素質也會逐漸提高的。