保護(hù)JavaScript客戶端APP的最有效方法
客戶端技術(shù),如 JavaScript,有很多有用的特性,正因?yàn)槿绱?,它成為了世界上最流行的語(yǔ)言之一。它有很多優(yōu)點(diǎn),即時(shí)解析就是其一。即時(shí)解析有不少優(yōu)點(diǎn),比如可以在瀏覽器下載代碼并立即執(zhí)行。然而,自由度越高,責(zé)任越大。
我們會(huì)在這篇文章中深入 JavaScript 的安全隱患,不過范圍僅限于瀏覽器中運(yùn)行的前端代碼。我們會(huì)關(guān)注一些將來產(chǎn)生的其它類型。
現(xiàn)在發(fā)揮你的想像,瀏覽器總是要執(zhí)行代碼的,它首先下載頁(yè)面并進(jìn)行解析。瀏覽器有著下載和解析同時(shí)進(jìn)行的能力,所以它不會(huì)等待所有東西下載完成。那么,它遇到 JavaScript 的時(shí)候會(huì)發(fā)生什么事情?
JavaScript會(huì)阻塞渲染,這在它執(zhí)行的時(shí)候是個(gè)巨大的優(yōu)勢(shì)。但這意味著瀏覽器將停止解析,直到執(zhí)行完 JavaScript 后才會(huì)繼續(xù)。這一特點(diǎn)給于這種編程語(yǔ)言極大的靈活性,它可以打開任意數(shù)量的代碼。
但問題在于,這個(gè)特性會(huì)帶來什么樣的影響?
- <div id="hack-target"></div>
- <button>Set Value</button>
- <script>
- document.querySelector('button').addEventListener('click', setValue);
- function setValue() {
- var value = '2';
- document.getElementById('hack-target').innerText = value;
- }</script>
這段代碼為 HTML 綁定事件,當(dāng)你點(diǎn)擊按鈕的時(shí)候,觸發(fā)回調(diào)。
對(duì)于客戶端的 JavaScript,你可以在設(shè)置值的地方設(shè)置一個(gè)斷點(diǎn)。這個(gè)斷點(diǎn)會(huì)在事件觸發(fā)的時(shí)候擊中。var value = '2'; 用于設(shè)置值,而且可以修改。調(diào)試器會(huì)在這里暫停并允許篡改頁(yè)面。這一功能非常有用,而且當(dāng)它發(fā)生的時(shí)候,瀏覽器不會(huì)對(duì)它進(jìn)行標(biāo)記。
既然調(diào)試器暫停了執(zhí)行代碼,它同時(shí)也暫停了渲染。調(diào)試器本身是瀏覽器提供的工具之一,任何人都可以使用。這就是 Web Developer Tools(開發(fā)者工具)。
在 Code Pen 上可以看到這種技術(shù)的應(yīng)用。下面是關(guān)于這個(gè)特性的截圖:
這一特性對(duì)調(diào)試 JavaScript 十分有用,但是它的安全性如何呢?
這個(gè)特性意味著攻擊者可以在運(yùn)行時(shí)改變 JavaScript。攻擊者可以通過斷點(diǎn)暫時(shí)執(zhí)行,然后修改 DOM 并在控制臺(tái)輸入任意 JavaScript 代碼。這類功能可以利用客戶端的漏洞,更改數(shù)據(jù),支持會(huì)話并在頁(yè)面內(nèi)用 JavaScript 作出任意改動(dòng)。
例如,打開開發(fā)者工具,進(jìn)入控制臺(tái)頁(yè)面,并輸入:
- document.querySelector('button')
- .addEventListener('click', function () {
- alert('sacked');
- });`
下次這個(gè)事件再觸發(fā)的時(shí)候,它會(huì)執(zhí)行修改后的 JavaScript 代碼。
為什么是 JavaScript?
你可能想問,這一切從何而來?Netscape 在1995年發(fā)布JavaScript的時(shí)候,這種新語(yǔ)言就成為了 Web 的 “膠水語(yǔ)言”。
Netscape 把 JavaScript 標(biāo)準(zhǔn)提交給Ecma國(guó)際組織之后,他們的版本就成為了標(biāo)準(zhǔn),也就是大家所知的 ECMAScript。既然 ECMAScript 是一個(gè)標(biāo)準(zhǔn),任何瀏覽器都被要求支持這個(gè)標(biāo)準(zhǔn),這樣在使用不同的瀏覽器時(shí)才會(huì)不發(fā)生沖突。也就是說,你可以為谷歌瀏覽器寫一段代碼,但它同時(shí)也能在 Opera、NetScape、Internet Explorer 和 Microsoft Edge 中運(yùn)行。JavaScript 創(chuàng)建于靈活的環(huán)境,它有能力讓你做你想做的事情。這些設(shè)計(jì)原則使用 JavaScript 自然具有了動(dòng)態(tài)的天賦,也使它成為瀏覽器的語(yǔ)言。
這些都已經(jīng)成為歷史,但與 JavaScript 的安全性有什么關(guān)系?
客戶端安全
為了防止惡意的 JavaScript 代碼,最好的選擇是添加運(yùn)行時(shí)保護(hù)。運(yùn)行時(shí)程序自我保護(hù)(Runtime Application Self-Protection,RASP)將在執(zhí)行客戶端代碼的時(shí)候?qū)λ右员Wo(hù)。隨著 Web 靈活性和動(dòng)態(tài)性的到來,攻擊者通過客戶端 JavaScript 進(jìn)行攻擊成為可能,運(yùn)行時(shí)安全也成為必要。
RASP 是最為有效的客戶端應(yīng)用保護(hù)方式,總結(jié)起來如下所示:
運(yùn)行時(shí)程序自我保護(hù)是一種安全技術(shù),它創(chuàng)建或鏈接到應(yīng)用程序或其運(yùn)行環(huán)境,并控制應(yīng)用程序執(zhí)行,檢測(cè)和防止實(shí)時(shí)攻擊。
一旦JavaScript 在瀏覽器中執(zhí)行,沒有任何東西對(duì)其完全防護(hù)。RASP 會(huì)防范發(fā)生在運(yùn)行時(shí)的高度和代碼篡改攻擊,包括在離線狀態(tài)修改應(yīng)用程序的攻擊。一個(gè)好的 RASP 解決方案也會(huì)保護(hù)自身代碼,使攻擊者不能篡改解決方案本身,或者直接繞過它。這幾層保護(hù)保證著開放網(wǎng)絡(luò)的安全。
如果 RASP 不錯(cuò),它會(huì)在攻擊者嘗試阻止代碼的時(shí)候發(fā)出通知,以便用戶知道并采取行動(dòng),比如取消用戶會(huì)話。
Jscrambler提供了一個(gè) RASP 解決方案來保證應(yīng)用不受到運(yùn)行時(shí)攻擊。它會(huì)自我防御并檢測(cè)篡改。它的自我防御能力會(huì)激活對(duì) JavaScript 應(yīng)用的保護(hù)。Jscrambler 使用反調(diào)試和反篡改技術(shù)——眾所周知的應(yīng)用程序保護(hù)概念——對(duì) JavaScript 而言明確現(xiàn)實(shí)和局限。反調(diào)試功能檢測(cè)調(diào)試工具(比如 DevTools, Firebug)的使用,并試圖阻止逆向工程師使用它來調(diào)試應(yīng)用。它包含一些預(yù)置的代碼陷阱,使調(diào)試器停止工作,造成堆棧的增長(zhǎng),阻止用戶探查應(yīng)用的控制流。反篡改功能則會(huì)檢查代碼的變化,并做出反應(yīng)。比如,你在自動(dòng)防御所保護(hù)的一個(gè)函數(shù)中添加/刪除一個(gè)分號(hào),它會(huì)檢測(cè)到變化,然后停止運(yùn)行代碼。兩種技術(shù)與代碼混淆結(jié)合會(huì)使得對(duì)應(yīng)用程序的篡改寸步難行。
結(jié)論
實(shí)現(xiàn) JavaScript 的安全性必須考慮在運(yùn)行時(shí)會(huì)發(fā)生什么。它本質(zhì)上來說是為 Web 的靈活性而生的動(dòng)態(tài)語(yǔ)言。它是一柄雙刃劍,使用的時(shí)候一定要注意到應(yīng)盡的責(zé)任。