dexter has uploaded this change for review.
osmo-smdpp.py: fix path Traversal Bypass in SM-DP+ (CWE-22)
Root Cause:
os.path.commonprefix() compares strings character-by-character, NOT by path
components. This is a well-known Python antipattern (Python docs explicitly
warn: "this function may return invalid paths because it works a character
at a time").
Attack Context:
The matchingId parameter is received from a network client via the GSMA
ES9+ authenticateClient API endpoint (POST to
/gsma/rsp2/es9plus/authenticateClient). The SM-DP+ server is a Twisted web
application listening on port 443. An unauthenticated eUICC client sends
the matchingId in the ctxParamsForCommonAuthentication ASN.1 structure.
Fix:
Replace os.path.commonprefix() with proper path component checking:
Change-Id: I7a42b40aa2bbcd5f0ec99f172503354c6eaa9828
---
M osmo-smdpp.py
1 file changed, 2 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/25/42625/1
diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index d1d6fd7..74d9ab6 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -117,6 +117,7 @@
import uuid # noqa: E402
import os # noqa: E402
import functools # noqa: E402
+import pathlib
from typing import Optional, Dict, List # noqa: E402
from pprint import pprint as pp # noqa: E402
@@ -640,7 +641,7 @@
# look up profile based on matchingID. We simply check if a given file exists for now..
path = os.path.join(self.upp_dir, matchingId) + '.der'
# prevent directory traversal attack
- if os.path.commonprefix((os.path.realpath(path),self.upp_dir)) != self.upp_dir:
+ if not pathlib.Path(path).resolve().is_relative_to(self.upp_dir):
raise ApiError('8.2.6', '3.8', 'Refused')
if not os.path.isfile(path) or not os.access(path, os.R_OK):
raise ApiError('8.2.6', '3.8', 'Refused')
To view, visit change 42625. To unsubscribe, or for help writing mail filters, visit settings.