前端 JS 安全對抗原理與實踐
作者:vivo 網際網路安全團隊- Luo Bingsong
前端程式碼都是公開的,為了提高程式碼的破jie成本、保證JS程式碼裡的一些重要邏輯不被居心叵測的人利用,需要使用一些加密和混淆的防護手段。
一、概念解析
1.1 什麼是介面加密
如今這個時代,資料已經變得越來越重要,網頁和APP是主流的資料載體,如果獲取資料的介面沒有設定任何的保護措施的話,資料就會被輕易地竊取或篡改。
除了資料洩露外,一些重要功能的介面如果沒有做好保護措施也會被惡意呼叫造成DDoS、條件競爭等攻擊效果,比如如下幾個場景:
一些營銷活動類的Web頁面,領紅包、領券、投票、抽獎等活動方式很常見。此類活動對於普通使用者來說應該是“拼手氣”,而對於非正常使用者來說,可以透過直接刷活動API介面的這種“作弊”方式來提升“手氣”。這樣對普通使用者來說就很不公平。
所以對重要介面都會採用加密驗籤的方式進行保護,而驗籤的加密邏輯大多數都透過JS程式碼實現,所以保護JS程式碼不被攻擊者竊取尤為重要。
1.2 為什麼要保護JS程式碼
-
JavaScript程式碼執行於客戶端
-
JavaScript程式碼是公開透明的
由於這兩個原因,致使JavaScript程式碼是不安全的,任何人都可以讀、分析、複製、盜用甚至篡改。
1.3 應用場景
以下場景就透過特定的防護措施提高了攻擊成本:
-
某些網站會在頁面中使用JavaScript對資料進行加密,以保護資料的安全性和隱私性,在爬取時需要透過解密JavaScript程式碼才能獲取到資料。
-
某些網站的URL會有某個引數帶有一些看不太懂的長串加密引數,攻擊者要爬取的話就必須要知道這些引數是怎麼構造的,否則無法正確地訪問該URL。
-
翻看網站的JavaScript原始碼,可以發現很多壓縮了或者看不太懂的字元,比如JavaScript檔名被編碼,JavaScript的檔案內容都壓縮成幾行,JavaScript變數也被修改成單個字元或者一些十六進位制的字元,所以我們不能輕易地根據JavaScript找出某些介面的加密邏輯。
1.4 涉及的技術
這些場景都是網站為了保護資料不被輕易抓取採取的措施,運用的技術主要有:
-
介面加密技術
-
JavaScript壓縮、混淆和加密技術
二、技術原理
2.1 介面加密技術
資料和功能一般是透過伺服器提供的介面來實現,為了提升介面的安全性,客戶端會和服務端約定一種介面檢驗方式,通常是各種加密和編碼演算法,如Base64、Hex、MD5、AES、DES、RSA等。
常用的資料介面都會攜帶一個sign引數用於許可權管控:
① 客戶端和服務端約定一種介面校驗邏輯,客戶端在每次請求服務端介面的時候附帶一個sign引數。② sign引數的邏輯自定義,可以由當前時間戳資訊、裝置ID、日期、雙方約定好的秘鑰經過一些加密演算法構造而成。③ 客戶端根據約定的加密演算法構造sign,每次請求伺服器的時候附帶上sign數。④ 服務端根據約定的加密演算法和請求的資料對sign進行校驗,如果檢驗透過,才返回資料,否則拒絕響應。
這就是一個比較簡單的介面引數加密的實現,如果有人想要呼叫這個介面的話,必須要破解sign的生成邏輯,否則是無法正常呼叫介面的。
當然上面的實現思路比較簡單,還可以增加一些時間戳資訊和訪問頻次來增加時效性判斷,或使用非對稱加密提高加密的複雜程度。
實現介面引數加密需要用到一些加密演算法,客戶端和伺服器都有對應的SDK來實現這些加密演算法,如JavaScript的crypto-js、Python的hashlib、Crypto等等。如果是網頁且客戶端的加密邏輯是用JavaScript來實現的話,其原始碼對使用者是完全可見的,所以我們需要用壓縮、混淆、加密的方式來對JavaScript程式碼進行一定程度的保護。
2.2 什麼是壓縮
去除JavaScript程式碼中不必要的空格、換行等內容,使原始碼都壓縮為幾行內容,降低程式碼可讀性,同時可提高網站的載入速度。
如果僅僅是去除空格換行這樣的壓縮方式,幾乎沒有任何防護作用,這種壓縮方式僅僅是降低了程式碼的直接可讀性,可以用IDE、線上工具或Chrome輕鬆將JavaScript程式碼變得易讀。
所以JavaScript壓縮技術只能在很小的程度上起到防護作用,想提高防護的效果還得依靠JavaScript混淆和加密技術。
2.3 什麼是混淆
使用變數混淆、字串混淆、屬性加密、控制流平坦化、除錯保護、多型變異等手段,使程式碼變得難以閱讀和分析,同時不影響程式碼原有功能,是一種理想且實用的JS保護方案。
-
變數混淆:將變數名、方法名、常量名隨機變為無意義的亂碼字串,降低程式碼可讀性,如轉成單個字元或十六進位制字串。
-
字串混淆:將字串陣列化集中放置,並進行MD5或Base64編碼儲存,使程式碼中不出現明文字串,可以避免使用全域性搜尋字串的方式定位到入口點。
-
屬性加密:針對JavaScript物件的屬性進行加密轉化,隱藏程式碼之間的呼叫關係,把key-value的對映關係混淆掉。
-
控制流平坦化:打亂函式原有程式碼執行流程及函式呼叫關係,使程式碼邏輯變得混亂無序。
-
除錯保護:基於偵錯程式特性,加入一些強制除錯debug語句,無限debug、定時debug、debug關鍵字,使其在除錯模式下難以順利執行JavaScript程式碼。
-
多型變異:JavaScript程式碼每次被呼叫時,程式碼自身立刻自動發生變異,變化為與之前完全不同的程式碼,避免程式碼被動態分析除錯。
2.4 什麼是加密
JavaScript加密是對JavaScript混淆技術防護的進一步升級,基本思路是將一些核心邏輯用C/C++語言來編寫,並透過JavaScript呼叫執行,從而起到二進位制級別的防護作用,加密的方式主要有Emscripten和WebAssembly等。
1. Emscripten
Emscripten編譯器可以將C/C++程式碼編譯成asm.js的JavaScript變體,再由JavaScript呼叫執行,因此某些JavaScript的核心功能可以使用C/C++語言實現。
2.WebAssembly
WebAssembly也能將C/C++程式碼轉成JavaScript引擎可以執行的程式碼,但轉出來的程式碼是二進位制位元組碼,而asm.js是文字,因此執行速度更快、體積更小,得到的位元組碼具有和JavaScript相同的功能,在語法上完全脫離JavaScript,同時具有沙盒化的執行環境,利用WebAssembly技術,可以將一些核心的功能用C/C++語言實現,形成瀏覽器位元組碼的形式,然後在JavaScript中透過類似如下的方式呼叫:
這種加密方式更加安全,想要逆向或破解需要逆向WebAssembly,難度極大。
2.5 工具介紹
2.5.1 壓縮混淆工具
-
(開源):
用NodeJS編寫的JavaScript壓縮工具,是目前zui流行的JS壓縮工具,JQuery就是使用此工具壓縮,UglifyJS壓縮率高,壓縮選項多,並且具有最佳化程式碼,格式化程式碼功能。
-
:
jshaman是一個商業級工具,看了很多社群的評論,這個目前是最好的,可以線上免費使用,也可以購買商業版。
-
:
開源的js混淆工具,原理比較簡單,透過特定的字串加上下標定位字元,再由這些字元替換原始碼,從而實現混淆。
-
:
業界巨頭yahoo提供的一個前端壓縮工具,透過java庫編譯css或js檔案進行壓縮
2.5.2 反混淆工具
-
:
jsbeautifier是一個為前端開發人員製作的Chrome擴充套件,能夠直接檢視經過壓縮的Javascript程式碼。
-
:
壓縮工具uglify對應的解混淆工具。
-
:
用PHP編寫的壓縮工具,可以混淆程式碼保護智慧財產權,產生的程式碼相容IE、FireFox等常用瀏覽器,國內大部分線上工具網站都採用這種演算法壓縮。
三、前端安全對抗
3.1 前端除錯手法
3.1.1 Elements
Elements 皮膚會顯示目前網頁中的 DOM、CSS 狀態,且可以修改頁面上的 DOM 和 CSS,即時看到結果,省去了在編輯器修改、儲存、瀏覽器檢視結果的流程。
有時候一些dom節點會巢狀很深,導致我們很難利用Element皮膚html程式碼來找到對應的節點。inspect(dom元素)可以讓我們快速跳轉到對應的dom節點的html程式碼上。
3.1.2 Console
Console物件提供了瀏覽器控制檯除錯的介面,Console是一個物件,上面有很多方便的方法。
-
console.log( ):最常用的語句,可以將變數輸出到瀏覽器的控制檯中,方便開發者呼叫JS程式碼
-
console.table( ):可用於列印obj/arr成表格
-
console.trace( ):可用於debugger堆疊除錯,方便檢視程式碼的執行邏輯,看一些庫的原始碼
-
console.count( ):列印標籤被執行了幾次,預設值是default,可用在快速計數
-
console.countReset( ):用來重置,可用在計算單次行為的觸發的計數
-
console.group( )/console.groupEnd( ):為了方便一眼看到自己的log,可以用console.group自定義message group標籤,還可以多層巢狀,並用console.groupEnd來關閉Group。
3.1.3 JS斷點除錯
JS斷點除錯,即在瀏覽器開發者工具中為JS程式碼新增斷點,讓JS執行到某一特定位置停住,方便開發者對該處程式碼段進行分析與邏輯處理。
Sources皮膚
① 普通斷點(breakpoint)
給一段程式碼新增斷點的流程是:"F12(Ctrl + Shift + I)開啟開發工具"->"點選Sources選單"->"左側樹中找到相應檔案"→"點選行號列"即完成在當前行新增/刪除斷點操作。當斷點新增完畢後,重新整理頁面JS執行到斷點位置停住,在Sources介面會看到當前作用域中所有變數和值。
-
恢復(Resume): 恢復按鈕(第一個按鈕),繼續執行,快捷鍵 F8,繼續執行,如果沒有其他的斷點,那麼程式就會繼續執行,並且偵錯程式不會再控制程式。
-
跨步(Step over):執行下一條指令,但不會進入到一個函式中,快捷鍵 F10。
-
步入(Step into):快捷鍵 F11,和“下一步(Step)”類似,但在非同步函式呼叫情況下表現不同,步入會進入到程式碼中並等待非同步函式執行。
-
步出(Step out):繼續執行到當前函式的末尾,快捷鍵 Shift+F11,繼續執行程式碼並停止在當前函式的最後一行,當我們使用偶然地進入到一個巢狀呼叫,但是我們又對這個函式不感興趣時,我們想要儘可能的繼續執行到最後的時候是非常方便的。
-
下一步(Step):執行下一條語句,快捷鍵 F9,一次接一次地點選此按鈕,整個指令碼的所有語句會被逐個執行,下一步命令會忽略非同步行為。
啟用/禁用所有的斷點:這個按鈕不會影響程式的執行。只是一個批次操作斷點的開/關。
-
察看(Watch):顯示任意表示式的當前值
-
呼叫棧(Call Stack):顯示巢狀的呼叫鏈
-
作用域(Scope):顯示當前的變數
-
Local:顯示當前函式中的變數
-
Global:顯示全域性變數
② 條件斷點(Conditional breakpoint)
給斷點新增條件,只有符合條件時,才會觸發斷點,條件斷點的顏色是橙色。
③ 日誌斷點(logpoint)
當程式碼執行到這裡時,會在控制檯輸出你的表示式,不會暫停程式碼執行,日誌斷點式粉紅色。
debugger命令
透過在程式碼中新增"debugger;"語句,當程式碼執行到該語句的時候就會自動斷點,之後的操作和在Sources皮膚新增斷點除錯,唯yi的區別在於除錯完後需要刪除該語句。
在開發中偶爾會遇到非同步載入html片段(包含內嵌JS程式碼)的情況,而這部分JS程式碼在Sources樹中無法找到,因此無法直接在開發工具中直接新增斷點,那麼如果想給非同步載入的指令碼新增斷點,此時"debugger;"就發揮作用了。
3.2 反除錯手段
3.2.1 禁用開發者工具
監聽是否開啟開發者工具,若開啟,則直接呼叫JavaScript的window.close( )方法關閉網頁
① 監聽F12按鍵、監聽Ctrl+Shift+I(Windows系統)組合鍵、監聽右鍵選單,監聽Ctrl+s禁止儲存至本地,避免被Overrides。
② 監聽視窗大小變化
③ 利用 Console.log
3.2.2 無限debugger反除錯
① constructor
② Function
有大佬寫了一個庫專門用來判斷是否開啟了開發者工具,可供參考使用:
點選檢視>>
3.3 反反除錯手段
3.3.1 禁用開發者工具
針對判斷是否開啟開發者工具的破解方式很簡單,只需兩步就可以搞定。
① 將開發者工具以獨立視窗形式開啟
② 開啟開發者工具後再開啟網址
3.3.2 無限 debugger
針對無限 debugger 反除錯,有以下破解方法
① 直接使用 dubbger 指令的,可以在 Chrome 找到對應行(格式化後),右鍵行號,選擇 Never pause here 即可。
② 使用了 constructor 構造 debugger 的,只需在 console 中輸入以下程式碼後,點選 F8(Resume script execution)回覆 js 程式碼執行即可(直接點選小的藍色放行按鈕即可)。
Function.prototype.constructor=function(){}
③ 使用了 Function 構造 debugger 的,只需在 console 中輸入以下程式碼。
Function = function () {}
3.4 總結
JavaScript 混淆加密使得程式碼更難以被反編譯和分析,從而提高了程式碼的安全性,攻擊者需要花費更多的時間和精力才能理解和分析程式碼,從而降低了攻擊者入侵的成功率,但它並不能完全保護程式碼不被反編譯和分析,如果攻擊者有足夠的時間和資源,他們仍然可以理解程式碼並找到其中的漏洞,道高一尺,魔高一丈,任何客戶端加密混淆都會被破解,只要用心都能解決,我們能做的就是拖延被破解的時間,所以儘量避免在前端程式碼中嵌入敏感資訊或業務邏輯。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/69912579/viewspace-3001158/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 前端效能優化原理與實踐前端優化
- GAN生成對抗網路-DCGAN原理與基本實現-深度卷積生成對抗網路03卷積
- 前端響應式佈局原理與實踐前端
- 20145302張薇《網路對抗技術》後門原理與實踐
- 20145302張薇 《網路對抗技術》免殺原理與實踐
- 《網路安全原理與實踐》一2.1安全區介紹
- angr原理與實踐(一)——原理
- Webpack原理與實踐Web
- 《網路安全原理與實踐》一2.5複習題
- 《網路安全原理與實踐》一1.2資產確定
- 聊聊微前端的原理和實踐前端
- 對抗樣本與生成式對抗網路
- 2022 SDC 議題 | 面向業務守護的移動安全對抗實踐
- MelGan原理與實踐篇
- Vue CLI 原理與實踐Vue
- RocketMQ的原理與實踐MQ
- 如何應用TFGAN快速實踐生成對抗網路?
- [深度學習]生成對抗網路的實踐例子深度學習
- Swift 網路安全原理及實踐Swift
- 前端跨域請求原理及實踐前端跨域
- 對抗拖庫 —— Web 前端慢加密Web前端加密
- 《雲安全原理與實踐》——3.2 主機虛擬化的主要安全威脅
- 《網路安全原理與實踐》一1.9審計和改進
- RACE IPEMD:構建安全基石的密碼學原理與實踐密碼學
- 前端乾貨之JS最佳實踐前端JS
- Flutter原理與美團的實踐Flutter
- mysql 複製原理與實踐MySql
- 代理重加密原理與實踐加密
- 前端模板的原理與實現前端
- Redis核心原理與實踐--事務實踐與原始碼分析Redis原始碼
- WebSocket原理與實踐(一)---基本原理Web
- 《網路安全原理與實踐》一1.8網路安全體系結構的部署
- Redis核心原理與實踐--列表實現原理之ziplistRedis
- 乾貨|白話SSL/TLS預設重協商漏洞原理與安全重協商對抗機制TLS
- 淺談:前端路由原理解析及實踐前端路由
- RC4Drop加密技術:原理、實踐與安全性探究加密
- 網路對抗 實驗一 逆向及Bof基礎實踐說明
- 生成對抗網路原理與應用:GAN如何使生活更美好