Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Credentials method fails (some params missing in api call) #261

Closed
monkykap opened this issue Feb 28, 2017 · 15 comments
Closed

Test Credentials method fails (some params missing in api call) #261

monkykap opened this issue Feb 28, 2017 · 15 comments
Labels

Comments

@monkykap
Copy link

monkykap commented Feb 28, 2017

Expected Behavior

XML response should return success="1" confirming authentication was successful same as console ui. Also parameters for the api call should match value made by the console.

Current Behavior

Receive error message in XML response (success="0") using same credential set that is working when scanning using the API.

nexpose_1

Working response from console ui:
nexpose_2

Possible Solution

I’m pretty new to ruby but I think something is off between the naming for the attribute/accessor methods between the two classes (SharedCredentialSummary inherits from Credential and SharedCredential inherits from SharedCredentialSummary) that is causing the discrepancy.

SharedCredentialSummary accessors:
nexpose_8

Shared Credential accessors:
nexpose_9

Assignment in Credential:
nexpose_10

Steps to Reproduce (for bugs)

  1. Create a set of credentials using client SharedCredentials
    nexpose_4
  2. Use test method to check if credentials are able to authenticate

nexpose_5
nexpose_11

  1. Use proxy to check API request being made by client:
    nexpose_7
  2. Compare to parameters made by console using proxy or browser extension (tamper data)
    nexpose_6
    Note: Some parameters set in SharedCredentials missing.

Ruby code that reproduces the issue:

#!/usr/bin/env ruby 

require 'nexpose'  
require 'csv' 

@host = '127.0.0.1'  
@userid = ''  
@password = ''  

str = '
 ____ ____ ____ ____ ____ ____ ____ _________ ____ ____ ____ ____ ____ 
||N |||e |||x |||p |||o |||s |||e |||       |||A |||d |||h |||o |||c ||
||__|||__|||__|||__|||__|||__|||__|||_______|||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/_______\|/__\|/__\|/__\|/__\|/__\|
 ____ ____ ____ ____ ____ ____ 
||C |||l |||i |||e |||n |||t ||
||__|||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|/__\|'


puts str
puts "\n\n\n"
      
nsc = Nexpose::Connection.new(@host, @userid, @password)  
puts 'Logging into Nexpose'  
nsc.login  
puts 'Logged into Nexpose'


=begin
list_templates = nsc.list_report_templates

list_templates.each do |template|
  puts template.id
end
=end

dmz_engine = '6'
list_engines = nsc.list_engines
list_engines.each do |engine|
	if engine.name == 'DMZ'
		dmz_engine = engine.id
	end

	if engine.name == '10.120.1.61(internal)'	
		internal_engine = engine.id
		puts internal_engine
	end
end

internal_site = '16'
dmz_site = '2'
list_sites = nsc.list_sites
list_sites.each do |site|
	if site.name == '(DISC)INTERNAL_SERVER'
		internal_site = site.id
	end
	
	if site.name == '(DISC)DMZ'
		dmz_site = site.id
	end
end


 
puts 'What is the IP of the server?'
@device_ip = $stdin.gets.chomp

ip_ad= @device_ip
#ip_ad.gsub('_','.')

puts "Is the host in the DMZ?\n\t1) Yes\n\t2) No\n"
option_dmz = $stdin.gets.chomp

if option_dmz == '1' || option_dmz == 'dmz' || option_dmz == 'Dmz' || option_dmz == 'DMZ' || option_dmz == 'Yes' || option_dmz == 'yes' || option_dmz == 'YES'
	dmz = true
	@dmz = "Yes"
else
	dmz = false
	@dmz = "No"
end

#Credentials
puts "What type of System is it?\n\t1) Windows\n\t2) Unix\n"
option = $stdin.gets.chomp

cred_list= nsc.shared_credentials

if option == '1' || option == 'Windows' || option == 'WINDOWS' || option == 'Window' || option == 'window' || option == 'WINDOW'

postscript = rand(1..1000)
@name = 'WindowsTeamTemporarySite' + postscript.to_s  

puts "Creating site #{@name}"  
site = Nexpose::Site.new(@name)  
site.include_asset(@device_ip) 

if dmz == true
site.engine_id = dmz_engine
else
end

site.save(nsc)  
puts 'Created site successfully'  

windows_cred = '1'
cred_list.each do |cred|
	if cred.name == 'Test' 
		windows_cred = cred.id	
	end
end

cred = Nexpose::SharedCredential.load(nsc, windows_cred)
cred.sites << site.id
cred.save(nsc)

elsif option == '2' || option == 'Unix' || option == 'Linux' || option == 'UNIX' || option == 'unix' || option == 'linux' || option == 'LINUX'


postscript = rand(1..1000)
@name = 'UnixTeamTemporarySite' + postscript.to_s  


if dmz == true
site.engine_id = dmz_engine
else
end

puts "Creating site #{@name}"  
site = Nexpose::Site.new(@name)  
site.include_asset(@device_ip) 
site.save(nsc)  
puts 'Created site successfully'  

cred_name = '(UNIX)' + @device_ip + Time.now.strftime('_%Y-%m-%d_%H-%M-%S')
cred = Nexpose::SharedCredential.new(cred_name)
cred.service = Nexpose::Credential::Service::SSH
puts 'What is the SSH account username'
cred.username= gets.chomp
cred.privilege_type = Nexpose::Credential::ElevationType::SUDO
cred.privilege_username = 'root'
puts 'What is the account password?'
cred.password = gets.chomp
puts 'Thank you. Please make sure this account can sudo to root.'
cred.privilege_password = cred.password 
cred.host = @device_ip
puts 'Please specify SSH Port (default 22)'
cred.port = gets.chomp 

=begin
rescue false
if cred.port == false
	puts 'Invalid type. Should be integer for port. Please restart script and enter correct type.'
	site.delete(nsc)
	nsc.logout
	exit 1
end
=end
cred.sites << site.id 

if dmz == true
	cred.sites << dmz_site
else
	cred.sites << internal_site
end



#result = cred.test(nsc, @device_ip, 5 , site.id)
#puts result


cred.save(nsc)

result = cred.test(nsc, @device_ip, 5, site.id)
puts result


else
  site.delete(nsc)  
  nsc.logout  
  exit 1  
  puts "Please Restart Script and choose 1 for Windows or 2 for Unix"
end

puts 'Starting scan'  
scan = site.scan(nsc)

begin  
  sleep(15)  
  status = nsc.scan_status(scan.id)  
  puts "Current scan status: #{status.to_s}"  
end while status == Nexpose::Scan::Status::RUNNING  

begin  
  sleep(15)  
  status = nsc.scan_status(scan.id)  
  puts "Current scan status: #{status.to_s}"  
end while status != Nexpose::Scan::Status::FINISHED  



query = "  
  SELECT DISTINCT ip_address, mac_address, host_name, title, date_published, severity, riskscore, summary, fix  
  
  FROM fact_asset_scan_vulnerability_finding  
   JOIN dim_asset USING (asset_id)  
   JOIN dim_vulnerability USING (vulnerability_id)  
   JOIN dim_vulnerability_solution USING (vulnerability_id)  
   JOIN dim_solution_highest_supercedence USING (solution_id)  
   JOIN dim_solution ds ON superceding_solution_id = ds.solution_id"  


    if status == Nexpose::Scan::Status::FINISHED  
      time = Time.now.strftime('_%Y-%m-%d_%H-%M-%S')
      dir_name = ip_ad + '/'
      puts "\nScan complete, generating report"  
      
      if File.exist?(dir_name) == false
        Dir.mkdir(dir_name, 0700)
      end
      
      report = Nexpose::AdhocReportConfig.new(nil, 'sql')  
      report.add_filter('version', '1.1.0')  
      report.add_filter('query', query)  
      report.add_filter('site', site.id)  
      report_output = report.generate(nsc)  
      csv_output = CSV.parse(report_output.chomp, { :headers => :first_row })  
      file_name_csv = 'adhoc-' + ip_ad + '-export' + time + '.csv'
      CSV.open(dir_name + file_name_csv, 'wb') do |csv_file|  
        csv_file << csv_output.headers  
        csv_output.each do |row|  
          csv_file << row  
        end  

      adhoc = Nexpose::AdhocReportConfig.new('prioritized-remediations-with-details', 'pdf', site.id)
      data = adhoc.generate(nsc)
     
      file_name_pdf = 'adhoc-' + ip_ad + '-top-remediation'+ time + '.pdf'
      File.open(dir_name + file_name_pdf, 'wb') { |file| file.write(data) }


      end  
    else  
      puts "It failed!"  
      site.delete(nsc)  
      nsc.logout  
      exit 1  
    end  



puts 'Report generation completed and saved, deleting site'  

=begin
puts cred_name
cred_list = nsc.shared_credentials
cred_list.each do |cred|
	puts cred.name
        if cred.name == cred_name 
                unix_cred = cred.id
		# Disable this credential on this site only.
		puts cred.id
		cred = Nexpose::SharedCredential.load(nsc, unix_cred)
		cred.disabled << site.id 
		cred.save(nsc)
        end
end
=end

site.delete(nsc)
puts 'Site deleted, logging out'  
nsc.logout  
exit  

Context

Trying to create Ad-Hoc Client for Server Build Process and other Business/Security Processes. Would like the AdHoc-Client to be able to test credentials and use the api call to validate user entered credentials work. This will help us automate some of the management of new credentials for assets in the credential manager for new assets (Unix/Linux Systems). It would be great if the object returned by shared credential list would in the future be able to perform test credential (currently not supposed to work and unrelated issue/feature request).

Your Environment

  • Nexpose gem version: 5.2.0
  • Ruby version: 2.3.3
  • Operating System and version: Kali Linux 2 (release kali-rolling)
  • Nexpose product version: 6.4.22
@sgreen-r7
Copy link
Contributor

First off, thank you SO much for the detail of this issue.
Going to verify that we are able to reproduce the issue, then we'll reply back asap.

And thank you for all the detail, and the time you spent bringing this to our attention!

@sgreen-r7
Copy link
Contributor

K, we've been able to confirm this is in fact a defect. We're going to try and see if we can find the best solution, and update (sometime today) with a better timeline when the fix should go out.

Thank you again @monkykap

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

You are very welcome. Thank you for supporting the API with a ruby client! We think it is very helpful in quickly addressing our team's use cases and adding automated functionality to to the existing Nexpose product.

@sgreen-r7
Copy link
Contributor

sgreen-r7 commented Mar 1, 2017

@monkykap let's see if this fixes your issue; try using the gem on the shared_cred_test branch. Hopefully that should fix it.

Can you let us know if all your use cases work correctly using this branch of the gem?

If you're using a Gemfile you can specify using this branch as follows:

gem 'nexpose`, github: 'rapid7/nexpose-client', branch: 'shared_cred_test'

Then after you bundle install again, you should be using that version of the nexpose gem.

If you're not using a Gemfile, then you'd have to clone our repo, checkout the branch, then build the gem locally, and install it.

As soon as you let us know this patch fixed your issue, we can go ahead and do an actual new release of the gem. Thanks again!!

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

@sgreen-r7 I installed gem from github, however I am still getting same results. I am not 100% sure the gem I installed was from the correct branch of the repo (not sure the checkout worked). Is there a specific line in the one of the classes you can point me to so I can verify the correct branch w/ the changes was installed. Thank you.

@sgreen-r7
Copy link
Contributor

@monkykap One thing that i probably should have mentioned is you should gem uninstall nexpose prior to installing the gem you've built locally.

Make sure you go ahead and do that, prior to checking the code of the gem you've installed.

You can see the lines I've added by viewing the pull request I have open. Also the SharedCredentials class will have it's own .test method

Let me know how that goes, or if you have any additional questions about testing the feature.
Thanks again.

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

I uninstalled old gem afterwards (it was version 5.2.0) so i don't think that is causing it, but i will make sure to uninstall before for future installs. I confirmed the one I installed does not have the new test method in sharedcredential. I will try re-installing gem. When i checkout the branch i get the following:

git checkout -b shared_cred_test nexpose-client/lib/nexpose/
fatal: Cannot update paths and switch to branch 'shared_cred_test' at the same time.
Did you intend to checkout 'nexpose-client/lib/nexpose/' which can not be resolved as commit?

Can you please help me with this command; i tried a few different paths with same error.

@sgreen-r7
Copy link
Contributor

you should only need to use git checkout shared_cred_test

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

okay,started from scratch:

uninstalled nexpose gem
cloned repo
cd nexpose-client

i get error on rake, should i proceed with installing the built gem?

root@kali:/Nexpose# cd nexpose-client
root@kali:
/Nexpose/nexpose-client# ls
COPYING examples Gemfile lib nexpose.gemspec Rakefile README.markdown scripts spec test
root@kali:/Nexpose/nexpose-client# git checkout shared_cred_test
Branch shared_cred_test set up to track remote branch shared_cred_test from origin.
Switched to a new branch 'shared_cred_test'
root@kali:
/Nexpose/nexpose-client# rake build gem
nexpose 5.3.0 built to pkg/nexpose-5.3.0.gem.
rake aborted!
Don't know how to build task 'gem' (see --tasks)
/var/lib/gems/2.2.0/gems/rake-11.2.2/exe/rake:27:in `<top (required)>'
(See full trace by running task with --trace)

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

i wonder if i should just do rake install instead?

edit: i will try again with rake build; rake install.

root@kali:/Nexpose/nexpose-client# cd pkg
root@kali:
/Nexpose/nexpose-client/pkg# ls
nexpose-5.3.0.gem
root@kali:/Nexpose/nexpose-client/pkg# --tasks
bash: --tasks: command not found
root@kali:
/Nexpose/nexpose-client/pkg# rake --tasks
(in /root/Nexpose/nexpose-client)
rake build # Build nexpose-5.3.0.gem into the pkg directory
rake install # Build and install nexpose-5.3.0.gem into system gems
rake install:local # Build and install nexpose-5.3.0.gem into system gems without network ac...
rake release # Create tag v5.3.0 and build and push nexpose-5.3.0.gem to Rubygems

@sgreen-r7
Copy link
Contributor

Alright, looks like that article I linked was a but old; the rake command has been updated.
Here should be the full process:

┌─[ruby-2.2.3@global] - [~] - [2017-03-01 03:47:03]
└─[0] <$> git clone git@github.com:rapid7/nexpose-client.git
Cloning into 'nexpose-client'...
remote: Counting objects: 5092, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5092 (delta 0), reused 0 (delta 0), pack-reused 5087
Receiving objects: 100% (5092/5092), 1.15 MiB | 1.00 MiB/s, done.
Resolving deltas: 100% (3427/3427), done.

┌─[ruby-2.2.3@global] - [~] - [2017-03-01 03:47:13]
└─[0] <$> cd nexpose-client

┌─[ruby-2.2.3@global] - [~/nexpose-client] - [2017-03-01 03:47:16]
└─[0] <git:(master e91dbfa) $> git checkout shared_cred_test
Branch shared_cred_test set up to track remote branch shared_cred_test from origin.
Switched to a new branch 'shared_cred_test'

┌─[ruby-2.2.3@global] - [~/nexpose-client] - [2017-03-01 03:47:51]
└─[0] <git:(shared_cred_test 476c8b8) $> rake install
nexpose 5.3.0 built to pkg/nexpose-5.3.0.gem.
nexpose (5.3.0) installed.

┌─[ruby-2.2.3@global] - [~/nexpose-client] - [2017-03-01 03:48:00]
└─[0] <git:(shared_cred_test 476c8b8) $> gem list | grep -i nexpose
nexpose (5.3.0)

@monkykap
Copy link
Author

monkykap commented Mar 1, 2017

nexpose_12
Works! test method returns true.

@sgreen-r7
Copy link
Contributor

Awesome! Thanks for working through it. We'll look to doing a public release by the end of today. So be only the lookout for 5.3.1 shortly.

Thanks again for your help and bringing this to our attention!

@sgreen-r7
Copy link
Contributor

Cool, going to close out this issue, and this fix was pushed live with Release 5.3.1.

@monkykap
Copy link
Author

monkykap commented Mar 2, 2017

Thank you for resolving this so quickly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants