"Excuse me? Did I read that correctly? You want me to have the credit card transaction response to bounce off the buyer's browser? You want me to rely on what the buyers machine has to say about the validity of the credit card?"
Good day (morning or evening) Fravia+
I have some information that I think might be of some interest to you since it involves commercial websites and payment processing. First of all I do not pretend to be a hot-shot hacker and you will not find me roaming the net under some cool name like v33zRd or whatever else. I am just a developer who worked with web based stuff from quite some time. I nether got up one morning and decided to become a hacker, nor have I planned this for years. It just happened that I was assigned by my employers to some projects that involved security and coding for load test. Well enough about me lets get to the meat of the matter. In one of my recent projects I had to build a payment processor integration for an eCommerce website. A decision was made to try out the GeoTrust. GeoTrust provides SSL certificates for websites and also resales credit card transactions from SkipJack for the commercial web. An astonishing discovery GeoTrust encourages its clients to bounce the credit card transaction from the buyers browser! Unbelievable stupid way of clearing a credit card. This opens the door for anyone with half way programming skill to compromise the response and order products and services from the merchant without actually paying for it. Of cause I have notified GeoTrust about it but they have buried their head in the sand on this issue. In fact they do not consider it an issue. I wonder why? It is either due to the fact that they do not want to admit to such as stupidity or due to the fact that they do not want to refund the money for the Quick Payments account closed by the merchant once I informed the merchant that the buyer's machine would be the last link in the credit card transaction chain. As many corporate swines GeoTrust has really pathetic support and rather poor understanding or web technology. Just the fact that they are using Microsoft ASP (Active Server Pages) speaks of it. But I will not go in to arguments of what technology is superior or inferior. That is not the point. The point is that some so called developers at this organization are so damn blind that they literally can not see beyond their noses. Here is how it works: A transaction is initiated from the server side by the merchant and sent to GeoTrust server over secure HTTPS connection for validation. The transaction contains a list of parameters and values and acts as an HTTP post. Here is the example of the string being passed to the gateway server: (I replaced the serial numbers with Xs and domain name is changed) szSerialNumber=XXXXXXXXX& szDeveloperSerialNumber=XXXXXXXXXX& szOrderNumber=777& szDesiredStatus=AUTHORIZE& szAmount=1.45& szTransactionId=& szForceSettlement=0& serialnumber=XXXXXXXXXXX& orderstring=1%7E1%7E1.45%7E1%7EN%7E%7C%7C& ordernumber=2& sjname=Test+Dude&email=null40Ssomewebsite.com& streetaddress=8320&streetaddress2=& city=Some+City& state=FL& zipcode=85284& transactionamount=1.45& accountnumber=4445999922225& month=09& year=05& shiptoname=Test+Dude& shiptostreetaddress=8320& shiptostreetaddress2=8320& shiptocity=85284& shiptostate=FL& shiptozipcode=85284& shiptophone=8005551212& comment=123456789Simple thing and simple to achieve. Here is a JSP example of how this can be posted: 1) // Define and connect to quickpayments URL 2) URL u = new URL("https://developer.quickpayments.com/scripts/evolvcc.dll?Authorize"); 3) URLConnection uc = u.openConnection(); 4) uc.setDoOutput(true); 5) uc.setDoInput(true); 6) uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 7) // POST the data 8) DataOutputStream output = new DataOutputStream( 9) uc.getOutputStream() ); 10) 11) // post the query string 12) // to the server and get the response 13) output.writeBytes( str.toString() ); 14) output.close(); The query string is the string above. So far so good, server side and secure, but now we have to get a response from quickpayments connection: 15) // get the response 16) BufferedReader in = new BufferedReader( 17) new InputStreamReader( 18) uc.getInputStream()) ); 19) tags = in.readLine(); 20) in.close(); and it comes something like this: NOTE: I have replaced the < with [ and > with ] since this mailer acts weird when an HTML snippet is used in the email. tags= “[html][head][title]Response File Redirect[/title][/head][body onload="document.myForm.submit()"][form action="http://www.mywebsite.com/servlet/jspcontroller" name="myForm"][input type="hidden" name="comment" value="test"][input type="hidden" name="shiptophone" value="8005551212"][input type="hidden" name="shiptozipcode" value="85284"][input type="hidden" name="shiptostate" value="FL"][input type="hidden" name="shiptocity" value="123 Some Street"][input type="hidden" name="shiptostreetaddress2" value=""][input type="hidden" name="shiptostreetaddress" value="8320"][input type="hidden" name="shiptoname" value="Test Dude"][input type="hidden" name="transactionamount" value="49.95"][input type="hidden" name="zipcode" value="85284"][input type="hidden" name="state" value="NY"][input type="hidden" name="city" value="123 Some Street"][input type="hidden" name="streetaddress2" value=""][input type="hidden" name="streetaddress" value="8320"][input type="hidden" name="email" value="test@nowhere.net"][input type="hidden" name="sjname" value="Test Dude"][input type="hidden" name="ordernumber" value="28976"][input type="hidden" name="orderstring" value="1~1~49.95~1~N~||"][input type="hidden" name="serialnumber" value="XXXXXXXX"][input type="hidden" name="szForceSettlement" value="0"][input type="hidden" name="szTransactionId" value="1"][input type="hidden" name="szAmount" value="10.95"][input type="hidden" name="szDesiredStatus" value="AUTHORIZE"][input type="hidden" name="szOrderNumber" value="777"][input type="hidden" name="szDeveloperSerialNumber" value="XXXXXXX"][input type="hidden" name="szSerialNumber" value="XXXXXXXXXX"][input type="hidden" name="szTransactionAmount" value="1095"][input type="hidden" name="szAuthorizationResponseCode" value=""][input type="hidden" name="szAuthorizationDeclinedMessage" value="Authorization failed, try again."][input type="hidden" name="szAVSResponseCode" value="0"][input type="hidden" name="szAVSResponseMessage" value=""][input type="hidden" name="szOrderNumber" value="2"][input type="hidden" name="szReturnCode" value="1"][input type="hidden" name="szCVV2ResponseCode" value=""][input type="hidden" name="szCVV2ResponseMessage" value=""][input type="hidden" name="szIsApproved" value="0"][input type="hidden" name="szTransactionFileName" value="XXXXXXXXXX.XXX"][input type="hidden" name="szCAVVResponseCode" value=""][/form][/body][/html]”When I saw that at first I was wondering whether what I was seeing is really true. Look for yourself. This is nothing less then a complete simple HTML page with a form filled with all the values meant to be posted back to my server via onLoad java script. From where(?) you might ask. From the buyer's browser! I was not too happy with that and at first I was convinced that I am just delusional and that this is not meant to be posted to the user browser. But if so I would have to parse this garbage. So I have contacted support at GeoTrust. It was not an easy task to get some one to talk to. My questions were: Can I get a response from your transaction server that I can parse and make the decision to mark the order as paid or unpaid before displaying my own response page to the user? Why do you post my serial numbers in the transaction that returns back to me? The first four emails were answered “I do not understand you question”. But after few futile attempts some bozo from second level support answered the following: “GeoTrust provides easiest integration... (blah blah blah) ... the data sent from our server should be printed in to the user browser and the javascript would redirect the client browser back to your server, so you can have your response page be in any language you desire...” Excuse me? Did I read that correctly? You want me to have the credit card transaction response to bounce off the buyer's browser? You want me to rely on what the buyers machine has to say about the validity of the credit card? Turns out that this is in fact what they mean. I am not a hacker but I can write my own browser using APIs available and change the [input type="hidden" name="szIsApproved" value="0"] to [input type="hidden" name="szIsApproved" value="1"] and post that instead. Simply use apache web browser API and HTMLUNIT code both are available on the net and really easy to use. Build a simple class that would walk the website and gather the goods in to the shopping cart then process the information and make sure that you parse the responses for the hidden tag mentioned above. Now replace the value from 0 to 1 and you would get all kind of free stuff! I asked the senior level integration engineer why they not use XML and the response was “XML does not support tag/value pairs”. Ok this tells me that this particular engineer does not know a thing about XML. May be his boss should buy her a book. Only he would probably understand even less himself. GeoTrust does not see this as security hole and refuses to admit to it's own stupidity. But I know, that if I can enter so easily, anyone can, and no cookies or javascritps would save you. The simple command lane browser can be build from the available APIs. It would present itself as any browser you want and will keep the session going and everything else that a browser does. It would take about a day and a half to write and debug. The pages coming from the merchant server are set in to HTMLPage object and all the data can be accessed and changed on the fly. I have done that for unit test of HTML on my previous jobs and I could do that again, only this time in order to get some free stuff. If I can do that – anyone can. Anonymous Lee.
Addenda (April 2004) Just a little note to point out that you could also do this stuff with proxomitron (etc) instead of writing your own custom browser. (proxo changes your browser into a custom browser hehe :)
You don't need proxomitron for this endeavour (most recent versions of javascript allows DOM 2 access;=) see for instance what bookmarklets can do with forms... see in particular show hiddens bookmarklet...
|