about:config
J|Down|left MB - nächster Punkt
K|Up|right MB - vorhergehender Punkt
Right - nächste Seite
Left - vorhergehende Seite
<Return> - zur Seite springen im Inhaltsverzeichnis
O - Outline Mode on/off
T|escape|F5 - Inhaltsverzeichnis on/off
S|. - zwischen Styles rotieren
Trafficanalyse und -modifikation mit IMP
Trafficanalyse und
-modifikation
mit IMP
Steffen Ullrich, genua mbH
Deutscher Perl-Workshop 2013, Berlin
who am I
- Steffen Ullrich
- Perl-Entwickler seit 1996
- cpan SULLR
- github.com/noxxi
- noxxi.de - Code, Talks..
- seit 2001 bei genua mbH
- Entwicklung von Firewalls für Hochsicherheitsumgebungen
- www.genua.de - Jobs, Abschlussarbeiten...
- seit 2011 Forschungsprojekt Padiofire
- Web 2.0 aus Sicht von Perimeterfirewalls
- zusammen mit Unis Cottbus, Erlangen, Innsbruck
- gefördert vom BMBF
Übersicht Talk
- was machen Firewalls
- was ist IMP und wie funktioniert es
- existente Implementationen
- Schreiben eigener Trafficanalysen
Funktionsweise
- Daten empfangen
- Daten analysieren
- Daten weiterreichen oder blockieren
- evtl. manipulieren, normalisieren
Vielfalt von Analysen
- Loggen von Verbindungen, evtl nach SSL/SSH Bridging
- in SSL/SSH Tunneln erlaubte Protokolle einschränken
- Normalisieren von Web-Traffic
- Filtern mit URL-Blacklists
- Virenscanning
- Angriffserkennung
- Ads/Malvertising blocken
- DNS Filtern
- ...
Vielfalt von Datenquellen
- Proxy, Application Level Gateway
- IDS
- Packet Captures
- ...
Trennung Datenquellen und Analyse
Trennung Datenquellen und Analyse
warum
- Entkoppeln Datenquellen von Analyse, damit...
- Re-Use von Analysen
- unabhängige Optimierung der Teile
- weniger Wartungsaufwand
- steigender Output/Qualität bei sinkendem Aufwand
- Konzentration auf die interessanten Sachen
Anforderungen an API
- einfach zu nutzen und implementieren
- jedoch flexibel genug
- streamingfähig
- performant
- stabil bzw. abwärtskompatibel
was heisst performant
- geringe Latenz
- hoher Durchsatz
- Wege
- geringer Overhead
- kein unnötiges Kopieren
- kein unnötiges Analysieren
existente Lösungen
- ICAP - Internet Content Adaption Protocol (2003)
- primär HTTP, aber auch API Virenscanner
- nur vollständige Anfragen/Antworten
- Modifikation nur alles oder nichts
- nicht tauglich
- OPES - Open Pluggable Edge Services (2005)
- "ICAP/2.0"
- streaming fähig
- deutlich leistungsfähiger als ICAP
- und deutlich komplexer (11 RFCs für Basis, HTTP, SMTP)
- nirgendwo implementiert
- ???
was ist IMP
- [I]nspection and [M]odification [P]rotocol
- Arbeit auf Datenchunks
- Kopie nur zur Analyse
- kein Rückkopieren wenn unverändert
- asynchron, Feedback per Callback
- DNS Anfragen o.ä blockieren System nicht
- Optimierungen zur Vermeidung von Analysen
- Optimierungen für geringe Latenz
Funktionsweise
- eine Verbindung, zwei Datenströme
- 0: Client -> Server
- 1: Server -> Client
- Position je Datenstrom wird mitgeführt
- Anfrage an Analyse
- Richtung, Datenchunk, [ Datentyp, Position ]
- Datenquelle muss puffern, bis Antwort kommt
- Feedback per Callback
- Durchlassen bis Position..
- Ersetzen bis Position..
- Blockieren der Verbindung
- ...
Funktionsweise im Bild (static)
IMP Callbacks
IMP Callbacks
Durchlassen
- IMP_PASS dir,offset
- akzeptiere Daten bis Position <offset> in Richtung <dir>
- offset in Zukunft: Akzeptieren ohne Analyse
- offset == IMP_MAXOFFSET - alles weitere akzeptieren
Beispiel PASS dir,infinite
Ersetzen
- IMP_REPLACE dir,offset,newdata
- ersetze Daten bis <offset> mit <newdata>
- Startposition letzter Offset
- offset kann nicht in Zukunft sein
Verbieten
- IMP_DENY dir,reason
- Verbindung abbrechen weil <reason> in <dir>
Vorab durchlassen
- IMP_PREPASS dir,offset
- Durchlassen bis <offset> (Zukunft), aber trotzdem analysieren
- Anwendungen
- Risiko vs. Latenz abwägen (window)
- State in Analyse halten
- nur loggen
Beispiel PREPASS infinite - SessionLog
Beispiel PREPASS Window - RTP Stream
sonst noch
- IMP_LOG - logging
- IMP_ACCTFIELD - accounting
- IMP_TOSENDER - Daten zum Sender, z.B. bei Kommando ablehnen
- ...
Daten füttern
- analyzer->data(dir,data,offset,type)
- dir - die Richtung
- data - die Daten
- offset - ab welcher Position, nach pass <zukunft>
- type - Datentyp
Datentypen
- streaming Daten, Typ <= -1
- können aneinandergehängt werden
- teilweise Ersetzungen mittendrin möglich
- z.B. IMP_DATA_STREAM(-1)
- Pakete, Typ >= +1
- jedes Paket unabhängig vom anderen
- nur im Stück durchlassen oder ersetzen
- z.B. IMP_DATA_PACKET(+1)
IMP Implementierungen
IMP Implementierungen
Implementierungen
- in-process Net::IMP in Perl
- imp-relay: Proxy, Socks4, transparent(?)
- imp-pcap-filter: pcap_in -> [IMP] -> pcap_out
- genugate Firewall
- client-server Ansätze in OpenBSD relayd
- evtl. Nutzung in OpenFlow Controllern (SDN)
- Implementation in weiteren IDS/IPS und Programmiersprachen gern gesehen
existierende IMP Plugins
- Pattern - deny|replace|..
- ProtocolPinning - Protokolle forcieren
- SessionLog - Session loggen als pcap Stream
- Cascade - mehrere Plugins in Reihe
- ...
Beispiel 1: SSL Analyse
Beispiel:
SSL Analyse
Funktionsweise
- Ziel: Server Zertifikat aus SSL-Datenstrom extrahieren
- Schritte:
- Server Hello einlesen (Record#1)
- Certificate Handshake finden (Record#2)
- commonName extrahieren und loggen
- siehe Net::IMP::Example::LogServerCertificate
Basics
package Net::IMP::Example::LogServerCertificate;
use base 'Net::IMP::Base';
use Net::IMP qw(:log :DEFAULT); # import IMP_ constants
use Net::IMP::Debug;
use fields (
'done', # set after Server Hello or if no SSL
'sbuf', # buffer data for processing Server Hello
);
Interface deklarieren
sub INTERFACE {
return ([
IMP_DATA_STREAM, # what we accept
[ IMP_PASS, IMP_PREPASS, IMP_LOG ] # what we return
])
}
Initialisierung
sub new_analyzer {
my ($factory,%args) = @_;
my $self = $factory->SUPER::new_analyzer(%args);
$self->run_callback(
# we are not interested in data from client
[ IMP_PASS, 0, IMP_MAXOFFSET ],
# and we will not change data from server, only inspect
[ IMP_PREPASS, 1, IMP_MAXOFFSET ],
);
$self->{sbuf} = '';
return $self;
}
Daten füttern (1)
sub data {
my ($self,$dir,$data) = @_;
return if $dir == 0; # should not happen
return if $self->{done}; # done or no SSL
return if $data eq ''; # eof from server
my $buf = $self->{sbuf} .= $data;
....
Daten füttern (2)
...
if ( _read_ssl_handshake($self,\$buf,2) # Server Hello
and my $certs = _read_ssl_handshake($self,\$buf,11) # Certificates
) {
$self->{done} = 1;
# find OID 2.5.4.3 (common name) the quick and dirty way
if ( $certs =~m{\x06\x03\x55\x04\x03.}g
and my $name = _get_asn1_string(substr($certs,pos($certs)))) {
$self->run_callback([ IMP_LOG,1,0,0,IMP_LOG_INFO,"cn=$name" ]);
}
}
$self->run_callback([ IMP_PASS,1,IMP_MAXOFFSET ])
if $self->{done};
Testen
$ imp-pcap-filter.pl \
-MNet::IMP::Example::LogServerCertificate \
-r rsasnakeoil2.cap \
-w x.pcap
[info] cn=Snake Oil CA
Variationen
- kein PREPASS, sondern PASS nach Prüfen Zertifikat
- nur wirkliches SSL durchlassen, einfaches Tunneling verhindern
- SSLv2 verbieten
- nur starke Verschlüsselung erlauben
- Zertifikate vom Debian Random Fauxpas ausschliessen
- Zertifikat gegen Perspectives/Convergence checken
- Zertifikatpinning
Beispiel 2 - IRC Shout
Beispiel:
IRC Shout
Funktionsweise
- Ziel: meine IRC Messages in GROSSBUCHSTABEN
- Weg:
- auf Clientseite lauschen
- PRIVMSG rcpt message abfangen
- und mit uc(message) weiterleiten
Basics
package IRCShout;
use Net::IMP; # import IMP_ constants
use base 'Net::IMP::Base';
use fields (
'pos', # current position in stream
'line', # buffer for unfinished lines
);
Interface
sub INTERFACE {
return ([
IMP_DATA_STREAM,
[ IMP_PASS, IMP_REPLACE ]
])
}
Initialisierung
sub new_analyzer {
my ($factory,%args) = @_;
my $self = $factory->SUPER::new_analyzer(%args);
$self->run_callback(
# we are not interested in data from server
[ IMP_PASS, 1, IMP_MAXOFFSET ],
);
$self->{line} = '';
$self->{pos} = 0;
return $self;
}
Daten verändern
sub data {
my ($self,$dir,$data) = @_;
return if $dir == 1; # should not happen
return if $data eq ''; # eof from client
$self->{line} .= $data;
my @rv; # collect callbacks
while ( $self->{line} =~s{\A([^\n]*\n)}{} ) {
my $line = $1;
$self->{pos} += length($line);
....
REPLACE
if ( shout(\$line)) {
if ( @rv and $rv[-1][0] == IMP_REPLACE ) {
# merge into last replacement
$rv[-1][2] = $self->{pos};
$rv[-1][3].= $line;
} else {
# add new replacement
push @rv, [ IMP_REPLACE,0,$self->{pos},$line ];
}
oder PASS
} else {
if ( @rv and $rv[-1][0] == IMP_PASS ) {
# merge into last pass
$rv[-1][2] = $self->{pos};
} else {
# add new pass
push @rv, [ IMP_PASS,0,$self->{pos} ];
}
}
Callback am Ende
}
$self->run_callback(@rv) if @rv;
}
howto shout
sub shout {
my $line = shift;
return $$line =~s{\A
(
(?: :\S+\x20+ )? # opt msg prefix
PRIVMSG\x20+\S+\x20+ # privmsg rcpt
)
(.+) # message
}{$1\U$2}x # shout message
}