我想分析用戶的表達式中使用標準的JavaScript這樣的驗證,以布爾:如何安全評估用戶輸入表達式
var1 > obj1.prop1 && var2 + 1 <= 5
因爲這個表達式是由用戶編寫的,我想,以確保它們是乾淨becase的他們將被用NodeJS評估服務器端。
而不是必須解析表達式作爲文本尋找模式和重新發明輪子,有沒有一種方法可以使用節點的能力直接評估表達式沒有代碼注入的風險?
我想分析用戶的表達式中使用標準的JavaScript這樣的驗證,以布爾:如何安全評估用戶輸入表達式
var1 > obj1.prop1 && var2 + 1 <= 5
因爲這個表達式是由用戶編寫的,我想,以確保它們是乾淨becase的他們將被用NodeJS評估服務器端。
而不是必須解析表達式作爲文本尋找模式和重新發明輪子,有沒有一種方法可以使用節點的能力直接評估表達式沒有代碼注入的風險?
你可能不喜歡這個答案。但你必須做工作。沒有魔法彈。
你的問題,要求「標準的javascript」和「無代碼注入的風險」自相矛盾。你不能擁有兩個。標準JavaScript允許表達式如'require("fs").rmdirSync("/")'
用戶輸入的表達式必須被限制爲嚴重受限的JavaScript子集。在嘗試評估輸入之前,服務器必須驗證輸入是否僅限於該子集。
所以首先你需要仔細考慮一下有限的子集是允許的。它看起來像你想允許常量整數像「5」,運營商如「>」,「& &」和「< =」。您還允許訪問像'var1''obj1.prop1''var2'這樣的變量。我想你需要對允許變量的列表非常具體。
防止腳本注入,關鍵是要定義一個子集,其中包括只有你知道是安全的事情。你不應該試圖從整個JavaScript開始,排除你認爲是危險的東西 - 因爲你會錯過一些。
一旦您仔細定義了表達式可能包含的內容,您需要實現代碼來解析和驗證表達式。您可能會找到一個庫或標準代碼來執行此操作,但您必須修改或配置它才能滿足您的特定要求。
在一般情況下,不管您最終會使用什麼,我都會啓動一個評估過程,您可以放棄所有權限並僅使用unix域套接字與其進行通信。並將你想評估的代碼發送給它。
以root用戶身份啓動它,並打開unix域套接字,然後刪除權限nobody。
process.setgid('nobody');
process.setuid('nobody');
一件事,你應該避免是做這樣的事情:
const root = global = {};
const require = function() {
console.log('tryed to call require', arguments);
}
eval("require('fs')");
這可能會在第一次看工作,但如與ES6存在的import
關鍵字引入,所以即使你覆蓋require
你仍然可以使用import
加載模塊。
另外Safely sandbox and execute user submitted JavaScript?中提到的方法,如vm.runInContext('globalVar *= 2;', sandbox);
也沒有幫助。但是引用的sandcastle,可能是你可以看到的東西,但即使你使用沙箱庫,我仍然會建議在一個孤立的非特權進程中運行它。
像James在答案中建議您應該採取白名單的方式,而不是列入有害的名單。
您可以使用自帶的表達式解析器附帶的mathjs
庫。
這個的幫助? http://jsep.from.so/ –
@IlayaRajaS很酷的庫!,但它不評估表達式,至少我能算出它 – DomingoSL
你是否在linux服務器上運行node.js? –