原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

admin 2023年11月21日16:23:56评论51 views字数 5032阅读16分46秒阅读模式

免责声明

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。



原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

自动化检测

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

自动化检测的灵感来源自GitHub项目:GitHub - HoLyVieR/prototype-pollution-nsec18: Content released at NorthSec 2018 for my talk on prototype pollution,我在他的基础上做了批量检查的改进。



原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

基本原理

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

首先明确检测思路就是,假定JavaScript中所有的库方法都存在原型链污染,那么我们提取出库中所有的方法,依次传入payload进行调用,然后检查Object函数是否被污染,就可以实现自动化的检测JavaScript原型链污染漏洞。我们可以细化每一步:

  1.  首先导入库文件:

var lib = require(pkgName);

2. 当然,为了更加自动化,我们可以自动下载并导入库文件:

// 使用npm install命令下载指定版本的包,或者默认下载最新版本try {    execSync(`npm install ${packageWithVersion}`, { stdio: 'inherit' , timeout: 60000});} catch (err) {    console.error(`Error installing ${packageWithVersion}:`, err);    continue;}

3. 随后,我们可以提取出库中的所有方法,使用for遍历出所有的属性和方法,使用typeof把方法筛选出来:

for (var k in lib) {    if (k == "abort") continue;    if (k == "__proto__") continue;    if (+k == k) continue;
console.log(k); if (typeof lib[k] == "function"){ ... }

4. 提取出方法后,我们需要调用方法来污染原型链,但因为JavaScript不支持反射,我们无从得知这个方法的调用规则是什么,我们只能准备一份最常见的函数signature表

var pattern = [{  fnct : function (totest) {    totest(BAD_JSON);  },  sig: "function (BAD_JSON)"},{  fnct : function (totest) {    totest(BAD_JSON, {});  },  sig: "function (BAD_JSON, {})"},{  fnct : function (totest) {    totest({}, BAD_JSON);  },  sig: "function ({}, BAD_JSON)"},{  fnct : function (totest) {    totest(BAD_JSON, BAD_JSON);  },  sig: "function (BAD_JSON, BAD_JSON)"},{  fnct : function (totest) {    totest({}, {}, BAD_JSON);  },  sig: "function ({}, {}, BAD_JSON)"},{  fnct : function (totest) {    totest({}, {}, {}, BAD_JSON);  },  sig: "function ({}, {}, {}, BAD_JSON)"},{  fnct : function (totest) {    totest({}, "__proto__.test", "123");  },  sig: "function ({}, BAD_PATH, VALUE)"},{  fnct : function (totest) {    totest({}, "__proto__[test]", "123");  },  sig: "function ({}, BAD_PATH, VALUE)"},{  fnct : function (totest) {    totest("__proto__.test", "123");  },  sig: "function (BAD_PATH, VALUE)"},{  fnct : function (totest) {    totest("__proto__[test]", "123");  },  sig: "function (BAD_PATH, VALUE)"},{  fnct : function (totest) {    totest({}, "__proto__", "test", "123");  },  sig: "function ({}, BAD_STRING, BAD_STRING, VALUE)"},{  fnct : function (totest) {    totest("__proto__", "test", "123");  },  sig: "function (BAD_STRING, BAD_STRING, VALUE)"}]

5. 有了这个表之后,我们就可以依次调用方法了:

function run(fnct, sig, name, totest) {  // Reinitialize to avoid issue if the previous function changed attributes.  let BAD_JSON = JSON.parse('{"__proto__":{"test":123}}');
if (typeof totest !== 'function') { console.warn(`Trouble: ${totest} is not a function in run() with name=${name}`); return; }
try { fnct(totest); } catch (e) {}
if (check()) { console.log("Detected : " + name + " (" + sig + ")"); }}

6. 运行了之后,我们怎么验证?其实很简单,如果原型链遭到污染,那么Object属性中就大概率会有我们输入的特殊属性,直接判断即可

function check() {  if ({}.test == "123" || {}.test == 123) {    delete Object.prototype.test;    return true;  }  return false;}



原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

批量刷洞

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

针对单个库文件的扫描程序我们已经写好了,但是作为一个成熟的脚本小子,我们当然不满足于一个库一个库的检测漏洞,一键批量刷洞才是我们的终极目标。

  1.  首先我们需要获得大量的库文件,npm有一个库all-the-package-names,已经帮我们实现:

const names = require("all-the-package-names")
names.includes('superagent')// => true
// Check if a given package name existsnames.includes('crazy-new-package-name')// => false
names.length// => 286289
names.filter(name => name.includes('banana'))// => [ 'banana', 'banana-banana', 'banana-split', ...]

2. 我们只需要其filter功能,筛选出我们想要的库名

let filterArray = names.filter(name => name.includes(packageName));

3. 然后对筛选出的库名进行循环检测

let filterArray = names.filter(name => name.includes(packageName));write_log("Filter " + filterArray.length + " Packages.");for (let pkgName of filterArray) {    exploreLib(lib, packageWithVersion, 5);}

4. 但是检测前,我们需要先下载对应的库,而在大量的检测中,往往因为下载的库过多大量的占用存储空间,所以我们可以下载后检测,检测后直接卸载,不断循环

let filterArray = names.filter(name => name.includes(packageName));write_log("Filter " + filterArray.length + " Packages.");for (let pkgName of filterArray) {  if (pkgName == "@deepcase/android-lodash-fix"){    continue;  }
// 如果没有指定版本号,就使用最新版本 var packageWithVersion = version ? `${pkgName}@${version}` : pkgName; write_log("Checking: " + packageWithVersion); console.log("Downloading: " + packageWithVersion);
// 使用npm install命令下载指定版本的包,或者默认下载最新版本 try { execSync(`npm install ${packageWithVersion}`, { stdio: 'inherit' , timeout: 60000}); } catch (err) { console.error(`Error installing ${packageWithVersion}:`, err); continue; } console.log("Exec: " + packageWithVersion); try { var lib = require(pkgName); } catch (e) { console.log("Missing library : " + packageWithVersion ); try { execSync(`npm uninstall ${pkgName}`, { stdio: 'inherit' }); console.log(`Successfully uninstalled ${pkgName}`); } catch (err) { console.error(`Error uninstalling ${pkgName}:`, err); } continue; }
//exploreLib(lib, packageWithVersion, 5); let startTime = new Date().getTime(); let maxDuration = 1500; // 在这里设置你的超时时间(毫秒)
while(new Date().getTime() - startTime < maxDuration) { try { exploreLib(lib, packageWithVersion, 5, startTime, maxDuration); break; } catch(e) { if(e.message !== 'RangeError') throw e; // 如果是其他错误,则抛出 } }
// 执行完毕后,卸载这个包 try { execSync(`npm uninstall ${pkgName}`, { stdio: 'inherit' }); console.log(`Successfully uninstalled ${pkgName}`); } catch (err) { console.error(`Error uninstalling ${pkgName}:`, err); }
// 设置为 null 以便于垃圾收集 pkgName = null; packageWithVersion = null; lib = null; }

5. ok,所有逻辑都处理完毕,可以愉快地刷洞了!代码已上传至GitHub:https://github.com/fatmo666/Proton-pollution-check



原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

总结

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

本文我们首先讲解了原型链污染的原理,列举了问题代码段,并讲解了漏洞CVE-2019-10744。最后引入了采用动态检测的方式批量刷原型链污染漏洞的方法。原型链作为JavaScript实现继承的替代方案,在JavaScript代码中广泛存在,一旦发生原型链污染,将导致严重后果(可以实现拒绝服务攻击甚至是远程代码执行)。实际上,原型链污染的思想同时存在于其他编程语言中,比如Python的继承机制就有可能导致类似JS原型链污染的问题,值得我们进一步探索。自动化刷洞的方法已经放在Github,点击原文链接可以直达。

原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

原文始发于微信公众号(赛博安全狗):原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月21日16:23:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   原型链污染:从原理分析到批量刷洞(四)—— 批量刷洞方法与源码https://cn-sec.com/archives/2218315.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息