From 360c22271664c0456b3e5b69a55c2c301559d86b Mon Sep 17 00:00:00 2001 From: Raphael Ahrens Date: Sat, 20 Apr 2024 14:13:45 +0200 Subject: [PATCH 1/2] Replaced AC22 with AC23 and AC24 As mentioned in #239 AC22 Credential Aging review the threat AC22 Credential Aging was not helpful. This commit replaces AC22 with two new threats AC23 Credential Disclosure and AC24 Hardcoded Credentials. AC23 checks if the lifetime of the credentials is LONG, MANAUL, or UNKNOWN. Currently there is no way to resolve this threat by changing the model, besides setting the a different lifetime. AC24 warns against the use of hardcoded credentials. --- pytm/threatlib/threats.json | 27 +++++++++++++++++++++------ tests/test_pytmfunc.py | 16 ++++++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/pytm/threatlib/threats.json b/pytm/threatlib/threats.json index e477fcc..f94c2ba 100644 --- a/pytm/threatlib/threats.json +++ b/pytm/threatlib/threats.json @@ -1559,18 +1559,33 @@ "references": "https://cwe.mitre.org/data/definitions/311.html, https://cwe.mitre.org/data/definitions/312.html, https://cwe.mitre.org/data/definitions/916.html, https://cwe.mitre.org/data/definitions/653.html" }, { - "SID": "AC22", + "SID": "AC23", "target": [ "Dataflow" ], - "description": "Credentials Aging", - "details": "If no mechanism is in place for managing credentials (passwords and certificates) aging, users will have no incentive to update passwords or rotate certificates in a timely manner. Allowing password aging to occur unchecked or long certificate expiration dates can result in the possibility of diminished password integrity.", + "description": "Credentials Disclosure", + "details": "If credentials (passwords or certificates) have a long lifetime their disclosure can have severe consequences, if the credentials cannot quickly be revoked and/or rotated.", "Likelihood Of Attack": "Medium", "severity": "High", "prerequisites": "", - "condition": "any(d.isCredentials for d in target.data) and target.sink.inScope and any(d.credentialsLife in (Lifetime.UNKNOWN, Lifetime.LONG, Lifetime.MANUAL, Lifetime.HARDCODED) for d in target.data)", - "mitigations": "All passwords and other credentials should have a relatively short expiration date with a possibility to be revoked immediately under special circumstances.", + "condition": "any(d.isCredentials for d in target.data) and target.sink.inScope and any(d.credentialsLife in (Lifetime.UNKNOWN, Lifetime.LONG, Lifetime.MANUAL) for d in target.data)", + "mitigations": "Long living credentials need to have high entropy and length to be future proof, especially if it is unknwon how long these credentials will be used. Further should there be a mechanism to revoke the credentials immediately if a disclosure is suspected. To detect disclosure of the credentials their use should be monitored for suspicions activity.", "example": "", - "references": "https://cwe.mitre.org/data/definitions/262.html, https://cwe.mitre.org/data/definitions/263.html, https://cwe.mitre.org/data/definitions/798.html" + "references": "https://pages.nist.gov/800-63-3/sp800-63b.html#sec6" + }, + { + "SID": "AC24", + "target": [ + "Dataflow" + ], + "description": "Use of hardcoded credentials", + "details": "Hardcoded credentials (password or certificates) cannot be changed and if these credentials are dislcosed they can be used by attackers to bypass the authentication mechanism.", + "Likelihood Of Attack": "High", + "severity": "Very High", + "prerequisites": "", + "condition": "any(d.isCredentials for d in target.data) and target.sink.inScope and any(d.credentialsLife == Lifetime.HARDCODED for d in target.data)", + "mitigations": "Avoid hardcoded credentials. If you have to use hardcoded credentials make is possible to change the credentials or to deactivate them. A typical design is to use a \"first login\"-mode which forces the user to create new credentials, on the first login. If the credentials cannot be changed the sole actions in prodcution for the defender is to deactivate/remove the effected product.", + "example": "", + "references": "https://cwe.mitre.org/data/definitions/798.html, https://cwe.mitre.org/data/definitions/259.html, https://cwe.mitre.org/data/definitions/321.html" } ] diff --git a/tests/test_pytmfunc.py b/tests/test_pytmfunc.py index f5129d5..220207a 100644 --- a/tests/test_pytmfunc.py +++ b/tests/test_pytmfunc.py @@ -1462,7 +1462,19 @@ def test_AC21(self): threat = threats["AC21"] self.assertTrue(threat.apply(process1)) - def test_AC22(self): + def test_AC23(self): + user = Actor("User") + web = Server("Web Server") + user_to_web = Dataflow(user, web, "User enters comments (*)") + user_to_web.data = Data( + "password", isCredentials=True, credentialsLife=Lifetime.LONG + ) + user_to_web.protocol = "HTTPS" + user_to_web.controls.isEncrypted = True + threat = threats["AC23"] + self.assertTrue(threat.apply(user_to_web)) + + def test_AC24(self): user = Actor("User") web = Server("Web Server") user_to_web = Dataflow(user, web, "User enters comments (*)") @@ -1471,7 +1483,7 @@ def test_AC22(self): ) user_to_web.protocol = "HTTPS" user_to_web.controls.isEncrypted = True - threat = threats["AC22"] + threat = threats["AC24"] self.assertTrue(threat.apply(user_to_web)) def test_DR01(self): From 283de31cd882e1767de72b2da1dab2288d4a6349 Mon Sep 17 00:00:00 2001 From: Raphael Ahrens Date: Fri, 26 Apr 2024 10:27:19 +0200 Subject: [PATCH 2/2] Added a DEPRECATED attribute When a threat in `threats.json` has a `DEPRECATED` attribute the threat will be ignored. The value of `DEPRECATED` is irrelevant for pytm, but it can describe the reason for the deprecation. --- pytm/pytm.py | 6 +++--- pytm/threatlib/threats.json | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/pytm/pytm.py b/pytm/pytm.py index 3bd7333..b9dbbe0 100644 --- a/pytm/pytm.py +++ b/pytm/pytm.py @@ -818,9 +818,9 @@ def _add_threats(self): raise UIError( e, f"while trying to open the the threat file ({self.threatsFile})." ) - - for i in threats_json: - TM._threats.append(Threat(**i)) + active_threats = (threat for threat in threats_json if "DEPRECATED" not in threat) + for threat in active_threats: + TM._threats.append(Threat(**threat)) def resolve(self): finding_count = 0 diff --git a/pytm/threatlib/threats.json b/pytm/threatlib/threats.json index f94c2ba..347a6d9 100644 --- a/pytm/threatlib/threats.json +++ b/pytm/threatlib/threats.json @@ -1558,6 +1558,22 @@ "example": "", "references": "https://cwe.mitre.org/data/definitions/311.html, https://cwe.mitre.org/data/definitions/312.html, https://cwe.mitre.org/data/definitions/916.html, https://cwe.mitre.org/data/definitions/653.html" }, + { + "SID": "AC22", + "DEPRECATED": "AC22 was replaced by AC23 and AC24. Forcing short lived credentials by rotating the credentials regularly is no longer recommended. It better to go for long living strong credentials, which can be easily replaced, when a disclosure has happend.", + "target": [ + "Dataflow" + ], + "description": "Credentials Aging", + "details": "If no mechanism is in place for managing credentials (passwords and certificates) aging, users will have no incentive to update passwords or rotate certificates in a timely manner. Allowing password aging to occur unchecked or long certificate expiration dates can result in the possibility of diminished password integrity.", + "Likelihood Of Attack": "Medium", + "severity": "High", + "prerequisites": "", + "condition": "any(d.isCredentials for d in target.data) and target.sink.inScope and any(d.credentialsLife in (Lifetime.UNKNOWN, Lifetime.LONG, Lifetime.MANUAL, Lifetime.HARDCODED) for d in target.data)", + "mitigations": "All passwords and other credentials should have a relatively short expiration date with a possibility to be revoked immediately under special circumstances.", + "example": "", + "references": "https://cwe.mitre.org/data/definitions/262.html, https://cwe.mitre.org/data/definitions/263.html, https://cwe.mitre.org/data/definitions/798.html" + }, { "SID": "AC23", "target": [