CloudyScripts 1.6.1 → 1.7.27
Sign up to get free protection for your applications and to get access to all the features.
- 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,290 @@
|
|
1
|
+
|
2
|
+
require 'rexml/document'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
include REXML
|
6
|
+
|
7
|
+
class Nessus
|
8
|
+
attr_reader :token
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
options = {:host => "127.0.0.1", :port => "8834", :timeout => "120"}.merge(options)
|
12
|
+
|
13
|
+
@host = options[:host]
|
14
|
+
@port = options[:port]
|
15
|
+
@timeout = options[:timeout]
|
16
|
+
|
17
|
+
if options[:logger] then
|
18
|
+
@logger = options[:logger]
|
19
|
+
else
|
20
|
+
@logger = Logger.new(STDOUT)
|
21
|
+
end
|
22
|
+
|
23
|
+
@token = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute_command(command, parameters, fail_on_error = true)
|
27
|
+
cmd = "curl --silent --max-time #{@timeout} --insecure "
|
28
|
+
parameters.each do|param|
|
29
|
+
if param[:type].nil? || param[:type] == :data then
|
30
|
+
cmd << "--data \"#{param[:value]}\" "
|
31
|
+
elsif param[:type] == :form then
|
32
|
+
cmd << "--form \"#{param[:value]}\" "
|
33
|
+
elsif param[:type] == :cookie then
|
34
|
+
cmd << "--cookie \"#{param[:value]}\" "
|
35
|
+
else
|
36
|
+
raise "unknown parameter type #{param[:type]}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
cmd << "https://#{@host}:#{@port}/#{command}"
|
41
|
+
|
42
|
+
@logger.info {"Executing command: #{cmd}"}
|
43
|
+
|
44
|
+
result_str = `#{cmd}`
|
45
|
+
|
46
|
+
raise "unexpected return value from nessus command #{command} " unless result_str.class == String
|
47
|
+
|
48
|
+
result = Document.new(result_str)
|
49
|
+
status = result.elements.inject("reply/status", []) {|r, x| r << x.text}
|
50
|
+
|
51
|
+
if fail_on_error then
|
52
|
+
raise "Invalid return status for nessus command #{command}" unless status && status.length == 1 && status[0] == "OK"
|
53
|
+
end
|
54
|
+
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
|
58
|
+
def login(username, password)
|
59
|
+
result = execute_command("login", [{:value => "login=#{username}"}, {:value => "password=#{password}"}])
|
60
|
+
token = result.elements.inject("reply/contents/token", []) {|r, x| r << x.text}
|
61
|
+
raise "Invalid token during nessus login" unless token && token.length == 1
|
62
|
+
|
63
|
+
@token = token[0]
|
64
|
+
end
|
65
|
+
|
66
|
+
def upload_file(file)
|
67
|
+
raise "File '#{file}' is not accessible" unless File.exist?(file) && File.readable?(file)
|
68
|
+
|
69
|
+
reply = execute_command("file/upload",
|
70
|
+
[{:type => :cookie, :value => "token=#{@token}"},
|
71
|
+
{:type => :form, :value => "Filedata=@#{file}"}])
|
72
|
+
return reply.elements.inject("/reply/contents/fileUploaded", []) {|r, x| r << x.text}[0]
|
73
|
+
end
|
74
|
+
|
75
|
+
def import_policy(filename)
|
76
|
+
return execute_command("file/policy/import",
|
77
|
+
[{:value => "file=#{filename}"},
|
78
|
+
{:type => :cookie, :value => "token=#{@token}"}])
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_policy(id)
|
82
|
+
return execute_command("policy/delete",
|
83
|
+
[{:value => "policy_id=#{id}"},
|
84
|
+
{:type => :cookie, :value => "token=#{@token}"}])
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_policy_ids(policy_name)
|
88
|
+
policies = execute_command("policy/list",
|
89
|
+
[{:type => :cookie, :value => "token=#{@token}"}])
|
90
|
+
return policies.elements.inject("/reply/contents/policies/policy[policyName='#{policy_name}']/policyID", []) {|r, x| r << x.text}
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def import_policy_file(file)
|
95
|
+
policy_name = Nessus.get_policy_name_from_file(file)
|
96
|
+
policy_ids = get_policy_ids(policy_name)
|
97
|
+
policy_ids.each do|id|
|
98
|
+
delete_policy(id)
|
99
|
+
end
|
100
|
+
uploaded_name = upload_file(file)
|
101
|
+
policies = import_policy(uploaded_name)
|
102
|
+
return policies.elements.inject("/reply/contents/policies/policy[policyName='#{policy_name}']/policyID", []) {|r, x| r << x.text}[0]
|
103
|
+
end
|
104
|
+
|
105
|
+
#Start a new nessus scan
|
106
|
+
#
|
107
|
+
# @param :policy_id The policy id of the policy to use (String)
|
108
|
+
# @param :targets The scan targets (String or Array of String)
|
109
|
+
def start_scan(options)
|
110
|
+
raise "Missing parameter :policy_id" unless options[:policy_id]
|
111
|
+
raise "Missing parameter :targets" unless options[:targets]
|
112
|
+
|
113
|
+
scan_opts = [{:value => "policy_id=#{options[:policy_id]}"},
|
114
|
+
{:type => :cookie, :value => "token=#{@token}"}]
|
115
|
+
|
116
|
+
if options[:targets].class() == String then
|
117
|
+
scan_opts << {:value => "target=#{options[:targets]}"}
|
118
|
+
elsif options[:targets].class() == Array then
|
119
|
+
options[:targets].each do|target|
|
120
|
+
scan_opts << {:value => "target=#{target}"}
|
121
|
+
end
|
122
|
+
else
|
123
|
+
raise "Unknown target type #{options[:targets].class().name()}"
|
124
|
+
end
|
125
|
+
|
126
|
+
scan_reply = execute_command("scan/new", scan_opts)
|
127
|
+
return scan_reply.elements.inject("/reply/contents/scan/uuid", []) {|r, x| r << x.text}[0]
|
128
|
+
end
|
129
|
+
|
130
|
+
def scan_status(uuid)
|
131
|
+
report = list_report(uuid)
|
132
|
+
return "unknown" unless report
|
133
|
+
|
134
|
+
return report["status"]
|
135
|
+
end
|
136
|
+
|
137
|
+
def list_reports()
|
138
|
+
reply = execute_command("report/list", [{:type => :cookie, :value => "token=#{@token}"}])
|
139
|
+
|
140
|
+
results = []
|
141
|
+
reply.elements.each("/reply/contents/reports/report") do|elem|
|
142
|
+
result = {}
|
143
|
+
elem.elements.each do|subelem|
|
144
|
+
result[subelem.name] = subelem.text
|
145
|
+
end
|
146
|
+
results << result
|
147
|
+
end
|
148
|
+
|
149
|
+
return results
|
150
|
+
end
|
151
|
+
|
152
|
+
def list_report(uuid)
|
153
|
+
reports = list_reports()
|
154
|
+
|
155
|
+
report = reports.reject {|rep| rep["name"] != uuid}
|
156
|
+
|
157
|
+
return nil if report.length != 1
|
158
|
+
|
159
|
+
return report[0]
|
160
|
+
end
|
161
|
+
|
162
|
+
def save_report(uuid, file)
|
163
|
+
report = execute_command("file/report/download",
|
164
|
+
[{:value => "report=#{uuid}"},
|
165
|
+
{:type => :cookie, :value => "token=#{@token}"}],
|
166
|
+
false)
|
167
|
+
if report.elements.inject("/NessusClientData_v2", []) {|r, x| r << x}.empty? then
|
168
|
+
raise "error during save_report"
|
169
|
+
end
|
170
|
+
|
171
|
+
File.open(file, 'w') {|file| file << report.to_s}
|
172
|
+
end
|
173
|
+
|
174
|
+
def delete_report(uuid)
|
175
|
+
report = execute_command("report/delete",
|
176
|
+
[{:value => "report=#{uuid}"},
|
177
|
+
{:type => :cookie, :value => "token=#{@token}"}])
|
178
|
+
end
|
179
|
+
|
180
|
+
# Scan targets completely and return when scan is finished
|
181
|
+
#
|
182
|
+
# Note: Only one of :policy_id, :policy_name or :policy_file needs to be specified.
|
183
|
+
# @param :targets Hosts to scan (String or Array of String)
|
184
|
+
# @param :report_file Path to report file (String)
|
185
|
+
# @param :policy_id Policy ID of policy to use (String)
|
186
|
+
# @param :policy_name Name of policy to use (String)
|
187
|
+
# @param :policy_file Path to policy file to import and use (String)
|
188
|
+
# @param :delete_policy (optional) Delete policy when scan is finished (Boolean)
|
189
|
+
# @param :delete_report (optional) Delete report when scan is finished (Boolean)
|
190
|
+
def scan_targets(options)
|
191
|
+
raise "Need parameter :targets" unless options[:targets]
|
192
|
+
raise "Need parameter :report_file" unless options[:report_file]
|
193
|
+
|
194
|
+
policy_id = ""
|
195
|
+
|
196
|
+
if options[:policy_id] then
|
197
|
+
policy_id = options[:policy_id]
|
198
|
+
elsif options[:policy_name] then
|
199
|
+
policy_ids = get_policy_ids(policy_name)
|
200
|
+
|
201
|
+
raise "No policy with this name (#{policy_name}) found" if policy_ids.empty?
|
202
|
+
raise "Several policies with this name (#{policy_name}) found" if policy_ids.length > 1
|
203
|
+
policy_id = policy_ids[0]
|
204
|
+
elsif options[:policy_file] then
|
205
|
+
policy_id = import_policy_file(options[:policy_file])
|
206
|
+
else
|
207
|
+
raise "Need parameter :policy_file, :policy_name or :policy_id"
|
208
|
+
end
|
209
|
+
|
210
|
+
scan_uuid = start_scan(:policy_id => policy_id, :targets => options[:targets])
|
211
|
+
while scan_status(scan_uuid) != "completed" do
|
212
|
+
sleep 30
|
213
|
+
end
|
214
|
+
save_report(scan_uuid, options[:report_file])
|
215
|
+
delete_policy(policy_id) if options[:delete_policy]
|
216
|
+
delete_report(scan_uuid) if options[:delete_report]
|
217
|
+
|
218
|
+
return scan_uuid
|
219
|
+
end
|
220
|
+
|
221
|
+
def logout()
|
222
|
+
execute_command("logout",
|
223
|
+
[{:type => :cookie, :value => "token=#{@token}"}])
|
224
|
+
@token = nil
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.get_policy_name_from_file(file)
|
228
|
+
return (Document.new(File.new(file)).elements.inject("NessusClientData_v2/Policy/policyName", []) {|r, x| r << x.text})[0]
|
229
|
+
end
|
230
|
+
|
231
|
+
# Allowed values for configuration keys are:
|
232
|
+
#
|
233
|
+
# "policy_name": "some_name"
|
234
|
+
# "policy_shared": "0" if the policy is not shared, or "1" if it is shared
|
235
|
+
# "SSH settings[entry]:SSH user name :": "root"
|
236
|
+
# "SSH settings[file]:SSH private key to use :": {:type => :file, :file => "/tmp/key.pem"}
|
237
|
+
# "plugin_selection.family.Service detection": "enabled", "disabled", "mixed"
|
238
|
+
# "plugin_selection.individual_plugin.19679": "enabled", "disabled"
|
239
|
+
# "SSH settings[radio]:Elevate privileges with :": "Nothing", "sudo", "su", ...
|
240
|
+
def new_policy(options)
|
241
|
+
raise "missing option \"policy_name\"" unless options["policy_name"]
|
242
|
+
raise "missing option \"policy_shared\"" unless options["policy_shared"]
|
243
|
+
|
244
|
+
cmd_params = [{:type => :cookie, :value => "token=#{@token}"}]
|
245
|
+
|
246
|
+
options.each do|key,value|
|
247
|
+
if value.class() == String then
|
248
|
+
cmd_params << {:value => "#{key}=#{value}"}
|
249
|
+
elsif value.class() == Hash then
|
250
|
+
if value[:type] == :file then
|
251
|
+
filename = upload_file(value[:file])
|
252
|
+
cmd_params << {:value => "#{key}=#{filename}"}
|
253
|
+
else
|
254
|
+
raise "Unknown value hash type '#{value[:type]}' for policy configuration key '#{key}'"
|
255
|
+
end
|
256
|
+
else
|
257
|
+
raise "Unknown value type '#{value.class()} for policy configuration key '#{key}'"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
reply = execute_command("policy/add", cmd_params)
|
262
|
+
policy_ids = reply.elements.inject("/reply/contents/policy/policyID", []) {|r, x| r << x.text}
|
263
|
+
|
264
|
+
raise "Policy '#{options["policy_name"]}' already exists or was not imported (#{policy_ids.length()})" unless policy_ids.length() == 1
|
265
|
+
|
266
|
+
return policy_ids[0]
|
267
|
+
end
|
268
|
+
|
269
|
+
def list_plugin_families()
|
270
|
+
reply = execute_command("plugins/list",
|
271
|
+
[{:type => :cookie, :value => "token=#{@token}"}])
|
272
|
+
return reply.elements.inject("/reply/contents/pluginFamilyList/family/familyName", []) {|r, x| r << x.text}
|
273
|
+
end
|
274
|
+
|
275
|
+
def list_plugin_family(family_name)
|
276
|
+
reply = execute_command("plugins/list/family",
|
277
|
+
[{:type => :cookie, :value => "token=#{@token}"},
|
278
|
+
{:value => "family=#{family_name}"}])
|
279
|
+
results = []
|
280
|
+
|
281
|
+
reply.elements.each("/reply/contents/pluginList/plugin") do|elem|
|
282
|
+
result = {}
|
283
|
+
elem.elements.each do|subelem|
|
284
|
+
result[subelem.name] = subelem.text
|
285
|
+
end
|
286
|
+
results << result
|
287
|
+
end
|
288
|
+
return results
|
289
|
+
end
|
290
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'nessus-xmlrpc'
|
2
|
+
|
3
|
+
module NessusXMLRPC
|
4
|
+
class NessusXMLRPCrexml
|
5
|
+
def file_upload(file)
|
6
|
+
cmd = "curl --max-time 120 --silent --insecure --cookie \"token=#{@token}\" --form \"Filedata=@#{file}\" #{@nurl}file/upload"
|
7
|
+
print "Executing Nessus command: '#{cmd}'\n"
|
8
|
+
body = `#{cmd}`
|
9
|
+
|
10
|
+
docxml = REXML::Document.new(body)
|
11
|
+
begin
|
12
|
+
status = docxml.root.elements['status'].text
|
13
|
+
filename = docxml.root.elements['contents'].elements['fileUploaded'].text
|
14
|
+
rescue => err
|
15
|
+
print "[e] Error in XML parsing\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
if status == "OK" then
|
19
|
+
return filename
|
20
|
+
else
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def policy_upload(policy_file)
|
26
|
+
filename = file_upload(policy_file)
|
27
|
+
|
28
|
+
if filename then
|
29
|
+
cmd = "curl --max-time 120 --silent --insecure --cookie \"token=#{@token}\" --data \"file=#{filename}\" #{@nurl}file/policy/import"
|
30
|
+
print "Executing Nessus command: '#{cmd}'\n"
|
31
|
+
body = `#{cmd}`
|
32
|
+
|
33
|
+
docxml = REXML::Document.new(body)
|
34
|
+
begin
|
35
|
+
status = docxml.root.elements['status'].text
|
36
|
+
rescue => err
|
37
|
+
print "[e] Error in XML parsing\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
if status == "OK" then
|
41
|
+
return docxml
|
42
|
+
else
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
else
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def policy_delete(policy_id)
|
51
|
+
cmd = "curl --max-time 120 --silent --insecure --cookie \"token=#{@token}\" --data \"policy_id=#{policy_id}\" #{@nurl}policy/delete"
|
52
|
+
print "Executing Nessus command: '#{cmd}'\n"
|
53
|
+
body = `#{cmd}`
|
54
|
+
|
55
|
+
docxml = REXML::Document.new(body)
|
56
|
+
begin
|
57
|
+
status = docxml.root.elements['status'].text
|
58
|
+
rescue => err
|
59
|
+
print "[e] Error in XML parsing\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
if status == "OK" then
|
63
|
+
return true
|
64
|
+
else
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def policy_file_get_policies(policy_file)
|
70
|
+
policy_names = []
|
71
|
+
|
72
|
+
REXML::Document.new(File.read(policy_file)).root.each_element('//Policy') {|p| policy_names << p.elements['policyName'].text}
|
73
|
+
return policy_names
|
74
|
+
end
|
75
|
+
|
76
|
+
def scan_execute(policy_file, policy_name, scan_name, target)
|
77
|
+
while (policy_id = policy_get_id(policy_name)) != '' do
|
78
|
+
policy_delete(policy_id)
|
79
|
+
end
|
80
|
+
|
81
|
+
policy_upload(policy_file)
|
82
|
+
|
83
|
+
policy_id = policy_get_id(policy_name)
|
84
|
+
|
85
|
+
if policy_id != '' then
|
86
|
+
scan = scan_new(policy_id, scan_name, target)
|
87
|
+
|
88
|
+
while scan_status(scan) == 'running' do
|
89
|
+
sleep(5)
|
90
|
+
end
|
91
|
+
|
92
|
+
report = report_file_download(scan)
|
93
|
+
report_delete(scan)
|
94
|
+
policy_delete(policy_id)
|
95
|
+
return report
|
96
|
+
else
|
97
|
+
return nil
|
98
|
+
# error: policy not found altough just imported
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# The superclass for all response commands from scripts
|
2
|
+
# each subclass must have a constant named COMMAND, which is the string
|
3
|
+
# version of the command as sent by the worker script
|
4
|
+
class AbstractCommand
|
5
|
+
# The check that issued this command.
|
6
|
+
attr_reader :check
|
7
|
+
# The severity of this command.
|
8
|
+
attr_reader :severity
|
9
|
+
# The message associated with this command.
|
10
|
+
attr_reader :message
|
11
|
+
|
12
|
+
# Create a new AbstractCommand.
|
13
|
+
# Should only be called from subclasses, as this class is abstract,
|
14
|
+
# * <em>check</em>
|
15
|
+
# * <em>severity</em>
|
16
|
+
# * <em>message</em>
|
17
|
+
def initialize(check, severity, message)
|
18
|
+
@check = check
|
19
|
+
@severity = severity
|
20
|
+
@message = message
|
21
|
+
end
|
22
|
+
|
23
|
+
# Abstract method to be implemented by subclasses.
|
24
|
+
# Perform any action neccessary to obtain results, like copying a file to the local host.
|
25
|
+
def process(parser)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Abstract method to be implemented by subclasses.
|
29
|
+
# return a result object, contained in an instance of kind AbstractCommandResult
|
30
|
+
def result()
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# To change this template, choose Tools | Templates
|
2
|
+
# and open the template in the editor.
|
3
|
+
class AbstractCommandResult
|
4
|
+
attr_reader :check
|
5
|
+
attr_reader :severity
|
6
|
+
attr_reader :message
|
7
|
+
attr_reader :type
|
8
|
+
|
9
|
+
def initialize(check, severity, message, type)
|
10
|
+
@check = check
|
11
|
+
@severity = severity
|
12
|
+
@message = message
|
13
|
+
@type = type
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_string()
|
17
|
+
return @message
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash()
|
21
|
+
return {:rule => @check.id,
|
22
|
+
:severity => @severity,
|
23
|
+
:message => @message,
|
24
|
+
:type => @type}
|
25
|
+
end
|
26
|
+
|
27
|
+
def visible?
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
end
|