最新:Lodash 严重安全漏洞背后你不得不知道的 JavaScript 知识

news/2024/5/20 22:35:35

可能有信息敏感的同学已经了解到:Lodash 库爆出严重安全漏洞,波及 400万+ 项目。这个漏洞使得 lodash “连夜”发版以解决潜在问题,并强烈建议开发者升级版本。

我们在忙着“看热闹”或者“”升级版本”的同时,静下心来想:真的有理解这个漏洞产生的原因,明白漏洞修复背后的原理了吗?

这篇短文将从原理层面分析这一事件,相信“小白”读者会有所收获。

漏洞原因

其实漏洞很简单,举一个例子:lodash 中 defaultsDeep 方法

_.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }) 

输出:

{ 'a': { 'b': 2, 'c': 3 } } 

如上例,该方法:

分配来源对象(该方法的第二个参数)的可枚举属性到目标对象(该方法的第一个参数)所有解析为 undefined 的属性上

这样的操作存在的隐患:

const payload = '{"constructor": {"prototype": {"toString": true}}}'

_.defaultsDeep({}, JSON.parse(payload)) 

如此一来,就触发了原型污染。原型污染是指:

攻击者通过某种手段修改 JavaScript 对象的原型(prototype)

对应上例,Object.prototype.toString 就会非常不安全了。

详解原型污染

理解原型污染,需要读者理解 JavaScript 当中的原型、原型链原型链的知识。我们先来看一个例子:

// person 是一个简单的 JavaScript 对象
let person = {name: 'lucas'}// 输出 lucas
console.log(person.name)// 修改 person 的原型
person.__proto__.name = 'messi'// 由于原型链顺序查找的原因,person.name 仍然是 lucas
console.log(person.name)// 再创建一个空的 person2 对象
let person2 = {}// 查看 person2.name,输出 messi
console.log(person2.name) 

把危害扩大化:

let person = {name: 'lucas'}console.log(person.name)person.__proto__.toString = () => {alert('evil')}console.log(person.name)let person2 = {}console.log(person2.toString()) 

 这段代码执行将会 alert 出 evil 文字。同时 Object.prototype.toString 这个方法会在隐式转换隐式转换隐式转换以及类型判断中经常被用到:

Object.prototype.toString 方法返回一个表示该对象的字符串

每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 [object type],其中 type 是对象的类型。

如果 Object 原型上的 toString 被污染,后果可想而知。以此为例,可见 lodash 这次漏洞算是比较严重了。

再谈原型污染(NodeJS 漏洞案例)

再谈原型污染(NodeJS 漏洞案例)

由上分析,我们知道原型污染并不是什么新鲜的漏洞,它“随时可见”,“随处可见”。在 Nullcon HackIM 比赛中就有一个类似的 hack 题目:

'use strict';const express = require('express');
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser');
const path = require('path');const isObject = obj => obj && obj.constructor && obj.constructor === Object;function merge(a, b) {for (var attr in b) {if (isObject(a[attr]) && isObject(b[attr])) {merge(a[attr], b[attr]);} else {a[attr] = b[attr];}}return a
}function clone(a) {return merge({}, a);
}// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
const admin = {};// App
const app = express();
app.use(bodyParser.json())
app.use(cookieParser());app.use('/', express.static(path.join(__dirname, 'views')));
app.post('/signup', (req, res) => {var body = JSON.parse(JSON.stringify(req.body));var copybody = clone(body)if (copybody.name) {res.cookie('name', copybody.name).json({"done": "cookie set"});} else {res.json({"error": "cookie not set"})}
});
app.get('/getFlag', (req, res) => {var аdmin = JSON.parse(JSON.stringify(req.cookies))if (admin.аdmin == 1) {res.send("hackim19{}");} else {res.send("You are not authorized");}
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`); 

 这段代码的漏洞就在于 merge 函数上,我们可以这样攻击:

curl -vv --header 'Content-type: application/json' -d '{"__proto__": {"admin": 1}}' 'http://0.0.0.0:4000/signup'; curl -vv 'http://0.0.0.0:4000/getFlag' 

首先请求 /signup 接口,在 NodeJS 服务中,我们调用了有漏洞的 merge 方法,并通过 __proto__ 为 Object.prototype(因为 {}.__proto__ === Object.prototype) 添加上一个新的属性 admin,且值为 1。

再次请求 getFlag 接口,条件语句 admin.аdmin == 1 为 true,服务被攻击。

防范原型污染

了解了漏洞潜在问题以及攻击手段,那么如何防范呢?

在 lodash “连夜”发版的修复中:

我们可以清晰的看到,在遍历 merge 时,当遇见 constructor 以及 __proto__ 敏感属性,则退出程序。

那么作为业务开发者,我们需要注意些什么,防止攻击出现呢?总结一下有:

  • 冻结 Object.prototype,使原型不能扩充属性

我们可以采用 Object.freeze 达到目的:

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

 看代码:

Object.freeze(Object.prototype);Object.prototype.toString = 'evil'consoel.log(Object.prototype.toString)
ƒ toString() { [native code] } 

对比: 

Object.prototype.toString = 'evil'console.log(Object.prototype.toString)
"evil" 
  • 建立 JSON schema 在解析用户输入内容是,通过 JSON schema 过滤敏感键名。
  • 规避不安全的递归性合并 这一点类似 lodash 修复手段,完善了合并操作的安全性,对敏感键名跳过处理
  • 使用无原型对象 在创建对象时,不采用字面量方式,而是使用 Object.create(null):

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ 

Object.create(null) 的返回值不会链接到 Object.prototype

let foo = Object.create(null)
console.log(foo.__proto__)
// undefined 

 

这样一来,无论如何扩充对象,都不会干扰到原型了。

  • 采用新的 Map 数据类型,代替 Object 类型

Map 对象保存键/值对,是键/值对的集合。任何值(对象或者原始值)都可以作为一个键或一个值。使用 Map 数据结构,不会存在 Object 原型污染状况。

这里总结一下 Map 和 Object 不同点::

  • Object 的键只支持 String 或者 Symbols 两种类型,Map 的键可以是任意值,包括函数、对象、基本类型
  • Map 中的键值是有序的,而 Object 中的键则不是
  • 具体 API 上的差异:比如,通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值无法获取;再比如迭代一个 Map 和 Object 差异也比较明显
  • Map 在频繁增删键值对的场景下会有些性能优势

网络安全学习路线 (2024最新整理)

 如图片过大被平台压缩导致看不清的话,评论区点赞和评论区留言扣1或者关注我我后台会主动发给你! 

第一阶段:安全基础

网络安全行业与法规

Linux操作系统

计算机网络

HTML PHP Mysql Python基础到实战掌握

  第二阶段:信息收集

IP信息收集

域名信息收集

服务器信息收集

Web网站信息收集

Google hacking

Fofa网络安全测绘

 第三阶段:Web安全 

SQL注入漏洞

XSS

CSRF漏洞

文件上传漏洞

文件包含漏洞

SSRF漏洞

XXE漏洞

远程代码执行漏洞

密码暴力破解与防御

中间件解析漏洞

反序列化漏洞

 第四阶段:渗透工具 

MSF

Cobalt strike

Burp suite

Nessus   Appscea   AWVS

Goby   XRay

Sqlmap

Nmap

Kali

 第五阶段:实战挖洞 

漏洞挖掘技巧

Src

Cnvd

众测项目

热门CVE漏洞复现

靶场实战

学习资料的推荐

学习框架已经整理完毕,现在就差资料资源了,我这里整理了所有知识点对应的资料资源文档,大家不想一个一个去找的话,可以参考一下这些资料!

1.视频教程

 2.SRC技术文档&PDF书籍 

3.大厂面试题    

特别声明:

此教程为纯技术分享!本教程的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本教程的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失。


http://www.mrgr.cn/p/35236684

相关文章

震惊,现在面试都加科技与狠货了

震惊,现在面试都加科技与狠货了 生成式AI盛行的现在,程序员找工作变容易了吗我和老痒喝着大酒,吃着他的高升宴,听他说他面试的各种细节,老狗我只恨自己动作慢了一步,不然现在在那侃侃而谈的就是我了。 面试…

电商核心技术揭秘53:社群营销的策略与实施

相关系列文章 电商技术揭秘相关系列文章合集(1) 电商技术揭秘相关系列文章合集(2) 电商技术揭秘相关系列文章合集(3) 电商技术揭秘四十一:电商平台的营销系统浅析 电商技术揭秘四十二&#…

Window7镜像注入USB驱动,解决系统安装后无法识别USB

Window7镜像注入usb驱动 Window7镜像注入usb驱动方法一方法二 Window7镜像注入usb驱动 一般4代酷睿之后的主机需要安装usb驱动才能驱动usb,导致很多Windows原版镜像安装后无法识别usb键盘 方法一 1.直接采购PS2 接口键盘、PS2 接口鼠标 方法二 使用联想镜像注入…

美食推荐网站设计

**中文摘要:**在当今信息化、网络化的时代背景下,美食文化正逐渐融入人们的日常生活,而网络平台成为人们获取美食信息、分享美食体验的重要途径。为了满足广大美食爱好者对美食信息的探索和推荐需求,本文提出了一种创新的美食推荐…

6.k8s中的secrets资源

一、Secret secrets资源,类似于configmap资源,只是secrets资源是用来传递重要的信息的; secret资源就是将value的值使用base64编译后传输,当pod引用secret后,k8s会自动将其base64的编码,反编译回正常的字符…

联芯集成电路产品与方案

联芯集成电路产品与方案 逻辑制程解决方案 逻辑 / 混合信号 / 射频技术是数字电视、蓝牙、Wi-Fi、图像处理器,射频收发器等众多应用中最常用的晶圆专工解决方案。联电为不同的数据处理、混合信号及射频组件技术建立了广泛的跨代技术,也同时为建立专业技术平台奠定了坚实的基础…

锂电池恒流恒压CCCV充电模型MATLAB仿真

微❤关注“电气仔推送”获得资料(专享优惠) CCCV简介 CCCV充电过程是恒流充电(CC)和恒压充电(CV)的结合。在CC阶段对电池施加恒定电流,以获得更快的充电速度,此时电池电压持续升高…

用keras识别狗狗

一、需求场景 从照片从识别出狗狗 from keras.applications.resnet50 import ResNet50 from keras.preprocessing import image from keras.applications.resnet50 import preprocess_input, decode_predictions import numpy as np# 加载预训练的ResNet50模型 model ResNet5…

Kubernetes(K8s)的基础概念

目录 一、Kubernetes(K8s)概述 1、K8s是什么? 2、k8s的作用 3、k8s的功能 二、k8s的特性 ①弹性伸缩: ②自我修复: ③服务发现和负载均衡: ④自动发布(默认滚动发布模式)和…

asp.net朱勇项目个人博客(3)

引文:按照书上的项目,我们最后实现管理端的三个增删改查的功能即可,相对与三个增删改查,文章,分类和留言,这里我们所需要用的的关联的一个表就是文章表,因为文章表每一个文章的增加显示和修改都需要对应的一个分类&…

鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程

一个.c源文件编译的整个过程如图. 编译过程要经过:源文件 --> 预处理 --> 编译(cc1) --> 汇编器(as) --> 链接器(ld) --> 可执行文件(PE/ELF) GCC GCC(GNU Compiler Collection,GNU编译器套件),官网:…

新火种AI|AI让大家都变“土”了!

作者:一号 编辑:美美 AI不仅要把人变“土”,还要把人变多样。 这个世界,终究是变“土”了。 今年五一假期,一个名为“Remini”的AI修图APP火遍了全网。注意,是Remini,而不是Redmi&#xff0…

nacos下载安装和nacos启动报错

nacos简介: Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您…

自动驾驶纵向控制算法

本文来源——b站忠厚老实的老王,链接:忠厚老实的老王投稿视频-忠厚老实的老王视频分享-哔哩哔哩视频 (bilibili.com),侵删。 功率和转速之间的关系就是:功率P等于转矩M乘以转速ω。并不是油门越大加速度就越大。 发动机和电机的转…

宁波方太集团项目管理办公室负责人王博受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 宁波方太集团项目管理办公室负责人王博先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“系统性建设卓越的组织级项目管理体系”。大会将于6月29-30日在北京举办,敬请关注! 议题简要&#xff1…

C# WinForm —— 12 ListBox绑定数据

ListBox加载大量数据时,避免窗体闪烁的方法: 在加载语句的前后分别加上 BeginUpdate()方法 和 EndUpdate()方法 指定一个集合为绑定的数据源 1. 首先,右键项目,添加类 2. 在新建的类文件中添加属性值信息 3. 构建初始化的对象…

【华为】IPSec VPN手动配置

【华为】IPSec VPN手动配置 拓扑配置ISP - 2AR1NAT - Easy IPIPSec VPN AR3NATIPsec VPN PC检验 配置文档AR1AR2 拓扑 配置 配置步骤 1、配置IP地址,ISP 路由器用 Lo0 模拟互联网 2、漳州和福州两个出口路由器配置默认路由指向ISP路由器 3、进行 IPsec VPN配置&…

【C++】C++11--- 列表初始化|关键字

目录 前言 列表初始化 创建对象时的列表初始化 单参数隐式类型转换 多参数的隐式类型转换 new表达式中使用列表初始化 列表初始化适用于STL 容器 模板类initializer_list 关键字auto 关键字decltype 关键字nullptr 前言 C标准10年磨一剑,第二个真正意义上…

【强训笔记】day16

NO.1 代码实现&#xff1a; class StringFormat { public:string formatString(string A, int n, vector<char> arg, int m) {string ret;int j0;for(int i0;i<n;i){if(A[i]%){if(i1<n&&A[i1]s){retarg[j];i;}else {retA[i];}}else {retA[i];}}while(j&l…

Golang:deepcopy深拷贝工具库

Golang:deepcopy深拷贝工具库 原创 吃个大西瓜 Coding Big Tree 2024-05-02 08:30 云南 听全文Deep copy things译文:事物的深度复制文档github https://github.com/mohae/deepcopy pkg.go https://pkg.go.dev/github.com/mohae/deepcopy安装 go get github.com/mohae/deepco…