pwn 0.5.136 → 0.5.137

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