pwn 0.5.295 → 0.5.297

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: 6566980d42184b4c0ef1c4c8d110baf0e4492b3f059a2cf792f259fcb7139188
4
- data.tar.gz: 993d8b37e6682844c751b999eaabe348592802a84632dd6fcf7eabe7033dd2ba
3
+ metadata.gz: d2a882d84c8a39cad218cec303b531edc9b7a0b8f8318a8d14731a666b898101
4
+ data.tar.gz: a87c7ff03ea231c405454b4e0f98df6d51648cb272a772bf4b518f5e2dbc7a6d
5
5
  SHA512:
6
- metadata.gz: e39119ed85012beac51422fc4bc8608d6922f82863f5a8172162ea429fc076be5e17809c7d787a1fc932f9413ec6efccb204e5a2e7d36f01646137fdbd14e343
7
- data.tar.gz: 19f370fc5a9141fe134e7bdd7cb4b891886ae6b94d92eb16a078d7529391b920263e7e393e5f4072ae155b0bb4ad325c3f80dcd4f77046bfc8a0ff8c8616e0f5
6
+ metadata.gz: 016cd67f87c5889557383311d6ea0d3a73f772c187ed2e8714983a452957d753a4a08b13f5a5c0831c0babf1df80e4ede655163309f6a0ca2298ea75770368d2
7
+ data.tar.gz: a0ab7b93947a1243a4fee67fe413f3de98497c0e1d0a9a9a373e5d7f08623d70cd633c43a14facd94b07b3db4b5e9f85a04304702e049777aa5b7530204b4e26
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.295]:001 >>> PWN.help
40
+ pwn[v0.5.297]: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.4.4@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.295]:001 >>> PWN.help
55
+ pwn[v0.5.297]: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.4.4@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.295]:001 >>> PWN.help
65
+ pwn[v0.5.297]: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:
@@ -22,6 +22,7 @@ module PWN
22
22
  # )
23
23
 
24
24
  private_class_method def self.rest_call(opts = {})
25
+ token = opts[:token]
25
26
  http_method = if opts[:http_method].nil?
26
27
  :get
27
28
  else
@@ -29,49 +30,62 @@ module PWN
29
30
  end
30
31
  rest_call = opts[:rest_call].to_s.scrub
31
32
  params = opts[:params]
33
+ headers = opts[:http_headers] ||= {
34
+ content_type: 'application/json; charset=UTF-8',
35
+ authorization: "Bearer #{token}"
36
+ }
37
+
32
38
  http_body = opts[:http_body]
33
39
  base_api_uri = opts[:base_api_uri]
34
40
 
35
41
  raise 'ERROR: base_api_uri cannot be nil.' if base_api_uri.nil?
36
42
 
37
- token = opts[:token]
38
-
39
43
  browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
40
44
  rest_client = browser_obj[:browser]::Request
41
45
 
42
46
  spinner = TTY::Spinner.new
43
47
  spinner.auto_spin
44
48
 
49
+ max_request_attempts = 3
50
+ tot_request_attempts ||= 1
51
+
45
52
  case http_method
46
53
  when :delete, :get
54
+ headers[:params] = params
47
55
  response = rest_client.execute(
48
56
  method: http_method,
49
57
  url: "#{base_api_uri}/#{rest_call}",
50
- headers: {
51
- content_type: 'application/json; charset=UTF-8',
52
- authorization: "Bearer #{token}",
53
- params: params
54
- },
55
- verify_ssl: false
58
+ headers: headers,
59
+ verify_ssl: false,
60
+ timeout: 180
56
61
  )
57
62
 
58
63
  when :post, :put
64
+ if http_body.is_a?(Hash)
65
+ if http_body.key?(:multipart)
66
+ headers[:content_type] = 'multipart/form-data'
67
+ headers[:x_atlassian_token] = 'no-check'
68
+ else
69
+ http_body = http_body.to_json
70
+ end
71
+ end
72
+
59
73
  response = rest_client.execute(
60
74
  method: http_method,
61
75
  url: "#{base_api_uri}/#{rest_call}",
62
- headers: {
63
- content_type: 'application/json; charset=UTF-8',
64
- authorization: "Bearer #{token}"
65
- },
66
- payload: http_body.to_json,
67
- verify_ssl: false
76
+ headers: headers,
77
+ payload: http_body,
78
+ verify_ssl: false,
79
+ timeout: 180
68
80
  )
69
-
70
81
  else
71
82
  raise @@logger.error("Unsupported HTTP Method #{http_method} for #{self} Plugin")
72
83
  end
73
84
 
74
- JSON.parse(response, symbolize_names: true)
85
+ jira_response = response if response.is_a?(RestClient::Response) && response.code == 204
86
+ jira_response = JSON.parse(response, symbolize_names: true) if response.is_a?(RestClient::Response) && response.code != 204
87
+
88
+ jira_response
75
89
  rescue RestClient::ExceptionWithResponse => e
76
90
  if e.response
77
91
  puts "HTTP BASE URL: #{base_api_uri}"
@@ -80,10 +94,31 @@ module PWN
80
94
  puts "HTTP RESPONSE HEADERS: #{e.response.headers}"
81
95
  puts "HTTP RESPONSE BODY:\n#{e.response.body}\n\n\n"
82
96
  end
97
+
98
+ raise e
99
+ rescue IO::TimeoutError => e
100
+ raise e if tot_request_attempts == max_request_attempts
101
+
102
+ tot_request_attempts += 1
103
+ @@logger.warn("Timeout Error: Retrying request (Attempt #{tot_request_attempts}/#{max_request_attempts})")
104
+ sleep(2)
105
+ retry
106
+ rescue Errno::ECONNREFUSED => e
107
+ raise e if tot_request_attempts == max_request_attempts
108
+
109
+ puts "\nTCP Connection Unavailable."
110
+ puts "Attempt (#{tot_request_attempts} of #{max_request_attempts}) in 60s"
111
+ 60.downto(1) do
112
+ print '.'
113
+ sleep 1
114
+ end
115
+ tot_request_attempts += 1
116
+
117
+ retry
83
118
  rescue StandardError => e
84
119
  raise e
85
120
  ensure
86
- spinner.stop
121
+ spinner.stop unless spinner.nil?
87
122
  end
88
123
 
89
124
  # Supported Method Parameters::
@@ -150,6 +185,7 @@ module PWN
150
185
  # description: 'optional - description of the issue',
151
186
  # epic_name: 'optional - name of the epic',
152
187
  # additional_fields: 'optional - additional fields to set in the issue (e.g. labels, components, custom fields, etc.)'
188
+ # attachments: 'optional - array of attachment paths to upload to the issue (e.g. ["/path/to/file1.txt", "/path/to/file2.png"])'
153
189
  # )
154
190
 
155
191
  public_class_method def self.create_issue(opts = {})
@@ -173,6 +209,9 @@ module PWN
173
209
  additional_fields = opts[:additional_fields] ||= { fields: {} }
174
210
  raise 'ERROR: additional_fields Hash must contain a :fields key that is also a Hash.' unless additional_fields.is_a?(Hash) && additional_fields.key?(:fields) && additional_fields[:fields].is_a?(Hash)
175
211
 
212
+ attachments = opts[:attachments] ||= []
213
+ raise 'ERROR: attachments must be an Array.' unless attachments.is_a?(Array)
214
+
176
215
  all_fields = get_all_fields(base_api_uri: base_api_uri, token: token)
177
216
  epic_name_field_key = all_fields.find { |field| field[:name] == 'Epic Name' }[:id]
178
217
 
@@ -194,13 +233,32 @@ module PWN
194
233
 
195
234
  http_body[:fields].merge!(additional_fields[:fields])
196
235
 
197
- rest_call(
236
+ issue_resp = rest_call(
198
237
  http_method: :post,
199
238
  base_api_uri: base_api_uri,
200
239
  token: token,
201
240
  rest_call: 'issue',
202
241
  http_body: http_body
203
242
  )
243
+
244
+ if attachments.any?
245
+ issue = issue_resp[:key]
246
+
247
+ http_body = {
248
+ multipart: true,
249
+ file: attachments.map { |attachment| File.new(attachment, 'rb') }
250
+ }
251
+
252
+ rest_call(
253
+ http_method: :post,
254
+ base_api_uri: base_api_uri,
255
+ token: token,
256
+ rest_call: "issue/#{issue}/attachments",
257
+ http_body: http_body
258
+ )
259
+ end
260
+
261
+ issue_resp
204
262
  rescue StandardError => e
205
263
  raise e
206
264
  end
@@ -299,7 +357,8 @@ module PWN
299
357
  issue_type: 'required - issue type (e.g. :epic, :story, :bug)',
300
358
  description: 'optional - description of the issue',
301
359
  epic_name: 'optional - name of the epic',
302
- additional_fields: 'optional - additional fields to set in the issue (e.g. labels, components, custom fields, etc.)'
360
+ additional_fields: 'optional - additional fields to set in the issue (e.g. labels, components, custom fields, etc.)',
361
+ attachments: 'optional - array of attachment paths to upload to the issue (e.g. ['/path/to/file1.txt', '/path/to/file2.png'])'
303
362
  )
304
363
 
305
364
  issue_resp = #{self}.update_issue(
@@ -309,6 +368,12 @@ module PWN
309
368
  fields: 'required - fields to update in the issue (e.g. summary, description, labels, components, custom fields, etc.)'
310
369
  )
311
370
 
371
+ issue_resp = #{self}.delete_issue(
372
+ base_api_uri: 'required - base URI for Jira (e.g. https:/jira.corp.com/rest/api/latest)',
373
+ token: 'required - bearer token',
374
+ issue: 'required - issue to delete (e.g. Bug, Issue, Story, or Epic ID)'
375
+ )
376
+
312
377
  **********************************************************************
313
378
  * For more information on the Jira Server REST API, see:
314
379
  * https://developer.atlassian.com/server/jira/platform/rest-apis/
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.295'
4
+ VERSION = '0.5.297'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.295
4
+ version: 0.5.297
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.