Skip to content

CVE-2020-8443: analysisd: OS_CleanMSG off-by-one heap overflow cleaning syslog msgs. #1816

@cpu

Description

@cpu

In src/analysisd/cleanevent.c the OS_CleanMSG function performs pattern matching and if applicable, tries to decode syslog messages to populate some lf structure fields according to the syslog data.

/* Check for the syslog date format
* ( ex: Dec 29 10:00:01
* or 2015-04-16 21:51:02,805 for proftpd 1.3.5
* or 2007-06-14T15:48:55-04:00 for syslog-ng isodate
* or 2007-06-14T15:48:55.3352-04:00 for syslog-ng isodate with up to 6 optional fraction of a second
* or 2009-05-22T09:36:46.214994-07:00 for rsyslog
* or 2015 Dec 29 10:00:01 )
*/
if (
( /* ex: Dec 29 10:00:01 */
(loglen > 17) &&
(pieces[3] == ' ') &&
(pieces[6] == ' ') &&
(pieces[9] == ':') &&
(pieces[12] == ':') &&
(pieces[15] == ' ') && (lf->log += 16)
)
||
( /* ex: 2015-04-16 21:51:02,805 */
(loglen > 24) &&
(pieces[4] == '-') &&
(pieces[7] == '-') &&
(pieces[10] == ' ') &&
(pieces[13] == ':') &&
(pieces[16] == ':') &&
(pieces[19] == ',') &&
(lf->log += 23)
)
||
(
(loglen > 33) &&
(pieces[4] == '-') &&
(pieces[7] == '-') &&
(pieces[10] == 'T') &&
(pieces[13] == ':') &&
(pieces[16] == ':') &&
( /* ex: 2007-06-14T15:48:55-04:00 */
(
(pieces[22] == ':') &&
(pieces[25] == ' ') && (lf->log += 26)
)
||
/* ex: 2007-06-14T15:48:55.3-04:00 or 2009-05-22T09:36:46,214994-07:00 */
(
(
(pieces[19] == '.') || (pieces[19] == ',')
)
&&
(
( (pieces[24] == ':') && (lf->log += 27) ) ||
( (pieces[25] == ':') && (lf->log += 28) ) ||
( (pieces[26] == ':') && (lf->log += 29) ) ||
( (pieces[27] == ':') && (lf->log += 30) ) ||
( (pieces[28] == ':') && (lf->log += 31) ) ||
( (pieces[29] == ':') && (lf->log += 32) )
)
)
)
)
||
( /* ex: 2015 Dec 29 10:00:01 */
(loglen > 21) &&
(isdigit(pieces[0])) &&
(pieces[4] == ' ') &&
(pieces[8] == ' ') &&
(pieces[11] == ' ') &&
(pieces[14] == ':') &&
(pieces[17] == ':') &&
(pieces[20] == ' ') && (lf->log += 21)
)
||
(
/* ex: 2019:11:06-00:08:03 */
(loglen > 20) &&
(isdigit(pieces[0])) &&
(pieces[4] == ':') &&
(pieces[7] == ':') &&
(pieces[10] == '-') &&
(pieces[13] == ':') &&
(pieces[16] == ':') && (lf->log += 20)
)
) {

When a message contains leading text matching the patterns expected for syslog, and contains a substring like "[ID xx facility.severity]" in the correct location OS_CleanMSG will attempt to remove it by advancing the lf->log pointer beyond the end of the substring:

/* Remove [ID xx facility.severity] */
if (pieces) {
/* Set log after program name */
lf->log = pieces;
if ((pieces[0] == '[') &&
(pieces[1] == 'I') &&
(pieces[2] == 'D') &&
(pieces[3] == ' ')) {
pieces += 4;
/* Going after the ] */
pieces = strchr(pieces, ']');
if (pieces) {
pieces += 2;
lf->log = pieces;
}
}
}

The code is careful about checking the result from strstr when advancing to the expected closing ], however it makes an assumption that there must be a non-null character following the ] when it subsequently advances the pieces pointer by 2:

If a message like "Oct 31 00:00:00 0 sshd: [ID 0 auth.notice]" is processed OS_CleanMSG will advance beyond the terminating null byte of lf->log, resulting in a heap overflow when operating on the lf->log pointer subsequently during decoding.

This code was introduced in 8672fa0 on Nov 18, 2006. I believe it affects OSSEC 2.7+.

This is triggerable via an authenticated client through the ossec-remoted. The client needs only write a message to the remote server of any queue type that will match the expected syslog format and authority substring, but end immediately after the ].

I think the best fix is to change the pieces pointer to be incremented by 1 instead of 2, or to update the strstr check for "[ " instead of just "[" (edit: implemented in #1824),.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions