rufus-treechecker 1.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rufus/treechecker.rb +75 -24
- data/test/ft_0_basic.rb +22 -3
- data/test/ft_1_old_treechecker.rb +3 -3
- metadata +1 -1
data/lib/rufus/treechecker.rb
CHANGED
@@ -82,9 +82,10 @@ module Rufus
|
|
82
82
|
# - exclude_fcall
|
83
83
|
# - exclude_vcall
|
84
84
|
# - exclude_fvcall
|
85
|
-
# -
|
85
|
+
# - exclude_fvccall
|
86
86
|
# - exclude_call_on
|
87
87
|
# - exclude_call_to
|
88
|
+
# - exclude_rebinding
|
88
89
|
# - exclude_def
|
89
90
|
# - exclude_class_tinkering
|
90
91
|
# - exclude_module_tinkering
|
@@ -95,6 +96,7 @@ module Rufus
|
|
95
96
|
#
|
96
97
|
# Those rules take no arguments
|
97
98
|
#
|
99
|
+
# - exclude_access_to : prevents calling or rebinding a list of classes
|
98
100
|
# - exclude_eval : bans eval, module_eval and instance_eval
|
99
101
|
# - exclude_global_vars : bans calling or modifying global vars
|
100
102
|
# - exclude_alias : bans calls to alias and alias_method
|
@@ -123,7 +125,7 @@ module Rufus
|
|
123
125
|
#
|
124
126
|
class TreeChecker
|
125
127
|
|
126
|
-
VERSION = '1.0'
|
128
|
+
VERSION = '1.0.1'
|
127
129
|
|
128
130
|
#
|
129
131
|
# pretty-prints the sexp tree of the given rubycode
|
@@ -209,9 +211,9 @@ module Rufus
|
|
209
211
|
# Here is how it's built :
|
210
212
|
#
|
211
213
|
# return TreeChecker.new do
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
214
|
+
# exclude_fvccall :abort
|
215
|
+
# exclude_fvccall :exit, :exit!
|
216
|
+
# exclude_fvccall :system
|
215
217
|
# exclude_eval
|
216
218
|
# exclude_alias
|
217
219
|
# exclude_global_vars
|
@@ -223,9 +225,9 @@ module Rufus
|
|
223
225
|
def self.new_classic_tree_checker
|
224
226
|
|
225
227
|
return TreeChecker.new do
|
226
|
-
|
227
|
-
|
228
|
-
|
228
|
+
exclude_fvccall :abort
|
229
|
+
exclude_fvccall :exit, :exit!
|
230
|
+
exclude_fvccall :system
|
229
231
|
exclude_eval
|
230
232
|
exclude_alias
|
231
233
|
exclude_global_vars
|
@@ -272,7 +274,7 @@ module Rufus
|
|
272
274
|
:exclude_fcall,
|
273
275
|
:exclude_vcall,
|
274
276
|
:exclude_fvcall,
|
275
|
-
:
|
277
|
+
:exclude_fvccall,
|
276
278
|
:exclude_call_on,
|
277
279
|
:exclude_call_to
|
278
280
|
|
@@ -293,6 +295,38 @@ module Rufus
|
|
293
295
|
EOS
|
294
296
|
end
|
295
297
|
|
298
|
+
#
|
299
|
+
# This rule :
|
300
|
+
#
|
301
|
+
# exclude_rebinding Kernel
|
302
|
+
#
|
303
|
+
# will raise a security error for those pieces of code :
|
304
|
+
#
|
305
|
+
# k = Kernel
|
306
|
+
# k = ::Kernel
|
307
|
+
#
|
308
|
+
def exclude_rebinding (*args)
|
309
|
+
|
310
|
+
message = args.last.is_a?(String) ? args.pop : nil
|
311
|
+
|
312
|
+
args.each do |a|
|
313
|
+
c0 = parse(a.to_s)
|
314
|
+
c1 = parse("::#{a.to_s}")
|
315
|
+
@current_checks << [ :do_exclude_rebinding, c0, message ]
|
316
|
+
@current_checks << [ :do_exclude_rebinding, c1, message ]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
#
|
321
|
+
# prevents access (calling methods and rebinding) to a class (or a list
|
322
|
+
# of classes
|
323
|
+
#
|
324
|
+
def exclude_access_to (*args)
|
325
|
+
|
326
|
+
exclude_call_on *args
|
327
|
+
exclude_rebinding *args
|
328
|
+
end
|
329
|
+
|
296
330
|
#
|
297
331
|
# bans method definitions
|
298
332
|
#
|
@@ -391,8 +425,8 @@ module Rufus
|
|
391
425
|
#
|
392
426
|
def exclude_raise
|
393
427
|
|
394
|
-
@current_checks << [ :
|
395
|
-
@current_checks << [ :
|
428
|
+
@current_checks << [ :do_exclude_fvccall, :raise, "raise is forbidden" ]
|
429
|
+
@current_checks << [ :do_exclude_fvccall, :throw, "throw is forbidden" ]
|
396
430
|
end
|
397
431
|
|
398
432
|
#
|
@@ -447,12 +481,13 @@ module Rufus
|
|
447
481
|
end
|
448
482
|
|
449
483
|
#
|
450
|
-
# excludes :fcall and :vcall and :call
|
484
|
+
# excludes :fcall and :vcall and :call (to)
|
451
485
|
#
|
452
|
-
def
|
486
|
+
def do_exclude_fvccall (sexp, args)
|
453
487
|
|
454
488
|
do_exclude_fvcall(sexp, args)
|
455
|
-
do_exclude_head(sexp, cons([ :call, [ :const, :Kernel ] ], args))
|
489
|
+
#do_exclude_head(sexp, cons([ :call, [ :const, :Kernel ] ], args))
|
490
|
+
do_exclude_call_to(sexp, args)
|
456
491
|
end
|
457
492
|
|
458
493
|
#
|
@@ -475,28 +510,44 @@ module Rufus
|
|
475
510
|
do_exclude_head(sexp, [ [:call, args[0]] ] + (args[1, -1] || []))
|
476
511
|
end
|
477
512
|
|
513
|
+
#
|
514
|
+
# this method is called by all the methods checking composite sexps.
|
515
|
+
#
|
516
|
+
def do__exclude (sexp, args, default_error_message, &block)
|
517
|
+
|
518
|
+
return unless sexp.is_a?(Array)
|
519
|
+
|
520
|
+
raise SecurityError.new(
|
521
|
+
args[1] || default_error_message
|
522
|
+
) if block.call(args)
|
523
|
+
end
|
524
|
+
|
478
525
|
#
|
479
526
|
# raises a security error if a call to a given method of any instance
|
480
527
|
# is found
|
481
528
|
#
|
482
529
|
def do_exclude_call_to (sexp, args)
|
483
530
|
|
484
|
-
|
531
|
+
do__exclude(sexp, args, "calls to '#{args[0]}' are forbidden") do
|
485
532
|
|
486
|
-
|
487
|
-
|
488
|
-
) if sexp[0] == :call and sexp[2] == args[0]
|
533
|
+
(sexp[0] == :call and sexp[2] == args[0])
|
534
|
+
end
|
489
535
|
end
|
490
536
|
|
491
|
-
def
|
537
|
+
def do_exclude_rebinding (sexp, args)
|
492
538
|
|
493
|
-
|
539
|
+
do__exclude(sexp, args, "rebinding '#{args[0]}' is forbidden") do
|
494
540
|
|
495
|
-
|
541
|
+
(sexp[0] == :lasgn and sexp[2] == args[0])
|
542
|
+
end
|
543
|
+
end
|
496
544
|
|
497
|
-
|
498
|
-
|
499
|
-
|
545
|
+
def do_exclude_head (sexp, args)
|
546
|
+
|
547
|
+
do__exclude(sexp, args, "#{args[0].inspect} is forbidden") do
|
548
|
+
|
549
|
+
(sexp[0, args[0].length] == args[0])
|
550
|
+
end
|
500
551
|
end
|
501
552
|
|
502
553
|
def do_exclude_class_tinkering (sexp, args)
|
data/test/ft_0_basic.rb
CHANGED
@@ -218,10 +218,29 @@ class BasicTest < Test::Unit::TestCase
|
|
218
218
|
assert_ok(tc, 'lambda { a = 2 }')
|
219
219
|
end
|
220
220
|
|
221
|
-
def
|
221
|
+
def test_12_rebinding
|
222
222
|
|
223
|
-
|
224
|
-
|
223
|
+
tc = Rufus::TreeChecker.new do
|
224
|
+
exclude_call_to :class
|
225
|
+
exclude_rebinding Kernel, Rufus::TreeChecker
|
226
|
+
end
|
227
|
+
|
228
|
+
assert_nok(tc, 'k = Kernel')
|
229
|
+
assert_nok(tc, 'k = ::Kernel')
|
230
|
+
assert_nok(tc, 'c = Rufus::TreeChecker')
|
231
|
+
assert_nok(tc, 'c = ::Rufus::TreeChecker')
|
232
|
+
assert_nok(tc, 's = "".class')
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_13_access_to
|
236
|
+
|
237
|
+
tc = Rufus::TreeChecker.new do
|
238
|
+
exclude_access_to File
|
239
|
+
end
|
240
|
+
|
241
|
+
assert_nok(tc, 'f = File')
|
242
|
+
assert_nok(tc, 'f = ::File')
|
243
|
+
assert_nok(tc, 'File.read "hello.txt"')
|
225
244
|
end
|
226
245
|
|
227
246
|
#def test_X
|
@@ -21,9 +21,9 @@ class OldTreeCheckerTest < Test::Unit::TestCase
|
|
21
21
|
def test_0
|
22
22
|
|
23
23
|
tc = Rufus::TreeChecker.new do
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
exclude_fvccall :abort
|
25
|
+
exclude_fvccall :exit, :exit!
|
26
|
+
exclude_fvccall :system
|
27
27
|
exclude_eval
|
28
28
|
exclude_alias
|
29
29
|
exclude_global_vars
|