is there a safe marshaler?

Alan Kennedy alanmk at hotmail.com
Thu Feb 10 19:55:22 EST 2005


[Alan Kennedy]
 >> Well, the python JSON codec provided appears to use eval, which might
 >> make it *seem* unsecure.
 >>
 >> http://www.json-rpc.org/pyjsonrpc/index.xhtml
 >>
 >> But a more detailed examination of the code indicates, to this reader
 >> at least, that it can be made completely secure very easily. The
 >> designer of the code could very easily have not used eval, and
 >> possibly didn't do so simply because he wasn't thinking in security
 >> terms.

[Irmen de Jong]
 > I think we (?) should do this then, and send it to the author
 > of the original version so that he can make an improved version
 > available? I think there are more people interested in a secure
 > marshaling implementation than just me :)

I should learn to keep my mouth zipped :-L

OK, I really don't have time for a detailed examination of either the 
JSON spec or the python impl of same. And I *definitely* don't have time 
for a detailed security audit, much though I'd love to.

But I'll try to help: the code changes are really very simple. So I've 
edited the single affected file, json.py, and here's a patch: But be 
warned that I haven't even run this code!

Index: json.py
===================================================================
--- json.py	(revision 2)
+++ json.py	(working copy)
@@ -66,8 +66,10 @@

      def parseValue(self, tkns):
          (ttype, tstr, ps, pe, lne) = tkns.next()
-        if ttype in [token.STRING, token.NUMBER]:
-            return eval(tstr)
+        if ttype  == token.STRING:
+            return unicode(tstr)
+        if ttype  == token.NUMBER:
+            return float(tstr)
          elif ttype == token.NAME:
              return self.parseName(tstr)
          elif ttype == token.OP:
@@ -110,7 +112,12 @@
              while 1:
                  (ttype, tstr, ps, pe, lne) = tkns.next()
                  if ttype == token.STRING:
-                    nme =  eval(tstr)
+                    possible_ident = unicode(tstr)
+                    try:
+                        # Python identifiers have to be ascii
+                        nme =  possible_ident.encode('ascii')
+                    except UnicodeEncodeError:
+                        raise "Non-ascii identifier"
                      (ttype, tstr, ps, pe, lne) = tkns.next()
                      if tstr == ":":
                          v = self.parseValue(tkns)

I'll leave contacting the author to you, if you wish.

 > I'll still have to look at Twisted's Jelly.

Hmmm, s-expressions, interesting. But you'd have to write your own 
s-expression parser and jelly RPC client to get up and running in other 
languages.

regards,

-- 
alan kennedy
------------------------------------------------------
email alan:              http://xhaus.com/contact/alan



More information about the Python-list mailing list