CVE-2022-23949: Authentication Bypass by Spoofing (CWE-290)
value: In Keylime before 6.3.0, unsanitized UUIDs can be passed by a rogue agent and can lead to log spoofing on the verifier and registrar.
CWE description: This attack-focused weakness is caused by incorrectly implemented authentication schemes that are subject to spoofing attacks.
CVSS v3 base score: 7.5
Published: 2022-09-21T19:15Z
Repository: https://github.com/keylime/keylime
Language: Python
Files changed: keylime/common/validators.py, test/test_validators.py
Commit date: 2022-01-27 11:09:26 -0500
Commit message: validators: add uuid and agent_id validators

Add valid_uuid and valid_agent_id validators, and tests for both.

Signed-off-by: Alberto Planas <aplanas@suse.com>

Diff: diff --git a/keylime/common/validators.py b/keylime/common/validators.py
index acc67e0..980d638 100644
--- a/keylime/common/validators.py
+++ b/keylime/common/validators.py
@@ -30,5 +30,31 @@ def valid_hex(value):
     try:
         int(value, 16)
     except Exception:
         return False
     return True
+
+
+def valid_uuid(uuid: str) -> bool:
+    """Check if the string is a valid UUID."""
+    valid = False
+    try:
+        valid = bool(
+            re.fullmatch(
+                r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
+                uuid,
+                re.I,
+            )
+        )
+    except Exception:
+        pass
+    return valid
+
+
+def valid_agent_id(agent_id: str) -> bool:
+    """Check if agent_id is valid."""
+    valid = False
+    try:
+        valid = bool(re.fullmatch(r"[\w.-]+", agent_id))
+    except Exception:
+        pass
+    return valid
diff --git a/test/test_validators.py b/test/test_validators.py
index b925ec3..eb6d6bd 100644
--- a/test/test_validators.py
+++ b/test/test_validators.py
@@ -76,7 +76,51 @@ class TestValidHex(unittest.TestCase):
     def test_invalid(self):
         """Check and invalid hexadecimal number."""
         self.assertFalse(validators.valid_hex("123xyz"))
 
 
+class TestValidUUID(unittest.TestCase):
+    """Tests for valid_uuid."""
+
+    def test_none(self):
+        """Check that None is not valid."""
+        self.assertFalse(validators.valid_uuid(None))
+
+    def test_empty(self):
+        """Check that the empty string is not valid."""
+        self.assertFalse(validators.valid_uuid(""))
+
+    def test_valid(self):
+        """Check a valid UUID that mix upper and lower case."""
+        self.assertTrue(validators.valid_uuid("74a93e15-da24-4ff1-ABC0-55beed02a16a"))
+
+    def test_invalid(self):
+        """Check an invalid UUID that mix upper and lower case."""
+        self.assertFalse(validators.valid_uuid("some text"))
+
+
+class TestValidAgentID(unittest.TestCase):
+    """Tests for valid_agent_id."""
+
+    def test_none(self):
+        """Check that None is not valid."""
+        self.assertFalse(validators.valid_agent_id(None))
+
+    def test_empty(self):
+        """Check that the empty string is not valid."""
+        self.assertFalse(validators.valid_agent_id(""))
+
+    def test_valid_uuid(self):
+        """Check a valid UUID that mix upper and lower case."""
+        self.assertTrue(validators.valid_agent_id("74a93e15-da24-4ff1-ABC0-55beed02a16a"))
+
+    def test_valid_hostname(self):
+        """Check a valid hostname that mix upper and lower case."""
+        self.assertTrue(validators.valid_agent_id("my-Hostname.example.com"))
+
+    def test_invalid(self):
+        """Check an invalid user ID with non valid characters."""
+        self.assertFalse(validators.valid_agent_id("rm -fr *"))
+
+
 if __name__ == "__main__":
     unittest.main()

Fixed code: 

def valid_uuid(uuid: str) -> bool:
    """Check if the string is a valid UUID."""
    valid = False
    try:
        valid = bool(
            re.fullmatch(
                r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
                uuid,
                re.I,
            )
        )
    except Exception:
        pass
    return valid


def valid_agent_id(agent_id: str) -> bool:
    """Check if agent_id is valid."""
    valid = False
    try:
        valid = bool(re.fullmatch(r"[\w.-]+", agent_id))
    except Exception:
        pass
    return valid
class TestValidUUID(unittest.TestCase):
    """Tests for valid_uuid."""

    def test_none(self):
        """Check that None is not valid."""
        self.assertFalse(validators.valid_uuid(None))

    def test_empty(self):
        """Check that the empty string is not valid."""
        self.assertFalse(validators.valid_uuid(""))

    def test_valid(self):
        """Check a valid UUID that mix upper and lower case."""
        self.assertTrue(validators.valid_uuid("74a93e15-da24-4ff1-ABC0-55beed02a16a"))

    def test_invalid(self):
        """Check an invalid UUID that mix upper and lower case."""
        self.assertFalse(validators.valid_uuid("some text"))


class TestValidAgentID(unittest.TestCase):
    """Tests for valid_agent_id."""

    def test_none(self):
        """Check that None is not valid."""
        self.assertFalse(validators.valid_agent_id(None))

    def test_empty(self):
        """Check that the empty string is not valid."""
        self.assertFalse(validators.valid_agent_id(""))

    def test_valid_uuid(self):
        """Check a valid UUID that mix upper and lower case."""
        self.assertTrue(validators.valid_agent_id("74a93e15-da24-4ff1-ABC0-55beed02a16a"))

    def test_valid_hostname(self):
        """Check a valid hostname that mix upper and lower case."""
        self.assertTrue(validators.valid_agent_id("my-Hostname.example.com"))

    def test_invalid(self):
        """Check an invalid user ID with non valid characters."""
        self.assertFalse(validators.valid_agent_id("rm -fr *"))