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,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
|