Merge lp:~openerp-dev/openobject-client/trunk-bug-671926-nch into lp:openobject-client

Proposed by Naresh(OpenERP)
Status: Merged
Merged at revision: 1923
Proposed branch: lp:~openerp-dev/openobject-client/trunk-bug-671926-nch
Merge into: lp:openobject-client
Diff against target: 59 lines (+20/-3)
1 file modified
bin/tiny_socket.py (+20/-3)
To merge this branch: bzr merge lp:~openerp-dev/openobject-client/trunk-bug-671926-nch
Reviewer Review Type Date Requested Status
tfr (Openerp) Pending
Olivier Dony (Odoo) Pending
Naresh(OpenERP) Pending
Review via email: mp+66747@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hi Naresh,

May I suggest some additional improvements:
- please include the module and name in the exceptions message, for diagnostics purpose, e.g:
   raise cPickle.UnpicklingError('Unsafe pickled class instance: %s.%s' % (module,name))

- different kinds of exceptions may be passed over netrpc apparently, so until we patch the server to wrap them all, we can allow them all like this (need to add import 'exceptions' and 'types'):

  EXCEPTION_CLASSES = [x for x in dir(exceptions) if type(getattr(exceptions,x)) == types.TypeType]
  SAFE_CLASSES = { 'exceptions' : EXCEPTION_CLASSES }

Thanks!

1918. By Naresh(OpenERP)

[IMP]:included module and name in the exceptions message

Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote :

> type(getattr(exceptions,x)) == types.TypeType

No need to go through `types.TypeType`, we can just use `type` here:

    >>> types.TypeType is type
    True

I'd also use `issubclass(getattr(exceptions, x), Exception)` as the filter, instead. Makes what we're interested in clearer, and lets system-stopping exceptions go through unmolested.

On the other hand, are we sure it's not possible for attackers to get new stuff into `exceptions` before this code runs?

1919. By Naresh(OpenERP)

[IMP]:added all types of exceptions in the safe_classes

Revision history for this message
Naresh(OpenERP) (nch-openerp) wrote :

Hello Olivier,

Thanks for the suggestions !

I have made the improvements. Can you please verify them.

Thanks,

Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

@Xavier: thanks for the suggestions. I don't think system-stopping exceptions should be sent via RPC to the client, but using issubclass() might be more readable anyhow. As for altering 'exceptions', if an attacker had a way to do it, then he also has a way to directly execute arbitrary code, so this check does not help.

@Naresh: looks good, could you apply Xavier's suggestion with issubclass()?

Revision history for this message
Naresh(OpenERP) (nch-openerp) wrote :

getattr will return a 'str' and not a class instance also we can have non Exception type like the built-ins , __doc__ the docstrings etc.

so the type check is appropriate.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/tiny_socket.py'
2--- bin/tiny_socket.py 2010-01-12 09:24:17 +0000
3+++ bin/tiny_socket.py 2011-07-12 06:51:23 +0000
4@@ -1,6 +1,6 @@
5 # -*- coding: utf-8 -*-
6 ##############################################################################
7-#
8+#
9 # OpenERP, Open Source Management Solution
10 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
11 #
12@@ -15,13 +15,15 @@
13 # GNU Affero General Public License for more details.
14 #
15 # You should have received a copy of the GNU Affero General Public License
16-# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19 ##############################################################################
20
21 import socket
22 import cPickle
23+import cStringIO
24 import sys
25+import exceptions
26 import options
27
28 DNS_CACHE = {}
29@@ -42,6 +44,17 @@
30 self.faultString = faultString
31 self.args = (faultCode, faultString)
32
33+# Safety class instance loader for unpickling.
34+# Inspired by http://nadiana.com/python-pickle-insecure#How_to_Make_Unpickling_Safer
35+EXCEPTION_CLASSES = [x for x in dir(exceptions) if type(getattr(exceptions,x)) == type]
36+SAFE_CLASSES = { 'exceptions' : EXCEPTION_CLASSES }
37+def find_global(module, name):
38+ if module not in SAFE_CLASSES or name not in SAFE_CLASSES[module]:
39+ raise cPickle.UnpicklingError('Attempting to unpickle unsafe module %s.%s' % (module,name))
40+ __import__(module)
41+ mod = sys.modules[module]
42+ return getattr(mod, name)
43+
44 class mysocket:
45 def __init__(self, sock=None):
46 if sock is None:
47@@ -84,7 +97,11 @@
48 size = int(read(self.sock, 8))
49 buf = read(self.sock, 1)
50 exception = buf != '0' and buf or False
51- res = cPickle.loads(read(self.sock, size))
52+ buf = read(self.sock, size)
53+ msgio = cStringIO.StringIO(buf)
54+ unpickler = cPickle.Unpickler(msgio)
55+ unpickler.find_global = find_global
56+ res = unpickler.load()
57
58 if isinstance(res[0],Exception):
59 if exception: