活动 Web 页面人机识别验证的探索与实践
在電商行業(yè),線上的營銷活動(dòng)特別多。在移動(dòng)互聯(lián)網(wǎng)時(shí)代,一般為了活動(dòng)的快速上線和內(nèi)容的即時(shí)更新,大部分的業(yè)務(wù)場景仍然通過 Web 頁面來承載。但由于 Web 頁面天生“環(huán)境透明”,相較于移動(dòng)客戶端頁面在安全性上存在更大的挑戰(zhàn)。本文主要以移動(dòng)端 Web 頁面為基礎(chǔ)來講述如何提升頁面安全性。
活動(dòng) Web 頁面的安全挑戰(zhàn)
對(duì)于營銷活動(dòng)類的 Web 頁面,領(lǐng)券、領(lǐng)紅包、抽獎(jiǎng)等活動(dòng)方式很常見。此類活動(dòng)對(duì)于普通用戶來說大多數(shù)時(shí)候就是“拼手氣”,而對(duì)于非正常用戶來說,可以通過直接刷活動(dòng) API 接口的“作弊”方式來提升“手氣”。這樣的話,對(duì)普通用戶來說,就變得很不公平。
對(duì)于活動(dòng)運(yùn)營的主辦方來說,如果風(fēng)控措施做的不好,這類刷接口的“拼手氣”方式可能會(huì)對(duì)企業(yè)造成較大的損失。如本來計(jì)劃按 7 天發(fā)放的紅包,在上線 1 天就被刷光了,活動(dòng)的營銷成本就會(huì)被意外提升。主辦方想發(fā)放給用戶的滿減券、紅包,卻大部分被黃牛使用自動(dòng)腳本刷走,而真正想?yún)⑴c活動(dòng)的用,卻無法享受活動(dòng)優(yōu)惠。
終端用戶到底是人還是機(jī)器,網(wǎng)絡(luò)請(qǐng)求是否為真實(shí)用戶發(fā)起,是否存在安全漏洞并且已被“羊毛黨”惡意利用等等,這些都是運(yùn)營主辦方要擔(dān)心的問題。
安全防范的基本流程
為了提升活動(dòng) Web 頁面的安全性,通常會(huì)引入專業(yè)的風(fēng)控服務(wù)。引入風(fēng)控服務(wù)后,安全防護(hù)的流程大致如圖所示。
Web 前端:用戶通過 Web 頁面來參與活動(dòng),同時(shí) Web 前端也會(huì)收集用于人機(jī)識(shí)別驗(yàn)證的用戶交互行為數(shù)據(jù)。由于不同終端(移動(dòng)端 H5 頁面和 PC 端頁面)交互形式不同,收集用戶交互行為數(shù)據(jù)的側(cè)重點(diǎn)也會(huì)有所不同。
風(fēng)控服務(wù):一般大公司都會(huì)有專業(yè)的風(fēng)控團(tuán)隊(duì)來提供風(fēng)控服務(wù),在美團(tuán)內(nèi)部有智能反爬系統(tǒng)來基于地理位置、IP地址等大數(shù)據(jù)來提供頻次限制、黑白名單限制等常規(guī)的基礎(chǔ)風(fēng)控?cái)r截服務(wù)。甚至還有依托于海量的全業(yè)務(wù)場景的用戶大數(shù)據(jù),使用貝葉斯模型、神經(jīng)網(wǎng)絡(luò)等來構(gòu)建專業(yè)度較深的服務(wù)。風(fēng)控服務(wù)可以為 Web 前端提供通用的獨(dú)立驗(yàn)證 SDK:驗(yàn)證碼、滑塊驗(yàn)證等區(qū)分人機(jī)的“圖靈驗(yàn)證”,也可以為服務(wù)端提供 Web API 接口的驗(yàn)證等。
后端業(yè)務(wù)服務(wù):負(fù)責(zé)處理活動(dòng)業(yè)務(wù)邏輯,如給用戶發(fā)券、發(fā)紅包,處理用戶抽獎(jiǎng)等。請(qǐng)求需要經(jīng)過風(fēng)控服務(wù)的驗(yàn)證,確保其安全性,然后再來處理實(shí)際業(yè)務(wù)邏輯,通常,在處理完實(shí)際業(yè)務(wù)邏輯時(shí),還會(huì)有針對(duì)業(yè)務(wù)本身的風(fēng)控防范。
對(duì)于活動(dòng) Web 頁面來說,加入的風(fēng)控服務(wù)主要為了做人機(jī)識(shí)別驗(yàn)證。在人機(jī)識(shí)別驗(yàn)證的專業(yè)領(lǐng)域上,我們可以先看看業(yè)界巨頭 Google 是怎么做的。
Google 如何處理人機(jī)驗(yàn)證
Google 使用的人機(jī)驗(yàn)證服務(wù)是著名的 reCAPTCHA(Completely Automated Public Turing Test To Tell Computers and Humans Apart,區(qū)分人機(jī)的全自動(dòng)圖靈測試系統(tǒng)),也是應(yīng)用最廣的驗(yàn)證碼系統(tǒng)。早年的 reCAPTCHA 驗(yàn)證碼是這樣的:
如今的 reCAPTCHA 已經(jīng)不再需要人工輸入難以識(shí)別的字符,它會(huì)檢測用戶的終端環(huán)境,追蹤用戶的鼠標(biāo)軌跡,只需用戶點(diǎn)擊“我不是機(jī)器人”就能進(jìn)行人機(jī)驗(yàn)證(reCAPTCHA騙用戶進(jìn)行數(shù)據(jù)標(biāo)注而進(jìn)行AI訓(xùn)練的驗(yàn)證另說)。
reCAPTCHA 的驗(yàn)證方式從早先的輸入字符到現(xiàn)在的輕點(diǎn)按鈕,在用戶體驗(yàn)上,有了較大的提升。
而在活動(dòng)場景中引入人機(jī)識(shí)別驗(yàn)證,如果只是簡單粗暴地增加驗(yàn)證碼,或者只是像 reCAPTCHA 那樣增加點(diǎn)擊“我不是機(jī)器人”的驗(yàn)證,都會(huì)犧牲用戶體驗(yàn),降低用戶參加活動(dòng)的積極性。
Google 的普通 Web 頁面的瀏覽和有強(qiáng)交互的活動(dòng) Web 頁面雖是不同的業(yè)務(wù)場景,但對(duì)于活動(dòng) Web 頁面來說,強(qiáng)交互恰好為人機(jī)識(shí)別驗(yàn)證提供了用戶交互行為數(shù)據(jù)收集的契機(jī)。
人機(jī)識(shí)別驗(yàn)證的技術(shù)挑戰(zhàn)
理想的方案是在用戶無感知的情況下做人機(jī)識(shí)別驗(yàn)證,這樣既確保了安全又對(duì)用戶體驗(yàn)無損傷。
從實(shí)際的業(yè)務(wù)場景出發(fā)再結(jié)合 Web 本身的環(huán)境,如果想實(shí)現(xiàn)理想的方案,可能會(huì)面臨如下的技術(shù)挑戰(zhàn):
- (1)需要根據(jù)用戶的使用場景來定制人機(jī)識(shí)別驗(yàn)證的算法:Web 前端負(fù)責(zé)收集、上報(bào)用戶交互行為數(shù)據(jù),風(fēng)控服務(wù)端校驗(yàn)上報(bào)的數(shù)據(jù)是否符合正常的用戶行為邏輯。
- (2)確保 Web 前端和風(fēng)控服務(wù)端之間通信和數(shù)據(jù)傳輸?shù)陌踩浴?/li>
- (3)確保上述兩大挑戰(zhàn)中提到的邏輯和算法不會(huì)被代碼反編譯來破解。
在上述的三個(gè)挑戰(zhàn)中,(1)已經(jīng)實(shí)現(xiàn)了人機(jī)識(shí)別驗(yàn)證的功能,而(2)和(3)都是為了確保人機(jī)識(shí)別驗(yàn)證不被破解而做的安全防范。接下來,本文會(huì)分別針對(duì)這三個(gè)技術(shù)挑戰(zhàn)來說明如何設(shè)計(jì)技術(shù)方案。
挑戰(zhàn)一:根據(jù)用戶使用場景來定制人機(jī)識(shí)別驗(yàn)證算法
先來分析一下用戶的使用場景,正常用戶參與活動(dòng)的步驟是用戶進(jìn)入活動(dòng)頁面后,會(huì)有短暫的停留,然后點(diǎn)擊按鈕參與活動(dòng)。這里所說的“參與活動(dòng)”,最終都會(huì)在活動(dòng)頁面發(fā)起一個(gè)接口的請(qǐng)求。如果是非正常用戶,可以直接跳過以上的實(shí)際動(dòng)作而去直接請(qǐng)求參與活動(dòng)的接口。
那么區(qū)別于正常用戶和非正常用戶就是那些被跳過的動(dòng)作,對(duì)實(shí)際動(dòng)作進(jìn)一步歸納如下:
以上的動(dòng)作又可以分為必需的操作和可選的操作。對(duì)這一連串動(dòng)作產(chǎn)生的日志數(shù)據(jù)進(jìn)行收集,在請(qǐng)求參與活動(dòng)的接口時(shí),將這些數(shù)據(jù)提交至后端,驗(yàn)證其合法性。這就是一個(gè)簡單的人機(jī)識(shí)別驗(yàn)證。
在驗(yàn)證動(dòng)作的合法性時(shí),需要考慮到這些動(dòng)作數(shù)據(jù)是不是能被輕易模擬。另外,動(dòng)作的發(fā)生應(yīng)該有一條時(shí)間線,可以給每個(gè)動(dòng)作都增加一個(gè)時(shí)間戳,比如點(diǎn)擊按鈕肯定是在進(jìn)入頁面之后發(fā)生的。
一些特定的動(dòng)作的日志數(shù)據(jù)也會(huì)有合理的區(qū)間,進(jìn)入頁面的動(dòng)作如果以 JS 資源加載的時(shí)間為基準(zhǔn),那么加載時(shí)間可能大于 100 毫秒,小于 5 秒。而對(duì)于移動(dòng)端的按鈕點(diǎn)擊,點(diǎn)擊時(shí)記錄的坐標(biāo)值也會(huì)有對(duì)應(yīng)的合理區(qū)間,這些合理的區(qū)間會(huì)根據(jù)實(shí)際的環(huán)境和情況來進(jìn)行設(shè)置。
除此之外,設(shè)備環(huán)境的數(shù)據(jù)也可以進(jìn)行收集,包括用戶參與活動(dòng)時(shí)使用的終端類型、瀏覽器的類型、瀏覽器是否為客戶端的容器等,如果使用了客戶端,客戶端是否會(huì)攜帶特殊的標(biāo)識(shí)等。
最后,還可以收集一些“無效”的數(shù)據(jù),這些數(shù)據(jù)用于障人耳目,驗(yàn)證算法會(huì)將其忽略。盡管收集數(shù)據(jù)的動(dòng)作是透明的,但是驗(yàn)證數(shù)據(jù)合法性不是透明的,攻擊者無法知道,驗(yàn)證的算法中怎么區(qū)分哪些是有效、哪些是無效。這已經(jīng)有點(diǎn)“蜜罐數(shù)據(jù)”的意思了。
挑戰(zhàn)二:確保通信的安全性
收集的敏感數(shù)據(jù)要發(fā)送給風(fēng)控服務(wù)端,進(jìn)而確保通信過程的安全。
Token 的設(shè)計(jì)
Token 是一個(gè)簡短的字符串,主要為了確保通信的安全。用戶進(jìn)入活動(dòng) Web 頁面后,請(qǐng)求參與活動(dòng)的接口之前,會(huì)從服務(wù)端獲取 Token。該 Token 的生成算法要確保 Token 的唯一性,通過接口或 Cookie 傳遞給前端,然后,前端在真正請(qǐng)求參與活動(dòng)的接口時(shí)需要帶上該 Token,風(fēng)控服務(wù)端需要驗(yàn)證 Token 的合法性。也就是說,Token 由服務(wù)端生成,傳給前端,前端再原封不動(dòng)的回傳給服務(wù)端。一旦加入了 Token 的步驟,攻擊者就不能直接去請(qǐng)求參與活動(dòng)的接口了。
Token 由風(fēng)控服務(wù)端基于用戶的身份,根據(jù)一定的算法來生成,無法偽造,為了提升安全等級(jí),Token 需要具有時(shí)效性,比如 10 分鐘。可以使用 Redis 這類緩存服務(wù)來存儲(chǔ) Token,使用用戶身份標(biāo)識(shí)和 Token 建立 KV 映射表,并設(shè)置過期時(shí)間為 10 分鐘。
雖然前端在 Cookie 中可以獲取到 Token,但是前端不能對(duì) Token 做持久化的緩存。一旦在 Cookie 中獲取到了 Token,那么前端可以立即從 Cookie 中刪除該 Token,這樣能盡量確保 Token 的安全性和時(shí)效性。Token 存儲(chǔ)在 Redis 中,也不會(huì)因?yàn)橛脩粼趨⑴c活動(dòng)時(shí)頻繁的切換頁面請(qǐng)求,而對(duì)服務(wù)造成太大的壓力。
另外,Token 還可以有更多的用處:
- 標(biāo)識(shí)參與活動(dòng)用戶的有效性。
- 敏感數(shù)據(jù)對(duì)稱加密時(shí)生成動(dòng)態(tài)密鑰。
- API 接口的數(shù)字簽名。
敏感數(shù)據(jù)加密
通信時(shí),傳遞的敏感數(shù)據(jù)可以使用常見的對(duì)稱加密算法進(jìn)行加密。
為了提升加密的安全等級(jí),加密時(shí)的密鑰可以動(dòng)態(tài)生成,前端和風(fēng)控服務(wù)端約定好動(dòng)態(tài)密鑰的生成規(guī)則即可。加密的算法和密鑰也要確保不被暴露。
通過對(duì)敏感數(shù)據(jù)加密,攻擊者在不了解敏感數(shù)據(jù)內(nèi)容的前提下就更別提模擬構(gòu)造請(qǐng)求內(nèi)容了。
挑戰(zhàn)三:化解紙老虎的尷尬
有經(jīng)驗(yàn)的 Web 開發(fā)者看到這里,可能已經(jīng)開始質(zhì)疑了:在透明的前端環(huán)境中折騰安全不是白折騰嗎?這就好比費(fèi)了很大的勁卻只是造了一個(gè)“紙老虎”,質(zhì)疑是有道理的,但是且慢,通過一些安全機(jī)制的加強(qiáng)是可以讓“紙老虎”盡可能的逼真。
本文一再提及的 Web 環(huán)境的透明性,是因?yàn)樵趯?shí)際的生產(chǎn)環(huán)境中的問題:前端的代碼在壓縮后,通過使用瀏覽器自帶的格式化工具和斷點(diǎn)工具,仍然具備一定的可讀性,花點(diǎn)時(shí)間仍然可以理解代碼的邏輯,這就給攻擊者提供了大好的代碼反編譯機(jī)會(huì)。
如果要化解“紙老虎”的尷尬,就要對(duì)前端的代碼進(jìn)行混淆。
前端代碼混淆
前端的 JS 代碼壓縮工具基本都是對(duì)變量、函數(shù)名稱等進(jìn)行縮短,壓縮對(duì)于混淆的作用是比較弱。除了對(duì)代碼進(jìn)行壓縮,還需要進(jìn)行專門的混淆。
對(duì)代碼進(jìn)行混淆可以降低可讀性,混淆工具有條件的話最好自研,開源的工具要慎用。或者基于 Uglify.js 來自定義混淆的規(guī)則,混淆程度越高可讀性就越低。
代碼混淆也需要把握一個(gè)度,太復(fù)雜的混淆可能會(huì)讓代碼無法運(yùn)行,也有可能會(huì)影響本身的執(zhí)行效率。同時(shí)還需要兼顧混淆后的代碼體積,混淆前后的體積不能有太大的差距,合理的混淆程度很重要。
斷點(diǎn)工具的防范會(huì)更麻煩些。在使用斷點(diǎn)工具時(shí)通常都會(huì)導(dǎo)致代碼延遲執(zhí)行,而正常的業(yè)務(wù)邏輯都會(huì)立即執(zhí)行,這是一個(gè)可以利用的點(diǎn),可以考慮在代碼執(zhí)行間隔上來防范斷點(diǎn)工具。
通過代碼混淆和對(duì)代碼進(jìn)行特殊的處理,可以讓格式化工具和斷點(diǎn)工具變得沒有用武之地。唯一有些小遺憾,就是處理后的代碼也不能正常使用 Source Map 的功能了。
有了代碼混淆,反編譯的成本會(huì)非常高,這樣“紙老虎”已經(jīng)變得很逼真了。
技術(shù)方案設(shè)計(jì)
在講解完如何解決關(guān)鍵的技術(shù)挑戰(zhàn)后,就可以把相應(yīng)的方案串起來,然后設(shè)計(jì)成一套可以實(shí)施的技術(shù)方案了。相對(duì)理想的技術(shù)方案架構(gòu)圖如下:
下面會(huì)按步驟來講解技術(shù)方案的處理流程:
Step 0 基礎(chǔ)風(fēng)控?cái)r截
基礎(chǔ)風(fēng)控?cái)r截是上面提到的頻次、名單等的攔截限制,在 Nginx 層就能直接實(shí)施攔截。如果發(fā)現(xiàn)是惡意請(qǐng)求,直接將請(qǐng)求過濾返回 403,這是初步的攔截,用戶在請(qǐng)求 Web 頁面的時(shí)候就開始起作用了。
Step 1 風(fēng)控服務(wù)端生成 Token 后傳給前端
Step 0 可能還沒進(jìn)入到活動(dòng) Web 頁面,進(jìn)入活動(dòng) Web 頁面后才真正開始人機(jī)識(shí)別驗(yàn)證的流程,前端會(huì)先開始獲取 Token。
Step 2 前端生成敏感數(shù)據(jù)
敏感數(shù)據(jù)應(yīng)包含用戶交互行為數(shù)據(jù)、設(shè)備環(huán)境數(shù)據(jù)、活動(dòng)業(yè)務(wù)邏輯數(shù)據(jù)以及無效數(shù)據(jù)。
Step 3 使用 HTTPS 的簽名接口發(fā)送數(shù)據(jù)
Token 可以作為 Authorization 的值添加到 Header 中,數(shù)據(jù)接口的簽名可以有效防止 CSRF 的攻擊。
Step 4 數(shù)據(jù)接口的校驗(yàn)
風(fēng)控服務(wù)端收到請(qǐng)求后,會(huì)先驗(yàn)證數(shù)據(jù)接口簽名中的 Token 是否有效。驗(yàn)證完 Token,才會(huì)對(duì)敏感數(shù)據(jù)進(jìn)行解密。數(shù)據(jù)解密成功,再進(jìn)一步對(duì)人機(jī)識(shí)別的數(shù)據(jù)合法性進(jìn)行校驗(yàn)。
Step 5 業(yè)務(wù)邏輯的處理
前面的步驟為了做人機(jī)識(shí)別驗(yàn)證,這些驗(yàn)證不涉及到業(yè)務(wù)邏輯。在所有這些驗(yàn)證都通過后,后端業(yè)務(wù)服務(wù)才會(huì)開始處理實(shí)際的活動(dòng)業(yè)務(wù)邏輯。處理完活動(dòng)業(yè)務(wù)邏輯,最終才會(huì)返回用戶參與活動(dòng)的結(jié)果。
總結(jié)
為了提升活動(dòng) Web 頁面的安全性,使用了各種各樣的技術(shù)方案,我們將這些技術(shù)方案組合起來才能發(fā)揮安全防范的作用,如果其中某個(gè)環(huán)節(jié)處理不當(dāng),都可能會(huì)被當(dāng)作漏洞來利用,從而導(dǎo)致整個(gè)驗(yàn)證方案被攻破。
為了驗(yàn)證技術(shù)方案的有效性,可以持續(xù)觀察活動(dòng) API 接口的請(qǐng)求成功率。從請(qǐng)求成功率的數(shù)據(jù)中進(jìn)一步分析“誤傷”和“攔截”的數(shù)據(jù),以進(jìn)一步確定是否要對(duì)方案進(jìn)行調(diào)優(yōu)。
通過上述的人機(jī)識(shí)別驗(yàn)證的組合方案,可以大幅提升活動(dòng) Web 頁面的安全性。在活動(dòng) Web 頁面應(yīng)作為一個(gè)標(biāo)準(zhǔn)化的安全防范流程,除了美團(tuán),像淘寶和天貓也有類似的流程。由于活動(dòng)運(yùn)營的環(huán)節(jié)和方法多且復(fù)雜,僅僅提升了 Web 頁面也不敢保證就是鐵板一塊,安全需要關(guān)注的環(huán)節(jié)還很多,安全攻防是一項(xiàng)長期的“拉鋸升級(jí)戰(zhàn)”,安全防范措施也需要持續(xù)地優(yōu)化升級(jí)。
參考資料
- https://www.google.com/recaptcha/intro/v3.html
- https://segmentfault.com/a/1190000006226236
- https://www.freebuf.com/articles/web/102269.html
作者簡介
益國,美團(tuán)點(diǎn)評(píng) Web 前端開發(fā)工程師。2015年加入美團(tuán),曾先后負(fù)責(zé)過風(fēng)控前端SDK和活動(dòng)運(yùn)營平臺(tái)的研發(fā),現(xiàn)負(fù)責(zé)大數(shù)據(jù)平臺(tái)的研發(fā)工作。
總結(jié)
以上是生活随笔為你收集整理的活动 Web 页面人机识别验证的探索与实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新天猫Java3轮面试题目:虚拟机+并
- 下一篇: Solr Facet技术的应用与研究