diff options
author | Christian Heimes <christian@python.org> | 2015-10-01 13:30:13 +0200 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2015-10-19 12:17:58 -0400 |
commit | 785fc87f38b4811bc4ce43a0a9b2267ee7d500b4 (patch) | |
tree | cd8fac0416065cb5451311b354f25362ff632767 | |
parent | 0ca07419bbc2c4e499b4c37d2183d82b2640e816 (diff) | |
download | custodia-785fc87f38b4811bc4ce43a0a9b2267ee7d500b4.tar.gz custodia-785fc87f38b4811bc4ce43a0a9b2267ee7d500b4.tar.xz custodia-785fc87f38b4811bc4ce43a0a9b2267ee7d500b4.zip |
etcdstore: prevent path traversal attacks
A new internal method _absolute_key() is used to join key name and name
space. etcd treats the key space like a file system so the method checks
the key for '//', '.', and '..' to prevent invalid paths and path traversal
attacks.
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r-- | custodia/store/etcdstore.py | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/custodia/store/etcdstore.py b/custodia/store/etcdstore.py index 9a9e535..f7e55f4 100644 --- a/custodia/store/etcdstore.py +++ b/custodia/store/etcdstore.py @@ -2,7 +2,6 @@ from __future__ import print_function -import os import sys import etcd @@ -33,16 +32,25 @@ class EtcdStore(CSStore): repr(err))) raise CSStoreError('Error occurred while trying to init db') + def _absolute_key(self, key): + """Get absolute path to key and validate key""" + if '//' in key: + raise ValueError("Invalid empty components in key '%s'" % key) + parts = key.split('/') + if set(parts).intersection({'.', '..'}): + raise ValueError("Invalid relative components in key '%s'" % key) + return '/'.join([self.namespace] + parts).replace('//', '/') + def get(self, key): try: - result = self.etcd.get(os.path.join(self.namespace, key)) + result = self.etcd.get(self._absolute_key(key)) except etcd.EtcdException as err: log_error("Error fetching key %s: [%r]" % (key, repr(err))) raise CSStoreError('Error occurred while trying to get key') return result.value def set(self, key, value, replace=False): - path = os.path.join(self.namespace, key) + path = self._absolute_key(key) try: self.etcd.write(path, value, prevExist=replace) except etcd.EtcdAlreadyExist as err: @@ -52,7 +60,7 @@ class EtcdStore(CSStore): raise CSStoreError('Error occurred while trying to store key') def span(self, key): - path = os.path.join(self.namespace, key) + path = self._absolute_key(key) try: self.etcd.write(path, None, dir=True, prevExist=False) except etcd.EtcdAlreadyExist as err: @@ -62,7 +70,7 @@ class EtcdStore(CSStore): raise CSStoreError('Error occurred while trying to store key') def list(self, keyfilter='/'): - path = os.path.join(self.namespace, keyfilter) + path = self._absolute_key(keyfilter) if path != '/': path = path.rstrip('/') try: @@ -85,7 +93,7 @@ class EtcdStore(CSStore): def cut(self, key): try: - self.etcd.delete(os.path.join(self.namespace, key)) + self.etcd.delete(self._absolute_key(key)) except etcd.EtcdKeyNotFound: return False except etcd.EtcdException as err: |