FlawOpen

flawopen.com/Teardowns/cve-2024-32002-git-submodule-rce

● CVE-2024-32002 · CVSS 9.0 · अति गंभीर
सुरक्षा अनुसंधान · FlawOpen

CVE-2024-32002: Git सबमॉड्यूल सिम्लिंक रिमोट कोड निष्पादन (RCE)

CVE-2024-32002 में विशेष रूप से तैयार Git repository recursive clone के दौरान case-collision वाले symlink से .git में लिख सकता था, जिससे जाँच से पहले hook चल सकता था। Git का upstream सुधार clone से पहले और बाद में submodule का लक्ष्य जाँचता है और अनपेक्षित सामग्री मिलने पर रुक जाता है। Git के सुधारे गए संस्करण पर upgrade करें।

💡 आसान भाषा में (ELI5)

ऐसे गोदाम की कल्पना करें जहाँ संकेत-पट्ट A और a को एक ही दरवाज़ा मानते हैं। यदि submodule का रास्ता अभिलेख-कक्ष (.git) की ओर मोड़ने वाले संकेत से गुज़रता है, तो एक भंडारण-खाने के लिए बनी फ़ाइलें Git के नियंत्रण रिकॉर्ड में पहुँच सकती हैं। Git का सुधार clone से पहले और बाद में लक्ष्य जाँचता है और अनपेक्षित सामग्री मिलने पर रुक जाता है।

इस पेज के मुख्य शब्द

Git सबमॉड्यूल (Submodule)
एक मुख्य रिपॉजिटरी के अंदर सबडायरेक्टरी के रूप में एम्बेडेड अलग Git रिपॉजिटरी।
सिम्बोलिक लिंक (Symlink)
एक फ़ाइल सिस्टम ऑब्जेक्ट जो पाथ को दूसरे लक्षित फ़ोल्डर पर पुनर्निर्देशित करता है।
केस कोलिजन (Case Collision)
NTFS और APFS पर व्यवहार जहाँ केवल अक्षरों के केस में भिन्न पाथ एक ही इनोड को इंगित करते हैं।
Git हुक्स (Hooks)
.git/hooks/ में स्थित निष्पादन योग्य स्क्रिप्ट जो post-checkout पर स्वतः चलती हैं।

फ्रेमवर्क मैपिंग

  • इस गाइड में बताई गई कमजोरी के लिए CWE संदर्भ: CWE-22 CWE-59 CWE-434

मूल कारण विश्लेषण (Root Cause)

ऐसे फ़ाइल सिस्टम पर जो बड़े और छोटे अक्षरों में भेद नहीं करता और symlink का समर्थन करता है, विशेष रूप से तैयार repository ऐसा submodule path दे सकता था जो अक्षर-रूप सामान्य करने के बाद symlink से टकराए। Recursive clone के दौरान Git clone के लिए बनाए गए directory को उस symlink से बदल सकता था और submodule worktree के बाहर .git में फ़ाइलें लिख सकता था। वहाँ रखा hook उपयोगकर्ता के checkout जाँचने से पहले चल सकता था। Upstream patch पहले से मौजूद और खाली न होने वाले submodule लक्ष्य में clone करने से मना करता है और clone के बाद उस लक्ष्य को अस्वीकार करता है जिसमें .git metadata के अलावा कुछ हो।

हमले का चरण-दर-चरण प्रवाह

चरण 1

Recursive clone repository-नियंत्रित metadata तक पहुँचता है

उपयोगकर्ता ऐसे फ़ाइल सिस्टम पर किसी अविश्वसनीय repository को recursively clone करता है जो बड़े और छोटे अक्षरों में भेद नहीं करता और symlink का समर्थन करता है। Repository में ऐसे submodule paths और tracked entries हैं जो अक्षर-रूप सामान्य करने के बाद टकराते हैं।

चरण 2

Path collision विश्वास-सीमा पार करता है

Git टकराते हुए submodule path को अपेक्षित worktree के बजाय symlink के माध्यम से resolve कर सकता था। प्रभावित सीमा recursive submodule clone के दौरान Git का फ़ाइल-सिस्टम path handling है।

चरण 3

फ़ाइलें Git metadata में पहुँचती हैं

Redirected write repository के .git क्षेत्र में hook रख सकता है। Git project advisory बताती है कि clone जारी रहते हुए वहाँ hook लिखा और चलाया जा सकता है।

चरण 4

जाँच से पहले clone code चला सकता है

Git clone प्रक्रिया के दौरान hook चलाता है, इससे पहले कि उपयोगकर्ता checkout की फ़ाइलें जाँच सके। Patched Git releases लक्ष्य की स्थिति जाँचते हैं और अनपेक्षित फ़ाइलें मिलने पर रुक जाते हैं।

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

यह Git के upstream C बदलाव में clone_submodule() का अंश है, स्वतंत्र रूप से उपयोग की जा सकने वाली पूरी function नहीं। सुधार से पहले दिखाए गए clone path में destination की सामग्री जाँचने वाला संबंधित guard नहीं था। सुधार पहले से मौजूद और खाली न होने वाली checkout directory को अस्वीकार करता है और clone के बाद जाँचता है कि केवल .git metadata मौजूद हो; helper function directory entries जाँचता है। पूरी implementation upstream commit में है।

कमज़ोर कार्यान्वयन
if (!file_exists(sm_gitdir)) {
    if (safe_create_leading_directories_const(sm_gitdir) < 0)
        die(_("could not create directory '%s'"), sm_gitdir);

    if (run_command(&cp))
        die(_("clone of '%s' into submodule path '%s' failed"),
            clone_data->url, clone_data_path);
}
सुरक्षित और सुदृढ़ फ़िक्स
struct stat st;

if (!file_exists(sm_gitdir)) {
    if (clone_data->require_init && !stat(clone_data_path, &st) &&
        !is_empty_dir(clone_data_path))
        die(_("directory not empty: '%s'"), clone_data_path);

    if (safe_create_leading_directories_const(sm_gitdir) < 0)
        die(_("could not create directory '%s'"), sm_gitdir);

    if (run_command(&cp))
        die(_("clone of '%s' into submodule path '%s' failed"),
            clone_data->url, clone_data_path);

    if (clone_data->require_init && !stat(clone_data_path, &st) &&
        !dir_contains_only_dotgit(clone_data_path)) {
        char *dot_git = xstrfmt("%s/.git", clone_data_path);
        unlink(dot_git);
        free(dot_git);
        die(_("directory not empty: '%s'"), clone_data_path);
    }
}

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत