File: protocols\rdp\plugins\guac-common-svc\guac-common-svc.c
Function: guac_rdp_common_svc_handle_open_event()

  1. RDP channel messages support a simple fragmentation that is determined by the “flags” field in the message.
  2. There are improper state machine checks in FreeRDP and in the Guacamole Proxy.
  3. A malicious RDP server could send channel fragments without sending the “first” fragment in the chain.
  4. This will lead to the use of a dangling pointer that remained from the previous channel message, and ultimately enables a malicious RDP server to take over the Guacamole Proxy.

Code Snippet:

/* If receiving first chunk, allocate sufficient space for all remaining chunks */
if (data_flags & CHANNEL_FLAG_FIRST) {

	/* Limit maximum received size */
	if (total_length > GUAC_SVC_MAX_ASSEMBLED_LENGTH) {

	svc->_input_stream = Stream_New(NULL, total_length);

// EI-DBG: Missing input check that svc->_input_stream != NULL.
// EI-DBG: This leads to the use of a dangling "stream" instead.

/* Add chunk to buffer only if sufficient space remains */
if (Stream_EnsureRemainingCapacity(svc->_input_stream, data_length))
	Stream_Write(svc->_input_stream, data, data_length);

/* Fire event once last chunk has been received */
if (data_flags & CHANNEL_FLAG_LAST) {

	Stream_SetPosition(svc->_input_stream, 0);

	/* Handle channel-specific data receipt tasks, if any */
	if (svc->_receive_handler)
		svc->_receive_handler(svc, svc->_input_stream);

	// EI-DBG: The stream is being free()ed here, *without* setting svc->_input_stream to NULL.
	Stream_Free(svc->_input_stream, TRUE);