XSS in ViewVC
I found a cross-site scripting (XSS) vulnerability in ViewVC, a source code repository web frontend.
ViewVC is a Python webapp to browse code repositories. It supports CVS and SVN, which people used when git didn’t exist yet. I found a simple HTML injection vulnerability in it. When browsing a source code repository, it shows filenames of files. If the filename contains HTML tags, these are not encoded correctly. The browser interprets these as HTML, and this leads to XSS.
Getting to the source
I actually started searching for vulnerabilities in Tuleap, which is a code management suite with a repository browser and issue tracker. I found a XSS vulnerability in its page that shows Subversion repositories. However, the source code showed that they forwarded requests to ViewVC. So I tested whether I could reproduce the bug in ViewVC, and I could.
Here, I used the following payload as filename:
The most obvious XSS payload is
<script>alert(1)</script>. Sometimes this works a little too well, and keeps showing popups on every page you visit. This is pretty annoying when you want to test more of the application, so now I usually use a payload that needs some user interaction to trigger.
<marquee> tag to test for XSS. This causes text to move, which is easy to detect. At the same time, it is rare for applications to use this tag, so searching for
<marquee> in Burp or the page source will give only XSS payloads as result.The movement does not show well in screenshots, though.
Automatic encoding in template engines
ViewVC uses a template engine, EZT. EZT does support automatic HTML encoding of all variables. However, you have to explicitly enable it, and ViewVC doesn’t.
By default, variables are not encoded at all. In lib/viewvc.py:
To HTML-encode variables by default, pass the
return ezt.Template(cfg.path(tname), base_format=ezt.FORMAT_HTML)
If you don’t have automatic encoding, you have to encode each parameter manually. This is hard to get right. It is easy to forget encoding a parameter. This was also underscored in my XSS finding. After the developers had encoded the path name, someone on Twitter pointed out that there was another variable (copied from path) that should also be encoded.
So, CVE-2023-22456 is a XSS vulnerability in ViewVC, where the input is the name of a file in the repository. CVE-2023-22464 was discovered immediately after that by someone else.
This is my first CVE actually, that I know of. I found many vulnerabilities, but didn’t bother with CVEs, or didn’t get permission from the client I worked for to share the vulnerability.
If your template engine does not automatically encode variables, you are going to have a bad time. It’s hard to be certain that you encoded every single variable, whereas it’s secure by default when the template engine does it.