Exploit CVE-2021-42567, a POST-based XSS on Apereo CAS

In early December 2021, MITRE announced CVE-2021-42567, an unauthenticated POST-based XSS via REST API endpoints. The CVE references have a link that refers to the advisory of Apereo CAS, an open-source authentication system for Enterprise Single Sign-On (SSO). This advisory, however, was disclosed on October 18th, 2021. The patch versions, and 6.4.2, were released on Github on November 15th and 13th, respectively.


The Apereo's vulnerability disclosure said:

CAS is vulnerable to a Reflected Cross Site Scripting attack, via POST requests sent to the REST API endpoints. The payload could be injected on URLs: /cas/v1/tickets/. Malicious scripts can be submitted to CAS via parameters such as the ticket id or the username. That results in CAS rejecting the request and produce a response in which the value of the vulnerable parameter is echoed back, resulting in its execution.

At this point, we know that:

  • The vulnerable endpoint is "/cas/v1/tickets/"
  • The vulnerable parameters are "ticket id" and "username"
  • The vulnerable parameters are reflected on the HTTP response without sanitizing or escaping and get executed by the browser. The response's content type must be "text/html" instead of "application/json" as we often see in REST API.

I often read these commits of the patch version to see where the vulnerability locates. However, a faster way for this case is a quick search on Google to find a sample of a normal request to the ticket API. Luckily, I saw it in a post on Stack Overflow. The ticket API can take a POST request with the ticket's ID in the URL ("/cas/v1/tickets/[ticket's ID]") or the parameter "username" in the request's body.

Proof of Concept

Let's try to make a PoC for the XSS vulnerability on the ticket API. It seems easy as you just need to drop the XSS payload inside the parameter "username" or at the end of the endpoint's path (in URL-encoded form, of course). Apereo CAS rejects the request and echoed back the ticket's ID or the username in the HTTP response without sanitizing or escaping while the header "Content-Type" is "text/html".

For the "username" parameter (the path can contain the last slash "/" or not):

For the ticket's ID (in a request contains both the ticket's ID and the username, the ticket's ID will be processed first so the username will be ignored):

To exploit a POST-based XSS, you need to do the same as CSRF. This means you craft a malicious HTML file on your website, lure the victim to visit this file by sending them the link via email, message,... Then the exploit code in the HTML file automatically sends the POST request to trigger the XSS vulnerability. Here is an example for only popping up an alert window when you open it on the browser using the "username" parameter:

  <body onload="document.forms[0].submit()">
    <form action="https://example.com/cas/v1/tickets/" method="POST">
      <input type="hidden" name="username" value="<img/src/onerror=alert(document.domain)>" />
      <input type="hidden" name="password" value="Mellon" />

Another example for the ticket's ID:

  <body onload="document.forms[0].submit()">
    <form action="https://example.com/cas/v1/tickets/%3c%69%6d%67%20%73%72%63%20%6f%6e%65%72%72%6f%72%3d%61%6c%65%72%74%28%64%6f%63%75%6d%65%6e%74%2e%64%6f%6d%61%69%6e%29%3e" method="POST">
      <input type="hidden" name="username" value="test" />
      <input type="hidden" name="password" value="Mellon" />


Apereo CAS is an SSO system so it is often able to reach from the Internet. You can search for the public Apereo CAS servers on Shodan by the query "Server: Apereo CAS" because this header is inside the HTTP response by default.

Some servers are configured to not display the "Server" header's value or remove it. In this case, you can query http.title:"CAS - Central Authentication Service" on Shodan. This is the default title in the HTML of Apereo CAS.

At the time I wrote this post, not all Apereo CAS servers I found on Shodan are vulnerable to CVE-2021-42567, but many of them still are, of course. A vulnerable server needs to have these things:

  • Apereo CAS version 6.3.x before, or 6.4.x before 6.4.2
  • Apereo CAS uses the CAS REST functionality to create or query tickets.

If an Apereo CAS server doesn't use the CAS REST functionality to create or query tickets, visiting the endpoint "/cas/v1/tickets" will return 404 Not Found. Otherwise, it will return HTTP 405 instead.


The patch versions still reflect the ticket's ID and the "username" parameter but they are HTML encoded and cannot trigger the XSS payload anymore.

If you are administrating an Apereo CAS server, you should check the server's version and update to ... not the versions and 6.4.2, but the versions and to mitigate this XSS and the critical Log4J vulnerability as well.

Thank you for reading!