From e5984fbfc3141d83184c13b627a918f4d9913d0c Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Sun, 29 Jul 2018 14:10:42 +0200 Subject: [PATCH] [FIX] base: strengthen ir.attachment access rights An ir.attachment record can be served as a request's reponse if: - a request triggers a 404 - the ir.attachment record has its url field matching the url of the failed and is of binary type Following rev[1], portal users have the right to create these kind of records, and it is a security concern. This patch restrict the ability to create and write on the ir.attachment records that may be served through the dispatch's exception mechanism to settings users. As the asset bundles files are served through the use of these special ir.attachment, we make sure to retrieve only ir.attachment records created by the superuser in the `get_attachment` method. As website administrators often need to play with these special ir.attachment, we also let to this group the permission to manage them. [1] 61065b6d04248aa496765e1035c4c90cbdc38de7 --- addons/website/models/website.py | 3 +++ openerp/addons/base/ir/ir_attachment.py | 23 +++++++++++++++++++++++ openerp/addons/base/ir/ir_qweb.py | 5 ++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index b4b95f00ab5..82934bc7bf0 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -646,6 +646,9 @@ class ir_attachment(osv.osv): 'website_url': fields.related("local_url", string="Attachment URL", type='char', deprecated=True), # related for backward compatibility with saas-6 } + def get_serving_groups(self): + return super(ir_attachment, self).get_serving_groups() + ['base.group_website_designer'] + class res_partner(osv.osv): _inherit = "res.partner" diff --git a/openerp/addons/base/ir/ir_attachment.py b/openerp/addons/base/ir/ir_attachment.py index eab322fb7b5..b485876a353 100644 --- a/openerp/addons/base/ir/ir_attachment.py +++ b/openerp/addons/base/ir/ir_attachment.py @@ -235,6 +235,29 @@ class ir_attachment(osv.osv): index_content = ustr("\n".join(words)) return index_content + def get_serving_groups(self): + """ An ir.attachment record may be used as a fallback in the + http dispatch if its type field is set to "binary" and its url + field is set as the request's url. Only the groups returned by + this method are allowed to create and write on such records. + """ + return ['base.group_system'] + + def _check_serving_attachments(self, cr, uid, ids, context=None): + # restrict writing on attachments that could be served by the + # ir.http's dispatch exception handling + user = self.pool['res.users'].browse(cr, uid, uid, context=context) + for ira in self.browse(cr, uid, ids, context): + if ira.type == 'binary' and ira.url: + has_group = user.has_group + print self.get_serving_groups() + if not any([has_group(g) for g in self.get_serving_groups()]): + return False + return True + + _constraints = [ + (_check_serving_attachments, 'Sorry, you are not allowed to write on this document', ['type', 'url']) + ] _name = 'ir.attachment' _columns = { diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index 8045497e429..e0027652d4c 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -1259,7 +1259,10 @@ class AssetsBundle(object): def get_attachments(self, type, inc=None): ira = self.registry['ir.attachment'] - domain = [('url', '=like', '/web/content/%%-%s/%s%s.%s' % (self.version, self.xmlid, ('%%' if inc is None else '.%s' % inc), type))] + domain = [ + ('url', '=like', '/web/content/%%-%s/%s%s.%s' % (self.version, self.xmlid, ('%%' if inc is None else '.%s' % inc), type)), + ('create_uid', '=', openerp.SUPERUSER_ID), + ] attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, order='name asc', context=self.context) return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)