
Apache Spark 4.2.0 - उच्च - रिमोट - फ़ाइल लेखन - History appStorePath असैनिटाइज़्ड App ID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-history-store-path
वर्ग: फ़ाइल लेखन (कॉन्फ़िग-गेटेड) पहुँच: रिमोट
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
HistoryServerDiskManager.appStorePath बिना किसी सैनिटाइज़ेशन के new File(appStoreDir, appId + extension) करता है। Utils.sanitizeDirName केवल इवेंट-लॉग फ़ाइलनामों के लिए है। JSON App ID asText() है। लिस्टिंग event.appId.orNull संग्रहीत करती है। Lease.commit उसी स्ट्रिंग का उपयोग करता है। App ID ../ spark.history.store.path के बाहर एक .rdb लिखता है। डिफ़ॉल्ट रूप से अनसेट store.path इन-मेमोरी होता है (कोई लेखन नहीं)। सामग्री एक स्टोर फ़ाइल है, RCE नहीं।
| ID | अभी तक कोई CVE नहीं |
| वर्ग | फ़ाइल लेखन (कॉन्फ़िग-गेटेड History डिस्क स्टोर) |
| पहुँच | रिमोट (इवेंट-लॉग राइटर के साथ-साथ History जिसमें spark.history.store.path सेट है; UI ACL डिफ़ॉल्ट रूप से बंद) |
| CWE | CWE-22 |
| CVSS | उच्च: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N जब spark.history.store.path सेट हो |
| उत्पाद | Apache Spark History Server |
| प्रभावित | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) |
| प्रमाणीकरण | spark.history.fs.logDirectory का राइटर (डिफ़ॉल्ट file:/tmp/spark-events); History में spark.history.store.path सेट होना चाहिए |
| लाइसेंस | GNU Affero GPL v3.0 |
| लैब | केवल 127.0.0.1:18990। उद्धृत जॉइन का गैजेट। store.path के बाहर विटनेस .rdb। |
CVE-2025-54920 जैसा ही विक्टिम मॉडल: History Server एक ऐसी लॉग डायरेक्टरी की ओर इंगित है जिसमें हमलावर लिख सकता है। Jackson अब HiveConnection-श्रेणी के गैजेट्स का निर्माण नहीं करता। डिस्क-स्टोर पथ अभी भी इवेंट-JSON App ID पर भरोसा करता है।
| विधि | सिंक | विशेषाधिकार | लैब बनाम अनुमानित |
|---|---|---|---|
एक इवेंट लॉग रोपित करें जिसका JSON App ID ../<name> (या ../../oracle/...) है। स्कैन की प्रतीक्षा करें। उस ऐप UI / getAppUI / loadDiskStore / createDiskStore को लोड करने वाला GET | HistoryServerDiskManager.appStorePath फिर Lease.commit renameTo | अखंडता: History UID के रूप में {store.path}/apps के बाहर एक .rdb (डिफ़ॉल्ट RocksDB) या .ldb (LevelDB) पथ बनाएँ। गैजेट पर लैब-प्रमाणित: escaped=yes, फ़ाइल /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb में विटनेस मौजूद है। सामग्री एक स्टोर फ़ाइल है, हमलावर-चयनित होस्ट बाइटकोड नहीं, शेल नहीं। | लैब-प्रमाणित (एस्केप्ड पथ पर विटनेस बाइट्स का गैजेट लेखन)। RocksDB डायरेक्टरी का पूर्ण History renameTo वही जॉइन है। |
| वही App ID जब एस्केप्ड गंतव्य पहले से एक डायरेक्टरी हो | Lease.commit if (dst.isDirectory()) deleteStore(dst) फिर Utils.deleteRecursively | उपलब्धता: एक मौजूदा डायरेक्टरी को हटाएँ जिसका नाम पहले से बैकएंड सफ़िक्स पर समाप्त होता है, फिर उसे लीज़्ड स्टोर से बदलें। | अनुमानित (पिन HistoryServerDiskManager.scala कमिट)। गैजेट ने एक फ़ाइल लिखी, deleteRecursively को कॉल नहीं किया। |
डिफ़ॉल्ट अनसेट spark.history.store.path | LOCAL_STORE_DIR createOptional; diskManager = storePath.map | बंद। इन-मेमोरी लिस्टिंग। कोई HistoryServerDiskManager नहीं। लैब-प्रमाणित gated=yes written=no। | लैब-प्रमाणित |
पहले App ID पर Utils.sanitizeDirName लागू करें | इवेंट-लॉग फ़ाइलनाम हेल्पर | apps/ के अंदर रहता है। / और : - बन जाते हैं। लैब-प्रमाणित नेगेटिव। | लैब-प्रमाणित |
store.path सेट के साथ App ID local-control नियंत्रित करें | वही जॉइन | {store.path}/apps/local-control.rdb लिखता है। apps/ के अंदर रहता है। | लैब-प्रमाणित |
निकटवर्ती बंद: डिफ़ॉल्ट अनसेट स्टोर (इन-मेमोरी)। Jackson sparkEventFromJson को अभी भी SparkListenerEvent की आवश्यकता है (CVE-2025-54920)। URL getAppUI फ़ॉलबैक eventlog_v2_ + nameForAppAndAttempt सैनिटाइज़्ड है। लिस्टिंग KV कुंजी फ़ाइलसिस्टम पथ नहीं है। HybridStore / kvstore मैपर में कोई Id.CLASS नहीं है। History HTTP अपलोड पथ स्वीकार नहीं करता। कम्पैक्शन डिफ़ॉल्ट रूप से बंद। क्लीनर डिफ़ॉल्ट रूप से बंद। खुले क्लस्टर पर जॉब सबमिट (SECURITY.md FAQ)। ML मॉडल लोड (docs/ml-security.md)। यह शेष होस्ट RCE नहीं है।
मैंने Spark 4.2.0 पिन किया, master नहीं, 4.3 RC नहीं। अट्ठाईस शिकार। सार्वजनिक History Jackson RCE इस पील पर बंद है। इवेंट-लॉग राइटर पहले से ही Utils.sanitizeDirName को कॉल करते हैं इसलिए लॉग फ़ाइल में / नहीं हो सकता। डिस्क-कैश फ़ाइल नाम कच्चे App ID का उपयोग करता है।
private[history] def appStorePath(appId: String, attemptId: Option[String]): File = {
val fileName = appId + attemptId.map("_" + _).getOrElse("") + extension
new File(appStoreDir, fileName)
}
appStoreDir {spark.history.store.path}/apps है। Unix new File(parent, "../../oracle/name.rdb") parent के बाहर रिज़ॉल्व होता है। JsonProtocol.applicationStartFromJson json.get("App ID").asText() लेता है। AppListingListener.onApplicationStart event.appId.orNull संग्रहीत करता है। lease.commit(appId, attempt.info.attemptId) उस स्ट्रिंग को appStorePath तक पहुँचाता है।
पहले से दर्ज गलत मोड़: डिफ़ॉल्ट अनसेट store.path को लेखन मानना (यह इन-मेमोरी है); यह अपेक्षा करना कि Unix new File(dir, "/abs") parent को अनदेखा करेगा (यह नहीं करता; शेष .. है); सफ़िक्स .rdb होने के कारण RCE का दावा करना; जब जॉइन ही ओरेकल है तो पूर्ण History Server बूट करना; sanitizeDirName को इस पथ को कवर करने वाला मानना।
python3 spark-history-store-path-Abraxas-Labs.py
या
cd lab
./run.sh
127.0.0.1:18990 पर HistoryServerDiskManager.appStorePath का गैजेट। lab/pin/ के अंतर्गत पिन अंश। पूर्ण History Server बूट नहीं किया गया है। इसे लूपबैक पर बाइंड करें।
SUCCESS SPARK-HISTORY-STORE-PATH how=gadget escaped=yes gated=yes outside=/work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb SPARK-HISTORY-STORE-PATH-WITNESS
new File से पहले appStorePath के अंदर appId और attemptId पर Utils.sanitizeDirName चलाएँ (या .. / / / NUL अस्वीकार करें)। जॉइन के बाद, आवश्यकता है कि dst.getCanonicalFile() appStoreDir.getCanonicalFile() के अंतर्गत रहे। अनसेट spark.history.store.path सुरक्षित डिफ़ॉल्ट बना रहता है।