Develop-Zone
== Das Sicherheitslabor ==

Achtung: Diese Informationen sind veraltet!

Die Orginalseite kommt aus dem Jahre 1998. Was falsch war ist immer noch falsch. Aber die Rezepte für das richtige Vorgehen sind vermutlich nicht mehr die erste Wahl, möglicherweis haben sie sogar Sicherheitsprobleme. Ich habe die letzten Jahre das Thema nicht mehr verfolgt.

Da es einige Links auf diese Seite gibt, habe ich sie nicht gelöscht.

Falsch & Richtig: Email versenden

Von einen Cgi-Skript Email zu versenden ist eine schöne Sache, viele praktische Anwendungen werden dadurch möglich. In modernen Skriptsprachen wie Perl ist es auch sehr leicht, weil man von seinen Skript einfach ein anderes Programm aufruft.
Zu leicht vergißt man jedoch die Implikationen für die Sicherheit. Eine der schlimmsten Sachen ist, das UNIX-Programm "mail" zu verwenden, etwa wie im folgenden Perl Fragment:

...
open(M, "|/bin/mail $address);
print M "$Subject\n\n";
print M "$emailbody\n";
close M;

Das Programm hat nämlich eine "Hintertür": Gibt man als erstes Zeichen einer Spalte ein bestimmtes Zeichen ein, so wird der Rest der Zeile von der Shell interpretiert. Um es einen Gelegenheitshacker nicht zu einfach zu machen, verrate ich hier nicht welches Zeichen das ist.

Besser ist es das Programm "sendmail" zu benutzen. Es hat so einen Mechanismus nicht. Seine Sicherheit kann man erhöhen, indem man die Kommandozeilenoption -t verwendet: sie bewirkt, daß die Adresse nicht auf der Kommandozeile, sondern später über die Standardeingabe geliefert wird. Der Aufruf des Programmes wird so von Benutzereingaben frei gehalten, die Shell kann nicht ausgetrickst werden.

open(M, "|/lib/sendmail -t") 
   or die "sendmail kann ich nicht aufmachen";
print M "To: $recipient\n";
print M "From: $address\n";
print M "Subject: a nice litte mail\n";
print M "\n";
print M "$emailbody\n";
close M;

Sieht eigentlich fast genauso aus, ist aber viel sicherer. Mehr über dieses Problem ist in dem Buch CGI Programming in C & Perl zu erfahren.

Aber viele Leute fragen sich schon die ganze Zeit:

Was, wenn ich kein Unix habe?

Unter Windows NT gibt es portierte sendmail Programme, so daß nur der Aufrufpfad geändert werden muß. Aber es geht auch ganz anders:

Perl kann direkt mit einem Mailserver sprechen !!

Möglich wird dies mit Hilfe der "net"-Module, speziell des Moduls "net::smtp". Sie sind im CPAN erhältlich, MacPerl hat diese Module sogar in der Standarddistribution. Smtp steht übrigens für "simple mail transfer protocol" und sollte nicht mit snmp verwechselt werden. Im Folgenden zeige ich ein Beispielprogram, welches mit Hilfe von smtp eine Mail verschicken kann:

#!/usr/local/bin/perl -w
#----------------------------------------------------------------
# smtptest.pl  Mailen einer einfachen Nachricht mittels		
# Perls Net::SMTP Modul	
# erhaeltlich auf www.perl.com/cpan/
 
use Net::SMTP;
	
#------- Konfiguration: Bitte Aendern -------
$recipient  = 'info@meier-online.com';  					
$ownAddress = 'myname@whitehouse.gov';
$host       = 'smtp1.ibm.net';     
$subject    = 'Testen Perl Skript mit Smtp';
$message    = "Hallo, hier sind wir.\nHoffentlich zumindestens\n";
 
&send_via_smtp($host, $ownAddress, $recipient, $subject, $message);  
 
# --------------------------------------------------------------
# send_via_sntp: send an email using the a smtp email server
# Arguments: 
# 1)smtp-host: use the address you use in your email software
# 2)myAddress: Address of the Sender
# 3)$emails:   Address of the recipient, may be more then one
# 4)subject:   the Subject Line
# 5)$message:   may be more then one Line 
#
 
sub send_via_smtp{
	my($smtp_host, $myAddress, $emails, $subject, $message) = @_;
	my($smtp);
	$smtp = Net::SMTP->new($smtp_host,
	                       Timeout => 30,
				           Debug   => 1); # set to 0 after testing
	if( !defined($smtp)) {
		return 0;
	}
	print "bad init" unless $smtp->ok();
	$smtp->mail($myAddress);              # my address
	print "bad mail" unless $smtp->ok();
	$smtp->to($emails);
	print "bad to" unless $smtp->ok();
	$smtp->data();
	print "bad data" unless $smtp->ok();
	$smtp->datasend("Subject: $subject\n\n");
	print "bad datasend" unless $smtp->ok();
	$smtp->datasend($message);
	print "bad datasend" unless $smtp->ok();
	$smtp->dataend();
	print "bad dataend" unless $smtp->ok();
	$smtp->quit();
	print "bad quit" unless $smtp->ok();
	return 1;
}					

Diese Vorgehen funktioniert unter UNIX, Mac/OS, Windows 95, und wahrscheinlich noch einigen anderen Betriebsystemen. Wie mir Martin Vorländer mitgeteilt hat, gibt es mit bestimmten Kombinationen von Betriebssystemen und Mailserveren ein Problem: Der Email Versender (Rechner) muß eventuell seinen eigenen Namen mitteilen. Normalerweise findet das smtp Modul diesen mit Hilfe des Net::Domain Modul selbst herraus, aber auf Windows und vielleicht auch anderswo funktioniert dies manchmal nicht. Als Abhilfe kann man diesen Namen aber auch explizit mitteilen:
  $smtp = Net::SMTP->new($smtp_host, 
  Timeout => 30, 
  hello => 'mycomputer.mydomain.net',
  Debug   => 1); # set to 0 after testing 

Ein Problem sei hier aber nicht verschwiegen: Wenn es gerade keine Verbindung zum EMail-Server gibt, hat man Pech gehabt. Das Skript muß auch so lange warten, bis die Email versendet ist. Das sendmail Programm dagegen schreibt die EMail zunächst in einen Puffer und versendet sie dann wenn möglich.

Zum Sicherheitslabor


home - contact - dev-zone
Copyright © 1997-1998 by Karsten Meier. All Rights reserved.