路由攻击(ospf attack)及C/C++代码实现

开放式最短路径优先(OSPF)是应用最广泛的域内路由协议之一。不幸的是,它有许多严重的安全问题。OSPF上的伪造是可能导致路由循环和黑洞的最关键的漏洞之一。

大多数已知的OSPF攻击基于伪造攻击者控制的路由器的链路状态通告(LSA)。如果攻击者控制的路由器地理位置优越。然而,这些攻击只能伪造路由域的拓扑结构;因此它们的效果通常是有的。更多强大的攻击会影响其他未受控制的路由器的LSA攻击者。然而,这些攻击通常会引发“反击”受害者路由器的机制,该机制通告校正LSA攻击的影响是不持久的。

OSPF协议基础

从OSPF协议的概述开始。OSPF不使用TCP/IP传输协议,其消息直接封装在协议号为89的IP数据报。OSPF句柄其自身的错误检测和校正功能。

路由攻击(ospf attack)及C/C++代码实现_第1张图片
OSPF是一种链路状态路由协议,这意味着每个路由器通告其到相邻路由器和网络的链接。动态路由器通过执行Hello协议发现其邻居,其中每个路由器在本地网络上广播消息。一旦邻居发现路由器向他们通告其链接。这些通过是称为链路状态通告(LSA)。

路由攻击(ospf attack)及C/C++代码实现_第2张图片

一条重要信息在LSA中是每个链路的成本。链路的成本通常是静态的由网络管理员配置。LSA通过AS。一个路由器从它的一个邻居那里接收LSA,并将其重新发送给另一个邻居。通过这种方式,每个路由器都会编译一个包含AS。这个数据库在所有路由器中都是相同的。使用此数据库作为路由器获得AS拓扑的完整视图。这使得它可以使用Dijksatra算法计算其与每个其他通告网络或路由器。从这些路径,下一跳路由器为每个目的地派生。这形成了路由器的路由表。在这项工作中,我们提出了新的强大攻击,利用OSPF。这些袭击大大提高了艺术水平,并带来了新的阐明OSPF的安全弱点。所有攻击都利用设计RFC2328中定义的协议规范中的漏洞。

伪装LSA

根据RFC 2328 Sec.13.1,考虑LSA的两个实例相同,如果它们具有:

1) 相同的序列号,
2) 相同的校验和值
3) 大致相同的age(在15分钟的时间差内)。

即使LSA的实际内容不同,也是如此!攻击者可以通过向LSA发布相同的三个字段(序列、校验和和age)作为正在播发的有效LSA受害者路由器。这样做的好处是,即使受害者收到欺骗LSA由于LSA被伪装,因此不会触发反击被认为是与有效LSA相同的副本(同样,即使其内容非常不同),因此忽略它。

然而,AS中的所有其他路由器也会将虚假LSA视为重复,因此他们不会在LSA数据库中安装LSA。修复这样,攻击者将把LSA伪装成LSA的下一个有效实例受害者的起源。当攻击者发送伪装的LSA它触发受害者发起LSA的下一个有效实例。这个触发只是通过利用反击机制来完成的。也就是说攻击者向受害者发送虚假LSA,受害者通过发送LSA进行反击LSA的下一个有效实例。下图说明了

路由攻击(ospf attack)及C/C++代码实现_第3张图片
(1) 攻击开始于向R1自身发送一个伪造的R1 LSA。这将肯定会引发反击。让我们把这个数据包称为“触发器”。

(2) 同时,攻击者向R2发送R1的伪装LSA。这个伪装的LSA是具有相同序列的特制分组,校验和和age(+/-15分钟)作为R1的未来反击LSA。

(3) R1发送反击LSA。这将由R2接收,但具有与伪装的LSA相同的三个字段,R2会将反击视为其刚刚接收的LSA的相同副本。因此,它不会更新其LSA数据库并且它不会重新洪泛数据包。

(4) R2重新洪泛伪装的LSA。这将由R1接收,但具有与反击LSA相同的三个字段该LSA将被R1视为它刚刚发送的LSA的相同副本。因此,它不会更新其LSA数据库不会重新淹没数据包或引发另一次反击。在该分组序列之后,R1和R2在其LSA DB中具有两个不同的R1的LSA的副本。这种状态是持久的。路由器将再次仅在R1将在30之后通告其下一个LSA实例之后同步分钟(默认LSA间隔)

OSPF攻击序列

路由攻击(ospf attack)及C/C++代码实现_第4张图片
攻击从向受害者路由器发送Hello数据包开始。自从Hello在其邻居中包含受害者ID列表,受害者进入双向状态。受害者被假定为指定路由器(DR),因此它开始设置与幻影相邻,并进入ExStart状态。受害者然后发送具有他自己的序列y的DB描述(DBD)分组与受害者发送的所有数据包一样,攻击者没有接收到数据包因为它的目的地是受害者的虚幻路由器的伪造IP地址子网。

然后,攻击者发送其第一个DBD。数据包的定时不是重要的是,受害者每隔几次就会重新发送他的第一个DBD秒(默认为5秒)。攻击者的第一个DBD(实际上是phantom)设置Initialize(I)、More(M)和Master(MS)位,并将序列号设置为任意值(x)。由于数据包是这样制作的幻影的ID大于受害者的ID承认自己是奴隶,幻影成为主人。这意味着受害者采用幻影(x)的序列号,并发送他的下一个DBD只有在他从幻影中得到DBD之后。然后,攻击者继续重复发送DBD序列值。所有幻影的DBD都没有LSA,就好像幻影是空的。攻击者不断发送这些DBD,让受害者发送LSA数据库中的所有LSA。攻击者真的不知道怎么做然而,受害者需要发送许多DBD消息来发送其所有DB内容
他可以很容易地绑定这个数字(通常10个BDB就足够了)。

在这个界是N的例子。如果N是一个过冲,这并不重要;受害者会当他没有LSA要发送时,继续发送空的DBD。在攻击者(phantom)发送他的最后一个DBD(我们假设现在受害者也完成了发送自己的DB)受害者跳过加载状态因为幻影没有新的LSA,然后受害者进入完整状态。此时,受害者与幻影完全相邻,并更新相应地,其网络的网络LSA。

路由攻击(ospf attack)及C/C++代码实现

...
/* OSPF header format */
struct ospf_header {
	__u8	ospf_version;	/* Version Number		*/
	__u8	ospf_type;	/* Packet Type			*/
	__u16	ospf_len;	/* Packet Length		*/
	__u32	ospf_rid;	/* Router Identifier		*/
	__u32	ospf_aid;	/* Area Identifier		*/
	__u16	ospf_cksum;	/* Check Sum			*/
	__u16	ospf_authtype;	/* Authentication Type		*/
	__u64	ospf_auth; /* Authentication Field	*/
};

/* OSPF Hello Packet */

struct	ospf_hello {
  __u32	oh_netmask; /* Network Mask                */
  __u16	oh_hintv;   /* Hello Interval (seconds)    */
  __u8	oh_opts;    /* Options                     */
  __u8	oh_prio;    /* Sender's Router Priority	   */
  __u32	oh_rdintv;  /* Seconds Before Declare Dead */
  __u32	oh_drid;    /* Designated Router ID        */
  __u32	oh_brid;    /* Backup Designated Router ID */
  __u32	oh_neighbor; /* Living Neighbors           */
};

#define	OSPF_HELLO_INTERVAL	0x0a00				/* 10 seconts defined */
#define	OSPF_HELLO_OPTIONS	0X12			/* Take default options from wireshark message */
#define	OSPF_HELLO_PRIORITY	1				/* Take default priority from wireshark message */
// #define	OSPF_HELLO_DEAD_INTERVAL	0X28000000		/* Take default dead interval from wireshark message */

/* OSPF Database Description Packet */

struct	ospf_dd {
	__u16	dd_mbz;		/* Must Be Zero			*/
	__u8	dd_opts;	/* Options			*/
	__u8	dd_control;	/* Control Bits	(DDC_* below)	*/
	__u32	dd_seq;		/* Sequence Number		*/
};

#define DD_OPTIONS	0X52		/* Take default options from wireshark message */
#define	DDC_INIT	0x04		/* Initial Sequence		*/
#define	DDC_MORE	0x02		/* More to follow		*/
#define	DDC_MSTR	0x01		/* This Router is Master	*/

/* OSPF LSS */

struct ospf_lls {
  __u32 data[3];
};

/* Link State Update Packet Format */
struct	ospf_lsu {
  __u32 lsu_nads; /* # Advertisments This Packet */
};

/* OSPF Link State Summary */

struct	ospf_lss {
	__u16	lss_age;	/* Time (secs) Since Originated	*/
	__u8	lss_opts;	/* Options Supported		*/
	__u8	lss_type;	/* LST_* below			*/
	__u32	lss_lsid;	/* Link State Identifier	*/
	__u32	lss_rid;	/* Advertising Router Identifier*/
	__u32	lss_seq;	/* Link State Adv. Sequence #	*/
	__u16	lss_cksum;	/* Fletcher Checksum of LSA	*/
	__u16	lss_len;	/* Length of Advertisement	*/
};

/* Network Links Advertisement */
struct	ospf_na {
	__u32 na_mask;	/* Network Mask			*/
	__u32 na_rid[2];	/* IDs of All Attached Routers	*/
};

...
int ospf_write_header(unsigned char *buffer, char *local_ip, int ospf_len, unsigned char packet_type);
int ospf_write_hello(unsigned char *buffer, char *router_ip);
int ospf_write_lss_data_block(unsigned char *buffer);
int ospf_write_db_description(unsigned char* buffer, unsigned long sequence_number, __u8 control);
int ospf_write_ls_update(unsigned char *buffer, char *local_ip, char *router_ip, __u32 seq_number);
...
int attack_wait_ospf_packet(struct attack_env *env);
int attack_wait_for_db_description(struct attack_env *env);
void attack_sync_db_desc(struct attack_env *env);
int attack_send_db_description(struct attack_env *env, __u32 sequence_number, __u8 control);
int attack_wait_for_ls_update(struct attack_env *env);
...

int create_socket(char *iface_name);
int send_packet(int sock_fd, unsigned char *dest_mac, unsigned char *buffer, int interface_index, int packet_size);
...
unsigned char *parse_mac_addr(char *mac_str);
int write_ipv4_ethernet_header(unsigned char *buffer, unsigned char *source_mac, unsigned char *dest_mac);
int write_ipv4_header(unsigned char *buffer, char *source_ip, char *dest_ip, int ip_data_len);
...
int main(int argc, char *argv[]) 
{
  if (argc != 5) 
  {
    printf("Usage: route-attack INTERFACE_NAME INTERFACE_NUMBER LOCAL_MAC_ADDR LOCAL_IP_ADDR\n\n");
    exit(1);
  }

...
  attack_establish_adjacency(&env);
  attack_send_keepalive(&env);

  return 0;
}

编译运行:

路由攻击(ospf attack)及C/C++代码实现_第5张图片
If you need the complete source code, please add the WeChat number (c17865354792)

ospf attack效果图:
路由攻击(ospf attack)及C/C++代码实现_第6张图片
攻击有几个注意事项:

1.必须通过发送Hello来持续保持相邻,每个RouterDeadInterval发送一条消息。默认情况下,此值为40秒。
路由攻击(ospf attack)及C/C++代码实现_第7张图片

2.在相邻设置之后,受害者将LSA洪泛到幻影并期望从其接收Ack。根据OSPF规范,如果相邻路由器不响应Ack,受害者只会无休止地重复发送LSA。尽管如此,我们观察到思科路由器在125秒后放弃,然后撕裂沿着邻接处往下走。最后一条警告意味着,对于思科路由器,应该重新启动攻击每125秒一次。但是,需要注意的是,如果攻击者受害者路由器位于同一区域,攻击者原则上知道每个LSA受害者洪水泛滥。这意味着它可以欺骗Ack消息以及(它具有超过120秒的时间窗口以Ack进行响应)。

总结

不同类型的攻击都利用了OSPF漏洞,尽管它在过去二十年中被广泛使用。我们已经深入分析了LSA伪造,这是近年来威胁OSPF协议的最严重的攻击之一。

Welcome to follow WeChat official account【程序猿编码

参考:RFC 2328

你可能感兴趣的:(C/C++,c语言,c++,ospf协议,attack,网络)