Bug 11224 - multiple vulnerabilities in python-oauth2 (CVE-2013-4346, CVE-2013-4347)
: multiple vulnerabilities in python-oauth2 (CVE-2013-4346, CVE-2013-4347)
Product: Mageia
Classification: Unclassified
Component: Security
: 3
: i586 Linux
: Normal Severity: normal
: ---
Assigned To: QA Team
: Sec team
: http://lwn.net/Vulnerabilities/571988/
: MGA2TOO mga2-32-ok mga2-64-ok mga3-32...
: validated_update
  Show dependency treegraph
Reported: 2013-09-13 11:59 CEST by Oden Eriksson
Modified: 2013-10-28 22:26 CET (History)
3 users (show)

See Also:
Source RPM: python-oauth2
Status comment:

server.py (10.12 KB, text/x-python)
2013-10-26 12:41 CEST, claire robinson
client.py (6.68 KB, text/x-python)
2013-10-26 12:42 CEST, claire robinson

Description Oden Eriksson 2013-09-13 11:59:08 CEST

"Date: Thu, 12 Sep 2013 13:55:51 -0600
From: Kurt Seifried <kseifried@...hat.com>
To: oss-security@...ts.openwall.com, security@...ntu.com,
Subject: Re: cve requests for python-oauth2

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
Version: GnuPG v1.4.14 (GNU/Linux)




Steps to Reproduce:
Comment 1 Philippe Makowski 2013-10-09 09:12:27 CEST
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
Comment 2 Philippe Makowski 2013-10-09 10:06:04 CEST
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 ?
Comment 3 Colin Guthrie 2013-10-09 10:24:24 CEST
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!
Comment 4 Philippe Makowski 2013-10-09 19:25:08 CEST
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).
Comment 5 David Walser 2013-10-09 19:31:52 CEST
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.
Comment 6 Philippe Makowski 2013-10-14 15:04:41 CEST
done in cauldron
Comment 7 Philippe Makowski 2013-10-18 17:06:21 CEST
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.
Comment 8 David Walser 2013-10-18 21:28:27 CEST
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.
Comment 9 Philippe Makowski 2013-10-21 13:45:52 CEST

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)
Comment 10 David Walser 2013-10-21 19:12:10 CEST
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.
Comment 11 claire robinson 2013-10-24 13:16:03 CEST
Testing mga3 64 - some issues with the update..

Testing with the examples here

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.

Starting the server in one terminal tab and then the client in another terminal tab..

$ python server.py
Test server running... - - [24/Oct/2013 12:10:39] "GET https://photos.example.net/request_token HTTP/1.1" 200 - - - [24/Oct/2013 12:10:42] "GET https://photos.example.net/authorize?oauth_token=requestkey HTTP/1.1" 200 - - - [24/Oct/2013 12:10:45] "GET https://photos.example.net/access_token HTTP/1.1" 200 - - - [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'}

key: requestkey
secret: requestsecret
callback confirmed? true

* Authorize the request token ...

REQUEST (via url query string)
parameters: {u'oauth_token': u'requestkey'}

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'}

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='}

non-oauth parameters: {u'file': u'vacation.jpg', u'size': u'original'}


Kill the server with ctrl-c

Some regression here..

$ python server.py
Test server running...
Exception happened during processing of request from ('', 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__
  File "/usr/lib64/python2.7/BaseHTTPServer.py", line 340, in handle
  File "/usr/lib64/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
  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>
  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
  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: ''
Comment 12 Philippe Makowski 2013-10-24 21:28:23 CEST
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
Comment 13 Philippe Makowski 2013-10-25 16:01:36 CEST

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.
Comment 14 claire robinson 2013-10-25 18:08:29 CEST
Testing complete mga3 64

Well done Philippe, it completes successfully this time.
Comment 15 claire robinson 2013-10-25 18:10:17 CEST
Could somebody give an advisory for this please. Testing the others shortly.
Comment 16 claire robinson 2013-10-25 18:24:49 CEST
Testing complete mga2 32 & 64 and mga3 32
Comment 17 David Walser 2013-10-25 18:54:49 CEST
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.
Comment 18 Philippe Makowski 2013-10-25 19:27:23 CEST
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.
Comment 19 claire robinson 2013-10-25 19:36:04 CEST
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

Comment 20 claire robinson 2013-10-25 19:38:47 CEST
Altered to 'authorization flows'
Comment 21 Thomas Backlund 2013-10-25 23:19:20 CEST
Update pushed:
Comment 22 claire robinson 2013-10-26 12:41:54 CEST
Created attachment 4458 [details]

Attaching test scripts for next time this is updated.
Comment 23 claire robinson 2013-10-26 12:42:15 CEST
Created attachment 4459 [details]

Note You need to log in before you can comment on or make changes to this bug.