A member reported a XSS vulnerability in stock JForum 2.1.9. We confirmed it was a vulnerability/exposure on CodeRanch as well and fixed our fork. Luckily, it was an easy fix unlike the CSRF problems last year.
In addition to saying how to fix the issue in this post, I’m going to outline some of the other techniques JForum uses to defeat XSS. For the actual (two character) fix, scroll down to “the fix.”
What is XSS?
- Reflected XSS – A reflected XSS attack targets specific users but is not stored in the database of the server with the issue. You might see a reflected XSS attack if you click on a link that takes you to the page. Others going to the page normally wouldn’t see the issue.
- Persistent XSS – A persistent XSS attack gets the attack code stored in the database of the server with the issue. It could still target a specific user (in the case of the private message issue reported here.) Or it could target all users – even non logged in users – if the same attack was made in a post instead of a private message. I was able to reproduce this problem in posts as well.
Both types of XSS attack are bad and up to the website to prevent. So how does Jforum 2.1.X protect against XSS attacks?
Approach #1 – Use Freemarker HTML escape sequence
JForum uses Freemarker as the view technology. Freemarker allows you to specify that all HTML should be escaped. This means attacks that reply on outputting HTML characters like < (tags) or ” (attributes) will be prevented. Instead the raw characters of < and " will be output instead. Which the browser will not run. As an example of this technique, the code writes:
Approach #2 – Escape characters in Java
Approach #1 is very powerful, but it has a limitation. Forum posts typically contain HTML code. For example, you write code in a special format, bold posts, etc. JForum uses Java code to do a search and replace on the special characters in text before adding the HTML formatting. Since the Freemarker view has to be able to render the HTML formatting, it can’t use approach #1. See an example of just one of these transformations:
ViewCommon.replaceAll(text, "<", "<");
This approach is not foolproof because it relies on a blacklist of “not allowed” characters and hackers are creative. But it is really hard to come up with a whitelist of allowed characters in forum posts. And worse, the characters used in attacks are ones that are used in normal writing.
Approach #3 – Limit raw HTML
While JForum does allow HTML in posts, it only allows a limited set of tags and attributes. This one does use a whitelist with code like:
private static Set welcomeTags; private static Set welcomeAttributes;
Approach #4 – Use BB code instead of HTML
The forum also allows use of BB (bulletin board) codes. This lets you write [b] instead of <b>. If the user isn’t entering HTML, the chance of a problem is lower.
The actual problem here
The XSS vulnerability reported was caused by the interaction between approach #2 and approach #4.
Approach #2 guarantees the quotes are safe with
ViewCommon.replaceAll(tmp, "\"", """);
Approach #4 contains the following BB mapping code in bb_config.xml
<!-- COLOR --> <match name="color" removeQuotes="true"> <regex>(?s)(?i)\[color=['"]?(.*?[^'"])['"]?\](.*?)\[/color\]</regex> <replace> <![CDATA[ <font color='$1'>$2</font> ]]> </replace> </match>
This is a problem because the replace uses single quotes instead of double quotes. The system doesn’t escape single quotes. Allowing all manners of code to be injected in the color attribute.
Luckily, there is an easy fix. Just change this one line of code in bb_config.xml to:
I’ve tested and this does in fact solve the problem.
For more learning about XSS
Hi Jeanne, just wondering the easy fix really fix the problem?
I tested on my own with the double quote fix; if the injection use ” instead of ‘, we still can get the xss.
just wondering “The system doesn’t escape single quotes” – does it escape double quote?
Also I am not clear of how do you approach the #2; shall we change the java code? or the Freemarker templates?
Approach #1 does escape properly. (It’s escaping all HTML, not just the quotes.) The problem is that we need to render HTML code so it doesn’t display quotes/bold/etc properly.
For approach #2, you need to change the Java code.
Pingback: fixing clickjacking and brute force login for jforum | Down Home Country Coding With Scott Selikoff and Jeanne Boyarsky