ff3dbe1ea9
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=131
144 lines
5.5 KiB
Diff
144 lines
5.5 KiB
Diff
From 43b1f8fb6608c944812bc5bcd9da407624409ac7 Mon Sep 17 00:00:00 2001
|
|
From: Erik Johnson <palehose@gmail.com>
|
|
Date: Fri, 24 Aug 2018 10:35:55 -0500
|
|
Subject: [PATCH] Fixes: CVE-2018-15750, CVE-2018-15751
|
|
|
|
Ensure that tokens are hex to avoid hanging/errors in cherrypy
|
|
|
|
Add empty token salt-api integration tests
|
|
|
|
Handle Auth exceptions in run_job
|
|
|
|
Update tornado test to correct authentication message
|
|
---
|
|
salt/client/__init__.py | 8 ++++
|
|
salt/netapi/rest_cherrypy/app.py | 13 ++++++-
|
|
.../netapi/rest_cherrypy/test_app.py | 39 +++++++++++++++++++
|
|
.../netapi/rest_tornado/test_app.py | 2 +-
|
|
4 files changed, 60 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
|
|
index dcbc1473e1..77f2a963f7 100644
|
|
--- a/salt/client/__init__.py
|
|
+++ b/salt/client/__init__.py
|
|
@@ -349,6 +349,10 @@ class LocalClient(object):
|
|
raise SaltClientError(
|
|
'The salt master could not be contacted. Is master running?'
|
|
)
|
|
+ except AuthenticationError as err:
|
|
+ raise AuthenticationError(err)
|
|
+ except AuthorizationError as err:
|
|
+ raise AuthorizationError(err)
|
|
except Exception as general_exception:
|
|
# Convert to generic client error and pass along message
|
|
raise SaltClientError(general_exception)
|
|
@@ -415,6 +419,10 @@ class LocalClient(object):
|
|
raise SaltClientError(
|
|
'The salt master could not be contacted. Is master running?'
|
|
)
|
|
+ except AuthenticationError as err:
|
|
+ raise AuthenticationError(err)
|
|
+ except AuthorizationError as err:
|
|
+ raise AuthorizationError(err)
|
|
except Exception as general_exception:
|
|
# Convert to generic client error and pass along message
|
|
raise SaltClientError(general_exception)
|
|
diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py
|
|
index 78ea3c3fef..c272674146 100644
|
|
--- a/salt/netapi/rest_cherrypy/app.py
|
|
+++ b/salt/netapi/rest_cherrypy/app.py
|
|
@@ -1167,6 +1167,13 @@ class LowDataAdapter(object):
|
|
if token:
|
|
chunk['token'] = token
|
|
|
|
+ if 'token' in chunk:
|
|
+ # Make sure that auth token is hex
|
|
+ try:
|
|
+ int(chunk['token'], 16)
|
|
+ except (TypeError, ValueError):
|
|
+ raise cherrypy.HTTPError(401, 'Invalid token')
|
|
+
|
|
if client:
|
|
chunk['client'] = client
|
|
|
|
@@ -2167,7 +2174,11 @@ class Events(object):
|
|
|
|
:return bool: True if valid, False if not valid.
|
|
'''
|
|
- if auth_token is None:
|
|
+ # Make sure that auth token is hex. If it's None, or something other
|
|
+ # than hex, this will raise a ValueError.
|
|
+ try:
|
|
+ int(auth_token, 16)
|
|
+ except ValueError:
|
|
return False
|
|
|
|
# First check if the given token is in our session table; if so it's a
|
|
diff --git a/tests/integration/netapi/rest_cherrypy/test_app.py b/tests/integration/netapi/rest_cherrypy/test_app.py
|
|
index 000b7418bf..5865510fd7 100644
|
|
--- a/tests/integration/netapi/rest_cherrypy/test_app.py
|
|
+++ b/tests/integration/netapi/rest_cherrypy/test_app.py
|
|
@@ -124,6 +124,45 @@ class TestRun(cptc.BaseRestCherryPyTest):
|
|
})
|
|
self.assertEqual(response.status, '401 Unauthorized')
|
|
|
|
+ def test_run_empty_token(self):
|
|
+ '''
|
|
+ Test the run URL with empty token
|
|
+ '''
|
|
+ cmd = dict(self.low, **{'token': ''})
|
|
+ body = urlencode(cmd)
|
|
+
|
|
+ request, response = self.request('/run', method='POST', body=body,
|
|
+ headers={
|
|
+ 'content-type': 'application/x-www-form-urlencoded'
|
|
+ })
|
|
+ assert response.status == '401 Unauthorized'
|
|
+
|
|
+ def test_run_empty_token_upercase(self):
|
|
+ '''
|
|
+ Test the run URL with empty token with upercase characters
|
|
+ '''
|
|
+ cmd = dict(self.low, **{'ToKen': ''})
|
|
+ body = urlencode(cmd)
|
|
+
|
|
+ request, response = self.request('/run', method='POST', body=body,
|
|
+ headers={
|
|
+ 'content-type': 'application/x-www-form-urlencoded'
|
|
+ })
|
|
+ assert response.status == '401 Unauthorized'
|
|
+
|
|
+ def test_run_wrong_token(self):
|
|
+ '''
|
|
+ Test the run URL with incorrect token
|
|
+ '''
|
|
+ cmd = dict(self.low, **{'token': 'bad'})
|
|
+ body = urlencode(cmd)
|
|
+
|
|
+ request, response = self.request('/run', method='POST', body=body,
|
|
+ headers={
|
|
+ 'content-type': 'application/x-www-form-urlencoded'
|
|
+ })
|
|
+ assert response.status == '401 Unauthorized'
|
|
+
|
|
|
|
class TestWebhookDisableAuth(cptc.BaseRestCherryPyTest):
|
|
|
|
diff --git a/tests/integration/netapi/rest_tornado/test_app.py b/tests/integration/netapi/rest_tornado/test_app.py
|
|
index beb085db1e..01abd354a7 100644
|
|
--- a/tests/integration/netapi/rest_tornado/test_app.py
|
|
+++ b/tests/integration/netapi/rest_tornado/test_app.py
|
|
@@ -237,7 +237,7 @@ class TestSaltAPIHandler(_SaltnadoIntegrationTestCase):
|
|
self.assertEqual(len(ret), 3) # make sure we got 3 responses
|
|
self.assertIn('jid', ret[0]) # the first 2 are regular returns
|
|
self.assertIn('jid', ret[1])
|
|
- self.assertIn('Authentication error occurred.', ret[2]) # bad auth
|
|
+ self.assertIn('Failed to authenticate', ret[2]) # bad auth
|
|
self.assertEqual(ret[0]['minions'], sorted(['minion', 'sub_minion', 'localhost']))
|
|
self.assertEqual(ret[1]['minions'], sorted(['minion', 'sub_minion', 'localhost']))
|
|
|
|
--
|
|
2.17.1
|
|
|
|
|