Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I want to use Elavon VirtualMerchant to make credit card payments on my website.

I don't want to do PCI DSS certifications other than SAQ A, so don't want to process or store card data on my site. I want to use VirtualMerchant payment forms so user enters sensitive data to fields of PCI DSS certified site.

It seems that VirtualMerchant can give me this possibility, but... Let's see what VirtualMerchant can give:

  1. I have button on my website which submits some basic data such as purchase description, payment amount. And my id and pin in hidden fields that can be easily seen by any user.
  2. When user presses the button, data is POSTed to virtualmerchant site and browser shows the VirtualMerchant payment form. User enters sensitive data to approriate fields and presses Process button.
  3. Data is verified by virtualmerchant and then the best that can be done is so-called REDG (redirect get to merchant receipt), i.e. user's browser is redirected to the webpage-i-can-specify carrying additional info such as transaction id.
  4. My application knows that transaction is done when it receives GET on the webpage-i-can-specify.

But there is a bunch of questions.

  1. How do I verify that transaction with the details provided on step (4) was really done? For example, I POST transaction id and some transaction details to trusted VirtualMerchant URL and get the result - either it is VERIFIED or INVALID, like I can do with PayPal.
  2. What happens if client has lost connection in the end of step (3)? So that client already has lost money but there is no way for my application to know that transaction ever happened?
  3. Is it ok that client knows all the transaction detail fields when client's browser is redirected to "merchant receipt" page? Client then can so easily get to step (4) - get the item - skipping through step (3) - pay the money.
  4. Am I right that I cannot provide secure way for payments without PCI DSS certification (other than SAQ A) with VirtualMerchant? If I process user sensitive card data with server-side scripts then I can use virtualmerchant's ip-address-filter, don't publish id/pin, do communications through secure channel and get callbacks to secure urls. But If I just want to use virtualmerchant's payment forms - I can't imagine how to provide good way which is not so easy to fraud.

P.S. Yes, I know how I can do it with paypal, for example. The question is - can I ever do it with VirtualMerchant?

share|improve this question

migrated from stackoverflow.com Jun 11 '13 at 22:43

This question came from our site for professional and enthusiast programmers.

    
Seriously, what of the first three question isn't covered in the VirtualMerchant's Developer Guide (PDF), Chapter 4 - Payment Integration, Page 37 through Chapter 5 - Transaction Flows, starting on Page 46? With examples and whatnot. Payment systems like this one would all already anticipate the need to process transactions (including exchange of payment and confirmation tokens) using external processes. #4 depends on whether you'll process PCI data at all, and by your method you wouldn't - your processor would. –  Noordung Jun 11 '13 at 23:03
    
@TildalWave Seriously, not a single. For example, let's begin with question 1. Where and how should I post transaction id ssl_txn_id to verify that this transaction really happened? –  Andrey Regentov Jun 13 '13 at 10:25
    
I think all the queries are defined later in the API section (open, unsettled batch, authorized transaction, recurring transaction, inquiry, return, purchase,...) with input and output parameters and what addresses to query and how, and a few more bits and pieces near the beginning in the Communicating with VirtualMerchant section. It's per transaction type, so you'll be dealing with those that apply as per your requirements (debit cards, credit cards, food stamp, gift card, electronic checks, you name it). And yes, the documentation seems all over the place, I suggest you print it out. ;) –  Noordung Jun 13 '13 at 11:26
    
@TildalWave Yes, all the queries that this system supports are defined as you say. But there is no query "did the transaction with this id happen?" Then end-user can post me any data and I don't have any way to check whether it is real transaction or fraud. –  Andrey Regentov Jun 14 '13 at 4:23

2 Answers 2

Update following @Andrey Regentov's comment that he's getting hit on ssl_apprvl_get_url from the customer's IP address, not VirtualMerchant -

Wow. Just wow. Much of what I wrote below the "Original Post" line is incorrect because of me getting this detail wrong in my read of the Developer's Guide. And I probably got some of it wrong because my mind subconsciously rejected the possibility that someone would do something that "Wow".

But, you're right. Page 52:

The customer would be redirected to “http://www.website.com/approval.asp” for an Approved transaction or to “http://www.website.com/decline.asp” for a Declined transaction. The transaction data will be passed along as Get variables in the query string of the URL.

The URLs above were shown as being set in the form for ssl_receipt_apprvl_get_url and ssl_receipt_decl_get_url. (Upon closer reading, it looks like ssl_apprvl_get_url is just a typo where they meant ssl_receipt_apprvl_get_url, as it only shows up twice, and in at least one case page 47 they show ssl_receipt_apprvl_get_url being set and then describe how they just set ssl_apprvl_get_url.)

I'm kind of boggled by this because - as per the premise of your question - this allows the customer to rewrite the processor response to whatever they want, to tell you it was approved when it was in fact declined. It's actually a full MITM - the customer can adjust the hidden form parameters the merchant hands their browser, submit the modified form to the processor, and then intercept and modify the redirect the processor is sending to the merchant via them (the "customer").

And we may be missing more here, because as described on page 44, there are four ssl_receipt_link_method options you can choose from (GET, POST, LINK, REDG) and one of them (LINK) "does not transmit data back to your website." There's no particular indication what the difference is between GET and REDG (REDirect-Get), and no example of the GET method shown. So how the heck is it supposed to work? Beats me. Leave open the possibility that it's hard to figure this crap out from the Developer's Guide and that other documents exist which may make more sense.

But, fear not. To your original core question:

1 How do I verify that transaction with the details provided on step (4) was really done? For example, I POST transaction id and some transaction details to trusted VirtualMerchant URL and get the result - either it is VERIFIED or INVALID, like I can do with PayPal.

Review the section titled "Export Scripts" on pages 44-45. Essentially, you can configure the out-of-band callback so that VirtualMerchant will directly notify you of the details of a completed transaction:

The export script if set up will be run following completion of a transaction (approvals, declines, errors). It returns results of a payment to your web server using a standard web protocol HTTP to "call" a page on your server just as a browser calls any web page. The export script dumps data about the transaction response to the web page using a form POST.

This gives you the independent verification that I thought I was describing in my original answer; it's just an extra step to set it up.

At this point, I'm less comfortable I have a clue than I did before, so take anything I say with a grain of salt. But I'm going to suggest the following:

  1. Given some of the ambiguity I'm now seeing about the Developer's Guide, your best bet may be to just ask someone at VirtualMerchant. Get 15 minutes on the phone with someone who can understand top-level questions and point you to particular bits of documentation that will tie together to give you the answer.
  2. What I'm seeing is consistent with a product that was designed for one thing (API for direct merchant-to-processor calls) and then redesigned for something else (transaction redirection with customer in the middle). If I'm correct, be wary; such redesigns often breed security holes.
  3. From a security point of view, I would be very cautious - which is what you were doing when you first asked the question. You have a very legitimate concern about the transaction flow as we understand it from the Developer's Guide. The mind boggles that someone would implement a CITM (Customer-in-the-middle) system for card transactions without encryption and authentication of trusted parameters. It's literally hard to believe (in the literal sense of the word "literally").

Some more detail about #2 above - If you look in the "Best Practice Tips" of the "Transaction Security" chapter (page 219):

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.

This makes it seem like they're explicitly telling you (for Security's sake) not to do what they're explicitly telling you (to avoid PCI scope's sake) to do with their VirtualMerchant Payment Form. Something's rotten here, and we're not even in Denmark.


Original Post - SOME OF THIS IS WRONG

Okay, I've looked into your questions with the developers guide and I believe the following are true answers. As a caveat, I do work for a company with a competing product; I will try not to let that bias my answers, but I will describe an alternate solution at the end.

1 How do I verify that transaction with the details provided on step (4) was really done? For example, I POST transaction id and some transaction details to trusted VirtualMerchant URL and get the result - either it is VERIFIED or INVALID, like I can do with PayPal.

Step 4 on page 47 of VirtualMerchant Developer Guide (#VRM-002-B) states that when a transaction is approved, they'll call a GET to the URL you've provided them in the ssl_apprvl_get_url field which the client POSTed to you. Most importantly, you'll be given an obfuscated version of the customer's card (ssl_card_number), the $ amount the customer POSTed (ssl_amount), whether it was approved or not (ssl_result, ssl_result_message, ssl_approval_code), and a transaction id (ssl_txn_id). If the POST request included ssl_invoice_number, then that will be returned, as well. Although it's not being stated obviously in the manual, that appears to be the appropriate method to match ssl_apprvl_get_url calls with forms you handed out to customers.

If the customer messes with the ssl_amount field, then you'll see a different amount than you expected was authorized, and should deal with that appropriately - otherwise they'll fill their cart with a $999 TV, change it to $1 before POSTing, and if you rely upon ssl_invoice_number without validating ssl_amount and ship the TV, you're out $998.

Likewise, if the customer messes with ssl_invoice_number, they won't match up with their attempted transaction - but presumably they're only hurting themselves in that case, as you won't go through with the bogus transaction.

2 What happens if client has lost connection in the end of step (3)? So that client already has lost money but there is no way for my application to know that transaction ever happened?

This initial POST is the authorization, not the settlement. You shouldn't settle unless you have sent the customer off to POST, gotten the ssl_apprvl_get_url callback, reconciled the two, and reached the point where you've closed out your transaction with the customer. It's not intuitively obvious how VirtualMerchant is handling settlements, but see for example page 219 of the Developers Guide where it describes "Auth Pend – We recommend that you use this feature for any account that is set to Auto-Settle. This gives you the chance to review each transaction before it becomes finalized. This will help you to avoid settling fraudulent transactions or transactions that you are unable to fulfill."

3 Is it ok that client knows all the transaction detail fields when client's browser is redirected to "merchant receipt" page? Client then can so easily get to step (4) - get the item - skipping through step (3) - pay the money.

Well, there's two questions there.

Can the customer get the item without paying the money? Not if you're doing your job right. You should never ship the item unless you're notified via the ssl_apprvl_get_url callback that the specific transaction (ssl_invoice_number) was approved for the specific price (ssl_amount).

That being said, there are issues with the information the customer has their hands on.

The most obvious is that they can see and tamper with the ssl_appvl_get_url. If that page is accessible to them, they could concievably send the POST off to VirtualMerchant and then attempt to send a bogus GET with their own approval to that page. If your application gets a GET from VirtualMerchant saying DECLINED, and a GET from South Korea saying APPROVED, will it handle that correctly?

Another is that the merchant credentials for performing authorizations are accessible to the customer. They can now perform authorizations at will. This introduces a number of potential attacks - can they perform a DOS on valid cards by putting authorization holds in place? Can they perform CVV enumeration by trying 1000 authorizations on a valid card number and seeing which one works? Can they perform a DO$ on you, the merchant, by running up authorization fees with bogus transactions? Remember, they can point the ssl_appvl_get_url wherever they want, so you wouldn't know it was going on until you got your monthly bill.

4 Am I right that I cannot provide secure way for payments without PCI DSS certification (other than SAQ A) with VirtualMerchant? If I process user sensitive card data with server-side scripts then I can use virtualmerchant's ip-address-filter, don't publish id/pin, do communications through secure channel and get callbacks to secure urls. But If I just want to use virtualmerchant's payment forms - I can't imagine how to provide good way which is not so easy to fraud.

As I mentioned in the my other answer, no - once you're handling PAN data, you're out of SAQ A. Only brick-and-mortars qualify for SAQ B. And if you're writing a payment application on a web-available ecommerce platform, you don't qualify for SAQ C, so you're in for the SAQ D.


Potentially biased content

The company I work for has a product called PayPage which handles this differently and, I think, better. The initial POST from the customer to the processor doesn't authorize the transaction, it tokenizes the card. The customer's browser is handed back a registration ID, which it then smoothly passes in to the merchant page. The merchant page can take that registration ID to the processor and retrieve the token that represents the customer's card, and perform all authorization and settlement operations using that token.

The registration ID is not usable to the customer except in the context of handing it over to the merchant, and the customer can't perform authorizations, only tokenization. This removes a couple of the attack vectors that I've described above.

Once the merchant is handed the registration ID and uses it to retrieve the token, the merchant can perform all the actions with the same level of control that they would have with the card, but without the PCI DSS implications of storing, processing, or transmitting card data.

There's a diagram of this on page 2 of the PayPage Data Sheet, and some clearer verbiage.

...and, yes, the merchant STILL has to fill out the SAQ A.


Clarification: VirtualMerchant and PCI-DSS scope

Looking at @TildalWave's comment and re-reading what I wrote, I can see I didn't lay things out as clearly as I might. Let me try and summarize the key points briefly.

Using a VirtualMerchant Payment Form as described on page 39 of the Developers Guide, the merchant can avoid storing/processing/transmitting PAN data by having the HTML form which the customer fills out and submits be POSTed directly to VirtualMerchant. This potentially could allow the merchant to qualify for SAQ A, if they are careful to avoid handling cards in all other ways as well.

On the other hand, if the merchant doesn't want to offload PAN handling by using the VirtualMerchant Payment Form, if they want to take PAN data from the customer, "process user sensitive card data with server-side scripts", and then submit it directly to VirtualMerchant themselves, then they are increasing their PCI scope, and putting themselves firmly into SAQ D.

I've laid out some issues with the VirtualMerchant Payment Form in the main post body above. None are outright holes, just areas to be cautious and potential tangential problems (e.g., verify result authorized was the same as amount invoiced, attacker can use and abuse merchant's credentials, CVV enumeration might be easier since the attacker can modify the page VirtualMerchant uses to notify the merchant of the authorization result, etc. etc.).

The Developers Guide suggests that the ssl_txn_id might be used in other queries to retrieve PAN data, which would be a pitfall in keeping clean for SAQ A purposes. For example, on page 19 it says:

The transaction ID (ssl_txn_id) allows VirtualMerchant to pull all needed information associated with the original transaction (card number, expiration date, auth code, etc.) from the transaction record in the database to update the transaction.

I don't see any actual methods to "pull" the original transaction info in the Developers Guide, though. I have no doubt they exist, though, so that's what I mean about "being careful to avoid" PAN data.

share|improve this answer
    
+1 Great answer, thanks for taking the time. I see now that #4 avoided me, because I assumed it still tokenized transactions (not cards mind you, which I like a whole lot more also). But yes, simple search for ssl_card_number in the manual reveals OP will have to handle PANs, which unfortunately brings along a lot bigger responsibility, I'd dare say burden even. It's a bit strange model to me, as it's not any more convenient that handling a complete IP-based POS environment really. Will OP be required to have passing quarterly scans to validate PCI compliance also, on top of SAQ D? –  Noordung Jun 15 '13 at 8:46
    
Yes, as per 11.2, SAQ D requires quarterly network vulnerability scans, internal and external. You can do your own internal scans, but need an ASV for the external scans. Yes, SAQ D represents a lot of burden - arguably the responsibility is already there once you're handling cards :) –  gowenfawr Jun 15 '13 at 14:16
    
@TildalWave, I appended a clarification to my answer. The OP might avoid handling PANs, and thus reduce his PCI scope, but only by using the VirtualMerchant Payment Form, which OP felt limited his control (and which I feel has some shortcomings). And most of the methods described in the Developers Guide are discussing the more straightforward method of implementation, not the scope-limiting Payment Form, so it's easy to get a little lost. –  gowenfawr Jun 15 '13 at 16:14
    
Great effort and time put in that answer, thank you so much for that. Maybe I didn't emphasized it well, but on step (3) user's browser is redirected to ssl_apprvl_get_url, not the VirtualMerchant sends the request. Nothing about it is stated in documentation, but I checked it myself, and anyone can check it as well. And that's the security hole I talk about. So user can see all the fields generated by VirtualMerchant. –  Andrey Regentov Jun 18 '13 at 5:56
    
So, during normal operation, I do not receive GET on ssl_apprvl_get_url from VirtualMerchant IPs, I receive it from user's IP. Either during fraud operation I receive GET on ssl_apprvl_get_url from user's IP, and of course fraud will enter valid ssl_amount and valid ssl_invoice_number. So I cannot tell the difference betweed valid APPROVED from South Korea and fraud APPROVED from South Korea. I could tell the difference if only I had what I ask in (1) - the way to check with VirtualMerchant whether the transaction happen or not - but they don't provide the way. –  Andrey Regentov Jun 18 '13 at 5:56

TildalWave provided pertinent technical documentation pointers in the comments, but I'd like to point out the tangent that you can't escape PCI DSS certifications completely. Even if you “rely entirely on third party service provider(s)” you would be required to fill out the PCI DSS Self Assessment Questionnaire (SAQ) 'A'. It's a very short questionnaire, but you still would have to fill it out and attest to it.

(Update to reflect edited version)

You said:

.4. Am I right that I cannot provide secure way for payments without PCI DSS certification (other than SAQ A) with VirtualMerchant? If I process user sensitive card data with server-side scripts then I can use virtualmerchant's ip-address-filter, don't publish id/pin, do communications through secure channel and get callbacks to secure urls. But If I just want to use virtualmerchant's payment forms - I can't imagine how to provide good way which is not so easy to fraud.

If you "process user sensitive card data with server-side scripts", then you no longer qualify for the SAQ A. You'll jump all the way to the SAQ D, which is nearly 300 questions of audit-y goodness. And, looking at the developer guide, you might need to worry about PA-DSS (in addition to PCI-DSS) depending on what you're doing.

share|improve this answer
    
Right, thanks, edited the question. Initially meant that "Merchant does not store, process, or transmit any cardholder data on merchant systems or premises but relies entirely on third party service provider(s) to handle these functions" should be my case. –  Andrey Regentov Jun 14 '13 at 4:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.