Sakai is educational software, to keep track of classes, students and test marks.


Some applications are riddled with XSS, because they don’t have a structural prevention in place. If you have to call htmlentities for every output, you are going to forget a couple of places, which directly leads to XSS. A better solution is to have a templating system that escapes content by default. Sakai does have such a templating system, so in most places the user input is correctly escaped. However, I found one place that doesn’t correctly escape input.

XSS in first name

The username or given name of the user is always an interesting place to try XSS payloads, since it is displayed on many places and is often considered “trusted” by the application developers.

Sakai prevents the most straightforward XSS payloads through input sanitation. HTML tags are removed from the user input. So when inputting <h1>Sjoerd as the first name, only Sjoerd remains. Only matching brackets are removed, so single brackets remain. There are two ways around this:

  • Split the payload over multiple fields. The user can set his first name and last name, which are often displayed next to each other. By putting <svg in the first name and onload=alert(1)> in the last name, the input sanitation does not see a HTML tag in any of the fields, but the result is a complete tag: <svg onload=alert(1)>.
  • Insert a partial HTML tag. The tag doesn’t have to be closed, since there will be a > already on the page somewhere. If the first name is displayed within a <div> element, and we inject <svg onload=alert(1) , the closing element of the div closes our tag: <div><svg onload=alert(1) </div>.

In Sakai, both options work. In the Sakai chat room the first and last name are displayed next to each other. So to trigger XSS, modify the first name of the user to <img src=a onerror="alert(1)" or something similar. Then open the chat room. A popup appears, indicating that the XSS payload works. The page source contains this HTML:

<span class='chatNameDate'><span class='chatName'><img src=a onerror="alert(1)" Langkemper</span>

Abuse of the template system

The source of the XSS is this line in roomMonitor.jspf:

<c:out value="<span class='chatNameDate'><span class='chatName'>${message.owner}</span>" escapeXml="false" />

So Sakai is using a generic template system, which automatically encodes output. However, in this case they explicitly disabled it using escapeXml="false", in order to output HTML, which is something the template system is supposed to handle. The solution is to use the template system correctly, so that it escapes the variable.


Even web applications that use template systems that escape all output by default can be vulnerable to XSS. Developers have to use the template system correctly to profit from the protection it offers.

I reported this issue to Sakai and they quickly resolved it.

Read more

Sakai issues:

Other XSS posts: