Cover Photo by ChatGPT
Introduction
In this post, I’m going to talk about a recent experience having a vulnerability in this website reported to me, the whole experience and how I dealt with it.
What Happened?
On 29th January 2025 @ 12:07, I received an email into my admin mailbox for my domain, with the subject Security Issue in https://cirriustech.co.uk.
Now, that in itself isn’t that unusual, I get loads of emails purporting to have found issues in my site and offering services to help me fix - it’s almost always Search Engine Optimisation (SEO) spam.
This one was different - for one thing, it hadn’t been automatically moved to the spam folder of my mailbox.
That automatically sparked my interest.
What also caught my attention were two other things:
- The words “Security issue”
- The sender name 0x2458 (automatically makes me think this is from a security researcher rather than the usual marketing spammers)
On opening it, I read the following:
*Hey Graham! Hope you are doing well, I’m writing this mail to inform about a security vulnerability in your website- https://cirriustech.co.uk/
Website is affected with Cross-Site-Scripting (XSS) Vulnerability Vulnerable Endpoint- Search bar* Payload Used-
013371337;ext=
<Svg Only=1 OnLoad=confirm(document.domain)>
<Svg/OnLoad=alert(document.domain)>"@gmail.com
<Svg/OnLoad=alert(document.cookie)>"@gmail.com
<Svg Only=1 OnLoad=confirm(atob("WFNTX0JZXzB4MjQ1OA=="))>
POC-
Suggested Remediation To address this vulnerability, it is recommended to:
Input Validation: Implement strict server-side input validation to sanitize and validate all user-supplied input. Reject any unexpected or unsafe input.
Output Encoding: Ensure all output is properly encoded before rendering it to the browser. Use context-aware escaping techniques for HTML, JavaScript, and other output types.
Content Security Policy (CSP): Implement a robust CSP to restrict the sources from which scripts can be executed.
Disable Inline Scripts: Disable the use of inline JavaScript and HTML using appropriate security headers.
I hope the vulnerability gets fixed soon! Thanks :)
While I was caught a little off guard, it was a very well worded vulnerability disclosure - I want to applaud Aryawardhan Singh for his work here!
Disclosure Timeline
- 29th January 2025 @ 12:07: Initial Disclosure
- 29th January 2025 @ 12:20: Response to reporter acknowledging the report
- 30th January 2025 @ 17:43: Additional payload shared
- 30th January 2025 @ 18:24: Fix implemented on production domain
- 30th January 2025 @ 18:30: Confirmed fixed by reporter
- 31st January 2025 @ 15:45: Reporter advised that a subdomain was still vulnerable (I knew this and was using it to test).
- 1st February 2025 @ 07:09: Fix implemented on test subdomain
- 1st February 2025 @ 07:09; Subdomain fix confirmed by reporter
What is an XSS vulnerability?
Straight from the Open Worldwide Application Security Project (OWASP):
Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.
An attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not be trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by the browser and used with that site. These scripts can even rewrite the content of the HTML page. For more details on the different types of XSS flaws, see: Types of Cross-Site Scripting.
How did it manifest in your site?
My website runs on the Hugo static website generator stack and is hosted by Netlify.
I will quite happily admit that whilst I write code in my day job and also for fun, I am not a software engineer/developer and I’m especially NOT a web developer.
So I used an open source theme for my site and configured/tweaked as necessary to achieve the look and functionality I wanted.
Understanding that I wanted to make the site as secure as my stack and my knowledge permitted at the time, I recognised I should make use of a Content Security Policy (CSP) - this is “a feature that helps to prevent or minimize the risk of certain types of security threats. It consists of a series of instructions from a website to a browser, which instruct the browser to place restrictions on the things that the code comprising the site is allowed to do.
The primary use case for CSP is to control which resources, in particular JavaScript resources, a document is allowed to load. This is mainly used as a defense against cross-site scripting (XSS) attacks, in which an attacker is able to inject malicious code into the victim’s site.”
I had set mine up as much as possible to only load specific types of known and expected resources from known and expected sources.
I had, however, left the 'unsafe-inline'
setting configured (deliberately) on the script-src
and style-src
directives to allow local scripts and style elements in the theme to work.
I was quite happy with myself getting an A rating on SecurityHeaders.com.
Ideally I’d have computed hashes for those scripts and style elements and then removed 'unsafe-inline'
but we all know that I never did…
I also couldn’t use the nonce-
capability of CSP because that needs server-side access that I don’t have because I’m not hosting it myself (another example of where giving up control doesn’t absolve you of risk…)
This allowed Aryawardhan to insert code into the search bar on the site and because of both the gap in my CSP and also insecure coding in the JavaScript that provides the search capability, it allowed him to spawn a popup dialog from my site with a message of his choice (about the least malicious way this vulnerability could be exploited).
The additional shorter payload below:
<Img Src=OnXSS OnError=confirm(“xss_by_0x2458”)>
Also worked:
What did you do to fix it?
First I disabled an old and deprecated HTTP Header that can have unintended consequences - X-XSS-Protection.
Next, I rewrote the search.js script that came with the theme to adopt more secure coding practices and hardening.
Summary Of Fixes
Issue | Risk | Solution |
---|---|---|
Unsafe encodeURI() for URLs | Potential XSS via malicious permalink | Use encodeURIComponent(), validate URLs |
Use of innerHTML | XSS risk if encodeHTML() fails | Use .textContent instead |
Unsafe parsing of index.json | Attackers could modify JSON | Validate JSON structure before using it |
No debouncing in searchOnChange | Performance & DoS risk | Implement debounce (300ms delay) |
Insecure insertion of searchQuery into HTML | XSS risk if encodeHTML() fails | Use .textContent instead of innerHTML |
null reference errors in searchButtonEle | Crashes if elements are missing | Check if elements exist before accessing |
Result of Changes
As a result of the changes the vulnerability can no longer be exploited in the way that was demonstrated:
Summary
There are other changes I have made and will make but I wanted to share this with you.
I have also raised a pull request on the github repo for the theme I use so that, if it gets merged in, other users of the same theme will be protected too.
Nobody is perfect, nobody is immune and there is always room for improvement!
As ever, thanks for reading and feel free to leave comments down below!
If you like what I do and appreciate the time and effort and expense that goes into my content you can always