伪原创工具可靠不(0x01可信前端在可信系统中的可信也并不是说真的)

优采云 发布时间: 2021-10-28 21:26

  伪原创工具可靠不(0x01可信前端在可信系统中的可信也并不是说真的)

  0x00 前言

  在信息安全领域,可信系统是一个令人兴奋的目标,它是指通过实施特定的安全策略来实现一定程度的信任的系统。

  在计算机中,可信平台模块(TPM)已经投入使用。它符合可信计算组 (TCG) 制定的 TPM 规范。它是一种旨在实现可信系统目标的模型。安全芯片。TPM作为可信系统的信任根,是可信计算的核心模块,为计算机安全提供有力保障。

  

  在我们的网络系统中,试图建立一个可信的系统似乎是一个伪命题。“永远不要相信客户的输入”是基本的安全标准。事实上,在一个受信任的系统中值得信赖并不意味着它是真正安全的。维基上的解释是:“受信任”并不一定意味着对用户来说“受信任”(Trustworthy)。准确的说,就是可以完全相信,它的行为会更加完全的遵循设计,执行设计者和软件作者禁止的行为的概率非常低。

  从这个角度来看,我们认为这是一个美丽的愿景。我们希望能够在 Web 系统中构建一个 TPM,可以在一定概率内控制恶意行为,从而实现一个相对可信的 Web 系统。

  0x01 可信前端

  在可信系统中,TPM的一个重要作用是识别消息来源的真实性,保证终端的可信度。在网络系统中,我们的信息来源是用户。随着数据库崩溃、恶意注册、盗刷等行业的蓬勃发展,越来越多的场景下,我们需要识别请求的数据是否来自真实用户,保护真实用户的数据安全。

  因此,如果要在Web系统中构建TPM,首要的问题是保证输入数据的安全性,创建一个相对可靠的前端环境。但是由于web的开放性,前端是数据的最前端采集,js代码总是暴露在外。在这种情况下,防止恶意伪造请求变得非常困难,可信前端变得无意义。.

  在反复交锋中,代码保护的重要性,或者通常意义上的js代码混淆,逐渐浮出水面。今天想跟大家聊聊js的困惑。

  1、为什么需要js混淆

  很明显,是为了保护我们前端的代码逻辑。

  在web系统开发初期,js在web系统中并没有太多的职责,只是简单的提交表单,js文件很简单,不需要任何保护。

  随着js文件大小的增加,为了减小js的大小,加快http传输速度,出现了很多js的压缩工具,比如uglify、compressor、clouser。. . 他们的工作主要是

  

  【压缩代码】

  虽然压缩工具的出发点是减小js文件的大小,但是人们发现压缩替换后的代码可读性比源代码低很多,间接起到了代码保护的作用,所以压缩后的js文件有成为前端发布的标准。一。但后来市面上主流浏览器chrome、Firefox等都提供了js格式化功能,可以快速美化压缩后的js,再加上现代浏览器强大的调试功能,纯压缩的js代码不是真的 恶意的人可以不再做好防卫工作,出现了“防君不防小人”的尴尬局面。

  

  【chrome开发者工具格式化后的代码】

  在web应用越来越丰富的今天,随着浏览器性能和上网速度的提升,js承载了更多的工作,很多后端逻辑都转移到了前端。同时,它也使得更多的非法分子得以成倍增加。在web模式中,js往往是*敏*感*词*分子的第一个突破口。了解前端逻辑,*敏*感*词*分子就可以模拟普通用户实施自己的恶意行为。因此,在很多登录、注册、支付、交易等页面中,依赖关键业务和风控系统的js不想被人轻易破解,js混乱应运而生。

  2、js 混乱不是纸老虎

  这是一个司空见惯的问题。事实上,代码混淆在很长一段时间内都不是一个新名词。在桌面软件时代,大多数软件都会使用代码混淆和脱壳来保护自己的代码。Java 和 .NET 都有相应的混淆器。黑客当然对此并不陌生,很多病毒程序也会为了反查杀而高度混淆。只是因为js是动态脚本语言,源代码是http传输的,比打包编译的软件逆向简单很多,很多人认为没有必要混淆。

  

  [.NET 混淆器 dotFuscator]

  事实上,正是因为js传输了源代码,我们才需要进行混淆。暴露的代码并不是绝对安全的。但是,在对抗中,精心设计的混淆代码会给破坏者带来很多麻烦,也可以帮助防御者争取更多的时间。与破解相比,混淆器规则的替换成本要小得多。在高强度的攻防中,可以大大增加破解者的工作量,起到防守的作用。从这个角度来看,关键代码的混淆是必不可少的一步。

  3、如何进行js混淆

  js混淆器大致有两种:

  第一种实现成本低,但效果也一般,适用于对混淆度要求不高的场景。第二种实现成本更高,但更灵活、更安全,更适合对抗场景。我这里主要讲第二种。基于语法层面的混淆器其实和编译器类似,基本原理和编译器类似。首先介绍一下编译器。

  词汇表

  

  [编译器 VS 混淆器]

  编译器工作流程

  简单的说,当我们读取一段字符串文本(源代码)时,词法分析器会将它分解成一个小单元(token),例如数字1是一个token,字符串'abc'是一个token等等。 等待。接下来,解析器会将这些单元组合成一个树结构(AST),它表示令牌的组合关系。比如1+2会显示为加法树,左右子节点分别是token-1和token-2,中间的token代表加法。编译器根据生成的AST转换为中间代码,最后转换为机器码。

  对编译器的更多细节感兴趣的同学可以移步龙之书:编译原理

  混淆器工作流程

  编译器需要将源代码编译成中间代码或机器码,而我们的混淆器输出实际上是js。所以我们不需要从语法分析进行下一步。想想我们的目标,就是修改原来的js代码结构。这个结构对应什么?它是AST。任何一段正确的 js 代码都必须能够形成 AST。同样,因为AST代表了每个token的逻辑关系,我们也可以通过AST依次生成一段js代码。所以,你只需要构造一个AST就可以生成任何js代码!混淆过程如上右图所示

  通过修改 AST 生成新的 AST,新的 AST 可以对应新的 JavaScript 代码。

  规则设计

  了解了一般的混淆过程,最重要的环节就是设计规则。正如我们上面所说,我们需要生成一个新的AST结构,这意味着会生成与源代码不同的js代码,但是我们的混淆不能破坏原代码的执行结果,所以混淆规则必须保证代码没有被破坏。在执行结果的情况下,代码变得更加难以阅读。

  可以根据自己的需要设计具体的混淆规则,比如拆分字符串、拆分数组、添加废代码等。

  参考:jscramble的混淆规则,提供商业混淆服务

  

  完成

  很多人看到这一点都犹豫不决,因为词法分析和语法分析对编译原理的要求更高。其实这些工具现在已经可以帮到我们了,借助工具,我们可以直接进行到最后一步,修改AST。

  市场上有许多 JavaScript 词法和语法分析器。比如v8就是其中之一,还有Mozilla的SpiderMonkey,大名鼎鼎的esprima等等。这里我推荐的是uglify,一个基于nodejs的解析器。它具有以下功能:

  对比我上面给出的混淆器设计图,我发现其实只需要修改语法树这一步就可以自己完成了。

  实例

  说到这里,很多人可能还是一头雾水。为了帮助大家理解,我准备了一个简单的例子。假设我们的混淆规则是改变var a = 1中的数字1;到十六进制,我们如何设计一个混淆器。首先对源码进行词法分析和语法分析,uglify可以通过一种方式,生成语法树,我们需要做的就是在语法树中找到数字并修改为十六进制结果,如如下图所示:

  

  示例代码:

  var UglifyJS = require("uglify-js");

var code = "var a = 1;";

var toplevel = UglifyJS.parse(code); //toplevel就是语法树

var transformer = new UglifyJS.TreeTransformer(function (node) {

if (node instanceof UglifyJS.AST_Number) { //查找需要修改的叶子节点

node.value = '0x' + Number(node.value).toString(16);

return node; //返回一个新的叶子节点 替换原来的叶子节点

};

});

toplevel.transform(transformer); //遍历AST树

var ncode = toplevel.print_to_string(); //从AST还原成字符串

console.log(ncode); // var a = 0x1;

  上面的代码很简单,先通过parse方法构造语法树,再通过TreeTransformer遍历语法树。当节点是 UglifyJS.AST_Number 类型时(所有 AST 类型见 ast),这个 token 有一个属性值,持有数字类型的具体值,我们把它改成十六进制表示,然后返回节点会用新节点。

  显示结果

  发布一个我自己设计的混淆器来混淆前后的代码:

  

  4、混淆对性能的影响

  由于增加了浪费代码和改变了原来的AST,混乱肯定会对性能产生一定的影响,但是我们可以通过规则来控制影响的大小。

  我们可以通过一定的规则将性能影响控制在合理范围内。事实上,一些混淆规则会加快代码的执行速度,比如变量名和属性名的压缩和混淆,会减小文件大小,比如全局变量的重复会减小搜索的范围等等在。在现代浏览器中,混淆对代码的影响越来越小。我们只需要关注合理的混淆规则,你就可以放心的使用混淆了。

  5、混乱的安全

  混淆的目的是为了保护代码,但是如果正常的功能受到混淆的影响,那就是最后了。

  既然混淆后的 AST 与原 AST 完全不同,但混淆后的文件和原文件的执行结果必须相同,那么如何保证在不破坏代码执行的情况下兼顾混淆的强度呢?高覆盖率测试必不可少:

  0x02 摘要 0x03 参考

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线