summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2015-10-01 13:30:13 +0200
committerSimo Sorce <simo@redhat.com>2015-10-19 12:17:58 -0400
commit785fc87f38b4811bc4ce43a0a9b2267ee7d500b4 (patch)
treecd8fac0416065cb5451311b354f25362ff632767
parent0ca07419bbc2c4e499b4c37d2183d82b2640e816 (diff)
downloadcustodia-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.py20
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: