[Esd-l] strange error...
Kjartan Furnes
kjartan.furnes at sensetech.no
Tue Mar 4 01:49:25 PST 2003
Hi,
I have been running the procmail e-mail sanitizer for about a year. I
have stripped all pif (and others) attachments and mangled exe
attachments. Suddenly this doesn't work anymore and all attachments are
delivered to the recipient. This is my log file:
procmail: Skipped "MANGLE_EXTENSIONS"
procmail: Skipped "p[lm]|exe|vb[se]|com|js|cmd|bat|sc[rt]|pif"
Defanging active HTML content in "FW: " from "NN" <n.n at domain.com> to nn
msgid=<001701c2e225$60852100$5ede7a94 at domain.com>
Sanitizing MIME attachment headers in "FW: " from "NN" <n.n at domain.com>
to nn msgid=<001701c2e225$60852100$5ede7a94 at domain.com>
procmail: Error while writing to "/var/log/procmail.log"
/bin/sh: /var/log/procmail.log: Permission denied
procmail: Error while writing to " perl -p -e ' #\
$pastmsghdr = 1 if /^\s*$/; #\
$XCS = "X-Content-Security: [" . $ENV{"HOST"} . "]" unless $XCS;
#\
if ($pastmsghdr) { #\
if (!$mimebdry && $mimebdrs[0]) { #\
warn " Found no MIME boundary.\n" if $ENV{"DEBUG"}; #\
$mimebdry = pop @mimebdrs; #\
$newbdry = pop @newbdrs; #\
$rawbdry = pop @rawbdrs; #\
$bdrytoolong = pop @bdrstoolong; #\
$gotbdry = pop @gotbdrs; #\
$nullbdry = pop @nullbdrs; #\
} #\
} else { #\
if (($type,$format,$junk) =
/^Content-Type\s*:\s.*(application|multipart|message)\/(\S+)(;.*)?$/i) {
#\
$wanthdr = 1; #\
print "X-Security: MIME headers sanitized on ", $ENV{"HOST"},
"\n"; #\
print "\tSee
http://www.impsec.org/email-tools/procmail-security.html\n"; #\
print "\tfor details. \$Revision: 1.130 $x\$Date: 2001-09-08
11:40:29-07 $x\n"; #\
print "X-Security: The postmaster has not enabled quarantine
of poisoned messages.\n" unless $ENV{"SECURITY_QUARANTINE"}; #\
if ($type =~ /application/i) { #\
$inmimehdr = 1; #\
} elsif ($type =~ /message/i && $format =~ /rfc822/i) {
#\
$rcrsmsg = $inmimehdr = 1; #\
} #\
} elsif (/^\S/) { #\
$wanthdr = 0; #\
} #\
if ($wanthdr) { #\
if (($mimebdry) = /boundary\s*=\s*(("")|(".+")|([^"]\S+))/i) {
#\
$mimebdry =~ s/(^"|"$)//g; #\
$rawbdry = $mimebdry; #\
$gotbdry = 1; #\
$bdrytoolong = $nullbdry = 0; #\
if ($bdrytoolong = (length($mimebdry) > 80)) { #\
warn " Truncating long MIME body-part boundary string.\n";
#\
$newbdry = substr($mimebdry,0,64); #\
$mimebdry = quotemeta($mimebdry); #\
s/${mimebdry}/${newbdry}/; #\
$rawbdry =~ s/${mimebdry}/${newbdry}/; #\
} elsif ($nullbdry = (length($mimebdry) < 1)) { #\
warn " Replacing null MIME body-part boundary string.\n";
#\
$newbdry = "==NULL_MIME_BOUNDARY_ATTACK_SANITIZED-${$}==";
#\
s/boundary\s*=\s*""/boundary = "${newbdry}"/i; #\
} else { #\
$mimebdry = quotemeta($mimebdry); #\
} #\
} #\
} #\
} #\
if ($mimebdry || ($gotbdry && $nullbdry) || $inmimehdr) { #\
if (/^\s*$/) { #\
$inmimehdr = 0; #\
if ($rcrsmsg) { #\
push @mimebdrs, $mimebdry; #\
push @newbdrs, $newbdry; #\
push @rawbdrs, $rawbdry; #\
push @bdrstoolong, $bdrytoolong; #\
push @gotbdrs, $gotbdry; #\
push @nullbdrs, $nullbdry; #\
$mimebdry = $newbdry = ""; #\
$rcrsmsg = $pastmsghdr = $bdrytoolong = $gotbdry = 0;
#\
} #\
} elsif (/^--${mimebdry}(--)?$/) { #\
$mend = $1; #\
s/${mimebdry}/${newbdry}/ if $bdrytoolong; #\
s/^--/--${newbdry}${mend}/ if $nullbdry; #\
if ($mend) { #\
if ($mimebdrs[0]) { #\
$mimebdry = pop @mimebdrs; #\
$newbdry = pop @newbdrs; #\
$rawbdry = pop @rawbdrs; #\
$bdrytoolong = pop @bdrstoolong; #\
$gotbdry = pop @gotbdrs; #\
$nullbdry = pop @nullbdrs; #\
} #\
} else { #\
$inmimehdr = 1; #\
$rcrsmsg = $strip_attachment = $check_attachment = 0;
#\
} #\
} elsif (!$inmimehdr && $strip_attachment) { #\
$_ = ""; #\
} elsif (!$inmimehdr && $check_attachment) { #\
$check_attachment = 0; #\
if ($destf = `mktemp /tmp/mailchk.XXXXXX`) { #\
chomp($destf); #\
if (open(DECODE,"|mimencode -u -o $destf")) { #\
do { #\
print $_; #\
print DECODE $_; #\
$_ = <>; #\
$lastline = $_; #\
} until (/^\s*$/ || /^--/); #\
close(DECODE); #\
$msapp = $score = 0; #\
@scores = (); #\
$why = ""; #\
# Run virus-checker here. #\
open(ATTCH,"< $destf"); #\
while (<ATTCH>) { #\
if (/\000VirusProtection/i) { #\
$why .= " 99 for $&\n"; #\
$score+= 99; #\
} #\
if (/\000select\s[^\000]*shell\s*\(\s*["\047]/i) {
#\
$why .= " 99 for $&\n"; #\
$score+= 99; #\
} #\
if (/\000regedit/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000Shell\s*\(/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000Save(Normal|Properties)Prompt/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000Outlook\.Application\000/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000CountOfLines/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000AddFromString/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000StartupPath/i) { #\
$why .= " 9 for $&\n"; #\
$score+= 9; #\
} #\
if (/\000ID="{[-0-9A-F]+$/i) { #\
$why .= " 4 for $&\n"; #\
$score+= 4; #\
} #\
if (/\000CreateObject/i) { #\
$why .= " 4 for $&\n"; #\
$score+= 4; #\
} #\
if
(/(\000|\004)([a-z0-9_]\.)*(Autoexec|Workbook_(Open|BeforeClose|Window(D
e)?activate)|Document_(Open|New|Close))/i) { #\
$why .= " 4 for $&\n"; #\
$score+= 4; #\
} #\
if
(/(\000|\004)(Logon|AddressLists|AddressEntries|Recipients|Attachments|L
ogoff)/i) { #\
$why .= " 4 for $&\n"; #\
$score+= 4; #\
} #\
if (/(\000|\004)(Subject|Body)/i) { #\
$why .= " 4 for $&\n" unless $scores[0];
#\
$scores[0] = 4; #\
} #\
if (/\000Options[^\w\s]/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/\000CodeModule/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/\000([a-z]+\.)?Application\000/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/(\000|\004)stdole/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/(\000|\004)NormalTemplate/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/\000ID="{[-0-9A-F]+}"/i) { #\
$why .= " 2 for $&\n"; #\
$score+= 2; #\
} #\
if (/\000ThisWorkbook\000/i) { #\
$why .= " 1 for $&\n"; #\
$score+= 1; #\
} #\
if (/\000PrivateProfileString/i) { #\
$why .= " 1 for $&\n"; #\
$score+= 1; #\
} #\
if
(/(\000|\004)(ActiveDocument|ThisDocument|ThisWorkbook)/i) { #\
$why .= " 1 for $&\n"; #\
$score+= 1; #\
} #\
if
(/\000\[?HKEY_(CLASSES_ROOT|CURRENT_USER|LOCAL_MACHINE)/) { #\
$why .= " 1 for $&\n"; #\
$score+= 1; #\
} #\
$msapp+= 1 if /\000(Microsoft (Word Document|Excel
Worksheet|Excel|PowerPoint)|MSWordDoc|Word\.Document\.[0-9]+|Excel\.Shee
t\.[0-9]+)\000/; #\
} #\
close(ATTCH); #\
unlink($destf); #\
if ($msapp) { #\
for (@scores) { #\
$score += $_; #\
} #\
if ($histfile = $ENV{"SCORE_HISTORY"}) { #\
if (open(HIST,">>$histfile")) { #\
print HIST "score=$score to=".$ENV{"TO"}."
from=".$ENV{"FROM"}."\n"; #\
close HIST; #\
} #\
} #\
$poison_score = $ENV{"POISONED_SCORE"}; #\
$poison_score = 5 if $poison_score < 5; #\
if ($score > $poison_score && !$ENV{"SCORE_ONLY"}) {
#\
warn " POSSIBLE MACRO EXPLOIT: Score=$score\n";
#\
print "\n\n--$rawbdry\n"; #\
print "Content-Type: TEXT/PLAIN;\n"; #\
print "$XCS NOTIFY\n" if $ENV{"SECURITY_NOTIFY"} ||
$ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS REPORT: Trapped poisoned Microsoft
attachment\n" if $ENV{"SECURITY_NOTIFY"} ||
$ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS QUARANTINE\n" if
$ENV{"SECURITY_QUARANTINE"}; #\
print "Content-Description: SECURITY WARNING\n\n";
#\
print "SECURITY WARNING!\n"; #\
print "The mail delivery system has detected that the
preceding\n"; #\
print "document attachment appears to contain
hazardous macro code.\n"; #\
print "Macro Scanner score: $score\n"; #\
if ($ENV{"SCORE_DETAILS"}) { #\
print "Macro Scanner details:\n"; #\
$why =~ s/[\000-\011\013-\037]//g; #\
print $why; #\
} #\
print "Contact your system administrator
immediately!\n\n"; #\
} #\
} else { #\
$score = 0; #\
} #\
if ($lastline =~ /^--${mimebdry}(--)?$/) { #\
$inmimehdr = 1; #\
$check_attachment = 0; #\
$lastline =~ s/${mimebdry}/${newbdry}/ if $bdrytoolong;
#\
} #\
print $lastline; #\
} else { #\
warn "*** Decoding: $! - mimencode?\n"; #\
} #\
} else { #\
warn "*** Cannot extract - mktemp?\n"; #\
} #\
} #\
if ($inmimehdr || $hdrcnt) { #\
if (/^(\s+\S|(file)?name)/) { #\
s/^\s*/ /; #\
s/^\s*// if $hdrtxt =~ /"[^"]*[^;]$/; #\
s/\s*\n$//; #\
$hdrtxt .= $_; #\
$_ = ""; #\
} else { #\
if ($hdrtxt) { #\
$mangle_mime_type = 0; #\
$hdrtxt =~ s/([^\\])\\"/\1\\ÿ/g; #\
if ($hdrtxt =~ /`\s*`/) { #\
warn " Fixing double backquotes.\n"; #\
$hdrtxt =~ s/`\s*`/\\"/g; #\
} #\
if ($hdrtxt =~ /^[-\w]+\s*:.*name\s*=\s*"[^"]+$/i) {
#\
warn " Fixing missing close quote on filename.\n";
#\
$hdrtxt .= "\""; #\
} #\
while (($hdr, $val) = $hdrtxt =~
/^([-\w]+)\s*:.*\s(\S+)\s*=\s*""/i) { #\
warn " Null $val in $hdr header.\n"; #\
$sval = quotemeta($val); #\
$hdrtxt =~ s/\s$sval\s*=\s*""/ X-$val="{null value
sanitized}"/; #\
} #\
while (($junk,$filen) = $hdrtxt =~
/^Content-[-\w]+\s*:[^"]*("[^"]*"[^"]+)*name\s*=\s*([^"\s][^;]+)/i) {
#\
warn " Fixing unquoted filename \"$filen\".\n"; #\
$newfilen = $filen; #\
$newfilen =~ s/\"/\\"/g; #\
if ($newfilen =~ /\([^)]*\)/) { #\
warn " Filename contains embedded RFC822 comment -
removing.\n"; #\
$newfilen =~ s/\([^)]*\)//g; #\
} #\
$filen = quotemeta($filen); #\
$hdrtxt =~ s/name\s*=\s*${filen}/name="$newfilen"/ig;
#\
} #\
while (($filen) = $hdrtxt =~
/^Content-[-\w]+\s*:.*name\s*=\s*"(=\?[^"]+=2E[^"]+\?=)"/i) { #\
warn " Fixing encoded periods in \"$filen\".\n";
#\
$newfilen = $filen; #\
$newfilen =~ s/=2E/./ig; #\
$filen = quotemeta($filen); #\
$hdrtxt =~ s/name\s*=\s*"${filen}"/name="$newfilen"/ig;
#\
} #\
while (($filen) = $hdrtxt =~
/^Content-[-\w]+\s*:.*name\s*=\s*"([^"]{120})[^"]{16,}"/i) { #\
warn " Truncating long filename \"$filen...\".\n";
#\
$filen .= "..."; #\
$filen .= "?=" if $filen =~ /^=\?/; #\
$hdrtxt =~ s/name\s*=\s*"[^"]{128,}"/name="$filen"/i;
#\
$mangle_mime_type = 1; #\
} #\
if (($mtype) = $hdrtxt =~
/Content-Type:\s+([a-z0-9-_]+\/[a-z0-9-_]+)/i) { #\
unless ($mtype =~ /^(multipart|text|message)\//i) {
#\
unless ($hdrtxt =~ /name\s*=\s*"/i) { #\
warn "*** Supplying default filename.\n"; #\
$hdrtxt .= "; " unless $hdrtxt =~ /;\s*$/; #\
$hdrtxt .= "name=\"default.txt\";"; #\
} #\
} #\
} #\
if (($filen) = $hdrtxt =~
/^Content-[-\w]+\s*:.*name\s*=\s*"([^"]+\.(do[ct]|xl[swt]|p[po]t|rtf|pps
)(\?=)?)"/i) { #\
if (!$poisoned && ($specf =
$ENV{"POISONED_EXECUTABLES"})) { #\
if (open(POISONED,$specf)) { #\
warn "Checking \"$filen\".\n"; #\
while (chomp($psn_spec = <POISONED>)) { #\
$psn_spec =~ s/^\s+//g; #\
$psn_spec =~ s/\s+$//g; #\
next unless $psn_spec; #\
$psn_spec =~ s/([^\\])\./$1\\./g; #\
$psn_spec =~ s/\*/.*/g; #\
$psn_spec =~ s/\?/./g; #\
$psn_spec .= "(\\?=)?"; #\
warn "Checking against \"$psn_spec\"\n" if
$ENV{"DEBUG"}; #\
if ($filen =~ /^${psn_spec}$/i) { #\
warn " Trapped poisoned document \"$filen\".\n";
#\
$poisoned = 1; #\
print "Content-Type: TEXT/PLAIN;\n"; #\
print "$XCS NOTIFY\n" if $ENV{"SECURITY_NOTIFY"}
|| $ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS REPORT: Trapped poisoned Microsoft
attachment \"$filen\"\n" if $ENV{"SECURITY_NOTIFY"} ||
$ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS QUARANTINE\n" if
$ENV{"SECURITY_QUARANTINE"}; #\
print "Content-Description: SECURITY
WARNING\n\n"; #\
print $ENV{"POISONED_WARNING"}; #\
print "Macro Scanner score: 0 (poisoned by name,
scan skipped)\n\n"; #\
last; #\
} #\
} #\
close(POISONED); #\
} else { #\
warn " Unable to open poisoned-executables file
\"$specf\".\n"; #\
} #\
} #\
$check_attachment = 1 unless
$ENV{"DISABLE_MACRO_CHECK"}; #\
} #\
if (($bndry) = $hdrtxt =~
/^Content-Type:\s+multipart\/.*\s+boundary\s*=\s*"([^"]+)"/i) { #\
if (!$inmimehdr) { #\
push @mimebdrs, $mimebdry; #\
push @newbdrs, $newbdry; #\
push @rawbdrs, $rawbdry; #\
push @bdrstoolong, $bdrytoolong; #\
push @gotbdrs, $gotbdry; #\
push @nullbdrs, $nullbdry; #\
$mimebdry = $newbdry = $bndry; #\
$rcrsmsg = $pastmsghdr = $bdrytoolong = $gotbdry = 0;
#\
} else { #\
$rcrsmsg = 1; #\
} #\
} #\
if ($hdrtxt =~ /^Content-Type:\s+message\/rfc822/i) {
#\
if (!$inmimehdr) { #\
push @mimebdrs, $mimebdry; #\
push @newbdrs, $newbdry; #\
push @rawbdrs, $rawbdry; #\
push @bdrstoolong, $bdrytoolong; #\
push @gotbdrs, $gotbdry; #\
push @nullbdrs, $nullbdry; #\
$mimebdry = $newbdry = ""; #\
$rcrsmsg = $pastmsghdr = $bdrytoolong = $gotbdry = 0;
#\
} else { #\
$rcrsmsg = 1; #\
} #\
} #\
if ($ENV{"SECURITY_STRIP_MSTNEF"} && $hdrtxt =~
/^Content-Type:\s+application\/MS-TNEF/i) { #\
print "Content-Type: TEXT/PLAIN;\n"; #\
print "$XCS REPORT: Stripped MS-TNEF attachment\n";
#\
print "Content-Description: SECURITY NOTICE\n\n";
#\
print $ENV{"TNEF_WARNING"}; #\
$_ = $hdrtxt = ""; #\
$strip_attachment = 1; #\
$inmimehdr = 0; #\
} #\
while (($filen) = $hdrtxt =~
/^Content-[-\w]+\s*:.*name\s*=\s*"([^"]+\.($ENV{"MANGLE_EXTENSIONS"})(\?
=)?)"/io) { #\
if (!$poisoned && ($specf =
$ENV{"POISONED_EXECUTABLES"})) { #\
if (open(POISONED,$specf)) { #\
warn "Checking \"$filen\".\n"; #\
while (chomp($psn_spec = <POISONED>)) { #\
$psn_spec =~ s/^\s+//g; #\
$psn_spec =~ s/\s+$//g; #\
next unless $psn_spec; #\
$psn_spec =~ s/([^\\])\./$1\\./g; #\
$psn_spec =~ s/\*/.*/g; #\
$psn_spec =~ s/\?/./g; #\
$psn_spec .= "(\\?=)?"; #\
warn "Checking against \"$psn_spec\"\n" if
$ENV{"DEBUG"}; #\
if ($filen =~ /^${psn_spec}$/i) { #\
warn " Trapped poisoned executable
\"$filen\".\n"; #\
$poisoned = 1; #\
print "Content-Type: TEXT/PLAIN;\n"; #\
print "$XCS NOTIFY\n" if $ENV{"SECURITY_NOTIFY"}
|| $ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS REPORT: Trapped poisoned executable
\"$filen\"\n" if $ENV{"SECURITY_NOTIFY"} ||
$ENV{"SECURITY_NOTIFY_VERBOSE"}; #\
print "$XCS QUARANTINE\n" if
$ENV{"SECURITY_QUARANTINE"}; #\
print "Content-Description: SECURITY
WARNING\n\n"; #\
print $ENV{"POISONED_WARNING"}; #\
last; #\
} #\
} #\
close(POISONED); #\
} else { #\
warn " Unable to open poisoned-executables file
\"$specf\".\n"; #\
} #\
} #\
warn " Mangling executable filename \"$filen\".\n";
#\
$newfilen = $filen; #\
$newfilen =~
s/\.([-a-z0-9{}]+(\?=)?)$/.${$}DEFANGED-$1/i; #\
$filen = quotemeta($filen); #\
$hdrtxt =~
s/name\s*=\s*"?${filen}"?/name="$newfilen"/ig; #\
$mangle_mime_type = 1; #\
} #\
if ($mangle_mime_type && $hdrtxt =~ /^Content-Type:\s/i) {
#\
($oct) = $hdrtxt =~ /^Content-Type:.*\s(\S+\/\S+;?)/i;
#\
unless ($oct =~ /application\/octet-stream;/i) {
#\
print "$XCS original Content-Type was $oct\n";
#\
$oct = quotemeta($oct); #\
$hdrtxt =~ s/${oct}/application\/octet-stream;/i;
#\
} #\
} #\
if ($mangle_mime_type && $hdrtxt =~ /\sx-mac-\S+/i) {
#\
$eudora = ""; #\
while (($eh) = $hdrtxt =~ /(\sx-mac-\S+\s*=\s*\S+;?)/i)
{ #\
$eudora .= $eh; #\
$eh = quotemeta($eh); #\
$hdrtxt =~ s/${eh}//i; #\
} #\
print "$XCS removed$eudora\n"; #\
} #\
if (($junk) = $hdrtxt =~
/^Content-Type\s*:\s+(.{128}).{100,}$/i) { #\
warn " Truncating long Content-Type header.\n"; #\
$junk =~ s/"/\\"/g; #\
$hdrtxt = "Content-Type: X-BOGUS\/X-BOGUS;
originally=\"$junk...\""; #\
} elsif (($junk) = $hdrtxt =~
/^Content-Description\s*:\s+(.{128}).{100,}$/i) { #\
warn " Truncating long Content-Description header.\n";
#\
$hdrtxt = "Content-Description: $junk..."; #\
} elsif (($junk) = $hdrtxt =~
/^Content-[-\w]+\s*:\s+(.{128}).{100,}$/i) { #\
warn " Truncating long MIME header.\n"; #\
$junk =~ s/"/\\"/g; #\
$hdrtxt =~ s/^Content-([-\w]+)\s*:.*$/X-Overflow:
Content-$1; originally="$junk..."/i; #\
} #\
$hdrtxt =~ s/\\ÿ/\\"/g; #\
print $hdrtxt, "\n"; #\
$hdrtxt = ""; #\
} #\
if (/^\S/) { #\
s/\s*\n$//; #\
$hdrtxt = $_; #\
$_ = ""; #\
$hdrcnt++; #\
} else { #\
$hdrcnt = 0; #\
$hdrtxt = ""; #\
} #\
} #\
} else { #\
$poisoned = 0; #\
} #\
} #\
' 2>> $LOGFILE"
procmail: Rescue of unfiltered data succeeded
>From n.n at domain.com Tue Mar 4 07:46:07 2003
Subject: FW:
Folder: /var/spool/mail/nn 4502897
Best Regards
Kjartan Furnes
More information about the esd-l
mailing list