pwn 0.5.136 → 0.5.137

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ee45281ba2404409843a5305870cd35223a38eb349262c62fdeca8d5c6a54c2
4
- data.tar.gz: b4942a1b315b213da29c5d6645f00809f7aef25257bdba1c265a0f6bb191d181
3
+ metadata.gz: 0bedf6cda56027f5e6eddf96da4d189e88661216e06686506132bb75c9e2fa50
4
+ data.tar.gz: 8f2aeb827cb5c86fb77e89f8000cae7d45f22a13e6731a09bd0d1a51b3525d5a
5
5
  SHA512:
6
- metadata.gz: d92724874d4a07779bd7a51b05ffd0d12dcc8d9521d4a471507646d4cbe438dc1d3919f38186f3e5493deeec7b55f028353aee3b8c2782d2921dc8cc19efdb85
7
- data.tar.gz: 3ac5b4e6f7d492645bda680d2d36d4bc84f046d902327cda20d7fb02bb3230c332a8b9001337c0792eb04455f08b02363c79d79ae39f3869191ec43114f51390
6
+ metadata.gz: e3dbf22bfcb9aae550741c161f3184be90226269aba826165156db38cb3e00f5217fee71bed7d5e47161a1c8f2c1ff1aff48135b88cf8ddb66653942db93bea0
7
+ data.tar.gz: d0d008faac027711f9acc293b00aba1563e0543733964f0fd8d857636abc29f14c12593ad52ccb2cc3d865455504d1f11dcb892e146c68db2dae6f76b2599274
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.136]:001 >>> PWN.help
40
+ pwn[v0.5.137]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
@@ -52,7 +52,7 @@ $ rvm use ruby-3.3.1@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.136]:001 >>> PWN.help
55
+ pwn[v0.5.137]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.3.1@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.136]:001 >>> PWN.help
65
+ pwn[v0.5.137]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
@@ -40,6 +40,25 @@ module PWN
40
40
  irc_obj.gets
41
41
  irc_obj.flush
42
42
 
43
+ join(irc_obj: irc_obj, chan: chan)
44
+
45
+ irc_obj
46
+ rescue StandardError => e
47
+ irc_obj = disconnect(irc_obj: irc_obj) unless irc_obj.nil?
48
+ raise e
49
+ end
50
+
51
+ # Supported Method Parameters::
52
+ # PWN::Plugins::IRC.join(
53
+ # irc_obj: 'required - irc_obj returned from #connect method',
54
+ # nick: 'required - nickname',
55
+ # chan: 'required - channel to join'
56
+ # )
57
+ public_class_method def self.join(opts = {})
58
+ irc_obj = opts[:irc_obj]
59
+ nick = opts[:nick].to_s.scrub
60
+ chan = opts[:chan].to_s.scrub
61
+
43
62
  send(irc_obj: irc_obj, message: "JOIN #{chan}")
44
63
  irc_obj.gets
45
64
  irc_obj.flush
@@ -47,11 +66,44 @@ module PWN
47
66
  send(irc_obj: irc_obj, message: "PRIVMSG #{chan} :#{nick} joined.")
48
67
  irc_obj.gets
49
68
  irc_obj.flush
69
+ rescue StandardError => e
70
+ raise e
71
+ end
50
72
 
51
- irc_obj
73
+ # Supported Method Parameters::
74
+ # PWN::Plugins::IRC.part(
75
+ # irc_obj: 'required - irc_obj returned from #connect method',
76
+ # chan: 'required - channel to part',
77
+ # message: 'optional - message to send when parting'
78
+ # )
79
+ public_class_method def self.part(opts = {})
80
+ irc_obj = opts[:irc_obj]
81
+ chan = opts[:chan].to_s.scrub
82
+ message = opts[:message].to_s.scrub
83
+
84
+ send(irc_obj: irc_obj, message: "PART #{chan} :#{message}")
85
+ irc_obj.gets
86
+ irc_obj.flush
87
+ rescue StandardError => e
88
+ raise e
89
+ end
90
+
91
+ # Supported Method Parameters::
92
+ # PWN::Plugins::IRC.quit(
93
+ # irc_obj: 'required - irc_obj returned from #connect method',
94
+ # message: 'optional - message to send when quitting'
95
+ # )
96
+ public_class_method def self.quit(opts = {})
97
+ irc_obj = opts[:irc_obj]
98
+ message = opts[:message].to_s.scrub
99
+
100
+ send(irc_obj: irc_obj, message: "QUIT :#{message}")
101
+ irc_obj.gets
102
+ irc_obj.flush
52
103
  rescue StandardError => e
53
- irc_obj = disconnect(irc_obj: irc_obj) unless irc_obj.nil?
54
104
  raise e
105
+ ensure
106
+ disconnect(irc_obj: irc_obj) unless irc_obj.nil?
55
107
  end
56
108
 
57
109
  # Supported Method Parameters::
@@ -125,6 +177,23 @@ module PWN
125
177
  tls: 'optional - boolean connect to host socket using TLS (defaults to false)'
126
178
  )
127
179
 
180
+ #{self}.join(
181
+ irc_obj: 'required - irc_obj returned from #connect method',
182
+ nick: 'required - nickname',
183
+ chan: 'required - channel to join'
184
+ )
185
+
186
+ #{self}.part(
187
+ irc_obj: 'required - irc_obj returned from #connect method',
188
+ chan: 'required - channel to part',
189
+ message: 'optional - message to send when parting'
190
+ )
191
+
192
+ #{self}.quit(
193
+ irc_obj: 'required - irc_obj returned from #connect method',
194
+ message: 'optional - message to send when quitting'
195
+ )
196
+
128
197
  #{self}.listen(
129
198
  irc_obj: 'required - irc_obj returned from #connect method',
130
199
  verbose: 'optional - boolean to enable verbose output (defaults to false)'
data/lib/pwn/plugins.rb CHANGED
@@ -30,7 +30,6 @@ module PWN
30
30
  autoload :Github, 'pwn/plugins/github'
31
31
  autoload :GQRX, 'pwn/plugins/gqrx'
32
32
  autoload :HackerOne, 'pwn/plugins/hacker_one'
33
- autoload :IBMAppscan, 'pwn/plugins/ibm_appscan'
34
33
  autoload :IPInfo, 'pwn/plugins/ip_info'
35
34
  autoload :IRC, 'pwn/plugins/irc'
36
35
  autoload :Jenkins, 'pwn/plugins/jenkins'
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.136'
4
+ VERSION = '0.5.137'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.136
4
+ version: 0.5.137
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-23 00:00:00.000000000 Z
11
+ date: 2024-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -1803,7 +1803,6 @@ files:
1803
1803
  - lib/pwn/plugins/github.rb
1804
1804
  - lib/pwn/plugins/gqrx.rb
1805
1805
  - lib/pwn/plugins/hacker_one.rb
1806
- - lib/pwn/plugins/ibm_appscan.rb
1807
1806
  - lib/pwn/plugins/ip_info.rb
1808
1807
  - lib/pwn/plugins/irc.rb
1809
1808
  - lib/pwn/plugins/jenkins.rb
@@ -2135,7 +2134,6 @@ files:
2135
2134
  - spec/lib/pwn/plugins/github_spec.rb
2136
2135
  - spec/lib/pwn/plugins/gqrx_spec.rb
2137
2136
  - spec/lib/pwn/plugins/hacker_one_spec.rb
2138
- - spec/lib/pwn/plugins/ibm_appscan_spec.rb
2139
2137
  - spec/lib/pwn/plugins/ip_info_spec.rb
2140
2138
  - spec/lib/pwn/plugins/irc_spec.rb
2141
2139
  - spec/lib/pwn/plugins/jenkins_spec.rb
@@ -1,934 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'nokogiri'
4
- require 'wicked_pdf'
5
- require 'fileutils'
6
- require 'uri'
7
-
8
- module PWN
9
- module Plugins
10
- # This plugin is used for interacting w/ IBM Appscan Enterprise using
11
- # the 'rest' browser type of PWN::Plugins::TransparentBrowser.
12
- # The IBM Appscan Spec in which this PWN module is based is located here:
13
- # http://www-01.ibm.com/support/knowledgecenter/SSW2NF_9.0.0/com.ibm.ase.help.doc/topics/c_web_services.html?lang=en
14
- module IBMAppscan
15
- @@logger = PWN::Plugins::PWNLogger.create
16
-
17
- # Supported Method Parameters::
18
- # PWN::Plugins::IBMAppscan.login(
19
- # appscan_ip: 'required host/ip of IBM Appscan Server',
20
- # username: 'required username',
21
- # password: 'optional password (will prompt if nil)'
22
- # )
23
-
24
- public_class_method def self.login(opts = {})
25
- appscan_ip = opts[:appscan_ip]
26
- username = opts[:username].to_s.scrub
27
- base_appscan_api_uri = "https://#{appscan_ip}/ase/services".to_s.scrub
28
-
29
- password = if opts[:password].nil?
30
- PWN::Plugins::AuthenticationHelper.mask_password
31
- else
32
- opts[:password].to_s.scrub
33
- end
34
-
35
- @@logger.info("Logging into IBM Appscan Enterprise Server: #{appscan_ip}")
36
- browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
37
- rest_client = browser_obj[:browser]::Request
38
-
39
- response = rest_client.execute(
40
- method: :post,
41
- url: "#{base_appscan_api_uri}/login",
42
- payload: "userid=#{username}&password=#{password}",
43
- verify_ssl: false
44
- )
45
-
46
- # Return array containing the Appscan Server host/ip & post-authenticated Appscan REST cookie
47
- appscan_ip = URI.parse(response.args[:url]).host
48
- appscan_cookie = "asc_session_id=#{response.cookies['asc_session_id']}; ASP.NET_SessionId=#{response.cookies['ASP.NET_SessionId']}"
49
- appscan_obj = {}
50
- appscan_obj[:appscan_ip] = appscan_ip
51
- appscan_obj[:cookie] = appscan_cookie
52
- appscan_obj[:raw_response] = response
53
- appscan_obj[:xml_response] = Nokogiri::XML(response)
54
- appscan_obj[:build] = appscan_obj[:xml_response].xpath(
55
- '/xmlns:version/xmlns:build'
56
- ).text
57
- appscan_obj[:dbversion] = appscan_obj[:xml_response].xpath(
58
- '/xmlns:version/xmlns:dbversion'
59
- ).text
60
- appscan_obj[:rules_version] = appscan_obj[:xml_response].xpath(
61
- '/xmlns:version/xmlns:rules-version'
62
- ).text
63
- appscan_obj[:username] = appscan_obj[:xml_response].xpath(
64
- '/xmlns:version/xmlns:user-name'
65
- ).text
66
- appscan_obj[:password] = Base64.strict_encode64(password)
67
- appscan_obj[:logged_in] = true
68
-
69
- appscan_obj
70
- rescue StandardError => e
71
- raise e
72
- end
73
-
74
- # Supported Method Parameters::
75
- # appscan_rest_call(
76
- # appscan_obj: 'required appscan_obj returned from login method',
77
- # http_method: 'optional HTTP method (defaults to GET)
78
- # rest_call: 'required rest call to make per the schema',
79
- # http_body: 'optional HTTP body sent in HTTP methods that support it e.g. POST'
80
- # )
81
-
82
- private_class_method def self.appscan_rest_call(opts = {})
83
- appscan_obj = opts[:appscan_obj]
84
- http_method = if opts[:http_method].nil?
85
- :get
86
- else
87
- opts[:http_method].to_s.scrub.to_sym
88
- end
89
- rest_call = opts[:rest_call].to_s.scrub
90
- http_body = opts[:http_body].to_s.scrub
91
- appscan_ip = appscan_obj[:appscan_ip].to_s.scrub
92
- appscan_cookie = appscan_obj[:cookie]
93
- base_appscan_api_uri = "https://#{appscan_ip}/ase/services".to_s.scrub
94
- retry_count = 3
95
-
96
- browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
97
- rest_client = browser_obj[:browser]::Request
98
-
99
- case http_method
100
- when :get
101
- response = rest_client.execute(
102
- method: :get,
103
- url: "#{base_appscan_api_uri}/#{rest_call}",
104
- headers: { cookie: appscan_cookie },
105
- verify_ssl: false
106
- )
107
-
108
- when :post
109
- response = rest_client.execute(
110
- method: :post,
111
- url: "#{base_appscan_api_uri}/#{rest_call}",
112
- headers: { cookie: appscan_cookie },
113
- payload: http_body,
114
- verify_ssl: false
115
- )
116
-
117
- else
118
- return @@logger.error("Unsupported HTTP Method #{http_method} for #{self} Plugin")
119
- end
120
- response
121
- rescue StandardError => e
122
- if (e.message == '401 Unauthorized') && retry_count.positive? && appscan_obj[:logged_in]
123
- # Try logging back in to refresh the connection
124
- @@logger.warn("Got Response: #{e}...Attempting to Re-Authenticate; Retries left #{retry_count}")
125
- n_appscan_obj = login(
126
- appscan_ip: appscan_obj[:appscan_ip],
127
- username: appscan_obj[:username],
128
- password: Base64.decode64(appscan_obj[:password])
129
- )
130
- appscan_cookie = n_appscan_obj[:cookie]
131
- # "copy" the new app obj over the old app obj
132
- appscan_obj.each_key do |k|
133
- appscan_obj[k] = n_appscan_obj[k]
134
- end
135
- retry_count -= 1
136
- retry
137
- end
138
- raise e
139
- end
140
-
141
- # Supported Method Parameters::
142
- # PWN::Plugins::IBMAppscan.schema(
143
- # appscan_obj: 'required appscan_obj returned from login method'
144
- # )
145
-
146
- public_class_method def self.schema(opts = {})
147
- appscan_obj = opts[:appscan_obj]
148
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'schema')
149
- schema = {}
150
- schema[:raw_response] = response
151
- schema[:xml_response] = Nokogiri::XML(response)
152
- schema
153
- rescue StandardError => e
154
- raise e
155
- end
156
-
157
- # Supported Method Parameters::
158
- # PWN::Plugins::IBMAppscan.version(
159
- # appscan_obj: 'required appscan_obj returned from login method'
160
- # )
161
-
162
- public_class_method def self.version(opts = {})
163
- appscan_obj = opts[:appscan_obj]
164
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'version')
165
- version = {}
166
- version[:raw_response] = response
167
- version[:xml_response] = Nokogiri::XML(response)
168
- version[:build] = version[:xml_response].xpath(
169
- '/xmlns:version/xmlns:build'
170
- ).text
171
- version[:dbversion] = version[:xml_response].xpath(
172
- '/xmlns:version/xmlns:dbversion'
173
- ).text
174
- version[:rules_version] = version[:xml_response].xpath(
175
- '/xmlns:version/xmlns:rules-version'
176
- ).text
177
- version[:username] = version[:xml_response].xpath(
178
- '/xmlns:version/xmlns:user-name'
179
- ).text
180
- version
181
- rescue StandardError => e
182
- raise e
183
- end
184
-
185
- # Supported Method Parameters::
186
- # PWN::Plugins::IBMAppscan.get_folders(
187
- # appscan_obj: 'required appscan_obj returned from login method'
188
- # )
189
-
190
- public_class_method def self.get_folders(opts = {})
191
- appscan_obj = opts[:appscan_obj]
192
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'folders')
193
- folders = {}
194
- folders[:raw_response] = response
195
- folders[:xml_response] = Nokogiri::XML(response)
196
- folders
197
- rescue StandardError => e
198
- raise e
199
- end
200
-
201
- # Supported Method Parameters::
202
- # PWN::Plugins::IBMAppscan.get_subfolders_of_folder(
203
- # appscan_obj: 'required appscan_obj returned from login method',
204
- # folder_id: 'required folder to retrieve'
205
- # )
206
-
207
- public_class_method def self.get_subfolders_of_folder(opts = {})
208
- appscan_obj = opts[:appscan_obj]
209
- folder_id = opts[:folder_id].to_i
210
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folders/#{folder_id}/folders")
211
- subfolders = {}
212
- subfolders[:raw_response] = response
213
- subfolders[:xml_response] = Nokogiri::XML(response)
214
- subfolders
215
- rescue StandardError => e
216
- raise e
217
- end
218
-
219
- # Supported Method Parameters::
220
- # PWN::Plugins::IBMAppscan.get_folder_by_id(
221
- # appscan_obj: 'required appscan_obj returned from login method',
222
- # folder_id: 'required folder to retrieve'
223
- # )
224
-
225
- public_class_method def self.get_folder_by_id(opts = {})
226
- appscan_obj = opts[:appscan_obj]
227
- folder_id = opts[:folder_id].to_i
228
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folders/#{folder_id}")
229
- folder = {}
230
- folder[:raw_response] = response
231
- folder[:xml_response] = Nokogiri::XML(response)
232
- folder
233
- rescue StandardError => e
234
- raise e
235
- end
236
-
237
- # Supported Method Parameters::
238
- # PWN::Plugins::IBMAppscan.get_folder_items(
239
- # appscan_obj: 'required appscan_obj returned from login method'
240
- # )
241
-
242
- public_class_method def self.get_folder_items(opts = {})
243
- appscan_obj = opts[:appscan_obj]
244
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'folderitems')
245
- folder_items = {}
246
- folder_items[:raw_response] = response
247
- folder_items[:xml_response] = Nokogiri::XML(response)
248
- folder_items
249
- rescue StandardError => e
250
- raise e
251
- end
252
-
253
- # Supported Method Parameters::
254
- # PWN::Plugins::IBMAppscan.get_folder_item_by_id(
255
- # appscan_obj: 'required appscan_obj returned from login method',
256
- # folder_item_id: 'required folder item to retrieve'
257
- # )
258
-
259
- public_class_method def self.get_folder_item_by_id(opts = {})
260
- appscan_obj = opts[:appscan_obj]
261
- folder_item_id = opts[:folder_item_id].to_i
262
- retry_count = 3
263
-
264
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folderitems/#{folder_item_id}")
265
- folder_item = {}
266
- folder_item[:raw_response] = response
267
- folder_item[:xml_response] = Nokogiri::XML(response)
268
- # Get Current Status of a Scan
269
- # Available states:
270
- # READY = 1;
271
- # STARTING = 2;
272
- # RUNNING = 3;
273
- # RESUMING = 6;
274
- # CANCELING = 7;
275
- # SUSPENDING = 8;
276
- # SUSPENDED = 9;
277
- # POSTPROCESSING = 10;
278
- # ENDING = 12;
279
- folder_item[:state] = folder_item[:xml_response].xpath('//xmlns:state/xmlns:name').text
280
- folder_item
281
- rescue StandardError => e
282
- @@logger.error("Error: #{e} | #{e.class}\nResponse Returned: #{folder_item[:raw_response]}")
283
- end
284
-
285
- # Supported Method Parameters::
286
- # PWN::Plugins::IBMAppscan.get_a_folders_folder_items(
287
- # appscan_obj: 'required appscan_obj returned from login method',
288
- # folder_id: 'required folder to retrieve'
289
- # )
290
-
291
- public_class_method def self.get_a_folders_folder_items(opts = {})
292
- appscan_obj = opts[:appscan_obj]
293
- folder_id = opts[:folder_item_id].to_i
294
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folders/#{folder_id}/folderitems")
295
- a_folders_folder_items = {}
296
- a_folders_folder_items[:raw_response] = response
297
- a_folders_folder_items[:xml_response] = Nokogiri::XML(response)
298
- a_folders_folder_items
299
- rescue StandardError => e
300
- raise e
301
- end
302
-
303
- # Supported Method Parameters::
304
- # PWN::Plugins::IBMAppscan.get_folder_item_options(
305
- # appscan_obj: 'required appscan_obj returned from login method',
306
- # folder_item_id: 'required folder item to retrieve'
307
- # )
308
-
309
- public_class_method def self.get_folder_item_options(opts = {})
310
- appscan_obj = opts[:appscan_obj]
311
- folder_item_id = opts[:folder_item_id].to_i
312
- # TODO: Discover why not all options are returned
313
- # (e.g. esCOTAutoFormFillUserNameValue & esCOTAutoFormFillPasswordValue)
314
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folderitems/#{folder_item_id}/options")
315
- folder_item_options = {}
316
- folder_item_options[:raw_response] = response
317
- folder_item_options[:xml_response] = Nokogiri::XML(response)
318
- folder_item_options[:options] = folder_item_options[:xml_response].xpath(
319
- '//xmlns:available-option/@href'
320
- )
321
- folder_item_options
322
- rescue StandardError => e
323
- raise e
324
- end
325
-
326
- # Supported Method Parameters::
327
- # PWN::Plugins::IBMAppscan.get_scan_templates(
328
- # appscan_obj: 'required appscan_obj returned from login method'
329
- # )
330
-
331
- public_class_method def self.get_scan_templates(opts = {})
332
- appscan_obj = opts[:appscan_obj]
333
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'templates')
334
- templates = {}
335
- templates[:raw_response] = response
336
- templates[:xml_response] = Nokogiri::XML(response)
337
- templates
338
- rescue StandardError => e
339
- raise e
340
- end
341
-
342
- # Supported Method Parameters::
343
- # PWN::Plugins::IBMAppscan.create_scan_based_on_template(
344
- # appscan_obj: 'required appscan_obj returned from login method'
345
- # template_id: 'required template id returned from get_scan_templates method'
346
- # scan_name: 'required name of scan'
347
- # scan_desc: 'required description of scan'
348
- # )
349
-
350
- public_class_method def self.create_scan_based_on_template(opts = {})
351
- appscan_obj = opts[:appscan_obj]
352
- template_id = opts[:template_id].to_i
353
- scan_name = opts[:scan_name].to_s.scrub
354
- scan_desc = opts[:scan_desc].to_s.scrub
355
- response = appscan_rest_call(
356
- appscan_obj: appscan_obj,
357
- http_method: :post,
358
- rest_call: "folderitems?templateId=#{template_id}",
359
- http_body: "name=#{scan_name}&description=#{scan_desc}"
360
- )
361
-
362
- # Return an Easy to Use Data Structure
363
- # Instead of Leaving it to the End User
364
- # To Parse Out the XML on their own.
365
- scan = {}
366
- scan[:raw_response] = response
367
- scan[:xml_response] = Nokogiri::XML(response)
368
- scan[:folder_url] = scan[:xml_response].xpath(
369
- '/xmlns:folder-items/xmlns:content-scan-job/@href'
370
- ).text
371
- scan[:folder_item_id] = scan[:xml_response].xpath(
372
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:id'
373
- ).text
374
- scan[:scan_name] = scan[:xml_response].xpath(
375
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:name'
376
- ).text
377
- scan[:scan_desc] = scan[:xml_response].xpath(
378
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:description'
379
- ).text
380
- scan[:parent_folder_url] = scan[:xml_response].xpath(
381
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:parent/@href'
382
- ).text
383
- scan[:parent_folder_id] = scan[:xml_response].xpath(
384
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:parent/xmlns:id'
385
- ).text
386
- scan[:contact] = scan[:xml_response].xpath(
387
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:contact'
388
- ).text
389
- scan[:state_id] = scan[:xml_response].xpath(
390
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:state/xmlns:id'
391
- ).text
392
- scan[:state_name] = scan[:xml_response].xpath(
393
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:state/xmlns:name'
394
- ).text
395
- scan[:action_id] = scan[:xml_response].xpath(
396
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:action/xmlns:id'
397
- ).text
398
- scan[:action_name] = scan[:xml_response].xpath(
399
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:action/xmlns:name'
400
- ).text
401
- scan[:options_url] = scan[:xml_response].xpath(
402
- '/xmlns:folder-items/xmlns:content-scan-job/xmlns:options/@href'
403
- ).text
404
- scan[:report_pack_url] = scan[:xml_response].xpath(
405
- '/xmlns:folder-items/xmlns:report-pack/@href'
406
- ).text
407
- scan[:report_pack_id] = scan[:xml_response].xpath(
408
- '/xmlns:folder-items/xmlns:report-pack/xmlns:id'
409
- ).text
410
- scan[:reports_url] = scan[:xml_response].xpath(
411
- '/xmlns:folder-items/xmlns:report-pack/xmlns:reports/@href'
412
- ).text
413
- scan[:reports_count] = scan[:xml_response].xpath(
414
- '/xmlns:folder-items/xmlns:report-pack/xmlns:reports/xmlns:count'
415
- ).text.to_i
416
-
417
- scan
418
- rescue StandardError => e
419
- @@logger.error("Error #{e}:\nREST response returned:\n#{response}")
420
- end
421
-
422
- # Supported Method Parameters::
423
- # PWN::Plugins::IBMAppscan.configure_scan_options(
424
- # appscan_obj: 'required appscan_obj returned from login method',
425
- # folder_item_id: 'required folder item id',
426
- # option: 'required option to change within the scan (folder item)',
427
- # value: 'required option value(s)'
428
- # )
429
-
430
- public_class_method def self.configure_scan_options(opts = {})
431
- appscan_obj = opts[:appscan_obj]
432
- folder_item_id = opts[:folder_item_id].to_i
433
- option = opts[:option].to_s.scrub
434
- value = opts[:value]
435
-
436
- case option.to_sym
437
- when :epcsCOTListOfStartingUrls
438
- post_body = ''
439
- value.to_s.scrub.split(',').each_with_index do |url, index|
440
- post_body << '&' unless index.zero?
441
- post_body << "value=#{URI.encode_www_form(url.strip.chomp)}"
442
- end
443
- when :ebCOTHttpAuthentication
444
- post_body = if value == false
445
- 'value=0' # Don't require authentication
446
- else
447
- 'value=1' # Require authentication
448
- end
449
- when :esCOTHttpUser, :esCOTHttpPassword, :elCOTScanLimit
450
- post_body = "value=#{value.to_s.scrub}"
451
- when :help
452
- available_options = ''
453
- get_folder_item_options(
454
- appscan_obj: appscan_obj,
455
- folder_item_id: folder_item_id
456
- )[:options].each { |url| available_options << "#{File.basename(url)}\n" }
457
-
458
- return @@logger.info("Valid Options are:\n\n#{available_options}")
459
- else
460
- available_options = ''
461
- get_folder_item_options(
462
- appscan_obj: appscan_obj,
463
- folder_item_id: folder_item_id
464
- )[:options].each { |url| available_options << "#{File.basename(url)}\n" }
465
-
466
- return @@logger.error("Invalid option '#{option}' parameter passed.\nValid Options are:\n\n#{available_options}")
467
- end
468
-
469
- # Always Overwrite Existing Option Values
470
- response = appscan_rest_call(
471
- appscan_obj: appscan_obj,
472
- http_method: :post,
473
- rest_call: "folderitems/#{folder_item_id}/options/#{option}?put=1",
474
- http_body: post_body.to_s
475
- )
476
-
477
- scan_config = {}
478
- scan_config[:raw_response] = response
479
- scan_config[:xml_response] = Nokogiri::XML(response)
480
- scan_config[:options] = scan_config[:xml_response].xpath('//xmlns:option/@value')
481
-
482
- scan_config
483
- rescue StandardError => e
484
- raise e
485
- end
486
-
487
- # Supported Method Parameters::
488
- # PWN::Plugins::IBMAppscan.folder_item_scan_action(
489
- # appscan_obj: 'required appscan_obj returned from login method',
490
- # folder_item_id: 'required folder item id',
491
- # action: 'required action for scan to follow. Available actions are: :run, :suspend, :cancel, & :end',
492
- # poll_interval: 'optional setting to determine length in seconds to poll for scan state (defaults to 60)'
493
- # )
494
-
495
- public_class_method def self.folder_item_scan_action(opts = {})
496
- appscan_obj = opts[:appscan_obj]
497
- folder_item_id = opts[:folder_item_id].to_i
498
- action = opts[:action].to_s.scrub.to_sym
499
- poll_interval = if opts[:poll_interval].nil?
500
- 60
501
- else
502
- opts[:poll_interval].to_i
503
- end
504
-
505
- case action
506
- when :run
507
- # Make sure scan is in a Ready state
508
- this_folder_item = PWN::Plugins::IBMAppscan.get_folder_item_by_id(
509
- appscan_obj: appscan_obj,
510
- folder_item_id: folder_item_id
511
- )
512
- state = this_folder_item[:state]
513
- return @@logger.error("Scan isn't in a Ready state. Current state: #{state}, abort.") if state != 'Ready'
514
-
515
- @@logger.info("Kicking Off Scan for Folder Item: #{folder_item_id}")
516
- response = appscan_rest_call(
517
- appscan_obj: appscan_obj,
518
- http_method: :post,
519
- rest_call: "folderitems/#{folder_item_id}",
520
- http_body: 'action=2'
521
- )
522
- # Obtain Status to Monitor Scan Completion
523
- state = nil
524
- until state == 'Ready'
525
- sleep poll_interval
526
- this_folder_item = PWN::Plugins::IBMAppscan.get_folder_item_by_id(
527
- appscan_obj: appscan_obj,
528
- folder_item_id: folder_item_id
529
- )
530
- state = this_folder_item[:state]
531
- @@logger.info("Current Scan State: #{state}...")
532
- end
533
- @@logger.info("Scan Completed @ #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}")
534
- when :suspend
535
- response = appscan_rest_call(
536
- appscan_obj: appscan_obj,
537
- http_method: :post,
538
- rest_call: "folderitems/#{folder_item_id}",
539
- http_body: 'action=3'
540
- )
541
- when :cancel
542
- response = appscan_rest_call(
543
- appscan_obj: appscan_obj,
544
- http_method: :post,
545
- rest_call: "folderitems/#{folder_item_id}",
546
- http_body: 'action=4'
547
- )
548
- when :end
549
- response = appscan_rest_call(
550
- appscan_obj: appscan_obj,
551
- http_method: :post,
552
- rest_call: "folderitems/#{folder_item_id}",
553
- http_body: 'action=5'
554
- )
555
- else
556
- return @@logger.error("Invalid action. Valid actions are:\n:run\n:suspend\n:cancel\n:end\n")
557
- end
558
-
559
- scan_action = {}
560
- scan_action[:raw_response] = response
561
- scan_action[:xml_response] = Nokogiri::XML(response)
562
-
563
- scan_action
564
- rescue StandardError => e
565
- raise e
566
- end
567
-
568
- # Supported Method Parameters::
569
- # PWN::Plugins::IBMAppscan.get_report_collection(
570
- # appscan_obj: 'required appscan_obj returned from login method',
571
- # report_folder_item_id: 'required report folder item id'
572
- # )
573
-
574
- public_class_method def self.get_report_collection(opts = {})
575
- appscan_obj = opts[:appscan_obj]
576
- report_folder_item_id = opts[:report_folder_item_id].to_i
577
-
578
- @@logger.info("Retrieving Report Collection ID: #{report_folder_item_id} - Available Report Pack Collection:")
579
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "folderitems/#{report_folder_item_id}/reports")
580
-
581
- report_collection = {}
582
- report_collection[:raw_response] = response
583
- report_collection[:xml_response] = Nokogiri::XML(response)
584
- # Output full report pack collection
585
- report_collection[:xml_response].xpath('//xmlns:report').each do |r|
586
- @@logger.info(" - #{r.xpath('xmlns:name').text}")
587
- end
588
-
589
- report_collection
590
- rescue StandardError => e
591
- raise e
592
- end
593
-
594
- # Supported Method Parameters::
595
- # PWN::Plugins::IBMAppscan.get_single_report(
596
- # appscan_obj: 'required appscan_obj returned from login method',
597
- # report_id: 'required report id'
598
- # )
599
-
600
- public_class_method def self.get_single_report(opts = {})
601
- appscan_obj = opts[:appscan_obj]
602
- report_id = opts[:report_id].to_i
603
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: "reports/#{report_id}")
604
-
605
- report = {}
606
- report[:raw_response] = response
607
- report[:xml_response] = Nokogiri::XML(response)
608
- @@logger.info("Retrieved Report ID/Name: #{report_id}/#{report[:xml_response].xpath('//xmlns:report/xmlns:name').text}")
609
-
610
- report
611
- rescue StandardError => e
612
- raise e
613
- end
614
-
615
- # Supported Method Parameters::
616
- # PWN::Plugins::IBMAppscan.get_single_report_data(
617
- # appscan_obj: 'required appscan_obj returned from login method',
618
- # report_id: 'required report id'
619
- # )
620
-
621
- public_class_method def self.get_single_report_data(opts = {})
622
- appscan_obj = opts[:appscan_obj]
623
- report_id = opts[:report_id].to_i
624
- response = appscan_rest_call(
625
- appscan_obj: appscan_obj,
626
- rest_call: "reports/#{report_id}/data?mode=all"
627
- )
628
-
629
- report_data = {}
630
- report_data[:raw_response] = response
631
- report_data[:xml_response] = Nokogiri::XML(response)
632
- @@logger.info("Retrieved Report Data for Report ID: #{report_id}")
633
-
634
- report_data
635
- rescue StandardError => e
636
- raise e
637
- end
638
-
639
- # Supported Method Parameters::
640
- # PWN::Plugins::IBMAppscan.get_single_report_schema(
641
- # appscan_obj: 'required appscan_obj returned from login method',
642
- # report_id: 'required report id'
643
- # )
644
-
645
- public_class_method def self.get_single_report_schema(opts = {})
646
- appscan_obj = opts[:appscan_obj]
647
- report_id = opts[:report_id].to_i
648
- response = appscan_rest_call(
649
- appscan_obj: appscan_obj,
650
- rest_call: "reports/#{report_id}/data?metadata=schema"
651
- )
652
-
653
- report_schema = {}
654
- report_schema[:raw_response] = response
655
- report_schema[:xml_response] = Nokogiri::XML(response)
656
- @@logger.info("Retrieved Report Schema for Report ID: #{report_id}")
657
-
658
- report_schema
659
- rescue StandardError => e
660
- raise e
661
- end
662
-
663
- # Supported Method Parameters::
664
- # PWN::Plugins::IBMAppscan.get_issue_collection(
665
- # appscan_obj: 'required appscan_obj returned from login method',
666
- # report_id: 'required report id'
667
- # )
668
-
669
- public_class_method def self.get_issue_collection(opts = {})
670
- appscan_obj = opts[:appscan_obj]
671
- report_id = opts[:report_id].to_i
672
- response = appscan_rest_call(
673
- appscan_obj: appscan_obj,
674
- rest_call: "reports/#{report_id}/issues?mode=all"
675
- )
676
-
677
- issue_collection = {}
678
- issue_collection[:raw_response] = response
679
- issue_collection[:xml_response] = Nokogiri::XML(response)
680
- @@logger.info("Retrieved Issue Collection for Report ID: #{report_id}")
681
-
682
- issue_collection
683
- rescue StandardError => e
684
- raise e
685
- end
686
-
687
- # Supported Method Parameters::
688
- # PWN::Plugins::IBMAppscan.get_report_data
689
- # appscan_obj: 'required appscan_obj returned from login method'
690
- # report_link: 'required report link to start report generation
691
- # output_name: 'required name to save generated report'
692
-
693
- private_class_method def self.get_report_data(opts = {})
694
- appscan_obj = opts[:appscan_obj]
695
- report_link = opts[:report_link]
696
- output_name = opts[:output_name]
697
-
698
- # First Get request
699
- uri = URI.parse(report_link)
700
- browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
701
- rb = browser_obj[:browser]
702
-
703
- res = rb.get(report_link, 'Cookie' => appscan_obj[:cookie], :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
704
- location = "https://#{uri.host}#{res.headers['location']}"
705
-
706
- puts "Location: #{location}"
707
- # Generate the report on the server side
708
- res = rb.get(location, 'Cookie' => appscan_obj[:cookie], :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
709
-
710
- # Now get the file
711
- f = File.open(output_name, 'wb')
712
- location['Export'] = 'Stream'
713
- begin
714
- rb.get(location, 'Cookie' => appscan_obj[:cookie], :verify_ssl => OpenSSL::SSL::VERIFY_NONE) do |resp|
715
- resp.read_body do |seg|
716
- f.write(seg)
717
- end
718
- end
719
- ensure
720
- f.close
721
- end
722
- rescue StandardError => e
723
- @@logger.error("Could not get report data: #{e}")
724
- end
725
-
726
- # Supported Method Parameters::
727
- # PWN::Plugins::IBMAppscan.generate_scan_report
728
- # appscan_obj: 'required appscan_obj returned from login method'
729
- # scan_name: 'required name of scan for which to generate a report'
730
- # output_path: 'required path to save generated report'
731
-
732
- public_class_method def self.generate_scan_report(opts = {})
733
- appscan_obj = opts[:appscan_obj]
734
- scan_name = opts[:scan_name]
735
- output_path = opts[:output_path]
736
- appscan_ip = appscan_obj[:appscan_ip].to_s.scrub
737
- login_uri = "https://#{appscan_ip}:9443/ase/pages/Login.jsp"
738
- base_appscan_uri = "https://#{appscan_ip}/ase/FolderExplorer.aspx"
739
- logout_uri = "https://#{appscan_ip}/ase/LogOut.aspx"
740
-
741
- # verify the output path actually exists
742
- return @@logger.error("Output directory does not exist: #{output_path}") unless File.directory?(output_path)
743
-
744
- browser_obj = PWN::Plugins::TransparentBrowser.open(
745
- browser_type: :headless,
746
- proxy: 'http://127.0.0.1:8080'
747
- )
748
- h_browser = browser_obj[:browser]
749
-
750
- # log into the system
751
- h_browser.goto login_uri.to_s.to_s.scrub
752
- h_browser.text_field(name: 'j_username').when_present.set(appscan_obj[:username])
753
- h_browser.text_field(name: 'j_password').when_present.set(Base64.decode64(appscan_obj[:password]))
754
- h_browser.button(name: 'login').when_present.click
755
-
756
- # head over to the reports page and click on the report link
757
- h_browser.goto base_appscan_uri.to_s.to_s.scrub
758
- h_browser.link(:text, 'ASE').when_present.click
759
-
760
- # Search for the report link with a matching name and click it
761
- clicked = false
762
- h_browser.links.each do |link|
763
- next unless (link.text == scan_name.to_s) && link.href =~ /^https:.+XReports.+/
764
-
765
- link.when_present.click
766
- clicked = true
767
- break
768
- end
769
- return @@logger.error("Could not find matching scan name for name #{scan_name}") unless clicked
770
-
771
- output_path = "#{output_path}/#{scan_name.gsub(/[^\w.-]/, '_')}/"
772
- FileUtils.rm_rf output_path if File.directory?(output_path)
773
- FileUtils.mkpath output_path
774
-
775
- # Download the top level report
776
- report_link = "#{h_browser.url}&exportformat=pdf&exportdelivery=download"
777
- output_name = "#{output_path}Top_Level.pdf"
778
- get_report_data(
779
- appscan_obj: appscan_obj,
780
- report_link: report_link,
781
- output_name: output_name
782
- )
783
- rescue StandardError => e
784
- @@logger.error("Error retrieving report for '#{scan_name}': #{e}")
785
- ensure
786
- # make sure we always logout
787
- h_browser.goto logout_uri.to_s.to_s.scrub
788
- h_browser.close
789
- end
790
-
791
- # Supported Method Parameters::
792
- # PWN::Plugins::IBMAppscan.logout(
793
- # appscan_obj: 'required appscan_obj returned from login method'
794
- # )
795
-
796
- public_class_method def self.logout(opts = {})
797
- appscan_obj = opts[:appscan_obj]
798
- @@logger.info('Logging out...')
799
- response = appscan_rest_call(appscan_obj: appscan_obj, rest_call: 'logout')
800
- if response == ''
801
- appscan_obj[:logged_in] = false
802
- 'logout successful'
803
- else
804
- response
805
- end
806
- rescue StandardError => e
807
- raise e
808
- end
809
-
810
- # Author(s):: 0day Inc. <support@0dayinc.com>
811
-
812
- public_class_method def self.authors
813
- "AUTHOR(S):
814
- 0day Inc. <support@0dayinc.com>
815
- "
816
- end
817
-
818
- # Display Usage for this Module
819
-
820
- public_class_method def self.help
821
- puts "USAGE:
822
- appscan_obj = #{self}.login(
823
- appscan_ip: 'required host/ip of Nexpose Console (server)',
824
- username: 'required username',
825
- password: 'optional password (will prompt if nil)'
826
- )
827
-
828
- schema = #{self}.schema(
829
- appscan_obj: 'required appscan_obj returned from login method'
830
- )
831
-
832
- version = #{self}.version(
833
- appscan_obj: 'required appscan_obj returned from login method'
834
- )
835
-
836
- folders = #{self}.get_folders(
837
- appscan_obj: 'required appscan_obj returned from login method'
838
- )
839
-
840
- subfolders = #{self}.get_subfolders_of_folder(
841
- appscan_obj: 'required appscan_obj returned from login method',
842
- folder_id: 'required folder to retrieve'
843
- )
844
-
845
- folder = #{self}.get_folder_by_id(
846
- appscan_obj: 'required appscan_obj returned from login method',
847
- folder_id: 'required folder to retrieve'
848
- )
849
-
850
- folder_items = #{self}.get_folder_items(
851
- appscan_obj: 'required appscan_obj returned from login method'
852
- )
853
-
854
- folder_item = #{self}.get_folder_item_by_id(
855
- appscan_obj: 'required appscan_obj returned from login method',
856
- folder_item_id: 'required folder item to retrieve'
857
- )
858
-
859
- a_folders_folder_items = #{self}.get_a_folders_folder_items(
860
- appscan_obj: 'required appscan_obj returned from login method',
861
- folder_id: 'required folder to retrieve'
862
- )
863
-
864
- folder_item_options = #{self}.get_folder_item_options(
865
- appscan_obj: 'required appscan_obj returned from login method',
866
- folder_item_id: 'required folder item to retrieve'
867
- )
868
-
869
- scan = #{self}.create_scan_based_on_template(
870
- appscan_obj: 'required appscan_obj returned from login method'
871
- template_id: 'required template id returned from get_scan_templates method'
872
- scan_name: 'required name of scan'
873
- scan_desc: 'required description of scan'
874
- )
875
-
876
- templates = #{self}.get_scan_templates(
877
- appscan_obj: 'required appscan_obj returned from login method'
878
- )
879
-
880
- scan_config = #{self}.configure_scan_options(
881
- appscan_obj: 'required appscan_obj returned from login method',
882
- folder_item_id: 'required folder item id',
883
- option: 'required option to change within the scan (folder item). Pass :help for a list of options.',
884
- value: 'required option value(s)'
885
- )
886
-
887
- scan_action = #{self}.folder_item_scan_action(
888
- appscan_obj: 'required appscan_obj returned from login method',
889
- folder_item_id: 'required folder item id',
890
- action: 'required action for scan to follow. Available actions are: :run, :suspend, :cancel, & :end',
891
- poll_interval: 'optional setting to determine length in seconds to poll for scan state (defaults to 60)'
892
- )
893
-
894
- report_collection = #{self}.get_report_collection(
895
- appscan_obj: 'required appscan_obj returned from login method',
896
- report_folder_item_id: 'required report folder item id'
897
- )
898
-
899
- report = #{self}.get_single_report(
900
- appscan_obj: 'required appscan_obj returned from login method',
901
- report_id: 'required report id'
902
- )
903
-
904
- report_data = #{self}.get_single_report_data(
905
- appscan_obj: 'required appscan_obj returned from login method',
906
- report_id: 'required report id'
907
- )
908
-
909
- report_schema = #{self}.get_single_report_schema(
910
- appscan_obj: 'required appscan_obj returned from login method',
911
- report_id: 'required report id'
912
- )
913
-
914
- issue_collection = #{self}.get_issue_collection(
915
- appscan_obj: 'required appscan_obj returned from login method',
916
- report_id: 'required report id'
917
- )
918
-
919
- #{self}.generate_scan_report(
920
- appscan_obj: 'required appscan_obj returned from login',
921
- scan_name: 'required name of scan for which to generate a report',
922
- output_path: 'required path to save generated report'
923
- )
924
-
925
- #{self}.logout(
926
- appscan_obj: 'required appscan_obj returned from login method'
927
- )
928
-
929
- #{self}.authors
930
- "
931
- end
932
- end
933
- end
934
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe PWN::Plugins::IBMAppscan do
6
- it 'should display information for authors' do
7
- authors_response = PWN::Plugins::IBMAppscan
8
- expect(authors_response).to respond_to :authors
9
- end
10
-
11
- it 'should display information for existing help method' do
12
- help_response = PWN::Plugins::IBMAppscan
13
- expect(help_response).to respond_to :help
14
- end
15
- end