I'm working with a payment gateway that seems to have a fundamental misunderstanding of "clients" and how to protect sensitive data.

The integration instructions are mostly about a "redirect" mode of operation, where a customer is directed to the gateway's website to enter credit card details, where they see a receipt and then get directed back to your website.



Here's an example

.do" method="POST"> 
<input type="hidden" name="ssl_merchant_id" 
<input type="hidden" name="ssl_user_id" value="my_user_id"> 
<input type="hidden" name="ssl_pin" value="my_pin">
<input type="hidden" name="ssl_transaction_type" value="ccsale">
<input type="hidden" name="ssl_show_form" value="true"> 
<input type="hidden" name="ssl_amount" value="14.95"> 
<input type="submit" value="Click to Order"> 

This is the paragraph that has me concerned:

All sensitive data, specifically your VirtualMerchant credentials, should be placed in server side code rather than placing hidden value fields on an HTML form. This will limit the ability of malicious users to edit and use this data for their own fraudulent purposes. The use of server-side scripting allows custom HTML to be delivered to a client machine. The code that generates the custom HTML is processed on the Web server before the HTML is sent to the user's machine over the Internet. This is in contrast to client-side scripting where the HTML is modified, typically by java-script in the client's machine after the HTML and java are sent from the Web server. The primary strength of using serverside scripting with VirtualMerchant integration is the ability to hide the sensitive processing credentials from the browser.

That sounds great — not exposing my account ID to the client.

However I don't think that what they are suggesting takes care of it. I can only see two ways to hide the details entirely from the client:

  • Have the server act as the client and the browser is never directed to the payment gateway's website

    They offer this mode, but most of the documents refer to the HTML/client-side form mode instead.

  • Use a signed token of some sort — which they don't support.

This paragraph, however, seems to claim something about using "server-side scripting" to deliver "custom HTML", and therefore hide the details? I just don't see any way - even if the redirect took place via a Location header, that data would still be exposed to the browser and anyone with malicious intent could easily get it.

Can somebody please help me understand why this sounds so wrong to me?

2 Answers 2


At a glance, it looks like the instructions in the developers' guide are not so much wrong as simply misleading. As you note, pretty much all the examples do show the sensitive ssl_merchant_id, ssl_user_id and ssl_pin fields embedded as hidden form fields in HTML code sent to the customer. However, if you work your way all the way to chapter 9, "Transaction Security", you'll find the following paragraph under "Best Practice Tips" (boldface original, italics mine):

"Server Side Code – Your users can read HTML source code from your Web pages when they are downloaded to their Web browser. Although our simple examples in the document show this as a method for passing data to VirtualMerchant, we do not recommend this for your production website. All sensitive merchant data, including transaction amounts and your VirtualMerchant credentials, should be placed in server side code, rather than in hidden value fields on an HTML form. This will reduce the ability of malicious users to exploit client browser vulnerability to edit and use this data for their own fraudulent purposes. If you are not knowledgeable enough to implement this on your own, there are quite a few shopping cart providers that inherently provide this service and are compatible with VirtualMerchant."

So, basically, it's a case of "do as I say, not as I (show you how to) do".

That said, it does seem to me that, if you follow all the other security recommendations carefully, passing the merchant/user ID and PIN to the customer may not be as bad as it might seem. Done right, having those values should only give the customer access to a limited user account that only allows them to make payments to you — but that's what you're allowing them to do anyway, so it should be no big deal.

Of course, that only holds if you really can (and do) make the user account used for the form so limited that it's safe to hand out to customers. Without further study, I can't really tell whether that's possible or not.

  • I saw that second paragraph too - but I'm unsure what they mean by "server side code", since I can't see any way to secure the variables in "server side code" without doing a formless transaction (server is client, entire transaction is transparent to user's browser)
    – Nicole
    Jun 29, 2012 at 15:43
  • Yes, I assume that's exactly what they mean. It does seem like their API is somewhat limited -- in particular, I see no way to conduct a transaction such that the customer doesn't see your merchant/user ID and PIN and such that you don't see the customer's payment information (credit card number or equivalent). It should not be difficult to implement such a mechanism, either using server-to-server communications and single use tokens, and/or using encryption and message authentication codes, but I see nothing like that in their developers' guide. Jun 29, 2012 at 16:11
  • Yes! That's exactly what concerned me. I worried I was doing something wrong to do it entirely server-side, but I can't see another way and it actually sounds like that's what they are recommending (sounds like, but I wasn't 100% sure.).
    – Nicole
    Jun 29, 2012 at 16:27

I have been working with payment gateways for some time and this can be a bit confusing.

First the second statement made by Elavon on within chapter 9, "Transaction security" says that the server side code will "..reduce the ability of malicious users to exploit client browser vulnerability to edit and use this data for their own fraudulent purposes."

The above statement is correct that it will reduce the technical knowledge needed to gain access to these credentials. Instead of a client clicking view source and seeing the post data they would need to use fiddler or the like to capture the post data. Regardless this is an inherent vulnerability of this architecture. Prior to 2008 most CC processing went through as a server to server API call which can result in a compromised system collecting thousands of CC numbers, user data, etc. This architecture allows easy manipulation of data on a 1 to 1 basis, meaning each client can easily change and collect this data but not on a large scale. PCI compliance regulation also will place a huge burden on your organization if you complete server to server transactions.

What you need to do to mitigate any potential compromises:

  1. Make sure you create a non-admin user to complete these transactions.

  2. You MUST reconcile every day with the payment provider. To do this you can use the API to connect with the payment gateway provider and grab ALL transactions settled for the past x amount of days (I do 7). Loop over each batch and check every single transaction for accuracy between both systems (your's and payment gateway). I have created a sophisticated reconciliation routine that sends emails to IT staff and our security office if anything does not match correctly. This can be a user changing the billing amount using fiddler or manipulating the result of the transaction. Remember, both the transaction post and the result go through the client with some setups and you cannot rely upon the client to be "truthful". If you are creating a system which sends physical merchandise you must wait until the transaction is settled and has been reconciled before you mail the product to prevent fraud and abuse.

The compromising of the transaction keys do not mean much as the the malicious actor will be sending money to your bank account and no one wants to do that. You need to make sure your login credentials to the administration console are not compromised and I see no way this could happen in a secure environment.

You must however create a new user independent of one used to process transactions to reconcile with the gateway provider. With the user you created to process transactions you MUST turn off API access to reconcile. If someone gets access to your reconciliation user credentials they can write reconciliation code using those credentials and get a dump of all your customers along with purchase amounts and all sorts of other data such as name, address, etc.

Best of Luck, Eric

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .