risu 1.5.3 → 1.6.0

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.
Files changed (60) hide show
  1. data/Gemfile.ci +1 -0
  2. data/LICENSE +1 -1
  3. data/NEWS.markdown +80 -3
  4. data/README.markdown +9 -8
  5. data/Rakefile +7 -7
  6. data/bin/risu +1 -1
  7. data/lib/risu.rb +6 -3
  8. data/lib/risu/base.rb +2 -1
  9. data/lib/risu/base/schema.rb +8 -4
  10. data/lib/risu/base/template_base.rb +3 -1
  11. data/lib/risu/base/template_helper.rb +115 -0
  12. data/lib/risu/base/template_manager.rb +1 -1
  13. data/lib/risu/base/templater.rb +3 -4
  14. data/lib/risu/cli.rb +1 -1
  15. data/lib/risu/cli/application.rb +3 -10
  16. data/lib/risu/cli/banner.rb +1 -1
  17. data/lib/risu/exceptions.rb +1 -1
  18. data/lib/risu/exceptions/invaliddocument.rb +1 -1
  19. data/lib/risu/models.rb +1 -1
  20. data/lib/risu/models/familyselection.rb +1 -1
  21. data/lib/risu/models/host.rb +92 -9
  22. data/lib/risu/models/individualpluginselection.rb +1 -1
  23. data/lib/risu/models/item.rb +47 -13
  24. data/lib/risu/models/patch.rb +1 -1
  25. data/lib/risu/models/plugin.rb +9 -1
  26. data/lib/risu/models/pluginspreference.rb +1 -1
  27. data/lib/risu/models/policy.rb +1 -1
  28. data/lib/risu/models/reference.rb +69 -9
  29. data/lib/risu/models/report.rb +1 -1
  30. data/lib/risu/models/serverpreference.rb +1 -1
  31. data/lib/risu/models/servicedescription.rb +1 -1
  32. data/lib/risu/models/version.rb +1 -1
  33. data/lib/risu/parsers.rb +1 -1
  34. data/lib/risu/parsers/nessus/nessus_document.rb +1 -1
  35. data/lib/risu/parsers/nessus/nessus_sax_listener.rb +69 -50
  36. data/lib/risu/parsers/nexpose/nexpose_document.rb +2 -5
  37. data/lib/risu/parsers/nexpose/simple_nexpose.rb +1 -1
  38. data/lib/risu/renderers.rb +1 -1
  39. data/lib/risu/renderers/nilrenderer.rb +1 -1
  40. data/lib/risu/templates/assets.rb +17 -29
  41. data/lib/risu/templates/cover_sheet.rb +40 -44
  42. data/lib/risu/templates/exec_summary.rb +11 -20
  43. data/lib/risu/templates/{executive_summary.rb → executive_summary_detailed.rb} +2 -11
  44. data/lib/risu/templates/finding_statistics.rb +1 -1
  45. data/lib/risu/templates/findings_host.rb +1 -1
  46. data/lib/risu/templates/findings_summary.rb +25 -86
  47. data/lib/risu/templates/findings_summary_with_pluginid.rb +1 -1
  48. data/lib/risu/templates/graphs.rb +1 -1
  49. data/lib/risu/templates/host_summary.rb +18 -14
  50. data/lib/risu/templates/ms_patch_summary.rb +17 -24
  51. data/lib/risu/templates/ms_update_summary.rb +1 -1
  52. data/lib/risu/templates/ms_wsus_findings.rb +1 -1
  53. data/lib/risu/templates/notable.rb +10 -14
  54. data/lib/risu/templates/notable_detailed.rb +43 -54
  55. data/lib/risu/templates/pci_compliance.rb +28 -34
  56. data/lib/risu/templates/stig_findings_summary.rb +25 -38
  57. data/lib/risu/templates/technical_findings.rb +46 -55
  58. data/lib/risu/templates/template.rb +4 -3
  59. data/risu.gemspec +12 -11
  60. metadata +79 -61
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@ module Risu
28
28
  module Base
29
29
 
30
30
  # Templater class for generating a report from a ERB template
31
- #
32
31
  class Templater
33
32
  attr_accessor :template, :template_manager, :findings, :output_file
34
33
 
@@ -43,16 +42,16 @@ module Risu
43
42
  end
44
43
 
45
44
  # Generates a report based on the ERB template
46
- #
47
45
  def generate
48
46
  begin
49
47
  template = @template
50
48
  template_manager = @template_manager
51
49
 
52
50
  Prawn::Document.generate(@output_file, :margin => [75, 50, 75, 50]) do |output|
53
- output.font_size 12
51
+ output.font_size 10
54
52
  t = template_manager.find_template_by_name(template)
55
53
  t = t.class.new
54
+ t.output = output
56
55
  t.render(output) unless t == nil
57
56
  end
58
57
  rescue => e
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -28,13 +28,11 @@ module Risu
28
28
  module CLI
29
29
 
30
30
  # Application class for Risu
31
- #
32
31
  class Application
33
32
  include Risu::Base
34
33
  attr_accessor :database
35
34
 
36
35
  # Initializes a CLI Application
37
- #
38
36
  def initialize
39
37
  @options = {}
40
38
  @database = {}
@@ -146,7 +144,6 @@ module Risu
146
144
 
147
145
  # Establishes an [ActiveRecord::Base] database connection
148
146
  # @todo better comments
149
- #
150
147
  def db_connect
151
148
  begin
152
149
  if @database["adapter"] == nil
@@ -200,7 +197,6 @@ module Risu
200
197
  # Starts a console and executes anything in a block sent to it
201
198
  #
202
199
  # @param block Code block to transfer control
203
- #
204
200
  def consolize &block
205
201
 
206
202
  yield
@@ -222,12 +218,11 @@ module Risu
222
218
  end
223
219
  end
224
220
 
225
- # Parses all the command line
226
- #
221
+ # Parses all the command line options
227
222
  def parse_options
228
223
  begin
229
224
  opts = OptionParser.new do |opt|
230
- opt.banner = "#{APP_NAME} v#{VERSION}\nJacob Hammack\nhttp://www.hammackj.com\n\n"
225
+ opt.banner = "#{APP_NAME} v#{VERSION}\nJacob Hammack\nhttp://www.arxopia.com\n\n"
231
226
  opt.banner << "Usage: #{APP_NAME} [options] [files_to_parse]"
232
227
  opt.separator('')
233
228
  opt.separator("Reporting Options")
@@ -335,7 +330,6 @@ module Risu
335
330
 
336
331
  # Main Application loop, handles all of the command line arguments and
337
332
  #parsing of files on the command line
338
- #
339
333
  def run
340
334
  parse_options
341
335
 
@@ -419,7 +413,6 @@ module Risu
419
413
  # Handles the parsing of a single file
420
414
  #
421
415
  # @param file The to parse
422
- #
423
416
  def parse_file file
424
417
  begin
425
418
  puts "[*] Parsing #{file}..."
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@ module Risu
42
42
  # if blacklist_host_id == nil
43
43
  # where("id != ?", blacklist_host_id).count
44
44
  # else
45
- # count
45
+ # count
46
46
  # end
47
47
  #end
48
48
 
@@ -63,6 +63,20 @@ module Risu
63
63
  return hosts
64
64
  end
65
65
 
66
+ # Generates a list of hosts from the database
67
+ #
68
+ # @return [String] of hosts \n delimited
69
+ def ip_list
70
+ ips = Array.new
71
+ hosts = Host.where("ip is not NULL").order("ip").all
72
+
73
+ hosts.each do |host|
74
+ ips << host.ip if host.ip != nil
75
+ end
76
+
77
+ ips.join("\n")
78
+ end
79
+
66
80
  # Queries for hosts with a Windows based Operating System
67
81
  #
68
82
  # @return [ActiveRecord::Relation] with the query results
@@ -196,10 +210,27 @@ module Risu
196
210
  where("os LIKE '%Windows Server 2008%'")
197
211
  end
198
212
 
213
+ # Negation query for all hosts with a Windows Server 2008 based Operating system
214
+ #
215
+ # @return [ActiveRecord::Relation] with the query results
199
216
  def not_os_windows_2k8
200
217
  where("os NOT LIKE '%Windows Server 2008%'")
201
218
  end
202
219
 
220
+ # Queries for hosts with a Windows Server 2012 based Operating System
221
+ #
222
+ # @return [ActiveRecord::Relation] with the query results
223
+ def os_windows_2k12
224
+ where("os LIKE '%Windows Server 2012%'")
225
+ end
226
+
227
+ # Negation query for all hosts with a Windows Server 2012 based Operating system
228
+ #
229
+ # @return [ActiveRecord::Relation] with the query results
230
+ def not_os_windows_2k12
231
+ where("os NOT LIKE '%Windows Server 2012%'")
232
+ end
233
+
203
234
  # Queries for hosts with a Windows 7 based Operating System
204
235
  #
205
236
  # @return [ActiveRecord::Relation] with the query results
@@ -214,12 +245,26 @@ module Risu
214
245
  where("os NOT LIKE '%Windows 7%'")
215
246
  end
216
247
 
248
+ # Queries for hosts with a Windows 8 based Operating System
249
+ #
250
+ # @return [ActiveRecord::Relation] with the query results
251
+ def os_windows_8
252
+ where("os LIKE '%Windows 8%'")
253
+ end
254
+
255
+ # Negation query for all hosts with a Windows 8 based Operating system
256
+ #
257
+ # @return [ActiveRecord::Relation] with the query results
258
+ def not_os_windows_8
259
+ where("os NOT LIKE '%Windows 8%'")
260
+ end
261
+
217
262
  # Queries for hosts with a Windows Operating System that are not 2000,
218
263
  # XP, 2003, Vista, 2008 or 7
219
264
  #
220
265
  # @return [ActiveRecord::Relation] with the query results
221
266
  def os_windows_other
222
- not_os_windows_7.not_os_windows_2k8.not_os_windows_vista.not_os_windows_2k3.not_os_windows_xp.not_os_windows_2k.not_os_windows_nt
267
+ not_os_windows_2k12.not_os_windows_8.not_os_windows_7.not_os_windows_2k8.not_os_windows_vista.not_os_windows_2k3.not_os_windows_xp.not_os_windows_2k.not_os_windows_nt
223
268
  end
224
269
 
225
270
  # Queries for all hosts with a Linux based Operating system
@@ -422,7 +467,9 @@ module Risu
422
467
  w2k3 = Host.os_windows_2k3.all.count
423
468
  vista = Host.os_windows_vista.all.count
424
469
  w2k8 = Host.os_windows_2k8.all.count
470
+ w2k12 = Host.os_windows_2k12.all.count
425
471
  w7 = Host.os_windows_7.all.count
472
+ w8 = Host.os_windows_8.all.count
426
473
  other = (Host.os_windows.os_windows_other).all.count
427
474
 
428
475
  g.data("NT", nt) if nt >= 1
@@ -431,12 +478,15 @@ module Risu
431
478
  g.data("Server 2003", w2k3) if w2k3 >= 1
432
479
  g.data("Vista", vista) if vista >= 1
433
480
  g.data("Server 2008", w2k8) if w2k8 >= 1
481
+ g.data("Server 2012", w2k12) if w2k12 >= 1
434
482
  g.data("7", w7) if w7 >= 1
483
+ g.data("8", w8) if w8 >= 1
435
484
  g.data("Other Windows", other) if other >= 1
436
485
 
437
486
  StringIO.new(g.to_blob)
438
487
  end
439
488
 
489
+ #
440
490
  #@todo comment
441
491
  #
442
492
  def windows_os_graph_text
@@ -446,10 +496,12 @@ module Risu
446
496
  w2k3 = Host.os_windows_2k3.all.count
447
497
  vista = Host.os_windows_vista.all.count
448
498
  w2k8 = Host.os_windows_2k8.all.count
499
+ w2k12 = Host.os_windows_2k12.all.count
449
500
  w7 = Host.os_windows_7.all.count
501
+ w8 = Host.os_windows_8.all.count
450
502
  other = (Host.os_windows.os_windows_other).all.count
451
503
 
452
- windows_os_count = nt + w2k + xp + w2k3 + vista + w7 + w2k8 + other
504
+ windows_os_count = nt + w2k + xp + w2k3 + vista + w7 + w8 + w2k8 + w2k12 + other
453
505
 
454
506
  nt_percent = (nt.to_f / windows_os_count.to_f) * 100
455
507
  w2k_percent = (w2k.to_f / windows_os_count.to_f) * 100
@@ -459,6 +511,8 @@ module Risu
459
511
 
460
512
  w2k8_percent = (w2k8.to_f / windows_os_count.to_f) * 100
461
513
  w7_percent = (w7.to_f / windows_os_count.to_f) * 100
514
+ w8_percent = (w8.to_f / windows_os_count.to_f) * 100
515
+ w2k12_percent = (w2k12.to_f / windows_os_count.to_f) * 100
462
516
 
463
517
  text = "This graph shows the percentage of the different Microsoft Windows based operating systems " +
464
518
  "found on the #{Report.title} network.\n\n"
@@ -470,15 +524,37 @@ module Risu
470
524
  text << "#{vista_percent.round.to_i}% of the network is Windows Vista. " if vista_percent >= 1
471
525
  text << "#{w2k8_percent.round.to_i}% of the network is Windows Server 2008. " if w2k8_percent >= 1
472
526
  text << "#{w7_percent.round.to_i}% of the network is Windows 7. " if w7_percent >= 1
527
+ text << "#{w8_percent.round.to_i}% of the network is Windows 8. " if w8_percent >= 1
528
+ text << "#{w2k12_percent.round.to_i}% of the network is Windows Server 20012. " if w2k12_percent >= 1
473
529
 
474
530
  text << "\n\n" << unsupported_os_windows if nt > 0 or w2k > 0
475
531
 
476
532
  return text
477
533
  end
478
534
 
535
+ #
536
+ # @todo comments
537
+ #
538
+ def unsupported_os?
539
+ aix_text = unsupported_os_aix
540
+ win_text = unsupported_os_windows
541
+ freebsd_text = unsupported_os_freebsd
542
+
543
+ #If all the text is nil just return nil
544
+ if aix_text == "" && win_text == "" && freebsd_text == ""
545
+ return false
546
+ end
547
+
548
+ return true
549
+ end
550
+
479
551
  # @todo add plural check
480
552
  #
481
553
  def unsupported_os_text
554
+ if !unsupported_os?
555
+ return nil
556
+ end
557
+
482
558
  aix_text = unsupported_os_aix
483
559
  win_text = unsupported_os_windows
484
560
  freebsd_text = unsupported_os_freebsd
@@ -505,7 +581,8 @@ module Risu
505
581
  win_98 = Host.os_windows_98
506
582
  win_me = Host.os_windows_me
507
583
  win_nt = Host.os_windows_nt
508
- win_2000 = Host.os_windows_2k
584
+ #win_2000 = Host.os_windows_2k
585
+ win_2000 = Plugin.where(:plugin_name => "Microsoft Windows 2000 Unsupported Installation Detection")
509
586
 
510
587
  #Host.os_windows.not_os_windows_7.not_os_windows_2008.not_os_windows_vista.not_os_windows_2003.not_os_windows_xp
511
588
 
@@ -575,10 +652,10 @@ module Risu
575
652
 
576
653
  #todo add other os's here
577
654
 
578
- text << "#{linux_percent.to_i}% of the network is running an Linux based operating system. " if linux_percent >= 1
579
- text << "#{aix_percent.to_i}% of the network is running an AIX based operating system. " if aix_percent >= 1
580
- text << "#{freebsd_percent.to_i}% of the network is running an FreeBSD based operating system. " if freebsd_percent >= 1
581
- text << "#{vmware_percent.to_i}% of the network is running an VMware based operating system. " if vmware_percent >= 1
655
+ text << "#{linux_percent.to_i}% of the non-windows network is running an Linux based operating system. " if linux_percent >= 1
656
+ text << "#{aix_percent.to_i}% of the non-windows network is running an AIX based operating system. " if aix_percent >= 1
657
+ text << "#{freebsd_percent.to_i}% of the non-windows network is running an FreeBSD based operating system. " if freebsd_percent >= 1
658
+ text << "#{vmware_percent.to_i}% of the non-windows network is running an VMware based operating system. " if vmware_percent >= 1
582
659
 
583
660
  text << "\n\n"<< unsupported_os_aix if aix > 0
584
661
  text << "\n\n" << unsupported_os_freebsd if freebsd > 0
@@ -586,7 +663,9 @@ module Risu
586
663
  return text
587
664
  end
588
665
 
666
+ #
589
667
  # @todo comments
668
+ #
590
669
  def top_n_vulnerable(n)
591
670
  hosts = Item.risks_by_host(Host.all.count).count
592
671
  hosts = hosts.sort_by {|k, v| v}
@@ -601,14 +680,18 @@ module Risu
601
680
  hosts[0...n]
602
681
  end
603
682
 
683
+ #
604
684
  # @todo comments
685
+ #
605
686
  def unique_hosts_with_critical
606
687
  hosts = Item.critical_risks_by_host(Host.all.count).count
607
688
  hosts = hosts.sort_by {|k, v| v}
608
689
  hosts.reverse!
609
690
  end
610
691
 
692
+ #
611
693
  # @todo comments
694
+ #
612
695
  def unique_hosts_with_high
613
696
  hosts = Item.high_risks_by_host(Host.all.count).count
614
697
  hosts = hosts.sort_by {|k, v| v}
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2012 Arxopia LLC.
1
+ # Copyright (c) 2010-2013 Arxopia LLC.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -190,6 +190,24 @@ module Risu
190
190
  select("items.*").select("count(*) as count_all").joins(:host).where("plugin_id != 1").where(:severity => 3).group(:host_id).order("count_all DESC").limit(limit)
191
191
  end
192
192
 
193
+ # Queries for all the Medium risks by host
194
+ #
195
+ # @param limit Limits the result to a specific number, default 10
196
+ #
197
+ # @return [ActiveRecord::Relation] with the query results
198
+ def medium_risks_by_host(limit=10)
199
+ select("items.*").select("count(*) as count_all").joins(:host).where("plugin_id != 1").where(:severity => 2).group(:host_id).order("count_all DESC").limit(limit)
200
+ end
201
+
202
+ # Queries for all the Low risks by host
203
+ #
204
+ # @param limit Limits the result to a specific number, default 10
205
+ #
206
+ # @return [ActiveRecord::Relation] with the query results
207
+ def low_risks_by_host(limit=10)
208
+ select("items.*").select("count(*) as count_all").joins(:host).where("plugin_id != 1").where(:severity => 1).group(:host_id).order("count_all DESC").limit(limit)
209
+ end
210
+
193
211
  # Queries for all the hosts with the Microsoft patch summary plugin (38153)
194
212
  #
195
213
  # @return [ActiveRecord::Relation] with the query results
@@ -306,6 +324,7 @@ module Risu
306
324
  StringIO.new(g.to_blob)
307
325
  end
308
326
 
327
+ #
309
328
  # @todo comment
310
329
  #
311
330
  def calculate_vulnerable_host_percent
@@ -323,6 +342,7 @@ module Risu
323
342
  host_percent = (hosts_with_critical.count.to_f / Host.all.count.to_f) * 100
324
343
  end
325
344
 
345
+ #
326
346
  # @todo comments
327
347
  #
328
348
  def ajective_for_risk_text risk_percent
@@ -340,6 +360,7 @@ module Risu
340
360
  end
341
361
  end
342
362
 
363
+ #
343
364
  # @todo comments
344
365
  #
345
366
  def risk_text risk_percent
@@ -396,17 +417,25 @@ module Risu
396
417
  return graph_text
397
418
  end
398
419
 
420
+ #
421
+ # @todo comment
422
+ #
423
+ def notable_order_by_cvss_raw
424
+ return Item.joins(:plugin).where(:severity => 4).order("plugins.cvss_base_score").count(:all, :group => :plugin_id)
425
+ end
426
+
427
+ #
428
+ # @todo comment
429
+ #
430
+ def scrub_plugin_name (name)
431
+ return name.gsub("(remote check)", "").gsub("(uncredentialed check)", "").gsub(/(\(\d.*\))/, "")
432
+ end
433
+
434
+ #
399
435
  # @todo comment
436
+ #
400
437
  def top_10_sorted_raw
401
- raw = nil
402
-
403
- if ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /sqlite/
404
- raw = Item.joins(:plugin).where(:severity => 4).order("CAST(plugins.cvss_base_score AS REAL)").count(:all, :group => :plugin_id)
405
- elsif ActiveRecord::Base.connection.instance_values["config"][:adapter] =~ /mysql/
406
- raw = Item.joins(:plugin).where(:severity => 4).order("CAST(plugins.cvss_base_score AS DECIMAL(2,2))").count(:all, :group => :plugin_id)
407
- else
408
- raw = Item.joins(:plugin).where(:severity => 4).order(:plugins.cvss_base_score).count(:all, :group => :plugin_id)
409
- end
438
+ raw = notable_order_by_cvss_raw
410
439
 
411
440
  data = Array.new
412
441
 
@@ -427,9 +456,11 @@ module Risu
427
456
  return data
428
457
  end
429
458
 
459
+ #
460
+ # @todo comment
461
+ #
430
462
  def top_10_sorted
431
- #raw = Item.where(:severity => 3).count(:all, :group => :plugin_id)
432
- raw = Item.joins(:plugin).where(:severity => 4).order(:cvss_base_score).count(:all, :group => :plugin_id)
463
+ raw = notable_order_by_cvss_raw
433
464
  data = Array.new
434
465
 
435
466
  raw.each do |vuln|
@@ -437,7 +468,7 @@ module Risu
437
468
  plugin_id = vuln[0]
438
469
  count = vuln[1]
439
470
 
440
- name = Plugin.find_by_id(plugin_id).plugin_name
471
+ name = scrub_plugin_name(Plugin.find_by_id(plugin_id).plugin_name)
441
472
 
442
473
  row.push(name)
443
474
  row.push(count)
@@ -476,6 +507,9 @@ module Risu
476
507
  select("items.*").select("count(*) as count_all").group(:plugin_id).order("count_all DESC")
477
508
  end
478
509
 
510
+ def plugin
511
+ Plugin.where(:id => Item.first.attributes["plugin_id"])
512
+ end
479
513
  end
480
514
  end
481
515
  end