diff --git a/ironic_inspector/node_cache.py b/ironic_inspector/node_cache.py index 4dcc78b21..a08eed9f1 100644 --- a/ironic_inspector/node_cache.py +++ b/ironic_inspector/node_cache.py @@ -18,6 +18,7 @@ import contextlib import copy import datetime import json +import operator from automaton import exceptions as automaton_errors from ironicclient import exceptions @@ -30,7 +31,6 @@ from oslo_utils import timeutils from oslo_utils import uuidutils import six from sqlalchemy.orm import exc as orm_errors -from sqlalchemy import text from ironic_inspector.common.i18n import _ from ironic_inspector.common import ironic as ir_utils @@ -817,14 +817,11 @@ def find_node(**attributes): LOG.debug('Trying to use %s of value %s for node look up', name, value) - value_list = [] - for v in value: - value_list.append("name='%s' AND value='%s'" % (name, v)) - stmt = ('select distinct node_uuid from attributes where ' + - ' OR '.join(value_list)) - rows = (db.model_query(db.Attribute.node_uuid).from_statement( - text(stmt)).all()) - found.update(row.node_uuid for row in rows) + query = db.model_query(db.Attribute.node_uuid) + pairs = [(db.Attribute.name == name) & + (db.Attribute.value == v) for v in value] + query = query.filter(six.moves.reduce(operator.or_, pairs)) + found.update(row.node_uuid for row in query.distinct().all()) if not found: raise utils.NotFoundInCacheError(_( diff --git a/ironic_inspector/test/unit/test_node_cache.py b/ironic_inspector/test/unit/test_node_cache.py index 8bddf32c8..54d407b73 100644 --- a/ironic_inspector/test/unit/test_node_cache.py +++ b/ironic_inspector/test/unit/test_node_cache.py @@ -315,6 +315,11 @@ class TestNodeCacheFind(test_base.NodeTest): self.assertRaises(utils.Error, node_cache.find_node, bmc_address='1.2.3.4') + def test_input_filtering(self): + self.assertRaises(utils.NotFoundInCacheError, + node_cache.find_node, + bmc_address="' OR ''='") + class TestNodeCacheCleanUp(test_base.NodeTest): def setUp(self): diff --git a/releasenotes/notes/find-node-input-filtering-e8ea529252e80739.yaml b/releasenotes/notes/find-node-input-filtering-e8ea529252e80739.yaml new file mode 100644 index 000000000..f5e0b3f7d --- /dev/null +++ b/releasenotes/notes/find-node-input-filtering-e8ea529252e80739.yaml @@ -0,0 +1,7 @@ +--- +security: + - | + Fixes insufficient input filtering when looking up a node by information + from the introspection data. It could potentially allow SQL injections + via the ``/v1/continue`` API endpoint. See `story 2005678 + `_ for details.