CloudyScripts 1.6.1 → 1.7.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/lib/audit/checks/APACHE2.group +6 -0
- data/lib/audit/checks/APACHE2_CONFIG_01.check +36 -0
- data/lib/audit/checks/APACHE2_CONFIG_02.check +34 -0
- data/lib/audit/checks/APACHE2_CONFIG_03.check +60 -0
- data/lib/audit/checks/APACHE2_CONFIG_04.check +23 -0
- data/lib/audit/checks/APACHE2_CONFIG_05.check +23 -0
- data/lib/audit/checks/APACHE2_CONFIG_06.check +30 -0
- data/lib/audit/checks/APACHE2_INIT_1.check +14 -0
- data/lib/audit/checks/APACHE2_INIT_2.check +66 -0
- data/lib/audit/checks/APACHE2_INIT_3.check +13 -0
- data/lib/audit/checks/APACHE2_USER_7.check +17 -0
- data/lib/audit/checks/BACKUP_HOME_DOTFILES.check +26 -0
- data/lib/audit/checks/BACKUP_LOG.check +24 -0
- data/lib/audit/checks/BACKUP_MAIL.check +19 -0
- data/lib/audit/checks/BACKUP_WEB.check +12 -0
- data/lib/audit/checks/CONFIGURATION_BACKUP.check +14 -0
- data/lib/audit/checks/DIRECTORY_LISTING.check +14 -0
- data/lib/audit/checks/DISTRIBUTION_FACTS.check +60 -0
- data/lib/audit/checks/DMESG_OUTPUT.check +14 -0
- data/lib/audit/checks/FIND_GROUP_FILE.check +6 -0
- data/lib/audit/checks/FIND_PASSWD_FILE.check +8 -0
- data/lib/audit/checks/FIND_SHADOW_FILE.check +5 -0
- data/lib/audit/checks/FIND_SUDOERS_FILE.check +6 -0
- data/lib/audit/checks/FREE_SPACE.check +26 -0
- data/lib/audit/checks/HAS_AWK.check +30 -0
- data/lib/audit/checks/HAS_BASE.check +21 -0
- data/lib/audit/checks/HAS_CAT.check +18 -0
- data/lib/audit/checks/HAS_COMPRESSOR.check +30 -0
- data/lib/audit/checks/HAS_CUT.check +18 -0
- data/lib/audit/checks/HAS_DF.check +19 -0
- data/lib/audit/checks/HAS_DPKG.check +18 -0
- data/lib/audit/checks/HAS_FILE_DOWNLOADER.check +32 -0
- data/lib/audit/checks/HAS_FIND.check +18 -0
- data/lib/audit/checks/HAS_GREP.check +19 -0
- data/lib/audit/checks/HAS_GROUPCHECK.check +23 -0
- data/lib/audit/checks/HAS_GROUPS.check +19 -0
- data/lib/audit/checks/HAS_HOSTNAME.check +7 -0
- data/lib/audit/checks/HAS_ID.check +7 -0
- data/lib/audit/checks/HAS_LSB_RELEASE.check +16 -0
- data/lib/audit/checks/HAS_MOUNT.check +19 -0
- data/lib/audit/checks/HAS_NETSTAT.check +20 -0
- data/lib/audit/checks/HAS_PASSWD_CHECK.check +17 -0
- data/lib/audit/checks/HAS_PS.check +19 -0
- data/lib/audit/checks/HAS_ROUTE.check +19 -0
- data/lib/audit/checks/HAS_SH.check +19 -0
- data/lib/audit/checks/HAS_SORT.check +17 -0
- data/lib/audit/checks/HAS_STAT.check +17 -0
- data/lib/audit/checks/HAS_SUPERUSER.check +11 -0
- data/lib/audit/checks/HAS_TAIL.check +16 -0
- data/lib/audit/checks/HAS_TAR.check +7 -0
- data/lib/audit/checks/HAS_TR.check +22 -0
- data/lib/audit/checks/HAS_UNAME.check +7 -0
- data/lib/audit/checks/HAS_UNIQ.check +17 -0
- data/lib/audit/checks/HAS_WC.check +16 -0
- data/lib/audit/checks/HAS_WHO.check +18 -0
- data/lib/audit/checks/HAS_YUM.check +18 -0
- data/lib/audit/checks/LASTLOG.check +28 -0
- data/lib/audit/checks/LIST_ROUTES.check +33 -0
- data/lib/audit/checks/LIST_USER_ACCOUNTS.check +25 -0
- data/lib/audit/checks/LOADED_MODULES.check +22 -0
- data/lib/audit/checks/LOCAL_NMAP.check +97 -0
- data/lib/audit/checks/LOGGED_USERS.check +28 -0
- data/lib/audit/checks/LYNIS_AUTH.group +9 -0
- data/lib/audit/checks/LYNIS_AUTH_9204.check +43 -0
- data/lib/audit/checks/LYNIS_AUTH_9208.check +35 -0
- data/lib/audit/checks/LYNIS_AUTH_9216.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9222.check +25 -0
- data/lib/audit/checks/LYNIS_AUTH_9226.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9228.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9252.check +19 -0
- data/lib/audit/checks/MAYBE_HAS_BZIP2.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_CURL.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_DU.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_HOSTNAME.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_ID.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_LSB_RELEASE.check +15 -0
- data/lib/audit/checks/MAYBE_HAS_SUPERUSER.check +36 -0
- data/lib/audit/checks/MAYBE_HAS_TAR.check +19 -0
- data/lib/audit/checks/MAYBE_HAS_UNAME.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_WGET.check +17 -0
- data/lib/audit/checks/MOUNTED_DEVICES.check +22 -0
- data/lib/audit/checks/MYSQL_HISTORY_1.check +29 -0
- data/lib/audit/checks/MYSQL_INIT_1.check +9 -0
- data/lib/audit/checks/MYSQL_INIT_2.check +12 -0
- data/lib/audit/checks/MYSQL_INIT_3.check +7 -0
- data/lib/audit/checks/PACKAGES_INSTALLED_DPKG.check +38 -0
- data/lib/audit/checks/PACKAGES_INSTALLED_YUM.check +36 -0
- data/lib/audit/checks/PASSWORD_INFORMATION.check +33 -0
- data/lib/audit/checks/PLATFORM_FACTS.check +35 -0
- data/lib/audit/checks/PORTS_OPEN_NETSTAT.check +121 -0
- data/lib/audit/checks/PROCESS_LIST.check +87 -0
- data/lib/audit/checks/SLOW.group +7 -0
- data/lib/audit/checks/SLOW_1.check +4 -0
- data/lib/audit/checks/SLOW_2.check +4 -0
- data/lib/audit/checks/SLOW_3.check +4 -0
- data/lib/audit/checks/SSH.group +14 -0
- data/lib/audit/checks/SSH_CONFIG_01.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_02.check +15 -0
- data/lib/audit/checks/SSH_CONFIG_03.check +13 -0
- data/lib/audit/checks/SSH_CONFIG_04.check +11 -0
- data/lib/audit/checks/SSH_CONFIG_05.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_06.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_07.check +11 -0
- data/lib/audit/checks/SSH_CONFIG_08.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_09.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_10.check +15 -0
- data/lib/audit/checks/SSH_CONFIG_11.check +14 -0
- data/lib/audit/checks/SSH_INIT_1.check +9 -0
- data/lib/audit/checks/SSH_INIT_2.check +12 -0
- data/lib/audit/checks/SSH_KEYS_1.check +32 -0
- data/lib/audit/checks/USERS_INIT_1.check +9 -0
- data/lib/audit/checks/USERS_INIT_2.check +5 -0
- data/lib/audit/checks/USERS_INIT_3.check +5 -0
- data/lib/audit/checks/USERS_INIT_4.check +9 -0
- data/lib/audit/checks/USERS_INIT_5.check +10 -0
- data/lib/audit/checks/USER_INFORMATION.check +29 -0
- data/lib/audit/checks/VARIOUS.group +19 -0
- data/lib/audit/checks/VAR_LIST_HOME_DIRECTORIES.check +5 -0
- data/lib/audit/checks/benchmark.group +6 -0
- data/lib/audit/checks/footer.template +12 -0
- data/lib/audit/checks/header.template +10 -0
- data/lib/audit/checks/helpers/head.sh +59 -0
- data/lib/audit/checks/script_header.template +69 -0
- data/lib/audit/create_benchmark.sh +93 -0
- data/lib/audit/lib/audit.rb +136 -0
- data/lib/audit/lib/audit_facade.rb +5 -0
- data/lib/audit/lib/benchmark/audit_benchmark.rb +165 -0
- data/lib/audit/lib/benchmark/automatic_dependencies.rb +13 -0
- data/lib/audit/lib/benchmark/benchmark_factory.rb +23 -0
- data/lib/audit/lib/benchmark/benchmark_result.rb +25 -0
- data/lib/audit/lib/benchmark/check.rb +34 -0
- data/lib/audit/lib/benchmark/group.rb +30 -0
- data/lib/audit/lib/benchmark/item_exception.rb +13 -0
- data/lib/audit/lib/benchmark/result_code.rb +11 -0
- data/lib/audit/lib/benchmark/rule_result.rb +42 -0
- data/lib/audit/lib/benchmark/rule_role.rb +5 -0
- data/lib/audit/lib/benchmark/rule_severity.rb +13 -0
- data/lib/audit/lib/benchmark/yaml_benchmark.rb +133 -0
- data/lib/audit/lib/connection/ami_connection.rb +4 -0
- data/lib/audit/lib/connection/connection_factory.rb +27 -0
- data/lib/audit/lib/connection/ssh_connection.rb +243 -0
- data/lib/audit/lib/ec2_utils.rb +245 -0
- data/lib/audit/lib/http_fingerprint.rb +116 -0
- data/lib/audit/lib/lazy.rb +37 -0
- data/lib/audit/lib/linear_script_generator.rb +31 -0
- data/lib/audit/lib/main.rb +13 -0
- data/lib/audit/lib/my_option_parser.rb +106 -0
- data/lib/audit/lib/nessus_new.rb +290 -0
- data/lib/audit/lib/nessus_utils.rb +102 -0
- data/lib/audit/lib/parser/command/abstract_command.rb +32 -0
- data/lib/audit/lib/parser/command/abstract_command_result.rb +30 -0
- data/lib/audit/lib/parser/command/attach_file_command.rb +63 -0
- data/lib/audit/lib/parser/command/check_finished_command.rb +45 -0
- data/lib/audit/lib/parser/command/cpe_name_command.rb +37 -0
- data/lib/audit/lib/parser/command/data_command.rb +43 -0
- data/lib/audit/lib/parser/command/listening_port_command.rb +46 -0
- data/lib/audit/lib/parser/command/message_command.rb +21 -0
- data/lib/audit/lib/parser/command/program_name_command.rb +42 -0
- data/lib/audit/lib/parser/parse_exception.rb +2 -0
- data/lib/audit/lib/parser/result_type.rb +13 -0
- data/lib/audit/lib/parser/script_output_parser.rb +201 -0
- data/lib/audit/lib/parser/stdout_line_buffer.rb +43 -0
- data/lib/audit/lib/ssh_fingerprint.rb +220 -0
- data/lib/audit/lib/ssh_fingerprint2.rb +170 -0
- data/lib/audit/lib/ssh_utils.rb +292 -0
- data/lib/audit/lib/transformers/web_view_transformer.rb +171 -0
- data/lib/audit/lib/transformers/yaml_transformer.rb +50 -0
- data/lib/audit/lib/util/random_string.rb +22 -0
- data/lib/audit/lib/version.rb +7 -0
- data/lib/help/ec2_helper.rb +65 -2
- data/lib/help/remote_command_handler.rb +17 -0
- data/lib/help/state_transition_helper.rb +8 -0
- data/lib/scripts/ec2/open_port_checker.rb +112 -0
- data/lib/scripts/ec2/port_range_detector.rb +0 -1
- metadata +175 -16
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
require 'AWS'
|
|
2
|
+
|
|
3
|
+
class EC2_Utils
|
|
4
|
+
attr_reader :ec2
|
|
5
|
+
|
|
6
|
+
public
|
|
7
|
+
def initialize(ec2_options)
|
|
8
|
+
@ec2 = AWS::EC2::Base.new(ec2_options)
|
|
9
|
+
end
|
|
10
|
+
# Get public DNS name of an instance.
|
|
11
|
+
# If the instance is not yet started and the DNS name not known, block until the instance is started.
|
|
12
|
+
#
|
|
13
|
+
# @param instance_id Instance ID of the instance that you want to get the DNS from.
|
|
14
|
+
# @param ec2 The AWS::EC2::Base object that is used to access EC2.
|
|
15
|
+
# @return Public DNS name of the instance as String.
|
|
16
|
+
public
|
|
17
|
+
def get_instance_public_dns(instance_id)
|
|
18
|
+
error_count = 0
|
|
19
|
+
begin
|
|
20
|
+
while (true) do
|
|
21
|
+
instances = @ec2.describe_instances(:instance_id => instance_id)
|
|
22
|
+
# protect against nil errors because parts of the structure are not initialized when the DNS is not known
|
|
23
|
+
begin
|
|
24
|
+
dns_name = instances["reservationSet"]["item"][0]["instancesSet"]["item"][0]["dnsName"]
|
|
25
|
+
return dns_name if dns_name
|
|
26
|
+
rescue => err
|
|
27
|
+
end
|
|
28
|
+
sleep(5)
|
|
29
|
+
end
|
|
30
|
+
rescue => err
|
|
31
|
+
error_count += 1
|
|
32
|
+
raise err if error_count > 3
|
|
33
|
+
|
|
34
|
+
sleep(5)
|
|
35
|
+
retry
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get the AMI from a started instance.
|
|
40
|
+
#
|
|
41
|
+
# @param instance_id The instance id that the machine id is retrieved for.
|
|
42
|
+
# @param ec2 The AWS::EC2::Base object that is used to access EC2.
|
|
43
|
+
# @return Machine id of the instance as String.
|
|
44
|
+
public
|
|
45
|
+
def get_image_id(instance_id)
|
|
46
|
+
instances = @ec2.describe_instances(:instance_id => instance_id)
|
|
47
|
+
if instances then
|
|
48
|
+
return instances["reservationSet"]["item"][0]["instancesSet"]["item"][0]["imageId"]
|
|
49
|
+
else
|
|
50
|
+
return "none"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
public
|
|
55
|
+
def get_instance_states()
|
|
56
|
+
instanceStates = []
|
|
57
|
+
@ec2.describe_instances()['reservationSet']['item'].each do|x|
|
|
58
|
+
x['instancesSet']['item'].each do|y|
|
|
59
|
+
instanceStates << {:instance_id => y['instanceId'],
|
|
60
|
+
:state => y['instanceState']['name'],
|
|
61
|
+
:image_id => y['imageId'],
|
|
62
|
+
:runtime => (DateTime.now() - DateTime.strptime(y['launchTime'], "%Y-%m-%dT%H:%M:%S")) * 24.0}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
return instanceStates
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
public
|
|
69
|
+
def get_cheapest_instance_type(machine_id)
|
|
70
|
+
machines = @ec2.describe_images(:image_id => machine_id)
|
|
71
|
+
begin
|
|
72
|
+
return "t1.micro" if machines['imagesSet']['item'][0]['rootDeviceType'] == "ebs"
|
|
73
|
+
return 'm1.small' if machines['imagesSet']['item'][0]['architecture'] == "i386"
|
|
74
|
+
return "m1.large" if machines['imagesSet']['item'][0]['architecture'] == "x86_64"
|
|
75
|
+
rescue => err
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
puts "ERROR: Finding cheapest instance type in EC2_Utils::get_cheapest_instance_type for machine_id = #{machine_id}"
|
|
79
|
+
return "t1.micro"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
public
|
|
83
|
+
def start_instance(options)
|
|
84
|
+
raise "Invalid parameters to EC2_Utils::start_instance: :id is missing" unless options[:id]
|
|
85
|
+
|
|
86
|
+
if /^ami-.*$/.match(options[:id]) then
|
|
87
|
+
raise "Invalid parameters to EC2_Utils::start_instance: :ssh_keypair is missing" unless options[:ssh_keypair]
|
|
88
|
+
raise "Invalid parameters to EC2_Utils::start_instance: :instance_type is missing" unless options[:instance_type]
|
|
89
|
+
raise "Invalid parameters to EC2_Utils::start_instance: :security_group is missing" unless options[:security_group]
|
|
90
|
+
|
|
91
|
+
instance_id = false
|
|
92
|
+
if options[:max_price] then
|
|
93
|
+
spot_request = @ec2.request_spot_instances(
|
|
94
|
+
:image_id => options[:id],
|
|
95
|
+
:instance_count => 1,
|
|
96
|
+
:key_name => options[:ssh_keypair],
|
|
97
|
+
:security_group => options[:security_group],
|
|
98
|
+
:disable_api_termination => false,
|
|
99
|
+
:instance_type => options[:instance_type],
|
|
100
|
+
:spot_price => options[:max_price],
|
|
101
|
+
:valid_from => nil,
|
|
102
|
+
:valid_until => nil)
|
|
103
|
+
|
|
104
|
+
spot_request_id = spot_request['spotInstanceRequestSet']['item'][0]['spotInstanceRequestId']
|
|
105
|
+
begin
|
|
106
|
+
spot_reqs = ec2.describe_spot_instance_requests()
|
|
107
|
+
spot_req = spot_reqs['spotInstanceRequestSet']['item'].reject{|x| x['spotInstanceRequestId'] != spot_request_id}
|
|
108
|
+
|
|
109
|
+
raise "Spot request #{spot_request_id} seems to have disappeared" if spot_req.length() != 1
|
|
110
|
+
|
|
111
|
+
if spot_req[0]['instanceId'] then
|
|
112
|
+
instance_id = spot_req[0]['instanceId']
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
sleep(30)
|
|
116
|
+
end until instance_id
|
|
117
|
+
else
|
|
118
|
+
instance = @ec2.run_instances(
|
|
119
|
+
:image_id => options[:id],
|
|
120
|
+
:max_count => 1,
|
|
121
|
+
:key_name => options[:ssh_keypair],
|
|
122
|
+
:security_group => options[:security_group],
|
|
123
|
+
:disable_api_termination => false,
|
|
124
|
+
:instance_type => options[:instance_type])
|
|
125
|
+
instance_id = instance["instancesSet"]["item"][0]["instanceId"]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
image_id = options[:id]
|
|
129
|
+
elsif /^i-.*$/.match(options[:id]) then
|
|
130
|
+
instance_id = options[:id]
|
|
131
|
+
image_id = get_image_id(instance_id)
|
|
132
|
+
else
|
|
133
|
+
raise "Unknown identifier #{options[:id]}"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
puts "instance #{instance_id} started, waiting for IP address" if options[:verbose]
|
|
137
|
+
begin
|
|
138
|
+
dns_name = get_instance_public_dns(instance_id)
|
|
139
|
+
rescue => err
|
|
140
|
+
puts "ERROR: During DNS request of AMI" if options[:verbose]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
if dns_name.nil? || dns_name.empty? then
|
|
144
|
+
puts "ERROR: No DNS name for AMI found" if options[:verbose]
|
|
145
|
+
raise "No DNS name for AMI found"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
return {:machine_id => image_id,
|
|
149
|
+
:instance_id => instance_id,
|
|
150
|
+
:public_dns => dns_name}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
public
|
|
154
|
+
def get_instance_volumes(instance_id)
|
|
155
|
+
volumes = []
|
|
156
|
+
instances = @ec2.describe_instances(:instance_id => [instance_id])
|
|
157
|
+
|
|
158
|
+
instances['reservationSet']['item'].each do|reservationSet|
|
|
159
|
+
next unless reservationSet['instancesSet']
|
|
160
|
+
|
|
161
|
+
reservationSet['instancesSet']['item'].each do|instancesSet|
|
|
162
|
+
next unless instancesSet['blockDeviceMapping']
|
|
163
|
+
|
|
164
|
+
instancesSet['blockDeviceMapping']['item'].each do|blockDeviceMapping|
|
|
165
|
+
next unless blockDeviceMapping['ebs']
|
|
166
|
+
|
|
167
|
+
volumes << blockDeviceMapping['ebs']['volumeId']
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
return volumes
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
public
|
|
176
|
+
def terminate_instance(instance_id)
|
|
177
|
+
volumes = get_instance_volumes(instance_id)
|
|
178
|
+
|
|
179
|
+
@ec2.terminate_instances(:instance_id => [instance_id])
|
|
180
|
+
|
|
181
|
+
begin
|
|
182
|
+
#wait till instance is terminated
|
|
183
|
+
begin
|
|
184
|
+
instance_state = @ec2.describe_instances(:instance_id => [instance_id])['reservationSet']['item'][0]['instancesSet']['item'][0]['instanceState']['name']
|
|
185
|
+
end unless instance_state == "terminated"
|
|
186
|
+
|
|
187
|
+
#delete volumes
|
|
188
|
+
volumes.each do|volume|
|
|
189
|
+
begin
|
|
190
|
+
@ec2.detach_volumes(:volume_id => volume)
|
|
191
|
+
rescue => err
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
@ec2.delete_volume(:volume_id => volume)
|
|
195
|
+
end
|
|
196
|
+
rescue => err
|
|
197
|
+
if err.class() == AWS::Error && /The volume 'vol-[0-9a-f]{8}' does not exist/.match(err.message()) then
|
|
198
|
+
#ignore error
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
public
|
|
204
|
+
def get_spot_prices(options = {})
|
|
205
|
+
arg = {:start_time => Time.now() - 1, :end_time => Time.now()}
|
|
206
|
+
arg[:instance_type] = options[:instance_type] if options[:instance_type]
|
|
207
|
+
spot_prices = ec2.describe_spot_price_history(arg)
|
|
208
|
+
|
|
209
|
+
prices = {}
|
|
210
|
+
if spot_prices["spotPriceHistorySet"] then
|
|
211
|
+
spot_prices["spotPriceHistorySet"]["item"].each do|spot_price|
|
|
212
|
+
(prices[spot_price["instanceType"]] ||= {})[spot_price["productDescription"]] = {:price => spot_price["spotPrice"], :timestamp => spot_price["timestamp"]}
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
return prices
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# taken from https://github.com/grempe/amazon-ec2/blob/master/lib/AWS/EC2/console.rb ------------------------->
|
|
221
|
+
module AWS
|
|
222
|
+
module EC2
|
|
223
|
+
class Base < AWS::Base
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# The GetConsoleOutput operation retrieves console output that has been posted for the specified instance.
|
|
227
|
+
#
|
|
228
|
+
# Instance console output is buffered and posted shortly after instance boot, reboot and once the instance
|
|
229
|
+
# is terminated. Only the most recent 64 KB of posted output is available. Console output is available for
|
|
230
|
+
# at least 1 hour after the most recent post.
|
|
231
|
+
#
|
|
232
|
+
# @option options [String] :instance_id ("") an Instance ID
|
|
233
|
+
#
|
|
234
|
+
def get_console_output( options = {} )
|
|
235
|
+
options = {:instance_id => ""}.merge(options)
|
|
236
|
+
raise ArgumentError, "No instance ID provided" if options[:instance_id].nil? || options[:instance_id].empty?
|
|
237
|
+
params = { "InstanceId" => options[:instance_id] }
|
|
238
|
+
return response_generator(:action => "GetConsoleOutput", :params => params)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
# <----------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'timeout'
|
|
2
|
+
require 'socket'
|
|
3
|
+
|
|
4
|
+
# http://www.apachehaus.com/index.php?option=com_content&view=article&id=119:history-releases-apache&catid=41:catagory-change-logs&Itemid=93
|
|
5
|
+
|
|
6
|
+
#Contains code to take responses to revealing HTTP requests.
|
|
7
|
+
#This code needs Ruby 1.9 for the timeout module.
|
|
8
|
+
module HTTP_FINGERPRINT
|
|
9
|
+
#HTTP request timeout in seconds
|
|
10
|
+
HTTP_REQUEST_TIMEOUT = 10
|
|
11
|
+
|
|
12
|
+
def self.repeat_character(x, y)
|
|
13
|
+
if y == 0 then
|
|
14
|
+
return ""
|
|
15
|
+
else
|
|
16
|
+
return x + repeat_character(x, y - 1)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@http_methods = [["GET / HTTP/1.1\r\n", :get_existing],
|
|
21
|
+
["GET /" + repeat_character("x", 1024) + " HTTP/1.1\r\n", :get_long],
|
|
22
|
+
["GET /kC8CH9.html HTTP/1.1\r\n", :get_nonexisting],
|
|
23
|
+
["GET / HTTP/9.8\r\n", :wrong_version],
|
|
24
|
+
["GET / INVD/1.1\r\n", :wrong_protocol],
|
|
25
|
+
["HEAD / HTTP/1.1\r\n", :head_existing],
|
|
26
|
+
["OPTIONS / HTTP/1.1\r\n", :options],
|
|
27
|
+
["DELETE / HTTP/1.1\r\n", :delete_existing],
|
|
28
|
+
["GET /etc/passwd?format=%%%&xss=\"><script>alert('xss');" +
|
|
29
|
+
"</script>&traversal=../../&sql='%20OR%201; HTTP/1.1\r\n", :attack_request],
|
|
30
|
+
["TEST / HTTP/1.1\r\n", :wrong_method],
|
|
31
|
+
["GET \\ HTTP/1.1\r\n", :get_backslash_resource]]
|
|
32
|
+
|
|
33
|
+
def self.fingerprint_to_xml(fingerprint)
|
|
34
|
+
xml = [
|
|
35
|
+
"<scan_targethost>\n",
|
|
36
|
+
fingerprint[:scan_targethost] + "\n",
|
|
37
|
+
"</scan_targethost>\n",
|
|
38
|
+
"<scan_targetport>\n",
|
|
39
|
+
fingerprint[:scan_targetport].to_s + "\n",
|
|
40
|
+
"</scan_targetport>\n",
|
|
41
|
+
"<scan_targetsecure>\n",
|
|
42
|
+
fingerprint[:scan_targetsecure].to_s + "\n",
|
|
43
|
+
"</scan_targetsecure>\n",
|
|
44
|
+
"<scan_date>\n",
|
|
45
|
+
fingerprint[:scan_timestamp].strftime("%d.%m.%Y") + "\n",
|
|
46
|
+
"</scan_date>\n",
|
|
47
|
+
"<scan_time>\n",
|
|
48
|
+
fingerprint[:scan_timestamp].strftime("%H:%M:%S") + "\n",
|
|
49
|
+
"</scan_time>\n"]
|
|
50
|
+
@http_methods.each do|method|
|
|
51
|
+
xml << ("<" + method[1].to_s + ">\n")
|
|
52
|
+
fingerprint[method[1]].each {|l| xml << l}
|
|
53
|
+
xml << ("</" + method[1].to_s + ">\n")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
return xml.join
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
public
|
|
60
|
+
def self.fingerprint(host, port = 80, useragent = "(KHTML, like Gecko) " +
|
|
61
|
+
"Ubuntu/10.04 Chromium/8.0.552.224 Chrome/8.0.552.224" +
|
|
62
|
+
" Safari/534.10")
|
|
63
|
+
header_lines = ["User-Agent: " + useragent + "\r\n",
|
|
64
|
+
"Host: " + host + "\r\n",
|
|
65
|
+
"Connection: Close\r\n",
|
|
66
|
+
"Cache-Control: no-cache\r\n",
|
|
67
|
+
"\r\n"]
|
|
68
|
+
http_fingerprints= {
|
|
69
|
+
:scan_targethost => host,
|
|
70
|
+
:scan_targetport => port,
|
|
71
|
+
:scan_targetsecure => 0,
|
|
72
|
+
:scan_timestamp => Time.now}
|
|
73
|
+
# [
|
|
74
|
+
# "<scan_targethost>\n",
|
|
75
|
+
# host + "\n",
|
|
76
|
+
# "</scan_targethost>\n",
|
|
77
|
+
# "<scan_targetport>\n",
|
|
78
|
+
# port.to_s + "\n",
|
|
79
|
+
# "</scan_targetport>\n",
|
|
80
|
+
# "<scan_targetsecure>\n",
|
|
81
|
+
# "0\n",
|
|
82
|
+
# "</scan_targetsecure>\n",
|
|
83
|
+
# "<scan_date>\n",
|
|
84
|
+
# Time.now.strftime("%d.%m.%Y") + "\n",
|
|
85
|
+
# "</scan_date>\n",
|
|
86
|
+
# "<scan_time>\n",
|
|
87
|
+
# Time.now.strftime("%H:%M:%S") + "\n",
|
|
88
|
+
# "</scan_time>\n"]
|
|
89
|
+
|
|
90
|
+
@http_methods.each do|method|
|
|
91
|
+
http_fingerprints[method[1]] = []
|
|
92
|
+
# http_fingerprints << ("<" + method[1] + ">\n")
|
|
93
|
+
begin
|
|
94
|
+
timeout(HTTP_REQUEST_TIMEOUT) do
|
|
95
|
+
socket = TCPSocket.new(host, port)
|
|
96
|
+
socket.puts method[0]
|
|
97
|
+
header_lines.each do|hdr_line|
|
|
98
|
+
socket.puts hdr_line
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
received = socket.readlines
|
|
102
|
+
for i in 0 .. received.length
|
|
103
|
+
if received[i] == "\r\n" || received[i] == "\n" then
|
|
104
|
+
break
|
|
105
|
+
end
|
|
106
|
+
http_fingerprints[method[1]] << received[i]
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
rescue Timeout::Error
|
|
110
|
+
http_fingerprints[method[1]] = :TIMEOUT
|
|
111
|
+
end
|
|
112
|
+
# http_fingerprints << ("</" + method[1] + ">\n")
|
|
113
|
+
end
|
|
114
|
+
return http_fingerprints
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# To change this template, choose Tools | Templates
|
|
2
|
+
# and open the template in the editor.
|
|
3
|
+
|
|
4
|
+
class Lazy
|
|
5
|
+
def initialize(obj, eval_method, *eval_args, &eval_block)
|
|
6
|
+
@obj = obj
|
|
7
|
+
@eval_method = eval_method
|
|
8
|
+
@eval_args = *eval_args
|
|
9
|
+
@eval_block = eval_block
|
|
10
|
+
|
|
11
|
+
#debugging
|
|
12
|
+
raise "Object #{@obj.class.name} does not contain method #{@eval_method}" unless @obj.methods.include? @eval_method
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def method_missing(method, *args, &block)
|
|
16
|
+
@evaluated = @obj.send(@eval_method, *@eval_args, &@eval_block) if @evaluated.nil?
|
|
17
|
+
@evaluated.send(method, *args, &block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_yaml(opts = {})
|
|
21
|
+
@evaluated = @obj.send(@eval_method, *@eval_args, &@eval_block) if @evaluated.nil?
|
|
22
|
+
return @evaluated.to_yaml(opts)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def methods()
|
|
26
|
+
@evaluated = @obj.send(@eval_method, *@eval_args, &@eval_block) if @evaluated.nil?
|
|
27
|
+
return @evaluated.methods()
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def debug_lazy()
|
|
31
|
+
return [@obj, @eval_method, @eval_args, @eval_block]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get()
|
|
35
|
+
return @obj
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'benchmark'
|
|
2
|
+
|
|
3
|
+
class LinearScriptGenerator
|
|
4
|
+
|
|
5
|
+
def self.generate(benchmark)
|
|
6
|
+
retval = ""
|
|
7
|
+
resolved_dependencies = benchmark.execution_order
|
|
8
|
+
|
|
9
|
+
script_header = benchmark.element("script_header.template")
|
|
10
|
+
header = benchmark.element("header.template")
|
|
11
|
+
footer = benchmark.element("footer.template")
|
|
12
|
+
|
|
13
|
+
raise ItemNotFoundException.new("header.template"), "header template missing in benchmark" if header.nil?
|
|
14
|
+
raise ItemNotFoundException.new("footer.template"), "footer template missing in benchmark" if footer.nil?
|
|
15
|
+
raise ItemNotFoundException.new("script_header.template"), "script header template missing in benchmark" if script_header.nil?
|
|
16
|
+
|
|
17
|
+
retval = script_header if script_header
|
|
18
|
+
|
|
19
|
+
resolved_dependencies.flatten.each do|x|
|
|
20
|
+
depends_condition = ""
|
|
21
|
+
x.dependencies.each do|y|
|
|
22
|
+
depends_condition = depends_condition + "-a ${" + y.id + "_EXITCODE} -eq 0 "
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
retval = retval + "\n" + header.gsub(/%%SCRIPT_ID%%/, x.id).gsub(/%%DEPENDS_CONDITION%%/, depends_condition) + "\n"
|
|
26
|
+
retval = retval + (x.script)
|
|
27
|
+
retval = retval + "\n" + footer.gsub(/%%SCRIPT_ID%%/, x.id)
|
|
28
|
+
end
|
|
29
|
+
return retval
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'my_option_parser'
|
|
4
|
+
|
|
5
|
+
# Parsed options from command line
|
|
6
|
+
options = MyOptionParser.new(ARGV).parse()
|
|
7
|
+
|
|
8
|
+
print "Connection type: #{options.connection_type}\n"
|
|
9
|
+
print "SSH Credentials: #{options.ssh_credentials.to_s}\n" if options.connection_type == :ssh
|
|
10
|
+
#print "SSH: #{options[:ssh]}\n" unless options[:ssh].nil?
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
|
|
3
|
+
class MyOptionParser
|
|
4
|
+
|
|
5
|
+
attr_reader :options
|
|
6
|
+
|
|
7
|
+
def initialize(args)
|
|
8
|
+
@args = args
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def parse()
|
|
12
|
+
@options = {}
|
|
13
|
+
|
|
14
|
+
opts = OptionParser.new do|opts|
|
|
15
|
+
#Banner string displayed at top of help
|
|
16
|
+
opts.banner = "Usage: ./main.rb\t--ssh HOST[:PORT] [--user USERNAME] --key KEYFILE --benchmark BENCHMARK"
|
|
17
|
+
opts.separator "\t\t\t--ami AMI-ID --credentials CREDENTIALS --benchmark BENCHMARK"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@options[:verbose] = false
|
|
21
|
+
opts.on('-v', '--[no-]verbose', 'Output more information') do|v|
|
|
22
|
+
@options[:verbose] = v
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
opts.on('-A', '--ami AMI-ID', String, 'Select this AMI for audit') do|ami|
|
|
26
|
+
@options[:ami] = ami
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
opts.on('-S', '--ssh HOST', String, 'Select this host for audit') do|host|
|
|
30
|
+
@options[:ssh] = host
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
opts.on('-B', '--benchmark BENCHMARK', String, 'Use this benchmark file') do|bm|
|
|
34
|
+
@options[:benchmark] = bm
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
opts.on('-K', '--key KEY', String, 'Use this private key file for authentication') do|key|
|
|
38
|
+
@options[:key] = key
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
opts.on('-P', '--password PASSWORD', String, 'Use this password for authentication') do|pwd|
|
|
42
|
+
@options[:password] = pwd
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
opts.on('-C', '--credentials CREDENTIALS', String, 'Use these Amazon Account credentials to start the AMI') do|cd|
|
|
46
|
+
@options[:credentials] = cd
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
50
|
+
puts opts
|
|
51
|
+
exit
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
opts.parse(@args)
|
|
56
|
+
|
|
57
|
+
if @options[:ssh].nil? and @options[:ami].nil? then
|
|
58
|
+
print "You must specify one of the --ssh or --ami options. Exiting.\n"
|
|
59
|
+
exit 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if not @options[:ssh].nil? and not @options[:ami].nil? then
|
|
63
|
+
print "Options --ssh and --ami are mutually exclusive, but both chosen. Please specify only one of them. Exiting.\n"
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if @options[:benchmark].nil? then
|
|
68
|
+
print "Option --benchmark is required. Please specify a benchmark file for this audit. Exiting.\n"
|
|
69
|
+
exit 1
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if not @options[:ssh].nil? and @options[:key].nil? and @options[:password].nil? then
|
|
73
|
+
print "At least one authentication method for SSH is required. Please specify either --key or --password. Exiting.\n"
|
|
74
|
+
exit 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
return self
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def connection_type
|
|
81
|
+
return :ami unless @options[:ami].nil?
|
|
82
|
+
return :ssh unless @options[:ssh].nil?
|
|
83
|
+
return :none
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def ssh_credentials
|
|
87
|
+
raise "SSH credentials requested although SSH connection method is not chosen" if @options[:ssh].nil?
|
|
88
|
+
raise "No SSH authentication method chosen" if @options[:password].nil? and @options[:key].nil?
|
|
89
|
+
|
|
90
|
+
cred = {:host => @options[:ssh]}
|
|
91
|
+
if @options[:user].nil? then
|
|
92
|
+
cred[:user] = 'root'
|
|
93
|
+
else
|
|
94
|
+
cred[:user] = @options[:user]
|
|
95
|
+
end
|
|
96
|
+
cred[:key_data] = @options[:key] unless @options[:key].nil?
|
|
97
|
+
cred[:password] = @options[:password] unless @options[:password].nil?
|
|
98
|
+
|
|
99
|
+
return cred
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def benchmark
|
|
103
|
+
raise "No benchmark file specified" if @options[:benchmark].nil?
|
|
104
|
+
return @options[:benchmark]
|
|
105
|
+
end
|
|
106
|
+
end
|