[Weimer@CERT.Uni-Stuttgart.DE: [bt] Re: zlibscan : script to find suid binaries possibly affected by zlib vulnerability]
Scott Doty
scott at sonic.net
Wed Mar 13 15:26:33 PST 2002
Saw this on BUGTRAQ. Solves the problem of finding statically-linked zlib
binaries. (No, I haven't tried it.)
(BTW, the script posted earlier was from BUGTRAQ, too.)
-Scott
----- Forwarded message from Florian Weimer <Weimer at CERT.Uni-Stuttgart.DE> -----
Delivered-To: scott at ponzo.sonic.net
Delivered-To: mailing list bugtraq at securityfocus.com
Delivered-To: moderator for bugtraq at securityfocus.com
To: hologram <holo at brained.org>
Cc: <bugtraq at securityfocus.com>
Subject: [bt] Re: zlibscan : script to find suid binaries possibly affected by
zlib vulnerability
From: Florian Weimer <Weimer at CERT.Uni-Stuttgart.DE>
Date: Wed, 13 Mar 2002 19:53:41 +0100
hologram <holo at brained.org> writes:
> The following is a quick shell script to find suid binaries that are
> potentially affected by the zlib vulnability (i.e., those dynamically
> linked).
The hard case are statically linked binaries, though. I've written a
short Perl script which scans for signatures found in compiled zlib
code. The signatures are based on zlib's data tables, not machine
code, so they are fairly architecture-independent (modulo the 32/64
bit and endian issues addressed by the script).
--
Florian Weimer Weimer at CERT.Uni-Stuttgart.DE
University of Stuttgart http://CERT.Uni-Stuttgart.DE/people/fw/
RUS-CERT +49-711-685-5973/fax +49-711-685-5898
#!/usr/bin/perl -w
# find-zlib - scan for zlib tables in compiled code
# Copyright (C) 2002 RUS-CERT, University of Stuttgart.
# Written by Florian Weimer <Weimer at CERT.Uni-Stuttgart.DE>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# $Id: find-zlib,v 1.8 2002/03/13 18:42:44 rusfw Exp $
# <http://CERT.Uni-Stuttgart.DE/files/fw/find-zlib>
use strict;
if (@ARGV == 0 or $ARGV[0] eq '-h') {
print <<EOF;
find-zlib - scan for zlib tables in compiled code
Copyright (C) 2002 RUS-CERT, University of Stuttgart.
Usage: find-zlib [-v] filename...
In non-verbose mode (without the "-v" flag), find-zlib scans only for
three signatures:
- The "cplenx table". It is not specific to zlib, but used
by any inflate decoder.
- The "cplext table". This table is specific to zlib and
also gives some version information.
- The "inflate" copyright string.
Even if the copyright string has been removed, the other two signatures
permit the identification of zlib inflate code.
In verbose mode, additional signatures are tested:
- The "configuration table". It is specific to zlib, but not
required by the inflate code.
- Some common messages found in zlib.
- The "deflate" copyright string. Note that the deflate code is
independent of the inflate code.
Thanks to Mark Adler for helpful suggestions.
Send comments to fw-tracker\@CERT.Uni-Stuttgart.DE.
EOF
exit 1;
}
my $verbose = 0;
if ($ARGV[0] eq "-v") {
$verbose = 1;
shift @ARGV;
}
$/ = undef;
my @cplens_table = (3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227,
258, 0, 0);
my @cplext_table_092 = (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 128, 128);
my @cplext_table_104 = (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192);
my @cplext_table_114 = (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112);
sub table_to_re (@) {
my $be = "";
my $le = "";
my $e;
foreach $e (@_) {
$be .= pack "N", $e;
$le .= pack "V", $e;
}
return (quotemeta($be), quotemeta($le));
}
sub table_to_re_config (@) {
my $be = "";
my $le = "";
my $e;
foreach $e (@_) {
$be .= pack "n", $e;
$le .= pack "v", $e;
}
return (quotemeta($be), quotemeta($le));
}
sub table_to_re_combined (@) {
my ($be, $le) = table_to_re(@_);
return "($be|$le)";
}
my ($cplens_table_be, $cplens_table_le) = table_to_re (@cplens_table);
my ($cplext_table_092, $cplext_table_104, $cplext_table_114) =
(table_to_re_combined(@cplext_table_092),
table_to_re_combined(@cplext_table_104),
table_to_re_combined(@cplext_table_114));
my $line;
my (@config_table_le, @config_table_be) = ();
foreach $line ([8, 32, 128, 256],
[32, 128, 258, 1024],
[32, 258, 258, 4096]) {
my ($be, $le) = table_to_re_config(@$line);
push @config_table_be, $be;
push @config_table_le, $le;
}
my ($config_table_be_32,
$config_table_be_64,
$config_table_le_32,
$config_table_le_64)
= (join("....", @config_table_be),
join("........", @config_table_be),
join("....", @config_table_le),
join("........", @config_table_le));
my $file;
my $found = 1;
for $file (@ARGV) {
warn "$file: non-regular file ignored\n" unless -f $file;
unless (open(FILE, "<$file")) {
warn("$file: cannot read file\n");
next;
}
my $data = <FILE>;
close FILE;
if ($data =~/inflate ([0-9][ 0-9a-zA-Z.\-]{1,100}[0-9a-zA-Z.\-])/) {
print "$file: inflate version: \"$1\"\n";
$found = 0;
}
if ($verbose
and $data =~/deflate ([0-9][ 0-9a-zA-Z.\-]{1,100}[0-9a-zA-Z.\-])/) {
print "$file: deflate version: \"$1\"\n";
$found = 0;
}
if ($data =~ /$cplens_table_le/o) {
print "$file: zlib cplens table, little endian\n";
$found = 0;
}
if ($data =~ /$cplens_table_be/o) {
print "$file: zlib cplens table, big endian\n";
$found = 0;
}
if ($data =~ /$cplext_table_092/o) {
print "$file: zlib cplext table (version 0.1 to 0.92)\n";
$found = 0;
}
if ($data =~ /$cplext_table_104/o) {
print "$file: zlib cplext table (version 0.93 to 1.0.4)\n";
$found = 0;
}
if ($data =~ /$cplext_table_114/o) {
print "$file: zlib cplext table (version 1.0.5 to 1.1.4)\n";
$found = 0;
}
next if not $verbose;
if ($data =~ /$config_table_le_32/o) {
print "$file: zlib configuration table, little endian, 32 bit\n";
$found = 0;
}
if ($data =~ /$config_table_be_32/o) {
print "$file: zlib configuration table, big endian, 32 bit\n";
$found = 0;
}
if ($data =~ /$config_table_le_64/o) {
print "$file: zlib configuration table, little endian, 64 bit\n";
$found = 0;
}
if ($data =~ /$config_table_be_64/o) {
print "$file: zlib configuration table, big endian, 64bit\n";
$found = 0;
}
my $msg = 0;
my $total = 0;
$msg++ if $data =~ /empty distance tree with lengths/; $total++;
$msg++ if $data =~ /incomplete distance tree/; $total++;
$msg++ if $data =~ /incomplete dynamic bit lengths tree/; $total++;
$msg++ if $data =~ /incomplete literal\/length tree/; $total++;
$msg++ if $data =~ /incorrect data check/; $total++;
$msg++ if $data =~ /incorrect header check/; $total++;
$msg++ if $data =~ /invalid bit length repeat/; $total++;
$msg++ if $data =~ /invalid block type/; $total++;
$msg++ if $data =~ /invalid stored block lengths/; $total++;
$msg++ if $data =~ /invalid stored block lengths/; $total++;
$msg++ if $data =~ /invalid window size/; $total++;
$msg++ if $data =~ /need dictionary/; $total++;
$msg++ if $data =~ /oversubscribed distance tree/; $total++;
$msg++ if $data =~ /oversubscribed dynamic bit lengths tree/; $total++;
$msg++ if $data =~ /oversubscribed literal\/length tree/; $total++;
$msg++ if $data =~ /too many length or distance symbols/; $total++;
$msg++ if $data =~ /too many length or distance symbols/; $total++;
$msg++ if $data =~ /unknown compression method/; $total++;
if ($msg > 0) {
print "$file: $msg out of $total messages\n";
$found = 0;
}
}
exit $found;
----- End forwarded message -----
More information about the talk
mailing list