FlawOpen

flawopen.com/Teardowns/cve-2014-0160-heartbleed

● CVE-2014-0160 · CVSS 7.5 · उच्च
सुरक्षा अनुसंधान · FlawOpen

CVE-2014-0160: OpenSSL Heartbleed से मेमोरी लीक

CVE-2014-0160 में TLS या DTLS peer, Heartbeat record में मौजूद न होने वाली payload length पर OpenSSL के भरोसे का फायदा उठाकर record के आगे से 64 KiB तक पढ़ सकता था। upstream सुधार payload को parse और echo करने से पहले record की जाँच करता है।[1], [2]

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

मान लीजिए एक कर्मचारी को कुछ शब्दों वाला कार्ड मिलता है, लेकिन वह उस लेबल पर भरोसा कर लेता है जो उससे बहुत लंबी नकल माँगता है। कार्ड के किनारे पर रुकने के बजाय वह साझा ट्रे में आगे का पाठ भी नकल करता रहता है। Heartbleed में OpenSSL प्राप्त record के आगे तक पढ़ता था; कौन-से bytes उजागर हुए, यह process memory पर निर्भर था।[1], [3]

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

TLS/DTLS Heartbeat (RFC 6520)
TLS या DTLS का keep-alive संदेश। अनुरोध में payload होता है जिसे peer वापस echo करता है, साथ में protocol द्वारा आवश्यक padding भी।[3]
payload_length
Heartbeat payload का आकार बताने वाला 16-bit field। message type, length field और न्यूनतम padding के बाद इसे प्राप्त record में समाना चाहिए।[1], [3]
memcpy()
source pointer से तय संख्या में bytes copy करता है। इसे source buffer की वैध लंबाई नहीं पता होती; caller को पहले सीमा जाँचनी होती है।[1], [2]
Buffer over-read (CWE-126)
निर्धारित source buffer के अंत से आगे पढ़ना। Heartbleed में memory की सामग्री के आधार पर reply process memory के 64 KiB तक उजागर कर सकता था।[5]

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

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

tls1_process_heartbeat() और dtls1_process_heartbeat() Heartbeat संदेश की 16-bit payload length पढ़ते थे और जवाब के रास्ते में उसे memcpy() को दे देते थे, बिना यह साबित किए कि इतने payload bytes s->s3->rrec.length में मौजूद हैं। peer, TLS या DTLS record में मौजूद डेटा से अधिक लंबाई घोषित कर सकता था। तब OpenSSL प्राप्त record के बाद के bytes echo करता और process memory के 64 KiB तक उजागर हो सकते थे; सामग्री memory पर निर्भर थी, इसलिए किसी खास key, password या cookie के मिलने की गारंटी नहीं थी। upstream commit 96db902 पहले उन records को अस्वीकार करता है जिनमें type, length field और न्यूनतम padding नहीं समा सकते; फिर 1 + 2 + payload + 16 की तुलना प्राप्त record length से करता है। यह SSL3_RT_MAX_PLAIN_LENGTH से reply को सीमित करता है और गणना किया हुआ write_length उपयोग करता है। TLS और DTLS, दोनों handlers में समान जाँच जोड़ी गई।[1], [2], [3], [4]

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

चरण 1

Peer छोटा Heartbeat record भेजता है

TLS या DTLS peer ऐसा Heartbeat संदेश भेजता है जिसकी घोषित payload length record में मौजूद payload bytes से अधिक होती है।[1], [3]

चरण 2

OpenSSL घोषित लंबाई पर भरोसा करता है

सुधार से पहले handler record का न्यूनतम आकार जाँचे या payload को प्राप्त record से मिलाए बिना type और length पढ़ता है।[1], [2]

चरण 3

Reply record से आगे copy करता है

memcpy() record buffer से घोषित संख्या में bytes copy करता है। reply में प्राप्त Heartbeat संदेश के बाद के bytes आ सकते हैं; protocol सीमा 64 KiB है।[1], [2]

चरण 4

क्या उजागर होगा, यह process memory पर निर्भर है

Peer को process memory के bytes मिल सकते हैं। किसी खास secret के मिलने की गारंटी नहीं; परिणाम memory की सामग्री और endpoint की स्थिति पर निर्भर है।[1], [4]

चरण 5

Patched handler असंगति अस्वीकार करता है

सुधार parsing से पहले header और padding जाँचता है, पुष्टि करता है कि payload प्राप्त record में समाता है, और copy से पहले reply सीमित करता है।[2], [1]

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

ये OpenSSL के upstream बदलाव के अंश हैं, स्वतंत्र रूप से चलने वाला प्रोग्राम नहीं। असुरक्षित code, fixed header और न्यूनतम padding मौजूद हैं या नहीं यह जाँचे बिना fields parse करता है, फिर peer द्वारा घोषित payload length copy करता है। सुधार parsing से पहले record का न्यूनतम आकार जाँचता है, घोषित payload को प्राप्त record से मिलाता है और reply की लंबाई सीमित करता है। OpenSSL ने tls1_process_heartbeat() और dtls1_process_heartbeat() दोनों में इसी तरह के बदलाव किए।[2], [1]

सोर्स अंश: ssl/t1_lib.c

कमज़ोर कार्यान्वयन
/* सुधार से पहले tls1_process_heartbeat() का अंश। */
hbtype = *p++;
n2s(p, payload);
pl = p;

/* TLS1_HB_REQUEST के response path में: */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT,
                     buffer, 3 + payload + padding);
सुरक्षित और सुदृढ़ फ़िक्स
/* type, length और न्यूनतम padding के लिए बहुत छोटे record को अस्वीकार करें। */
if (1 + 2 + 16 > s->s3->rrec.length)
    return 0;

hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length)
    return 0;
pl = p;

/* TLS1_HB_REQUEST के response path में: */
unsigned int write_length = 1 + 2 + payload + padding;
if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
    return 0;
buffer = OPENSSL_malloc(write_length);
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);

घटना का समयक्रम (Timeline)

2012-03-14

OpenSSL 1.0.1 जारी हुआ, जिसमें TLS/DTLS Heartbeat processing में record-length जाँच नहीं थी।[3], [1]

2014-04-07

OpenSSL ने CVE-2014-0160 advisory प्रकाशित की और 1.0.1g जारी किया; advisory में Google Security के Neel Mehta को श्रेय दिया गया। 1.0.2 beta के लिए सुधार beta2 में आया।[1], [2]

2014-04

ऑपरेटरों ने प्रभावित endpoints patch किए और संभावित exposure का आकलन किया। Heartbleed.com के अनुसार सामान्य logs यह दर्ज नहीं करते कि response ने memory के कौन-से bytes लौटाए; patch के बाद keys, certificates, sessions और credentials बदलने का आकलन किया गया।[6], [1]

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

स्रोत