http://www.openwall.com/lists/oss-security/2013/09/12/7 "Date: Thu, 12 Sep 2013 13:55:51 -0600 From: Kurt Seifried <kseifried@...hat.com> To: oss-security@...ts.openwall.com, security@...ntu.com, chuck.short@...onical.com Subject: Re: cve requests for python-oauth2 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I have some clarifying questions, see below On 09/12/2013 11:34 AM, Seth Arnold wrote: > Hello Kurt, all, I recently gave python-oauth2 a quick audit and > believe it needs three CVE entries: > > - _check_signature() ignores the nonce value when validating signed > urls > > def _check_signature(self, request, consumer, token): timestamp, > nonce = request._get_timestamp_nonce() > self._check_timestamp(timestamp) signature_method = > self._get_signature_method(request) > > try: signature = request.get_parameter('oauth_signature') except: > raise MissingSignature('Missing oauth_signature.') > > # Validate the signature. valid = signature_method.check(request, > consumer, token, signature) > > if not valid: key, base = signature_method.signing_base(request, > consumer, token) > > raise Error('Invalid signature. Expected signature base ' 'string: > %s' % base) > > Ignoring the nonce value enables replay attacks. > > This appears to already be known (ignoring the misleading title): > https://github.com/simplegeo/python-oauth2/issues/129 Yeah ignoring nonces is not good. Oddly enough CWE only has CWE-323 "Reusing a Nonce, Key Pair in Encryption" there is nothing for "completely ignored nonce". So this gets a CVE. Please use CVE-2013-4346 for this issue. > - _check_timestamp() does not constrain how far into the future > times may be, (also does not prevent negative times, but probably > not relevant for a CVE) > > def _check_timestamp(self, timestamp): """Verify that timestamp is > recentish.""" timestamp = int(timestamp) now = int(time.time()) > lapsed = now - timestamp if lapsed > self.timestamp_threshold: > raise Error('Expired timestamp: given %d and now %s has a ' > 'greater difference than threshold %d' % (timestamp, now, > self.timestamp_threshold)) > > The timestamps are probably most useful to limit the number of > nonces that must be stored and compared but it seems generally > useful to prevent timestamps from the distant future from being > allowed. I see how this can be a problem, but with proper nonces it shouldn't be an issue on it on, correct? As such I'm leaning towards classifying this one as security hardening. > - make_nonce(), generate_nonce(), and generate_verifier() use a > poor prng: > > @classmethod def make_nonce(cls): """Generate pseudorandom > number.""" return str(random.randint(0, 100000000)) > > > def generate_nonce(length=8): """Generate pseudorandom number.""" > return ''.join([str(random.randint(0, 9)) for i in range(length)]) > > > def generate_verifier(length=8): """Generate pseudorandom > number.""" return ''.join([str(random.randint(0, 9)) for i in > range(length)]) > > Nonces may not need full-blown /dev/urandom but the Python > 'random' documentation clearly states the results are repeatable. > The lack of seeding in this module makes me think this is too weak > for this use. > > The safety of oauth depends upon the verifier being unguessable, > and this is both too short, with too few character choices, and > probably does need full-blown /dev/urandom style randomness. > > The poor PRNG for the nonce has been known since 2010-04-24 (silly > github, hover your _mouse pointer_ over the "3 years ago" text in > the bug report): > https://github.com/simplegeo/python-oauth2/issues/9 Yeah to quote Python random(): However, being completely deterministic, it is not suitable for all purposes, and is completely unsuitable for cryptographic purposes. so even with a 'random' seed can attacker could conceivably take a sample and then brute force the original seed allowing them to predict future values. So this would go under insufficient randomness and get a CVE. Please use CVE-2013-4347 for this issue. > > > Thanks > - -- Kurt Seifried Red Hat Security Response Team (SRT) PGP: 0x5E267993 A90B F995 7350 148F 66BF 7554 160D 4553 5E26 7993 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAEBAgAGBQJSMhxHAAoJEBYNRVNeJnmTo1MQALHLps+XJ37Nfge/ZO0lNh0F /CbiL9rkwYRdM61kKi13H995HcGeCcjiPI+v/6GlIEWJIrtHbf8bkYA1aqQF5cvi yb1cYQ0Q8h51q6mC57IPfx3EIRLbcHws+WzWrHYBrGz3yHzfLy9ZJs5D1CV8UHve X18QTmU654vEIZ4GhdWQnvktzCHlZ32tigP+PD+utXPQ/sjd0C3GGVicsh1BNVyG GB006iRrwlA1xgyyJxLXVcz24zeXFTDpHq8NQVXfj4LILAVGzyS53RWh8+FocdR0 HoUSPZfzg5N2+vt8HjjWJNdlaAW2uKijR6eNSNDF5HH3I+LuCY01sww+40IN6I+U ncVuo1U8c4F+Nt8EjrxMJAa1DCdy0voee1yn8fQt7/doAN7yZdElaispQ0YkWqJC HQVdz8+1k/NxrLyJQ3vKZPh6qiPIoYykRFkTUjZQJ/I5yJ2ffRP76/mNkIMsWZy2 YVMCeeZbHe7g7y56FWE6poCI7JYRGXPLWGOTioOI2RSVYGVfsyEEZAAdISKIpS9z xw9aPZCd3IYf9ouUV+Ra85egWWvZf7VC9sESa5CCqEWX1XO0lXKR3TadzVYtK9+q dY3ZhlaYlmZbZWlJagesCxp9KL+LYbRkw/Q+YoboLxJMaHBw2AaQsbEpK4mPAeXe JzSDqUqrfiG4W4qpITFb =hOZj -----END PGP SIGNATURE----- " Reproducible: Steps to Reproduce:
Version: 2 => CauldronAssignee: bugsquad => mageiaWhiteboard: (none) => MGA3TOO, MGA2TOO
CC: (none) => makowski.mageia
Colin, for what other packages you needed this one ? I'm looking with Debian and Fedora how to fix these, but a more long term solution would certainly be to drop this package and use for example https://pypi.python.org/pypi/oauthlib
we have this package only in Mga3 and Cauldron and only for python-twitter for what I know so I'm in favor to update python-twitter as the most recent version of python-twitter (v1.1) no longer uses that library - they switched to using Requests and it's oauth helper lib (https://code.google.com/p/python-twitter/issues/detail?id=257) and drop this buggy and not maintained package (python-oauth2) do you aggree ?
Yup, I agree. I only used it for python-twitter to make a supybot twitter plugin (or rather update an existing one). Happy to go with the new version of python-twitter. Would be happy enough to push the new version to mga3 too if that's easier. I doubt many people use it and they may as well use the new one if they do!
ok so I need to add Requests-OAuthlib as a new package (python-requests-oauthlib), update python-twitter to latest (1.1) that work with Twitter API v1.1 (python-twitter 0.8.2 that we have now only work with v1.0 API) remove python-oauth2 and doing that for Cauldron, Mga3 and Mga2 I every one agree I do it this way Today neither Debian, Ubuntu, Fedora have a patch for the two CVE and the mainstream seems dead. In fact they were discovered in Ubuntu when they investigate to get it including into main for what I saw in September and since then no patch (https://bugs.launchpad.net/ubuntu/+source/python-oauth2/+bug/1213934).
Sounds like a good plan. Thanks for looking at this Philippe! I wonder what other packages need updated because of the Twitter API. Probably one of the telepathy ones at least. Oh well, that's a problem for another day.
done in cauldron
There are more dependencies than only python-twitter, openstack-keystone and twixer need it too So I think I will submit a patch to fix these two CVE and re import python-oauth2 after looking at the code, I think I can do it.
We don't have openstack keystone in Mageia 3, so don't worry about that. If there isn't a newer twixer that doesn't use it, I guess we're stuck with patching it though. Thanks Philippe.
python-oauth2-1.5.170-1.2.mga2.noarch python-oauth2-1.5.170-1.2.mga2.src python-oauth2-1.5.170-2.2.mga3.noarch python-oauth2-1.5.170-2.2.mga3.src Are available By the way, these CVE (and even more CVE-2013-4346) are strange since python-oauth2 Server is only : """A skeletal implementation of a service provider, providing protected resources to requests from authorized consumers. It don't intend to be a full service provider And for Mageia, no packages use the server part of python-oauth2 (only a contrib part of openstack keystone potentially use it)
Assignee: mageia => qa-bugs
Thanks Philippe! Do you or Oden think you could come up with intelligible descriptions for these security issues that we could use for the advisory? Somehow I don't think talking about a "nonce" is going to be helpful for anyone.
CC: (none) => luigiwalser
CC: luigiwalser => (none)
Version: Cauldron => 3Whiteboard: MGA3TOO, MGA2TOO => MGA2TOO
Testing mga3 64 - some issues with the update.. Testing with the examples here https://github.com/simplegeo/python-oauth2/pull/64 server.py can be found here https://github.com/jace/python-oauth2/blob/261388117c7228c2e0d5bbf45e6b30c6dfe81da8/example/server.py client.py can be found here https://github.com/jace/python-oauth2/blob/261388117c7228c2e0d5bbf45e6b30c6dfe81da8/example/client.py These are not yet merged apparently and use oath2 rather then oauth. The examples in the simplegeo repository fail. Before ------ Starting the server in one terminal tab and then the client in another terminal tab.. $ python server.py Test server running... 127.0.0.1 - - [24/Oct/2013 12:10:39] "GET https://photos.example.net/request_token HTTP/1.1" 200 - 127.0.0.1 - - [24/Oct/2013 12:10:42] "GET https://photos.example.net/authorize?oauth_token=requestkey HTTP/1.1" 200 - 127.0.0.1 - - [24/Oct/2013 12:10:45] "GET https://photos.example.net/access_token HTTP/1.1" 200 - 127.0.0.1 - - [24/Oct/2013 12:10:48] "POST http://photos.example.net/photos HTTP/1.1" 200 - $ python client.py ** OAuth Python Library Example ** * Obtain a request token ... REQUEST (via headers) parameters: {'oauth_body_hash': '2jmj7l5rSw0yVb/vlWAYkK/YBwk=', u'oauth_nonce': u'3730088', u'oauth_timestamp': u'1382613038', u'oauth_consumer_key': u'key', 'oauth_signature_method': 'PLAINTEXT', u'oauth_version': u'1.0', 'oauth_signature': 'secret&', u'oauth_callback': u'http://printer.example.com/request_token_ready'} GOT key: requestkey secret: requestsecret callback confirmed? true * Authorize the request token ... REQUEST (via url query string) parameters: {u'oauth_token': u'requestkey'} GOT http://printer.example.com/request_token_ready?oauth_verifier=verifier verifier: verifier * Obtain an access token ... REQUEST (via headers) parameters: {'oauth_body_hash': '2jmj7l5rSw0yVb/vlWAYkK/YBwk=', u'oauth_nonce': u'2470446', u'oauth_timestamp': u'1382613044', 'oauth_signature_method': 'PLAINTEXT', u'oauth_consumer_key': u'key', u'oauth_verifier': u'verifier', u'oauth_version': u'1.0', u'oauth_token': u'requestkey', 'oauth_signature': 'secret&requestsecret'} GOT key: accesskey secret: accesssecret * Access protected resources ... REQUEST (via post body) parameters: {'oauth_body_hash': '2jmj7l5rSw0yVb/vlWAYkK/YBwk=', u'oauth_nonce': u'73312455', u'oauth_timestamp': u'1382613047', u'oauth_consumer_key': u'key', 'oauth_signature_method': 'HMAC-SHA1', u'oauth_version': u'1.0', u'oauth_token': u'accesskey', 'oauth_signature': 'LomNizxXVT+Rmx6RE6IXUU562iM='} GOT non-oauth parameters: {u'file': u'vacation.jpg', u'size': u'original'} Done. Kill the server with ctrl-c After ----- Some regression here.. $ python server.py Test server running... ---------------------------------------- Exception happened during processing of request from ('127.0.0.1', 56857) Traceback (most recent call last): File "/usr/lib64/python2.7/SocketServer.py", line 295, in _handle_request_noblock self.process_request(request, client_address) File "/usr/lib64/python2.7/SocketServer.py", line 321, in process_request self.finish_request(request, client_address) File "/usr/lib64/python2.7/SocketServer.py", line 334, in finish_request self.RequestHandlerClass(request, client_address, self) File "server.py", line 165, in __init__ BaseHTTPRequestHandler.__init__(self, *args, **kwargs) File "/usr/lib64/python2.7/SocketServer.py", line 649, in __init__ self.handle() File "/usr/lib64/python2.7/BaseHTTPServer.py", line 340, in handle self.handle_one_request() File "/usr/lib64/python2.7/BaseHTTPServer.py", line 328, in handle_one_request method() File "server.py", line 197, in do_GET token = self.oauth_server.fetch_request_token(oauth_request) File "server.py", line 108, in fetch_request_token consumer = self._get_consumer(oauth_request) File "server.py", line 144, in _get_consumer consumer = self.data_store.lookup_consumer(consumer_key) AttributeError: 'NoneType' object has no attribute 'lookup_consumer' ---------------------------------------- $ python client.py ** OAuth Python Library Example ** * Obtain a request token ... REQUEST (via headers) parameters: {'oauth_body_hash': '2jmj7l5rSw0yVb/vlWAYkK/YBwk=', u'oauth_nonce': u'94334183', u'oauth_timestamp': u'1382613291', u'oauth_consumer_key': u'key', 'oauth_signature_method': 'PLAINTEXT', u'oauth_version': u'1.0', 'oauth_signature': 'secret&', u'oauth_callback': u'http://printer.example.com/request_token_ready'} Traceback (most recent call last): File "client.py", line 169, in <module> run_example() File "client.py", line 107, in run_example token = client.fetch_request_token(oauth_request) File "client.py", line 63, in fetch_request_token response = self.connection.getresponse() File "/usr/lib64/python2.7/httplib.py", line 1045, in getresponse response.begin() File "/usr/lib64/python2.7/httplib.py", line 409, in begin version, status, reason = self._read_status() File "/usr/lib64/python2.7/httplib.py", line 373, in _read_status raise BadStatusLine(line) httplib.BadStatusLine: ''
Whiteboard: MGA2TOO => MGA2TOO feedback
may be I need to rewrite the second patch (oauth2-1.5.170-mga-nonce.patch) to be more exhaustive thanks for the feed back
python-oauth2-1.5.170-1.3.mga2.noarch python-oauth2-1.5.170-1.3.mga2.src python-oauth2-1.5.170-2.3.mga3.noarch python-oauth2-1.5.170-2.3.mga3.src Are available They fix CVE-2013-4347 for CVE-2013-4346 I don't have solution as I said python-oauth2 Server is only : """A skeletal implementation of a service provider, providing protected resources to requests from authorized consumers. It don't intend to be a full service provider if someone want to use this skeletal implementation, he have to be aware of CVE-2013-4346 and take care of this in his own code.
Whiteboard: MGA2TOO feedback => MGA2TOO
Testing complete mga3 64 Well done Philippe, it completes successfully this time.
Whiteboard: MGA2TOO => MGA2TOO mga3-64-ok
Could somebody give an advisory for this please. Testing the others shortly.
Testing complete mga2 32 & 64 and mga3 32
Whiteboard: MGA2TOO mga3-64-ok => MGA2TOO mga2-32-ok mga2-64-ok mga3-32-ok mga3-64-ok
All I know is the issue CVE-2013-4347 is about insufficient randomness, but I don't totally grasp what the random numbers are used for or the implications of insufficient randomness here. I'm hoping Oden or Philippe understand the issue well enough to write a description for it.
Something like that ? It was found that in python-oauth2, an application for authorizing flows for web application, the nonce value generated isn't random enough, because while doing bulk operations, nonce might get repeated, so there is a chance of predictability. This could allow MITM attackers to conduct replay attacks.
Thanks Philippe. Advisory uploaded as.. + It was found that in python-oauth2, an application for authorizing flows for + web applications, the nonce value generated isn't sufficiently random. + While doing bulk operations the nonce might be repeated, so there is a chance + of predictability. This could allow MITM attackers to conduct replay attacks. + (CVE-2013-4347) Could sysadmin please push from 2&3 core/updates_testing to updates Thanks!
Keywords: (none) => validated_updateCC: (none) => sysadmin-bugs
Altered to 'authorization flows'
Update pushed: http://advisories.mageia.org/MGASA-2013-0314.html
Status: NEW => RESOLVEDCC: (none) => tmbResolution: (none) => FIXED
Created attachment 4458 [details] server.py Attaching test scripts for next time this is updated.
Created attachment 4459 [details] client.py
URL: http://www.openwall.com/lists/oss-security/2013/09/12/7 => http://lwn.net/Vulnerabilities/571988/