[6.0/6.1/7.0/Trunk] get_sys_logs function may allows arbitrary code execution

Bug #1196847 reported by Nicolas Bessi - Camptocamp
268
This bug affects 4 people
Affects Status Importance Assigned to Milestone
Odoo Addons (MOVED TO GITHUB)
Expired
Undecided
Unassigned

Bug Description

The Warranty information retrieval function get_sys_logs is a major vulnerability.
The function is called by model "publisher_warranty.contract" function update_notification.

This function is called on a weekly basis using this cron definition:

        <record id="ir_cron_module_update_notification" model="ir.cron">
            <field name="name">Update Notification</field>
            <field eval="True" name="active" />
            <field name="user_id" ref="base.user_root" />
            <field name="interval_number">1</field>
            <field name="interval_type">weeks</field>
            <field name="numbercall">-1</field>
            <field eval="False" name="doall" />
            <field eval="'publisher_warranty.contract'" name="model" />
            <field eval="'update_notification'" name="function" />
            <field eval="'(None,)'" name="args" />
            <field name="priority">1000</field>
        </record>

This cron is explicitly silenced in log:
                if cron_mode: # we don't want to see any stack trace in cron

Except the fact that the cron send data to OpenERP SA silently.

The get_sys_logs function execute arbitrary code from an URL:

url = config.get("publisher_warranty_url")

    uo = urllib2.urlopen(url, arguments_raw, **add_arg)
    result = {}
    try:
        submit_result = uo.read()
        result = safe_eval(submit_result)
    finally:
        uo.close()
    return result

If someone corrupt the source server or DNS, code can be send to all OpenERP instances opened to Internet.

Regards

Nicolas

Tags: security

Related branches

tags: added: security
description: updated
information type: Public → Private Security
information type: Private Security → Public Security
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

Even without compromission of the server, this exposes the instance to all kinds of man in the middle attacks.

The information being sent and the answer are transmitted unencrypted and the remote server is not authenticated in any fashion. (http and not https).

Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

My opinion is that this features should be extracted into a warranty addons that has to be installed when user subscribe to an OPW. And these information have to be send on a secure manner to OpenERP.

Such code can not be "hidden" into mail addon

description: updated
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

For those who want to manually deactivate this you just have to deactivate the cron named: Update Notification

summary: - [7.0/Trunk] get_sys_logs function is a major vulnerability
+ [7.0/Trunk] get_sys_logs function may allows arbitrary code execution
summary: - [7.0/Trunk] get_sys_logs function may allows arbitrary code execution
+ [6.1/7.0/Trunk] get_sys_logs function may allows arbitrary code
+ execution
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote : Re: [6.1/7.0/Trunk] get_sys_logs function may allows arbitrary code execution

Bugs also affect publisher_warranty send function of version 6.1:

def send(self, cr, uid, tb, explanations, remarks=None, issue_name=None):
        """ Method called by the client to send a problem to the publisher warranty server. """

        if not remarks:
            remarks = ""

        valid_contracts = self._get_valid_contracts(cr, uid)
        valid_contract = valid_contracts[0]

        try:
            origin = 'client'
            dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
            db_create_date = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date')
            user = self.pool.get("res.users").browse(cr, uid, uid)
            user_name = user.name
            email = user.user_email

            msg = {'contract_name': valid_contract.name,
                'tb': tb,
                'explanations': explanations,
                'remarks': remarks,
                'origin': origin,
                'dbname': cr.dbname,
                'dbuuid': dbuuid,
                'db_create_date': db_create_date,
                'issue_name': issue_name,
                'email': email,
                'user_name': user_name,
            }

            add_arg = {"timeout":30} if sys.version_info >= (2,6) else {}
            uo = urllib2.urlopen(config.get("publisher_warranty_url"),
                                    urllib.urlencode({'arg0': msg, "action": "send",}),**add_arg)
            try:
                submit_result = uo.read()
            finally:
                uo.close()

            result = safe_eval(submit_result)

            crm_case_id = result

            if not crm_case_id:
                return False

        except osv.except_osv:
            raise
        except Exception:
            _logger.warning("Error sending problem report", exc_info=1)
            raise osv.except_osv(_("Error"),
                                 _("Error during communication with the publisher warranty server."))

        return True

summary: - [6.1/7.0/Trunk] get_sys_logs function may allows arbitrary code
+ [6.0/6.1/7.0/Trunk] get_sys_logs function may allows arbitrary code
execution
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hi,

This mechanism allows the OpenERP Security Team to send important notification messages to the relevant OpenERP users, for example for very critical security notifications. It was used in the past to notify all users (not just OE/OPW customers!) about a critical vulnerability in OpenERP 6.0 that needed to be patched urgently [1], and all users of affected versions received a notification. This mechanism is meant to be unobtrusive but it is enabled by default.

Now about your bug report, it's not clear why you are claiming this could allow "arbitrary code execution"?

The return value from the OpenERP Publisher Warranty Servers is always passed to safe_eval (without eval context, which means it is very similar to literal_eval). So unless you want to report a security issue about `safe_eval` (which would be important in its own right), the worst this issue can cause, in case an attacker performed a prior successful attack on the machine's DNS servers (or upstream ones) or on the Publisher Warranty Servers is:
 - leak information about the OpenERP installation to the attacker
 - allow the attacker to send messages to OpenERP users

Even if this would be a significant problem, it is greatly mitigated by the fact that a prior successful attack is necessary, and still seems to be far from arbitrary code execution.

The fact that this code is located in the mail module is indeed questionable, and is because its main purpose is to be able to send urgent notifications to the users, which is made easiest using the mail facilities. This could be refactored to have the main code in `base` and some default fallback notification system, with `mail` extending it with a regular mail notifications.

Thank you for clarifying your bug description.

PS: The appropriate way to report security issues is always to make them private initially (regardless of any public information about the subject), then to discuss the full disclosure with the security team, ensuring that all appropriate measures are taken in a timely manner (validated patches, proper description of the issue and its consequences, notification to customers, etc.)
Disregarding this procedure is very unfortunate for all OpenERP users, and I'm not sure you would appreciate anyone else doing the same for any issue they would have found first.

Changed in openobject-addons:
status: New → Incomplete
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

[1] in previous post was supposed to refer to bug 832601, sorry.

Revision history for this message
Florent (florent.x) wrote :

FWIW, it's easy to disable for your customer installation.

Insert this in your custom addon:

https://gist.github.com/florentx/5918226

DISCLAIMER: it voids the guarantee probably

Revision history for this message
Florent (florent.x) wrote :

Be careful that it is not at the same place if you're running 6.1 or 7.0 ...

This is a known characteristic of spywares: they are mutating.

Always.

Revision history for this message
Launchpad Janitor (janitor) wrote :

[Expired for OpenERP Addons because there has been no activity for 60 days.]

Changed in openobject-addons:
status: Incomplete → Expired
To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.