Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于在sablejs处理后的JS中使用document,window对象的问题 #10

Closed
zdrin opened this issue Jun 4, 2021 · 6 comments
Closed

Comments

@zdrin
Copy link

zdrin commented Jun 4, 2021

首先非常感谢您的耐心解答,已经解决了问题。但又遇到个问题,就是当丢到vm中的脚本里包含document,window对象时,会报not defined的错误,想问下,是不支持这些对象么?然后包含jquery的脚本也会报错。如果不行的话,是否有办法在外部这个脚本中调用vm中脚本里的函数呢?其实就是想实现浏览器和服务端传输数据的加密,又不想暴露加密思路。感谢感谢!

@ErosZy
Copy link
Member

ErosZy commented Jun 4, 2021

please follow #2 issue. you should import document and window to sablejs, this part you can follow cax4sablejs or ajax4sablejs.

@ErosZy ErosZy closed this as completed Jun 5, 2021
@zdrin
Copy link
Author

zdrin commented Jun 5, 2021

please follow #2 issue. you should import document and window to sablejs, this part you can follow cax4sablejs or ajax4sablejs.

哦,也就是说要想使用document等沙盒中不支持的对象或方法,就需要在表层脚本中建立连接,才能在沙盒中能够使用呗,就像通过:vm.setProperty(vGlobal, "console", vConsole);将外部的console功能下沉到沙盒中?但对于背后逻辑复杂的对象或方法,那就得深入了解js才能把完整功能移植过去了,像document和window的引入,目前的脚本中还没做是吧?我在cax4sablejs和ajax4sablejs中好像没看着。

然后我看了一下cax4sablejs,用了一下event-dispatcher.js中的__EventDispatcher__,我在沙盒中是这么写的,不知道哪儿有问题:
var this_event = new __EventDispatcher__();
this_event.addEventListener('click',function(){ console.log("click"); },false);
就是提示addEventListener undefined
然后我看源码中写道:
const vEventDispatcher = vm.createFunction("__EventDispatcher__", function () {});
是不是__EventDispatcher__不能new?那要怎样才能添加个事件监听呢?一直用jquery,对底层真是不太通,不知道在沙盒中怎么才能实现对某一元素的确定事件进行绑定监听呢?

然后,还有最后个问题,就是沙盒中可以通过console.log或者注册别的自定义函数把参数传递到表层脚本,但有办法在表层脚本中将参数传递到沙盒中么?或者执行沙盒中的函数?您说:“SecurityWorker 是獨立的 vm,程式碼會被編譯為 opcode bytes 然後混編,不存在 eval 之類的動態執行。但目前跟 WebWorker 一樣,沒有 DOM/BOM,需要兩個環境通訊”。不知道sablejs可否表层沙盒双向通信?如何实现呢?

非常感谢您的耐心解答,非常感谢!!!

@ErosZy
Copy link
Member

ErosZy commented Jun 5, 2021

@zdrin If you want to new EventDispatcher, you should bind cax to sablejs, like cax4sablejs doc said:

const cax4sablejs = require("cax4sablejs");
const VM = require("sablejs/runtime")();
const vm = new VM();
cax4sablejs(vm); // that's all!

If you want to call sablejs inner function from outside, you can use vm.call, for example:

// a function is on sablejs inner enviorment
function a(){
  print('a');
}
// get sablejs inner function and call it
const global = vm.getGlobal();
const vA = vm.getProperty(global, 'a');
vm.call(vA, vm.createUndefined()); // will log 'a'

@ErosZy ErosZy reopened this Jun 5, 2021
@zdrin
Copy link
Author

zdrin commented Jun 5, 2021

感谢感谢!!!然后又想到一个新问题,不知道我说得对不对哈,基于在 inner enviorment 中只能执行关于数字,字符串的处理工作,其他任务只能通过在 outside 写脚本的形式链接模拟出来,同时认为 outside enviorment 的所有内容均可破译的前提下,还是否能保证 inner enviorment 的绝对安全呢?就是如果攻击者通过重写 outside 脚本然后 run 原有的编译好的 inner enviorment 的代码(比如是个加密算法),是不是就能够绕过 inner enviorment 进行攻击呢?所以,不知道在 inner enviorment 中是否有原生的办法获取执行环境,比如类似浏览器环境下的window.location.hostname,来评估 inner enviorment 的安全性呢?

@ErosZy
Copy link
Member

ErosZy commented Jun 6, 2021

@zdrin For this problem you need to clearly understand one thing:

The outside environment is not safe, the inner environment is safe, so if the inner environment opens too many global functions for the outside environment to call, then this behavior is not safe.

Therefore, a better way is to include all relevant business logic only in the inner environment and provide only one call portal to the outside enviroment. An example of a mistake:

// sablejs inner enviroment
function a(){}
function b(){}
function c(){}
function __main__(){
  a();
  b();
  c();
}

The three inner a/b/c functions are easily accessible from outside. A better way for this example is:

;(function(){
  function a(){};
  function b(){};
  function c(){};
  function __main__(){
     a();
     b();
     c();
  }
  this.__main__ = __main__;
}())

Now the outside only can call __main__ function, but can't do that for a/b/c because of closure. Although this is just a small example, in summary, if you want to safely prevent outside calls, all you need to do is:

Limit the number of entry points for outside calls as much as possible (because the outside environment is not safe), and instead execute more code inside sablejs inner then notify the outside.

Based on this principle, you need to expose the api you need to sablejs inner as much as possible, just like:

for(let key in window){
   const value = window[key];
   if(typeof value === "string"){
       vm.setProperty(global, key, vm.createString(value));
   }else if(...){
       // something else binding
   }
}

Of course you need to use traversal whenever possible(like above), and avoid exposing a method or object exactly. Hope you code fun 😁.

@ErosZy
Copy link
Member

ErosZy commented Jun 7, 2021

If you still have problems, please reopen this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants