CVE-2023-24769
In this post I will go through CVE-2023-24769: the description, replication of the vulnerability and PoC.
changedetection.io is an Open-Source Python based platform notifying users about changes of public and private websites. It can be self-hosted (I have this solution installed locally on my second machine, a lightweight laptop) or it’s possible to let them host your website change monitor solution paying a monthly subscription.
From the GitHub description we can read:
"The best and simplest self-hosted free open source website change detection, monitor and notification service.
Restock Monitor, change detection.
Designed for simplicity - the main goal is to simply monitor which websites had a text change for free.
Free Open source web page change detection, Restock Monitoring, Visualping and Apify alternative."
Honestly I have to admit it’s really a fantastic product, I have it installed locally and it’s just amazing. All the promises are kept: it’s simple, fast, intuitive and effective.
- It supports 85 different notification systems (I use my Telegram bot)
- It’s possible to use a headless browser and monitor visual changes (instead of pure text)
- It’s possible to select specific changes to be monitored (through regular expressions)
- It’s possible to import multiple URLs as a list
- Open source, fast and effective support (my security issue fixed and closed in less than a day)
- Many more pros
Description of the vulnerability
When adding a new URL to monitor, it’s possible to add a URL having the protocol javascript
, this leads to a Cross Site Scripting vulnerability. Even if partially blocked by modern browsers (I’m using Chrome v110.*..), the attack is still possible if the victim uses CTRL + click to open the link.
The payload used to prove the vulnerability is javascript:alert(document.domain)
. As suggested by changedectection.io maintainer (@dgtlmoon), the best solution was to block the URLs with protocols not in this list: HTTP, HTTPS, FTP, FILE. These are the only protocols allowed. Note that file:// protocol is not used anymore because it can leads to security vulnerabilities as well (file:///etc/passwd
easy peasy).
I’ve opened an issue in GitHub issue tracker (https://github.com/dgtlmoon/changedetection.io/issues/1358) and after few hours the maintainer provided a patch (https://github.com/dgtlmoon/changedetection.io/pull/1359).
This attack can be carried out also using the Import feature:
{
"client":{
"local":1
},
"data":[
{
"name":"javascript:alert(document.domain)",
"uri":"javascript:alert(document.domain)",
"config":"{\"selections\":[]}",
"tags":[]
}
]
}
Note that as stated in the GitHub issue, there wasn’t a single way to exploit the vulnerability: an attacker could
- Deploy a changedetection.io instance locally
- Create a vulnerable watch with the payload specified above
- Click on share the watch and get a link like this: https://changedetection.io/share/LpbICKx5Rbca
- Use that link for phishing purposes
This is the code patching the vuln:
# Allowable protocols, protects against javascript: etc
# file:// is further checked by ALLOW_FILE_URI
SAFE_PROTOCOL_REGEX='^(http|https|ftp|file):'
def is_safe_url(test_url):
# See https://github.com/dgtlmoon/changedetection.io/issues/1358
# Remove 'source:' prefix so we dont get 'source:javascript:' etc
# 'source:' is a valid way to tell us to return the source
r = re.compile(re.escape('source:'), re.IGNORECASE)
test_url = r.sub('', test_url)
pattern = re.compile(os.getenv('SAFE_PROTOCOL_REGEX', SAFE_PROTOCOL_REGEX), re.IGNORECASE)
if not pattern.match(test_url.strip()):
return False
return True
With this patch the problem is now fixed.
Replication of the vulnerability
- Go to the main page
- Under Add a new change detection watch add as URL
javascript:alert(document.domain)
- Click Watch
- A new row is added under the websites watched
- CTRL + left click with mouse on the link taking to a new tab
- Javascript payload is executed