pwn 0.5.51 → 0.5.53

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: cfe0f518a0867cb7c25b3fa05d62b9497971f740288cf12cade05dfd32428063
4
- data.tar.gz: 3a79b2526bb5b1a8d312c42b335eea3bba9ff0518e5aa05fcbf663c11276064b
3
+ metadata.gz: 8d7b279b641bea38f8be26582ae7a126014489e2190f28752a48c4ea09410512
4
+ data.tar.gz: 691b05b08f109cc027cf108d6e601fba9f76d1c794a72e8ddb946cdbefc3a40f
5
5
  SHA512:
6
- metadata.gz: cf5419afa046d2259be2497bb82f994495530144f13873990c31691c869055205fe4106a9844f1c150be413afff1e7c38e0e24656b09134aca31b1acd2c63dae
7
- data.tar.gz: 06b5f917e2e63e88eee092751b39d308d7397dff0769a8ea786e6df4d18124865d698c7dcfa518db40f529ff2d609b50c2b8afbccd6f12538e42df461a50991d
6
+ metadata.gz: bb6a6d1c1a39c9a29af063304af7329ae094b801cdc4eab6f0f092fc65bf416c7f32301bd093bedf3a44eae5bea19c94005cdf7cde9e36cdc66bbea1a623c303
7
+ data.tar.gz: 7400d10c061b0f2bb4f0a89efe80a9244f3eced6df20f95905525abb48808b745ce343a6e434b1f1ca750e85640a4f1c7c36da9f2f4b3d9dd22a4ac1a7ebb714
data/Gemfile CHANGED
@@ -52,7 +52,7 @@ gem 'net-ldap', '0.19.0'
52
52
  gem 'net-openvpn', '0.8.7'
53
53
  gem 'net-smtp', '0.4.0.1'
54
54
  gem 'nexpose', '7.3.0'
55
- gem 'nokogiri', '1.16.2'
55
+ gem 'nokogiri', '1.16.3'
56
56
  gem 'nokogiri-diff', '0.3.0'
57
57
  gem 'oily_png', '1.2.1'
58
58
  gem 'open3', '0.2.1'
@@ -87,7 +87,7 @@ gem 'serialport', '1.3.2'
87
87
  gem 'slack-ruby-client', '2.3.0'
88
88
  gem 'socksify', '1.7.1'
89
89
  gem 'spreadsheet', '1.3.1'
90
- gem 'sqlite3', '1.7.2'
90
+ gem 'sqlite3', '1.7.3'
91
91
  gem 'thin', '1.8.2'
92
92
  gem 'tty-prompt', '0.23.1'
93
93
  gem 'tty-spinner', '0.9.3'
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.51]:001 >>> PWN.help
40
+ pwn[v0.5.53]: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.0@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.51]:001 >>> PWN.help
55
+ pwn[v0.5.53]: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.0@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.51]:001 >>> PWN.help
65
+ pwn[v0.5.53]: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/bin/pwn_gqrx_scanner CHANGED
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: false
3
3
 
4
4
  require 'pwn'
5
+ require 'json'
5
6
  require 'optparse'
6
7
 
7
8
  opts = {}
@@ -14,10 +15,6 @@ OptionParser.new do |options|
14
15
  opts[:target_freq] = e
15
16
  end
16
17
 
17
- options.on('-dMODE', '--demodulator-mode=MODE', '<Optional - Set Demodulator ModeOFF | RAW | AM | FM | WFM | WFM_ST | WFM_ST_OIRT | LSB |USB | CW | CWL | CWU (Defaults to AM)>') do |d|
18
- opts[:demodulator_mode] = d
19
- end
20
-
21
18
  options.on('-sFREQ', '--start-freq=FREQ', '<Optional - Frequency to Set when Scanning Begins (Defaults to last known frequency)>') do |s|
22
19
  opts[:start_freq] = s
23
20
  end
@@ -30,12 +27,32 @@ OptionParser.new do |options|
30
27
  opts[:port] = p
31
28
  end
32
29
 
33
- options.on('-PPLACE', '--precision=PLACE', '<Optional - Precision of Frequency 1-12 (Defaults to 3)>') do |p|
30
+ options.on('-AFLOAT', '--audio-gain=FLOAT', '<Optional - Set audio gain -80.0 to 50.0 (Defaults to 1.0)>') do |a|
31
+ opts[:audio_gain_db] = a
32
+ end
33
+
34
+ options.on('-BHZ', '--bandwidth=HZ', '<Optional - Set Bandwidth (Defaults to 240.000)>') do |b|
35
+ opts[:bandwidth] = b
36
+ end
37
+
38
+ options.on('-DMODE', '--demodulator-mode=MODE', '<Optional - Set Demodulator ModeOFF | RAW | AM | FM | WFM | WFM_ST | WFM_ST_OIRT | LSB |USB | CW | CWL | CWU (Defaults to WFM_ST)>') do |d|
39
+ opts[:demodulator_mode] = d
40
+ end
41
+
42
+ options.on('-LFLOAT', '--lock-freq-duration=FLOAT', '<Optional - Duration to lock onto Freqency when Strength < --strength value (Defaults to 3)>') do |l|
43
+ opts[:lock_on_freq_duration] = l
44
+ end
45
+
46
+ options.on('-QFLOAT', '--squelch=FLOAT', '<Optional - Squelch Threshold -150 to 0(Defaults to -63.0)>') do |q|
47
+ opts[:squelch] = q
48
+ end
49
+
50
+ options.on('-PINT', '--precision=INT', '<Optional - Precision of Frequency 1-12 (Defaults to 6)>') do |p|
34
51
  opts[:precision] = p
35
52
  end
36
53
 
37
- options.on('-SFLOAT', '--sleep-between-hops=FLOAT', '<Optional - Float to Sleep Between Hops (Defaults to 0)>') do |s|
38
- opts[:sleep_between_hops] = s
54
+ options.on('-SFLOAT', '--strength=FLOAT', '<Optional - Strength to trigger sleep (Defaults to -63.3)>') do |s|
55
+ opts[:strength] = s
39
56
  end
40
57
  end.parse!
41
58
 
@@ -45,76 +62,204 @@ if opts.empty?
45
62
  end
46
63
 
47
64
  def gqrx_cmd(opts = {})
48
- # f - Get frequency [Hz]
49
- # F - Set frequency [Hz]
50
- # m - Get demodulator mode
51
- # M - Set demodulator mode (OFF, RAW, AM, FM, WFM, WFM_ST,
52
- # WFM_ST_OIRT, LSB, USB, CW, CWL, CWU)
53
- # l STRENGTH - Get signal strength [dBFS]
54
- # l SQL - Get squelch threshold [dBFS]
55
- # L SQL <sql> - Set squelch threshold to <sql> [dBFS]
56
- # u RECORD - Get status of audio recorder
57
- # U RECORD <status> - Set status of audio recorder to <status>
58
- # c - Close connection
59
- # AOS - Acquisition of signal (AOS) event, start audio recording
60
- # LOS - Loss of signal (LOS) event, stop audio recording
61
- # \dump_state - Dump state (only usable for compatibility)
62
65
  gqrx_sock = opts[:gqrx_sock]
63
66
  cmd = opts[:cmd]
67
+ resp_ok = opts[:resp_ok]
68
+
69
+ # Most Recent GQRX Command Set:
70
+ # https://raw.githubusercontent.com/gqrx-sdr/gqrx/master/resources/remote-control.txt
71
+ # Supported commands:
72
+ # f Get frequency [Hz]
73
+ # F <frequency> Set frequency [Hz]
74
+ # m Get demodulator mode and passband
75
+ # M <mode> [passband]
76
+ # Set demodulator mode and passband [Hz]
77
+ # Passing a '?' as the first argument instead of 'mode' will return
78
+ # a space separated list of radio backend supported modes.
79
+ # l|L ?
80
+ # Get a space separated list of settings available for reading (l) or writing (L).
81
+ # l STRENGTH
82
+ # Get signal strength [dBFS]
83
+ # l SQL
84
+ # Get squelch threshold [dBFS]
85
+ # L SQL <sql>
86
+ # Set squelch threshold to <sql> [dBFS]
87
+ # l AF
88
+ # Get audio gain [dB]
89
+ # L AF <gain>
90
+ # Set audio gain to <gain> [dB]
91
+ # l <gain_name>_GAIN
92
+ # Get the value of the gain setting with the name <gain_name>
93
+ # L <gain_name>_GAIN <value>
94
+ # Set the value of the gain setting with the name <gain_name> to <value>
95
+ # p RDS_PI
96
+ # Get the RDS PI code (in hexadecimal). Returns 0000 if not applicable.
97
+ # u RECORD
98
+ # Get status of audio recorder
99
+ # U RECORD <status>
100
+ # Set status of audio recorder to <status>
101
+ # u DSP
102
+ # Get DSP (SDR receiver) status
103
+ # U DSP <status>
104
+ # Set DSP (SDR receiver) status to <status>
105
+ # u RDS
106
+ # Get RDS decoder to <status>. Only functions in WFM mode.
107
+ # U RDS <status>
108
+ # Set RDS decoder to <status>. Only functions in WFM mode.
109
+ # q|Q
110
+ # Close connection
111
+ # AOS
112
+ # Acquisition of signal (AOS) event, start audio recording
113
+ # LOS
114
+ # Loss of signal (LOS) event, stop audio recording
115
+ # LNB_LO [frequency]
116
+ # If frequency [Hz] is specified set the LNB LO frequency used for
117
+ # display. Otherwise print the current LNB LO frequency [Hz].
118
+ # \chk_vfo
119
+ # Get VFO option status (only usable for hamlib compatibility)
120
+ # \dump_state
121
+ # Dump state (only usable for hamlib compatibility)
122
+ # \get_powerstat
123
+ # Get power status (only usable for hamlib compatibility)
124
+ # v
125
+ # Get 'VFO' (only usable for hamlib compatibility)
126
+ # V
127
+ # Set 'VFO' (only usable for hamlib compatibility)
128
+ # s
129
+ # Get 'Split' mode (only usable for hamlib compatibility)
130
+ # S
131
+ # Set 'Split' mode (only usable for hamlib compatibility)
132
+ # _
133
+ # Get version
134
+ #
135
+ # Reply:
136
+ # RPRT 0
137
+ # Command successful
138
+ # RPRT 1
139
+ # Command failed
64
140
 
65
141
  gqrx_sock.write("#{cmd}\n")
66
- does_respond = gqrx_sock.wait_readable
67
- gqrx_sock.readline.chomp if does_respond
142
+ response = []
143
+ got_freq = false
144
+ # Read all responses from gqrx_sock.write
145
+ timeout = 0.01 if timeout.nil?
146
+ begin
147
+ response.push(gqrx_sock.readline.chomp) while gqrx_sock.wait_readable(timeout)
148
+ raise IOError if response.empty?
149
+ rescue IOError
150
+ timeout += 0.001
151
+ retry
152
+ end
153
+
154
+ got_int_value_in_resp = true if response.first.to_i.positive?
155
+ response = response.first if response.length == 1
156
+
157
+ raise "ERROR!!! Command: #{cmd} Expected Resp: #{resp_ok}, Got: #{response}" if resp_ok && response != resp_ok
158
+
159
+ if got_int_value_in_resp
160
+ fixed_len_freq = format('%0.12d', response.to_i)
161
+ freq_segments = fixed_len_freq.scan(/.{3}/)
162
+ first_non_zero_index = freq_segments.index { |s| s.to_i.positive? }
163
+ freq_segments = freq_segments[first_non_zero_index..-1]
164
+ freq_segments[0] = freq_segments.first.to_i.to_s
165
+ response = freq_segments.join('.')
166
+ end
167
+
168
+ # DEBUG
169
+ # puts response.inspect
170
+ # puts response.length
171
+
172
+ response
68
173
  end
69
174
 
70
175
  def init_freq(opts = {})
71
176
  gqrx_sock = opts[:gqrx_sock]
177
+ demodulator_mode = opts[:demodulator_mode]
178
+ bandwidth = opts[:bandwidth]
72
179
  this_freq = opts[:this_freq]
73
- sleep_between_hops = opts[:sleep_between_hops]
180
+ lock_on_freq_duration = opts[:lock_on_freq_duration]
181
+ strength = opts[:strength]
182
+
183
+ demod_n_passband = gqrx_cmd(
184
+ gqrx_sock: gqrx_sock,
185
+ cmd: 'm'
186
+ )
74
187
 
75
- resp = gqrx_cmd(
188
+ change_freq_resp = gqrx_cmd(
76
189
  gqrx_sock: gqrx_sock,
77
- cmd: "F #{this_freq}"
190
+ cmd: "F #{this_freq}",
191
+ resp_ok: 'RPRT 0'
78
192
  )
79
- raise "ERROR: Failed to set frequency to #{this_freq}" unless resp == 'RPRT 0'
80
193
 
81
- resp = gqrx_cmd(
194
+ current_freq = gqrx_cmd(
82
195
  gqrx_sock: gqrx_sock,
83
196
  cmd: 'f'
84
197
  )
85
198
 
86
- # Split the response from NNNNNNNNN
87
- # to NNN.NNN.NNN
88
- this_freq = resp.to_s.chars.insert(-4, '.').insert(-8, '.').join
89
- puts ">>> #{this_freq}"
90
- sleep sleep_between_hops
199
+ current_strength = gqrx_cmd(
200
+ gqrx_sock: gqrx_sock,
201
+ cmd: 'l STRENGTH'
202
+ ).to_f
203
+
204
+ current_squelch = gqrx_cmd(
205
+ gqrx_sock: gqrx_sock,
206
+ cmd: 'l SQL'
207
+ ).to_f
208
+
209
+ audio_gain_db = gqrx_cmd(
210
+ gqrx_sock: gqrx_sock,
211
+ cmd: 'l AF'
212
+ ).to_f
213
+
214
+ init_freq_hash = {
215
+ demod_mode_n_passband: demod_n_passband,
216
+ frequency: current_freq,
217
+ audio_gain_db: audio_gain_db,
218
+ squelch: current_squelch,
219
+ strength: current_strength,
220
+ trigger_lock_on_freq_strength: strength
221
+ }
222
+ puts JSON.pretty_generate(init_freq_hash)
223
+
224
+ sleep lock_on_freq_duration if current_strength < strength
225
+
226
+ init_freq_hash
91
227
  end
92
228
 
93
229
  def scan_range(opts = {})
94
230
  gqrx_sock = opts[:gqrx_sock]
231
+ demodulator_mode = opts[:demodulator_mode]
232
+ bandwidth = opts[:bandwidth]
95
233
  start_freq = opts[:start_freq]
96
234
  target_freq = opts[:target_freq]
97
235
  precision = opts[:precision]
98
- sleep_between_hops = opts[:sleep_between_hops]
236
+ lock_on_freq_duration = opts[:lock_on_freq_duration]
237
+ strength = opts[:strength]
99
238
 
100
239
  multiplier = 10**(precision - 1)
101
240
  if start_freq > target_freq
102
241
  start_freq.downto(target_freq) do |this_freq|
103
242
  next unless (i % multiplier).zero?
104
243
 
105
- init_freq(
244
+ init_freq_hash = init_freq(
106
245
  gqrx_sock: gqrx_sock,
246
+ demodulator_mode: demodulator_mode,
247
+ bandwidth: bandwidth,
107
248
  this_freq: this_freq,
108
- sleep_between_hops: sleep_between_hops
249
+ lock_on_freq_duration: lock_on_freq_duration,
250
+ strength: strength
109
251
  )
110
252
  end
111
253
  else
112
254
  this_freq = start_freq
113
255
  while this_freq <= target_freq
114
- init_freq(
256
+ init_freq_hash = init_freq(
115
257
  gqrx_sock: gqrx_sock,
258
+ demodulator_mode: demodulator_mode,
259
+ bandwidth: bandwidth,
116
260
  this_freq: this_freq,
117
- sleep_between_hops: sleep_between_hops
261
+ lock_on_freq_duration: lock_on_freq_duration,
262
+ strength: strength
118
263
  )
119
264
 
120
265
  this_freq += multiplier
@@ -126,46 +271,81 @@ begin
126
271
  pwn_provider = 'ruby-gem'
127
272
  pwn_provider = ENV.fetch('PWN_PROVIDER') if ENV.keys.any? { |s| s == 'PWN_PROVIDER' }
128
273
 
129
- demodulator_mode = opts[:demodulator_mode] ||= 'AM'
130
- demodulator_mode.upcase!
131
- raise "ERROR: Invalid demodulator mode: #{demodulator_mode}" unless %w[OFF RAW AM FM WFM WFM_ST WFM_ST_OIRT LSB USB CW CWL CWU].include?(demodulator_mode)
274
+ target_freq = opts[:target_freq]
275
+ target_freq = target_freq.to_s.delete('.') unless target_freq.nil?
276
+ target_freq = target_freq.to_i
277
+ raise "ERROR: Invalid target frequency #{target_freq}" if target_freq.zero?
132
278
 
133
279
  host = opts[:host] ||= '127.0.0.1'
134
280
  port = opts[:port] ||= 7356
135
- puts "Connecting to GQRX at #{host}:#{port}..."
136
281
 
282
+ puts "Connecting to GQRX at #{host}:#{port}..."
137
283
  gqrx_sock = PWN::Plugins::Sock.connect(target: host, port: port)
138
- puts "Setting demodulator mode to #{demodulator_mode}..."
139
- demod_resp = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: "M #{demodulator_mode}")
140
- puts demod_resp
141
284
 
142
285
  start_freq = opts[:start_freq]
143
- start_freq = start_freq.to_s.delete('.').to_i unless start_freq.nil?
144
- start_freq = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'f').to_i if start_freq.nil?
286
+ start_freq = start_freq.to_s.delete('.') unless start_freq.nil?
287
+ start_freq = start_freq.to_i
288
+ start_freq = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'f', resp_ok: 'RPRT 0').to_i if start_freq.zero?
145
289
 
146
- target_freq = opts[:target_freq]
147
- target_freq = target_freq.to_s.delete('.').to_i unless target_freq.nil?
148
- raise 'ERROR: Invalid end frequency' if target_freq.nil?
290
+ demodulator_mode = opts[:demodulator_mode] ||= 'WFM_ST'
291
+ demodulator_mode.upcase!
292
+ raise "ERROR: Invalid demodulator mode: #{demodulator_mode}" unless %w[OFF RAW AM FM WFM WFM_ST WFM_ST_OIRT LSB USB CW CWL CWU].include?(demodulator_mode)
149
293
 
150
- puts "Scanning from #{start_freq} to #{target_freq}..."
294
+ bandwidth = opts[:bandwidth] ||= '240.000'
151
295
 
152
- precision = opts[:precision] ||= 3
296
+ puts "Setting demodulator mode to #{demodulator_mode} and bandwidth to #{bandwidth}..."
297
+ bandwidth = bandwidth.to_s.delete('.').to_i unless bandwidth.nil?
298
+ demod_resp = gqrx_cmd(
299
+ gqrx_sock: gqrx_sock,
300
+ cmd: "M #{demodulator_mode} #{bandwidth}",
301
+ resp_ok: 'RPRT 0'
302
+ )
303
+
304
+ squelch = opts[:squelch] ||= -63.0
305
+ squelch = squelch.to_f
306
+ squelch_resp = gqrx_cmd(
307
+ gqrx_sock: gqrx_sock,
308
+ cmd: "L SQL #{squelch}",
309
+ resp_ok: 'RPRT 0'
310
+ )
311
+
312
+ precision = opts[:precision] ||= 6
153
313
  precision = precision.to_i
154
314
  raise "ERROR: Invalid precision: #{precision}" unless (1..12).include?(precision)
155
315
 
156
- sleep_between_hops = opts[:sleep_between_hops] ||= 0
157
- sleep_between_hops = sleep_between_hops.to_f
316
+ lock_on_freq_duration = opts[:lock_on_freq_duration] ||= 3
317
+ lock_on_freq_duration = lock_on_freq_duration.to_f
318
+
319
+ strength = opts[:strength] ||= -63.3
320
+ strength = strength.to_f
321
+
322
+ audio_gain_db = opts[:audio_gain_db] ||= 1.0
323
+ audio_gain_db = audio_gain_db.to_f
324
+ audio_gain_db_resp = gqrx_cmd(
325
+ gqrx_sock: gqrx_sock,
326
+ cmd: "L AF #{audio_gain_db}",
327
+ resp_ok: 'RPRT 0'
328
+ )
329
+
330
+ s_freq_pretty = start_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
331
+ t_freq_pretty = target_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
332
+ puts "*** Scanning from #{s_freq_pretty} to #{t_freq_pretty}"
158
333
 
159
334
  scan_range(
160
335
  gqrx_sock: gqrx_sock,
336
+ demodulator_mode: demodulator_mode,
161
337
  start_freq: start_freq,
162
338
  target_freq: target_freq,
163
339
  precision: precision,
164
- sleep_between_hops: sleep_between_hops
340
+ lock_on_freq_duration: lock_on_freq_duration,
341
+ strength: strength,
342
+ squelch: squelch
165
343
  )
166
- rescue SystemExit, Interrupt
344
+ puts 'Scan Complete.'
345
+ rescue StandardError => e
346
+ raise e
347
+ rescue Interrupt, SystemExit
167
348
  puts "\nGoodbye."
168
349
  ensure
169
- resp = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'c')
170
350
  gqrx_sock = PWN::Plugins::Sock.disconnect(sock_obj: gqrx_sock)
171
351
  end
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.51'
4
+ VERSION = '0.5.53'
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.51
4
+ version: 0.5.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -562,14 +562,14 @@ dependencies:
562
562
  requirements:
563
563
  - - '='
564
564
  - !ruby/object:Gem::Version
565
- version: 1.16.2
565
+ version: 1.16.3
566
566
  type: :runtime
567
567
  prerelease: false
568
568
  version_requirements: !ruby/object:Gem::Requirement
569
569
  requirements:
570
570
  - - '='
571
571
  - !ruby/object:Gem::Version
572
- version: 1.16.2
572
+ version: 1.16.3
573
573
  - !ruby/object:Gem::Dependency
574
574
  name: nokogiri-diff
575
575
  requirement: !ruby/object:Gem::Requirement
@@ -1038,14 +1038,14 @@ dependencies:
1038
1038
  requirements:
1039
1039
  - - '='
1040
1040
  - !ruby/object:Gem::Version
1041
- version: 1.7.2
1041
+ version: 1.7.3
1042
1042
  type: :runtime
1043
1043
  prerelease: false
1044
1044
  version_requirements: !ruby/object:Gem::Requirement
1045
1045
  requirements:
1046
1046
  - - '='
1047
1047
  - !ruby/object:Gem::Version
1048
- version: 1.7.2
1048
+ version: 1.7.3
1049
1049
  - !ruby/object:Gem::Dependency
1050
1050
  name: thin
1051
1051
  requirement: !ruby/object:Gem::Requirement