pwn 0.4.886 → 0.4.887

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a85fbb128c8c5ba0dafc425373d33839998f866ccc0982b9d0f596ce7ee2411
4
- data.tar.gz: ab8a86d182d5cc69e7509596bd38a0515b2c8c0b532ca61b59675558fb5df554
3
+ metadata.gz: eba0652465ac3cb7e848a84e78412952875ab79a2c47dbcda39068a65e9f5c5b
4
+ data.tar.gz: 2c03fbba16c08c1820d483e744e5e1dd70812081aff632a9f71f0227f582d2a7
5
5
  SHA512:
6
- metadata.gz: d3ef35410455de329014f16c01c6498ce9e7540a1edbf2028b3c181297e47084a4439e7e6344892ce33685868599cd44f3ffb21008bfcd83695f6b1931067a95
7
- data.tar.gz: 0e3155be591274c629fc0dd73a45d94b830261af83bf4a074d05c4579d0eea110815f5efb6ef5adf439c16e171da51f7287f44e032f29ec29b719c8a4c163a9d
6
+ metadata.gz: c9912c9c682b57c711c1a57e09e7ffad70c7018cf8e2689ecf7ff3a0f8fe3e5de9638588fd85c3475f58aaeb51a4892061e9cd4ceca6d1d3a40e5a2be8e88d31
7
+ data.tar.gz: c26189e41c966c8d3ca0e3988d9d901461b420a85e6d49123814b7e9331e8bcb6a7fe2dd2b3fa0d058f8b2b4f3948e3b5131a4ecb21854dc0a018e03f42d9b58
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ rvm use ruby-3.2.2@pwn
37
37
  $ rvm list gemsets
38
38
  $ gem install --verbose pwn
39
39
  $ pwn
40
- pwn[v0.4.886]:001 >>> PWN.help
40
+ pwn[v0.4.887]: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.2.2@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.4.886]:001 >>> PWN.help
55
+ pwn[v0.4.887]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
 
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'faker'
5
+ require 'json'
6
+ require 'optparse'
7
+ require 'pwn'
8
+
9
+ opts = {}
10
+ OptionParser.new do |options|
11
+ options.on('-jFILE', '--json-results=FILE', 'Required - JSON results file from pwn_shodan_search driver') do |j|
12
+ opts[:json_results] = j
13
+ end
14
+ end.parse!
15
+
16
+ if opts.empty?
17
+ puts `#{$PROGRAM_NAME} --help`
18
+ exit 1
19
+ end
20
+
21
+ json_results_path = opts[:json_results]
22
+ raise "ERROR: Shodan JSON Results File #{json_results_path} Does Not Exist." unless File.exist?(json_results_path)
23
+
24
+ search_results = JSON.parse(
25
+ File.read(json_results_path),
26
+ symbolize_names: true
27
+ )
28
+
29
+ print 'Extracting URIs from Shodan search results...'
30
+ uri_arr = PWN::Plugins::Shodan.get_uris(search_results: search_results)
31
+ puts 'complete.'
32
+
33
+ print "Extracting GraphQL URIs from #{uri_arr.count} URIs..."
34
+ graphql_uris = uri_arr.uniq.select do |uri|
35
+ uri if uri =~ %r{.+/graphql/?$} ||
36
+ uri =~ %r{.+/graphiql/?$} ||
37
+ uri =~ %r{.+/playground/?$} ||
38
+ uri =~ %r{.+/console/?$} ||
39
+ uri =~ %r{.+/query/?$} ||
40
+ uri =~ %r{.+/gql/?$} ||
41
+ uri =~ %r{.+/index.php?graphql$}
42
+ end
43
+ puts 'complete.'
44
+
45
+ browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
46
+ rest_client = browser_obj[:browser]::Request
47
+
48
+ graphql_payloads_arr = []
49
+
50
+ graphql_schema_payload = '{ "query": "{ __schema { types { name } } }" }'
51
+ graphql_payloads_arr.push(graphql_schema_payload)
52
+
53
+ graphql_introspection_payload1 = <<-END_OF_PAYLOAD
54
+ {
55
+ query IntrospectionQuery {
56
+ __schema {
57
+
58
+ queryType { name }
59
+ mutationType { name }
60
+ subscriptionType { name }
61
+ types { ...FullType }
62
+ directives {
63
+ name
64
+ description
65
+ locations
66
+ args { ...InputValue }
67
+ }
68
+ }
69
+ }
70
+
71
+ fragment FullType on __Type {
72
+ kind
73
+ name
74
+ description
75
+ fields(includeDeprecated: true) {
76
+ name
77
+ description
78
+ args { ...InputValue }
79
+ type { ...TypeRef }
80
+ isDeprecated
81
+ deprecationReason
82
+ }
83
+ inputFields {
84
+ ...InputValue
85
+ }
86
+ interfaces {
87
+ ...TypeRef
88
+ }
89
+ enumValues(includeDeprecated: true) {
90
+ name
91
+ description
92
+ isDeprecated
93
+ deprecationReason
94
+ }
95
+ possibleTypes {
96
+ ...TypeRef
97
+ }
98
+ }
99
+
100
+ fragment InputValue on __InputValue {
101
+ name
102
+ description
103
+ type { ...TypeRef }
104
+ defaultValue
105
+ }
106
+
107
+ fragment TypeRef on __Type {
108
+ kind
109
+ name
110
+ ofType {
111
+ kind
112
+ name
113
+ ofType {
114
+ kind
115
+ name
116
+ ofType {
117
+ kind
118
+ name
119
+ ofType {
120
+ kind
121
+ name
122
+ ofType {
123
+ kind
124
+ name
125
+ ofType {
126
+ kind
127
+ name
128
+ ofType {
129
+ kind
130
+ name
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ END_OF_PAYLOAD
141
+ graphql_payloads_arr.push(graphql_introspection_payload1)
142
+
143
+ graphql_introspection_payload2 = <<-END_OF_PAYLOAD
144
+ {
145
+ "operationName":"IntrospectionQuery",
146
+ "variables":{},
147
+ "query":"
148
+ fragment FullType on __Type {
149
+ kind
150
+ name
151
+ description
152
+ fields(includeDeprecated: true) {
153
+ name
154
+ description
155
+ args { ...InputValue }
156
+ type { ...TypeRef }
157
+ isDeprecated deprecationReason
158
+ }
159
+ inputFields { ...InputValue }
160
+ interfaces { ...TypeRef }
161
+ enumValues(includeDeprecated: true) {
162
+ name
163
+ description
164
+ isDeprecated
165
+ deprecationReason
166
+ }
167
+ possibleTypes { ...TypeRef }
168
+ }
169
+
170
+ fragment InputValue on __InputValue {
171
+ name
172
+ description
173
+ type { ...TypeRef }
174
+ defaultValue
175
+ }
176
+
177
+ fragment TypeRef on __Type {
178
+ kind
179
+ name
180
+ ofType {
181
+ kind
182
+ name
183
+ ofType {
184
+ kind
185
+ name
186
+ ofType {
187
+ kind
188
+ name
189
+ ofType {
190
+ kind
191
+ name
192
+ ofType {
193
+ kind
194
+ name
195
+ ofType {
196
+ kind
197
+ name
198
+ ofType {
199
+ kind
200
+ name
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ query IntrospectionQuery {
211
+ __schema {
212
+ queryType { name }
213
+ mutationType { name }
214
+ types { ...FullType }
215
+ directives {
216
+ name
217
+ description
218
+ locations
219
+ args { ...InputValue }
220
+ }
221
+ }
222
+ }"
223
+ }
224
+ END_OF_PAYLOAD
225
+ graphql_payloads_arr.push(graphql_introspection_payload2)
226
+
227
+ # Math Part
228
+ graphql_uri_tot = graphql_uris.length
229
+ payload_tot = graphql_payloads_arr.length
230
+ request_tot = payload_tot * graphql_uri_tot
231
+
232
+ puts "Sending #{payload_tot} payloads to #{graphql_uris.count} GraphQL URIs..."
233
+ puts "Total HTTP Requests: #{request_tot}"
234
+
235
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
236
+ introspection_arr_of_hashes = []
237
+ graphql_uris.each do |this_uri|
238
+ puts "IN PROGRESS: #{this_uri}..."
239
+ graphql_payloads_arr.each_with_index do |this_payload, payload_index|
240
+ # user_agent = Faker::Internet.user_agent
241
+ timestamp = Time.now.strftime('%Y-%m-%d_%H:%M:%S')
242
+ introspection_hash = {
243
+ time: timestamp,
244
+ uri: this_uri,
245
+ payload_index: payload_index,
246
+ response_code: nil,
247
+ response_headers: nil,
248
+ response: nil
249
+ }
250
+ resp = rest_client.execute(
251
+ method: :post,
252
+ url: this_uri,
253
+ headers: {
254
+ content_type: 'application/json; charset=UTF-8',
255
+ user_agent: user_agent
256
+ },
257
+ payload: this_payload,
258
+ verify_ssl: false,
259
+ timeout: 3.0,
260
+ max_redirects: 3
261
+ )
262
+ introspection_hash[:response_code] = resp.code
263
+ introspection_hash[:response_headers] = resp.headers
264
+ json_resp = JSON.parse(
265
+ resp.body,
266
+ symbolize_names: true
267
+ )
268
+
269
+ introspection_hash[:response] = json_resp
270
+ rescue Errno::ECONNREFUSED,
271
+ Errno::ENETUNREACH,
272
+ JSON::ParserError,
273
+ OpenSSL::SSL::SSLError,
274
+ SocketError => e
275
+
276
+ introspection_hash[:response_code] = "#{e.class}: #{e.message}"
277
+
278
+ next
279
+ rescue RestClient::ExceptionWithResponse => e
280
+ introspection_hash[:response_code] = "#{e.class}: #{e.message}" if e.response.nil?
281
+
282
+ if e.response
283
+ introspection_hash[:response_code] = e.response.code
284
+ introspection_hash[:response_headers] = e.response.headers
285
+ introspection_hash[:response] = e.response.body
286
+ end
287
+
288
+ next
289
+ ensure
290
+ introspection_arr_of_hashes.push(introspection_hash)
291
+ end
292
+ end
293
+ puts 'complete.'
294
+
295
+ timestamp = Time.now.strftime('%Y-%m-%d_%H:%M:%S')
296
+ print 'Saving Introspection Results...'
297
+ File.write(
298
+ "graphql_results-#{timestamp}-ALL.json",
299
+ JSON.pretty_generate(introspection_arr_of_hashes)
300
+ )
301
+
302
+ vulnerable_uris = introspection_arr_of_hashes.select do |h|
303
+ h if (h[:response].is_a?(Hash) && h[:response].keys.first.to_sym == :data) ||
304
+ (h[:response].is_a?(Integer) && h[:response_code] == 415) ||
305
+ (h[:response].is_a?(Integer) && h[:response_code] >= 500)
306
+ end
307
+ File.write(
308
+ "graphql_results-#{timestamp}-VULNERABLE.json",
309
+ JSON.pretty_generate(vulnerable_uris)
310
+ )
311
+ puts 'complete.'
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.4.886'
4
+ VERSION = '0.4.887'
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.4.886
4
+ version: 0.4.887
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -1167,6 +1167,7 @@ executables:
1167
1167
  - pwn_diff_csv_files_w_column_exclude
1168
1168
  - pwn_domain_reversewhois
1169
1169
  - pwn_fuzz_net_app_proto
1170
+ - pwn_graphql_introspection_detector
1170
1171
  - pwn_ibm_appscan_enterprise
1171
1172
  - pwn_jenkins_create_job
1172
1173
  - pwn_jenkins_create_view
@@ -1233,6 +1234,7 @@ files:
1233
1234
  - bin/pwn_diff_csv_files_w_column_exclude
1234
1235
  - bin/pwn_domain_reversewhois
1235
1236
  - bin/pwn_fuzz_net_app_proto
1237
+ - bin/pwn_graphql_introspection_detector
1236
1238
  - bin/pwn_ibm_appscan_enterprise
1237
1239
  - bin/pwn_jenkins_create_job
1238
1240
  - bin/pwn_jenkins_create_view