CVE-2015-1521 (Other, published 2017-04-24T06:59Z)
Description: value: analyzer/protocol/dnp3/DNP3.cc in Bro before 2.3.2 does not properly handle zero values of a packet length, which allows remote attackers to cause a denial of service (buffer overflow or buffer over-read if NDEBUG; otherwise assertion failure) via a crafted DNP3 packet.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-119 \u2014 Improper Restriction of Operations within the Bounds of a Memory Buffer
The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Repository: https://github.com/bro/bro
Files changed:
CHANGES
VERSION
src/analyzer/protocol/dnp3/DNP3.cc
src/analyzer/protocol/dnp3/DNP3.h
Commit message: DNP3: fix reachable assertion and buffer over-read/overflow.

A DNP3 packet using a link layer header that specifies a zero length can
trigger an assertion failure if assertions are enabled.  Assertions are
enabled unless Bro is compiled with the NDEBUG preprocessor macro
defined.  The default configuration of Bro will define this macro and so
disables assertions, but using the --enable-debug option in the
configure script will enable assertions.  When assertions are disabled,
or also for certain length values, the DNP3 parser may attempt to pass a
negative value as the third argument to memcpy (number of bytes to copy)
and result in a buffer over-read or overflow.

Reported by Travis Emmert.


Vulnerable code:
2.3-392
			if ( ! AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len) )
			assert(endp->pkt_length);
			if ( ! AddToBuffer(endp, n, &data, &len) )
bool DNP3_Base::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len)
		return true;
	return endp->buffer_len == target_len;
		assert(data + n < endp->buffer + endp->buffer_len);
	bool AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len);

Fixed code:
2.3-396 | 2015-01-23 10:49:15 -0600

  * DNP3: fix reachable assertion and buffer over-read/overflow.
    CVE number pending. (Travis Emmert, Jon Siwek)

  * Update binpac: Fix potential out-of-bounds memory reads in generated
    code. CVE-2014-9586. (John Villamil and Chris Rohlf - Yahoo
    Paranoids, Jon Siwek)

  * Fixing (harmless) Coverity warning. (Robin Sommer)

2.3-396
			int res = AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len);

			if ( res == 0 )
			if ( res < 0 )
				return false;

			if ( endp->pkt_length <= 0 )
				{
				analyzer->Weird("dnp3_negative_or_zero_length_link_layer");
				return false;
				}
			int res = AddToBuffer(endp, n, &data, &len);

			if ( res == 0 )
			if ( res < 0 )
				return false;

int DNP3_Base::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len)
		return 1;

	if ( *len < 0 )
		{
		reporter->AnalyzerError(analyzer, "dnp3 negative input length: %d", *len);
		return -1;
		}

	if ( target_len < endp->buffer_len )
		{
		reporter->AnalyzerError(analyzer, "dnp3 invalid target length: %d - %d",
		                        target_len, endp->buffer_len);
		return -1;
		}
	if ( endp->buffer_len + to_copy > MAX_BUFFER_SIZE )
		{
		reporter->AnalyzerError(analyzer, "dnp3 buffer length exceeded: %d + %d",
		                        endp->buffer_len, to_copy);
		return -1;
		}

	if ( endp->buffer_len == target_len )
		return 1;

	return 0;
		if ( data + n >= endp->buffer + endp->buffer_len )
			{
			reporter->AnalyzerError(analyzer,
			                        "dnp3 app layer parsing overflow %d - %d",
			                        endp->buffer_len, n);
			return false;
			}


	/**
	 * Buffers packet data until it reaches a specified length.
	 * @param endp an endpoint speaking DNP3 to which data will be buffered.
	 * @param target_len the required length of the buffer
	 * @param data source buffer to copy bytes from.  Will be incremented
	 * by the number of bytes copied by this function.
	 * @param len the number of bytes available in \a data.  Will be decremented
	 * by the number of bytes copied by this function.
	 * @return -1 if invalid input parameters were supplied, 0 if the endpoint's
	 * buffer is not yet \a target_len bytes in size, or 1 the buffer is the
	 * required size.
	 */
	int AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len);