[MASOCH-L] Solução para E-mail injection (SPAM através de formulários vulneráveis)
Marcelo Coelho
marcelo at tpn.com.br
Wed Dec 6 14:27:30 -03 2006
Olá,
Criei uma solução caseira pra resolver o problema de ataques de SPAMMERs
que exploram formulários vulneráveis. Talvez interesse a quem trabalha
com hospedagem compartilhada e não aguenta mais ficar caçando qual o
cliente que está com o script vulnerável.
Ainda a considero "beta", mas tem funciona muito bem tanto com PHP para
quem utiliza mail() como para CGIs (em perl, por exemplo), que chamam o
/usr/sbin/sendmail diretamente.
Devo alertar que como é uma solução que tenta identificar o
comportamento dos SPAMMERs, esta pode bloquear indevidamente alguma
mensagem legítima (por exemplo, mensagens com headers
incorretos/duplicados).
Eu utilizo esta solução em conjunto com o suhosin patch,
http://www.hardened-php.net/suhosin.127.html.
--
Marcelo Coelho
marcelo at tpn.com.br
-------------- next part --------------
#!/usr/bin/perl
###########################
#
# sendmail_wrapper v0.1
# Author: Marcelo Coelho ( marcelo _at_ tpn.com.br )
#
# INSTALL INSTRUCTIONS:
#
# 1) Edit sendmail_wrapper.txt, set "Configuration variables"
# 2) Copy and CHMOD this file
# cp sendmail_wrapper.txt /usr/sbin/sendmail_wrapper
# chmod 755 /usr/sbin/sendmail_wrapper
# 3) Edit your php.ini, put sendmail_path=/usr/sbin/sendmail_wrapper
#
###########################
###########################
# Configuration variables #
###########################
$mail_from = 'www at yourdomain.com';
$sendmail = '/usr/sbin/sendmail -t';
$abuse_email = 'abuse at yourdomain.com';
$max_recipients = 5;
$debug = 0;
###########################
@buffer = <STDIN>;
@headers = ();
@body = ();
$from = "";
$seen_from = 0;
$seen_to = 0;
$seen_cc = 0;
$seen_bcc = 0;
$seen_header = 0;
$seen_subject = 0;
$seen_dot = 0;
$nto = 0;
$ncc = 0;
$nbcc = 0;
$n = 0;
$suspect = 0;
$deny = "";
$deny2 = "";
$last_header = "";
foreach $line (@buffer) {
chop($line);
if ($seen_header == 0) {
if ($line =~ /^From: /i) {
if ($seen_from == 0) {
if ($line =~ /<\s*([a-z0-9\=\+\.\_\-]+@[a-z0-9\=\+\_\-]+\.[a-z0-9\=\+\.\_\-]+)\s*>/i) {
$from = $1;
} elsif ($line =~ /([a-z0-9\=\+\.\_\-]+@[a-z0-9\=\+\_\-]+\.[a-z0-9\=\+\.\_\-]+)/i) {
$from = $1;
} elsif ($line =~ /^From:.*\<\>$/i) {
$from = "";
} elsif ($line =~ /^From:\s*$/i) {
$from = "";
} elsif ($line =~ /^From:\s*(\(\))*$/i) {
$from = "";
} else {
$deny = "INVALID_FROM";
$deny2 = $line;
last;
}
}
++$seen_from;
}
if ($line =~ /^To: /i) {
++$seen_to;
@tmp = split(/,/,$line);
$nto += $#tmp + 1;
}
if ($line =~ /^Cc: /i) {
++$seen_cc;
@tmp = split(/,/,$line);
$ncc += $#tmp + 1;
}
if ($line =~ /^Bcc: /i) {
++$seen_bcc;
@tmp = split(/,/,$line);
$nbcc += $#tmp + 1;
++$suspect;
}
if ($line =~ /^Subject: /i) {
++$seen_subject;
}
if ($last_header ne '') {
if ($last_header eq 'to') {
@tmp = split(/,/,$line);
$nto += $#tmp + 1;
} elsif ($last_header eq 'cc') {
@tmp = split(/,/,$line);
$ncc += $#tmp + 1;
} elsif ($last_header eq 'bcc') {
@tmp = split(/,/,$line);
$nbcc += $#tmp + 1;
}
}
if ($line =~ /(To|Cc|Bcc):.*\,\s*$/i) {
$last_header = $1;
$last_header =~ tr/A-Z/a-z/;
} elsif ($line !~ /^(|\s\t ).*\,\s*$/) { $last_header = ''; }
if ($seen_from > 1) { $deny = "DOUBLE_FROM"; $deny2 = $line; last; }
if ($seen_to > 1) { $deny = "DOUBLE_TO"; $deny2 = $line; last; }
if ($seen_cc > 1) { $deny = "DOUBLE_CC"; $deny2 = $line; last; }
if ($seen_bcc > 1) { $deny = "DOUBLE_BCC"; $deny2 = $line; last; }
if ($seen_subject > 1) { $deny = "DOUBLE_SUBJECT"; $deny2 = $line; last; }
$n = $nto + $ncc + $nbcc;
if ($n > $max_recipients) {
$deny = "MAX_RECIPIENTS";
$deny2 = $n;
}
if ($line eq '') { $seen_header = 1; next; }
} else {
if ($line eq '.' && ++$seen_dot > 1) { $deny = "DOUBLE_DOT"; $deny2 = $line; last; }
if ($line =~ /^(From|To|Cc|Bcc|Subject): /i) {
++$suspect;
}
if ($suspect > 3) { $deny = "SUSPECT"; $deny2 = $line; last; }
}
if ($seen_header) {
push @body, $line . "\n";
} else {
if ($line ne '') { push @headers, $line . "\n"; }
if ($line =~ /^From: /i) {
push @headers, "X-AntiAbuse: report abuse to $abuse_email\n";
}
}
}
if ($from eq '') {
$deny = "NO_MAILFROM";
$deny2 = "";
}
$arg = "";
foreach(@ARGV) {
$arg .= " $_";
}
if ($arg =~ m/\-f\s?([a-z0-9_.-]+@[a-z0-9_.-]+)/i) {
$mail_from = $1;
} elsif ($from ne '') {
$mail_from = $from;
}
if ($deny eq '') {
open(SENDMAIL,"|$sendmail -f$mail_from") or die("Couldn't start sendmail");
print SENDMAIL @headers;
print SENDMAIL "\n";
print SENDMAIL @body;
close(SENDMAIL);
} else {
open(LOG,">>/var/log/sendmail_wrapper.log") or die("Couldn't open log");
$tmp = `date`;
chop($tmp);
$log = "$tmp $deny $deny2 $mail_from\n";
print LOG $log;
if ($debug == 1) { print $log; }
close(LOG);
}
if ($debug == 1) {
print "from = $from\n";
print "seen_from = $seen_from\n";
print "seen_to = $seen_to\n";
print "seen_cc = $seen_cc\n";
print "seen_bcc = $seen_bcc\n";
print "seen_header = $seen_header\n";
print "seen_subject = $seen_subject\n";
print "seen_dot = $seen_dot\n";
print "nto = $nto\n";
print "ncc = $ncc\n";
print "nbcc = $nbcc\n";
print "n = $n\n";
print "suspect = $suspect\n";
print "deny = $deny\n";
print "deny2 = $deny2\n";
}
exit;
More information about the masoch-l
mailing list