CVE-2020-16171: Exploiting Acronis Cyber Backup for Fun and Emails
You have probably read one or more blog posts about SSRFs, many being escalated to RCE. While this might be the ultimate goal, this post is about an often overlooked impact of SSRFs: application logic impact.
This post will tell you the story about an unauthenticated SSRF affecting Acronis Cyber Backup up to v12.5 Build 16341, which allows sending fully customizable emails to any recipient by abusing a web service that is bound to localhost. The fun thing about this issue is that the emails can be sent as backup indicators, including fully customizable attachments. Imagine sending Acronis “Backup Failed” emails to the whole organization with a nice backdoor attached to it? Here you go.
Root Cause Analysis
So Acronis Cyber Backup is essentially a backup solution that offers administrators a powerful way to automatically backup connected systems such as clients and even servers. The solution itself consists of dozens of internally connected (web) services and functionalities, so it’s essentially a mess of different C/C++, Go, and Python applications and libraries.
The application’s main web service runs on port 9877 and presents you with a login screen:
Now, every hacker’s goal is to find something unauthenticated. Something cool. So I’ve started to dig into the source
code of the main web service to find something cool. Actually, it didn’t take me too long to discover that something in
a method called
The main interesting thing here is the call to
get_ams_address(request.headers), which is used to construct a Uri.
The application reads out a specific request header called
Shard within that method:
When having a further look at the
make_request_to_ams call, things are getting pretty clear. The application
uses the value from the
Shard header in a
So this is a pretty straight-forward SSRF including a couple of bonus points making the SSRF even more powerful:
- The instantiation of the
urllib.request.Requestclass uses all original request headers, the HTTP method from the request, and the even the whole request body.
- The response is fully returned!
The only thing that needs to be bypassed is the hardcoded construction of the destination Uri since the API appends a semicolon, a port, and a resource to the requested Uri:
However, this is also trivially easy to bypass since you only need to append a
? to turn those into parameters. A
final payload for the Shard header, therefore, looks like the following:
Finding Unauthenticated Routes
To exploit this SSRF we need to find a route which is reachable without authentication. While most of CyberBackup’s routes
are only reachable with authentication, there is one interesting route called
/api/ams/agents which is kinda different:
Every request to this route is passed to the
This in return does only check whether the
allow_add_devices configuration is enabled (which is the standard config)
before passing the request to the vulnerable
So we’ve found our attackable route without authentication here.
Sending Fully Customized Emails Including An Attachment
Apart from doing meta-data stuff or similar, I wanted to entirely fire the SSRF against one of Cyber Backup’s internal web services. There are many these, and there are a whole bunch of web services whose authorization concept solely relies only on being callable from the localhost. Sounds like a weak spot, right?
One interesting internal web service is listening on
Notification Service. This service
offers a variety of functionality to send out notifications. One of the provided endpoints is
I’m not going through the
send_external_email method in detail since it is rather complex, but this endpoint
essentially uses parameters supplied via HTTP POST to construct an email that is send out afterwards.
The final working exploit looks like the following:
This involves a variety of “customizations” for the email including a base64-encoded
attachments value. Issuing
this POST request returns
but ultimately sends out the email to the given
mainRecipients including some
Perfectly spoofed mail, right ;-) ?
Acronis fixed the vulnerability in version
v12.5 Build 16342 of Acronis Cyber Backup by changing the way that
gets the actual
Shard address. It now requires an additional authorization header with a JWT that is passed to a method
While both values
jwt are not explicitly validated here, they are simply used in a new hardcoded
call to the API endpoint
/api/account_server/tenants/ which ultimately verifies the authorization: