nexty 0.20

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.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.csv
2
+ *.swp
3
+ config.yaml
4
+ *.gem
5
+ *.rbc
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@nexty
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "nexpose"#, :git=>"git@github.com:thesp0nge/nexpose-client.git", :branch=>"devel"
4
+ gem "rainbow"
5
+ gem "rake"
6
+ gem "rspec"
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2012 Paolo Perego
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Nexty
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'nexty'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install nexty
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
8
+ task :test => :spec
data/bin/nexty ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class String
4
+ def starts_with?(pattern)
5
+ ! self.match(/^#{pattern}/).nil?
6
+ end
7
+ end
8
+
9
+ class Numeric
10
+ def duration
11
+ secs = self.to_int
12
+ mins = secs / 60
13
+ hours = mins / 60
14
+ days = hours / 24
15
+
16
+ return "#{days} days and #{hours % 24} hours" if days > 0
17
+ return "#{hours} hours and #{mins % 60} minutes" if days == 0 and hours > 0
18
+ return "#{mins} minutes and #{secs % 60} seconds" if days == 0 and hours == 0 and mins > 0
19
+ return "#{secs} seconds" if days == 0 and hours == 0 and mins == 0
20
+ end
21
+ end
22
+
23
+ if RUBY_VERSION.split('.')[1] == "8"
24
+ require 'rubygems'
25
+ end
26
+
27
+ require 'time'
28
+ require 'rainbow'
29
+ require 'nexpose'
30
+ require 'nexty'
31
+ require 'getoptlong'
32
+ require 'csv'
33
+
34
+ opts = GetoptLong.new(
35
+ [ '--report', '-r', GetoptLong::REQUIRED_ARGUMENT ],
36
+ [ '--host', '-H', GetoptLong::REQUIRED_ARGUMENT ],
37
+ [ '--full-export', '-f', GetoptLong::REQUIRED_ARGUMENT ],
38
+ [ '--download', '-d', GetoptLong::REQUIRED_ARGUMENT ]
39
+ )
40
+
41
+
42
+
43
+ trap("INT") { puts '['+'INTERRUPTED'.color(:red)+']'; exit -1 }
44
+
45
+
46
+ # templates = nsc.report_template_listing
47
+ #
48
+ # templates.each do |template|
49
+ # p template[:template_id]
50
+ # end
51
+
52
+ conn = Nexty::Connector.new
53
+ nsc = conn.nsc
54
+
55
+ begin
56
+ printf "Connecting to #{conn.config["config"]["host"]}:#{conn.config["config"]["port"]} - ".color(:white)
57
+ nsc.login
58
+ rescue ::Nexpose::APIError => e
59
+ printf "failed\n".color(:red)
60
+ $stderr.puts("#{e.reason}")
61
+ exit(1)
62
+ end
63
+ printf "succeded\n".color(:green)
64
+
65
+
66
+ opts.each do |opt, arg|
67
+ case opt
68
+
69
+ when '--download'
70
+
71
+ file_name = "export_#{Time.now.strftime("%Y%m%d%H%M%s")}.csv"
72
+ puts "Report saved: #{Nexty::Report.download(arg, file_name, nsc)}".color(:white)
73
+
74
+ when '--full-export'
75
+
76
+ fn = Nexty::Report.generate_from_a_template(arg, nsc)
77
+ file_name = "export_#{Time.now.strftime("%Y%m%d%H%M%s")}.csv"
78
+ nsc.logout
79
+ begin
80
+ printf "Connecting to #{conn.config["config"]["host"]}:#{conn.config["config"]["port"]} - ".color(:white)
81
+ nsc.login
82
+ rescue ::Nexpose::APIError => e
83
+ printf "failed\n".color(:red)
84
+ $stderr.puts("#{e.reason}")
85
+ exit(1)
86
+ end
87
+ printf "succeded\n".color(:green)
88
+
89
+ puts "Report saved: #{Nexty::Report.download(fn, file_name, nsc)}".color(:white)
90
+
91
+ when '--report'
92
+ fn = Nexty::Report.generate_from_a_list_of_sites(arg, nsc)
93
+ puts "Report saved: #{fn}".color(:white)
94
+
95
+ when '--host'
96
+
97
+ dev= Nexty::Device.find_by_address(nsc, arg)
98
+ if ! dev.nil?
99
+ puts "#{dev.address} found @ site #{dev.site_id}. Risk score = #{dev.riskscore} * #{dev.riskfactor}".color(:green)
100
+ else
101
+ puts "#{arg} not found".color{:red}
102
+ end
103
+ end
104
+ end
105
+
106
+
107
+ nsc.logout
@@ -0,0 +1,6 @@
1
+ config:
2
+ host: "127.0.0.1"
3
+ port: "3790"
4
+ user: "nxadmin"
5
+ pass: "nxadmin"
6
+
@@ -0,0 +1,19 @@
1
+ require 'singleton'
2
+ require 'yaml'
3
+
4
+ module Nexty
5
+ class Config
6
+ include Singleton
7
+
8
+ def read(file)
9
+ if file.nil? or !File.exists?(file)
10
+ return {"config" => {"host"=>"127.0.0.1", "port"=>"3790", "user"=>"nxadmin", "pass"=>"nxadmin"}}
11
+ end
12
+ config = YAML.load_file(file)
13
+
14
+ return config
15
+ end
16
+
17
+
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ require 'nexty/config'
2
+ module Nexty
3
+ class Connector
4
+
5
+ attr_reader :nsc, :config
6
+ def initialize(file="./conf/config.yaml")
7
+ @config = Nexty::Config.instance.read(file)
8
+ @nsc = Nexpose::Connection.new(@config["config"]["host"],
9
+ @config["config"]["user"],
10
+ @config["config"]["pass"],
11
+ @config["config"]["port"])
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module Nexty
2
+ class Device
3
+ def self.all(connection)
4
+ @devices = []
5
+
6
+ r = connection.execute('<SiteDeviceListingRequest session-id="' + connection.session_id + '"/>')
7
+ if (r.success)
8
+ r.res.elements.each('SiteDeviceListingResponse/SiteDevices') do |rr|
9
+ @sid = rr.attribute("site-id")
10
+ rr.elements.each('device') do |d|
11
+ @devices.push(Nexpose::Device.new(d.attributes['id'], @sid, d.attributes["address"], d.attributes["riskfactor"], d.attributes['riskscore']))
12
+ end
13
+ end
14
+ end
15
+ @devices
16
+ end
17
+
18
+ def self.find_by_address(connection, address)
19
+ devices = Nexty::Device.all(connection)
20
+ devices.each do |d|
21
+ if d.address == address
22
+ return d
23
+ end
24
+ end
25
+
26
+ return nil
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ module Nexty
2
+ class Report
3
+
4
+ # def self.generate_from_ip_list(ip_list, nsc)
5
+ # ips = Nexty::Sites.load_from_file(ip_list)
6
+
7
+ # report = Nexpose::ReportAdHoc.new(nsc, 'SOX Vulns', 'csv')
8
+ # ips.each do |ip|
9
+ # report.addFilter('device',addFilter('device',
10
+ # end
11
+ # end
12
+
13
+
14
+ def self.download(url, filename, nsc)
15
+ return nil if url.nil? or url.empty?
16
+ uri = URI.parse(url)
17
+ http = Net::HTTP.new(uri.host, uri.port)
18
+ http.use_ssl = true
19
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE # XXX: security issue
20
+ headers = {'Cookie' => "nexposeCCSessionID=#{nsc.session_id}"}
21
+ resp = http.get(uri.path, headers)
22
+
23
+ file = File.open(filename, "w")
24
+ file.write(resp.body)
25
+ file.close
26
+
27
+ filename
28
+ end
29
+
30
+ def self.generate(nsc, list, options={:template=>'', :filename=> '', :format=>"csv", :scan_to_include=>1})
31
+
32
+ options[:filename] = "export_#{Time.now.strftime("%Y%m%d%H%M%s")}.csv" if options[:filename].nil? or options[:filename].empty?
33
+ report = Nexpose::ReportConfig.new(nsc)
34
+ report.set_name(options[:filename])
35
+ report.set_template_id(options[:template])
36
+ report.set_format(options[:format])
37
+
38
+ list.each do |item|
39
+ site_config = Nexpose::SiteConfig.new
40
+ site_config.getSiteConfig(nsc, item[:site_id])
41
+ scan_history = nsc.site_scan_history(item[:site_id])
42
+ scan_history.sort! { |a,b| b[:start_time] <=> a[:start_time]}
43
+ scan_history.take(options[:scan_to_include]).each do |scan|
44
+ report.addFilter('scan', scan[:scan_id])
45
+ end
46
+ end
47
+
48
+ report.saveReport
49
+
50
+ url = nil
51
+ while not url
52
+ url = nsc.report_last(report.config_id)
53
+ select(nil, nil, nil, 10)
54
+ end
55
+
56
+ full_url="https://#{nsc.host}:#{nsc.port}#{url}"
57
+
58
+ {:url=>full_url, :filename=>options[:filename]}
59
+ end
60
+
61
+ def self.generate_from_a_template(template_name, nsc)
62
+ sites=nsc.site_listing
63
+ result = Nexty::Report.generate(nsc, sites, {:template=>template_name, :filename=>nil, :format=>'csv', :scan_to_include=>1})
64
+ result[:url]
65
+ end
66
+
67
+ def self.generate_from_a_list_of_sites(site_list=nil, nsc)
68
+ sites=Nexty::Sites.load_from_file(site_list)
69
+ s = []
70
+ sites.each do |site|
71
+ s << nsc.find_site_by_name(site)
72
+ end
73
+ result = Nexty::Report.generate(nsc, s, {:template=>"template-per-vulnerability-meeting", :format=>'csv', :filename=>nil, :scan_to_include=>4})
74
+ Nexty::Report.download(result[:url], result[:filename], nsc)
75
+ end
76
+ end
77
+ end
data/lib/nexty/site.rb ADDED
@@ -0,0 +1,56 @@
1
+ module Nexty
2
+ class Sites
3
+ # Public: load site names from a text file returning it in an array
4
+ #
5
+ # file - the filename
6
+ #
7
+ # Example
8
+ # Nexty::Sites.load_from_file('./important_sites.txt')
9
+ # # => ['www', 'mail', 'dns']
10
+ #
11
+ # Nexty::Sites.load_from_file('./doesnt_exists_file.foo')
12
+ # # => []
13
+ #
14
+ # Returns an Array containing the site names or an empty Array if the file
15
+ # doesn't exist.
16
+ def self.load_from_file(file)
17
+ if !File.exists?(file)
18
+ return []
19
+ end
20
+
21
+ ret = []
22
+ File.open(file).each_line{ |s|
23
+ ret << s.chomp
24
+ }
25
+
26
+ ret
27
+
28
+ end
29
+ end
30
+ end
31
+
32
+ module Nexpose
33
+ module NexposeAPI
34
+ include XMLUtils
35
+
36
+ def find_site_by_name(name)
37
+ r = execute(make_xml('SiteListingRequest', {}))
38
+ res = {}
39
+
40
+ if (r.success)
41
+ r.res.elements.each("//SiteSummary") do |site|
42
+ if (site.attributes['name'] == name)
43
+ res = {
44
+ :site_id => site.attributes['id'].to_i,
45
+ :name => site.attributes['name'].to_s,
46
+ :risk_factor => site.attributes['riskfactor'].to_f,
47
+ :risk_score => site.attributes['riskscore'].to_f,
48
+ }
49
+ end
50
+ end
51
+ end
52
+ res
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,3 @@
1
+ module Nexty
2
+ VERSION = "0.20"
3
+ end
data/lib/nexty.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'nexty/version'
2
+ require 'nexty/connector'
3
+ require 'nexty/site'
4
+ require 'nexty/report'
5
+ require 'nexty/device'
data/nexty.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nexty/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Paolo Perego"]
6
+ gem.email = ["thesp0nge@gmail.com"]
7
+ gem.description = %q{A command line interface to your Nexpose VA tool}
8
+ gem.summary = %q{A command line interface to your Nexpose VA tool}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "nexty"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Nexty::VERSION
17
+
18
+ end
@@ -0,0 +1,5 @@
1
+ a
2
+ b
3
+ c
4
+ d
5
+ e
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Site loading from file " do
4
+ it "should return an empty array if the file doesn't exist" do
5
+ a = Nexty::Sites.load_from_file('./spec/data/sites_non_existant.txt')
6
+ a.should be_empty
7
+ a.should_not be_nil
8
+ end
9
+
10
+ it "should return an array with site names" do
11
+ a = Nexty::Sites.load_from_file('./spec/data/sites.txt')
12
+ a.should_not be_empty
13
+ a.should include 'a'
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ require 'nexty'
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexty
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.20'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paolo Perego
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A command line interface to your Nexpose VA tool
15
+ email:
16
+ - thesp0nge@gmail.com
17
+ executables:
18
+ - nexty
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .rvmrc
24
+ - Gemfile
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/nexty
29
+ - conf/config.yaml.sample
30
+ - lib/nexty.rb
31
+ - lib/nexty/config.rb
32
+ - lib/nexty/connector.rb
33
+ - lib/nexty/device.rb
34
+ - lib/nexty/report.rb
35
+ - lib/nexty/site.rb
36
+ - lib/nexty/version.rb
37
+ - nexty.gemspec
38
+ - spec/data/sites.txt
39
+ - spec/nexty_site_spec.rb
40
+ - spec/spec_helper.rb
41
+ homepage: ''
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ segments:
54
+ - 0
55
+ hash: -671521822909928412
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.24
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: A command line interface to your Nexpose VA tool
68
+ test_files:
69
+ - spec/data/sites.txt
70
+ - spec/nexty_site_spec.rb
71
+ - spec/spec_helper.rb