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 +4 -4
- data/README.md +3 -3
- data/lib/pwn/plugins/irc.rb +71 -2
- data/lib/pwn/plugins.rb +0 -1
- data/lib/pwn/version.rb +1 -1
- metadata +2 -4
- data/lib/pwn/plugins/ibm_appscan.rb +0 -934
- data/spec/lib/pwn/plugins/ibm_appscan_spec.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bedf6cda56027f5e6eddf96da4d189e88661216e06686506132bb75c9e2fa50
|
4
|
+
data.tar.gz: 8f2aeb827cb5c86fb77e89f8000cae7d45f22a13e6731a09bd0d1a51b3525d5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
40
|
+
pwn[v0.5.137]:001 >>> PWN.help
|
41
41
|
```
|
42
42
|
|
43
43
|
[](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.
|
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.
|
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:
|
data/lib/pwn/plugins/irc.rb
CHANGED
@@ -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
|
-
|
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
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.
|
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-
|
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
|