由于这个是开源的,直接源码对比 https://bugzilla.redhat.com/attachment.cgi?id=883475&action=diff
修复的另外一处也差不多
两处都对s->s3->rrec.length
进行了判断
这个rrec结构如下:
typedef struct ssl3_record_st
{
/*r */ int type; /* type of record */
/*rw*/ unsigned int length; /* How many bytes available */
/*r */ unsigned int off; /* read/write offset into 'buf' */
/*rw*/ unsigned char *data; /* pointer to the record data */
/*rw*/ unsigned char *input; /* where the decode bytes are */
/*r */ unsigned char *comp; /* only used with decompression - malloc()ed */
/*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */
/*r */ unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */
} SSL3_RECORD;
length(心跳包的长度)是用户可控的,而payload(也是储存长度)是也是用户可控的,那么当payload长度大于心跳包的长度,那么就可以读取内存中心跳包后面的数据了
我们看看泄露这一步,首先是是malloc的大小,复制的大小都是payload这个变量
buffer = OPENSSL_malloc(1 + 2 + payload + padding); //分配内存
bp = buffer; //buffer即bp
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload); //复制到bp
bp += payload;
/* Random padding */
RAND_pseudo_bytes(bp, padding);
r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); //将前面复制到bp的数据,写到s结构的特定变量返回到用户(因为buffer就是bp)
那么这个就可以越界读取内存的信息,可能读取到密码什么的
再说说SSL3_RT_MAX_PLAIN_LENGTH那个,SSL3_RT_MAX_PLAIN_LENGTH在源码中找到是16384,所以这里的判断应该不是最重点,这个限制了最大长度
#define SSL3_RT_MAX_PLAIN_LENGTH 16384