-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathattack.py
234 lines (190 loc) · 8.25 KB
/
attack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
"""
Author: Mor Sides
Purpose: Simulates a YoYo attack on an auto scaling group of EC2
Description:
1. Purge the SQS queue to keep track of the scaling actions
2. Initiate the auto scaling group (set minimum size to 1, etc.)
3. Connect to the attacker machine (Windows server with JMeter installed)
4. Simulate normal traffic
5. Simulate YoYo attack
6. Dump logs from JMeter, SQS and the script itself
"""
import boto3
import time
import os
import datetime
import paramiko
import pytz
import utils
import machine_connection
global ec2
client_machine_name = "windowsNotAutoScale"
auto_scaling_group_name = "my-asg-lbs"
sqs_url='https://us-west-2.queue.amazonaws.com/839913665213/ScalingActivityQueue'
local_results_dir = r"C:\Users\Mor\Documents\GitHub\YoYoServer\aws\results"
g_probnum = 1
def create_file_name():
return time.strftime("results_%H%M%S.csv")
def create_directory_name():
return time.strftime("%Y%m%d")
results_directory_name = create_directory_name()
results_file_name = create_file_name()
def yoyo_attack(attackMachine, cycles, sleep_between_cycles, group):
global ec2
attack_log = {}
for i in range(cycles):
if i>0:
print "wait cool down period of 60 seconds"
time.sleep(60)
print "Cycle#"+str(i)
ammount_of_running_machines_before_attack = ec2.get_ammount_of_running_machines()
now = attackMachine.get_datetime()
port = attackMachine.yoyo_on_attack()
#group.chage_cooldown(1300)
attack_log[now] = "start"
print " Now " + str(now) + ": Wait "+ str(sleep_between_cycles) + " seconds"
time.sleep(sleep_between_cycles)
now = attackMachine.get_datetime()
attackMachine.yoyo_off_attack(port)
#group.chage_cooldown(60)
attack_log[now] = "stop"
wait_for_steady_state(ammount_of_running_machines_before_attack)
#a = raw_input("Press Enter to continue next cycle...")
return attack_log
def prob(attackMachine, prob_duration):
global g_probnum
port = attackMachine.jmeter_user_on(g_probnum)
time.sleep(prob_duration)
attackMachine.jmeter_user_off(port)
attackMachine.copy_users_results_file(local_results_dir, g_probnum)
g_probnum = g_probnum+1
def yoyo_attack_with_probs(attackMachine, cycles, sleep_between_cycles):
global ec2
attack_log = {}
for i in range(cycles):
if i>0:
print "wait cool down period of 60 seconds"
time.sleep(60)
print "Cycle#"+str(i)
ammount_of_running_machines_before_attack = ec2.get_ammount_of_running_machines()
now = attackMachine.get_datetime()
port = attackMachine.yoyo_on_attack()
attack_log[now] = "start"
print " Now " + str(now) + ": Wait "+ str(sleep_between_cycles) + " seconds"
current_sleep_between_cycles = sleep_between_cycles
while current_sleep_between_cycles > 0:
time_before_prob = time.time()
prob(attackMachine, 10)
time.sleep(20)
time_after_prob = time.time()
current_sleep_between_cycles = current_sleep_between_cycles - (time_before_prob - time_after_prob)
time.sleep(sleep_between_cycles)
now = attackMachine.get_datetime()
attackMachine.yoyo_off_attack(port)
attack_log[now] = "stop"
wait_for_steady_state(ammount_of_running_machines_before_attack,20, True, attackMachine)
return attack_log
def detect_scale_state_cycle(attackMachine, cycles):
global ec2, g_probnum
attack_log = {}
ammount_of_running_machines_before_attack = ec2.get_ammount_of_running_machines()
print "probnum: " + str(g_probnum)
prob(attackMachine,20, False)
print " prob finish, sleep 20"
time.sleep(20)
print "probnum: " + str(g_probnum)
prob(attackMachine, 20, False)
print " prob finish, sleep 20"
time.sleep(20)
for i in range(cycles):
print "now start attack!"
now = attackMachine.get_datetime()
port = attackMachine.yoyo_on_attack()
attack_log[now] = "start"
time.sleep(5)
print "send probes:"
stop = False
while(not stop):
print " probnum: " + str(g_probnum)
prob(attackMachine, 20)
time.sleep(5)
current_amount_of_running_machines = ec2.get_ammount_of_running_machines()
if(current_amount_of_running_machines == 5):
stop = True
print "current_amount_of_running_machines: " + str(current_amount_of_running_machines)
print "now stop attack!"
now = attackMachine.get_datetime()
attackMachine.yoyo_off_attack(port)
attack_log[now] = "stop"
print "send probes:"
stop = False
while(not stop):
print " probnum: " + str(g_probnum)
prob(attackMachine,20)
time.sleep(5)
current_amount_of_running_machines = ec2.get_ammount_of_running_machines()
if(current_amount_of_running_machines == ammount_of_running_machines_before_attack):
stop = True
print "current_amount_of_running_machines: " + str(current_amount_of_running_machines)
print "finish cycle!"
return attack_log
def wait_for_steady_state(amount_of_machine_at_steady_state, sleep_between_checks = 20, with_prob = False, attackMachine = None):
global ec2
print " Wait for steady state"
while True:
time.sleep(sleep_between_checks)
current_amount_of_running_machines = ec2.get_ammount_of_running_machines()
#print " current amount of running machines " + str(current_amount_of_running_machines)
#if amount_of_machine_at_steady_state*2 >= current_amount_of_running_machines:
if amount_of_machine_at_steady_state == current_amount_of_running_machines:
print " Now " + str(datetime.datetime.now(pytz.utc)) + ": current amount of running machines " + str(current_amount_of_running_machines)
#wait a littel bit more, just to verify the all scaling activity recieve at the sqs
time.sleep(sleep_between_checks/2)
break
if(with_prob):
prob(attackMachine, sleep_between_checks/2)
def save_attack_log(attack_log, attack_log_filepath):
attack_log_data = ""
for event in sorted(attack_log):
attack_log_data = attack_log_data + str(event) + "," + attack_log[event]+"\n"
file = open(attack_log_filepath,'w')
file.write(attack_log_data)
file.close
print "attack log saved!"
def main():
global ec2
#init ec2
ec2 = utils.ec2()
#try:
#validate queue is empty
sqs = utils.sqs(sqs_url)
sqs.clear_queue()
#start auto-scaling group
group = utils.autoscaling_group(auto_scaling_group_name)
group.start_and_wait()
#start attacker machine, connect and create results directory
attacker_ip = ec2.start_and_get_machine_ip_by_mame(client_machine_name)
attacker = machine_connection.machine_connection(attacker_ip,results_directory_name,results_file_name)
attacker.connect()
attacker.create_results_directory()
#start notmal users
user_port = attacker.jmeter_user_on()
time.sleep(120)
#start attack
#attack_log = yoyo_attack(attacker, 2,1000, group)
#start test for probe
#attack_log = detect_scale_state_cycle(attacker, 2)
attack_log = yoyo_attack_with_probs(attacker, 2,1000)
#stop normal users
attacker.jmeter_user_off(user_port)
#collect results
attacker.copy_results_file(local_results_dir)
attacker.copy_users_results_file(local_results_dir)
#shutdown all system
utils.shutdown_all_system()
#continue collect results
sqs.save_scaling_history(local_results_dir+r"\\"+results_directory_name+"_"+results_file_name+"_scaling_log.json")
save_attack_log(attack_log, local_results_dir+r"\\"+results_directory_name+"_"+results_file_name+"_attack_log.txt")
#except:
# print "Error!"
main()