Forgive me guys, new to Ruby, actually this is the first lang I have taken up, so be gentle with me ok?
Writing a mod for Metasploit which will scan a system or net for 302/500 errors on the file ScriptResource.axd which can be used in further attacks.
It starts, it runs, then crashes with error:
msf auxiliary(Scriptresource) > exploit
[*] hxxp://192.168.0.18:80 hxxp://192.168.0.18:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.5:80 hxxp://192.168.0.5:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.106:80 hxxp://192.168.0.106:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.4:80 hxxp://192.168.0.4:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.43:80 hxxp://192.168.0.43:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[*] hxxp://192.168.0.236:80 hxxp://192.168.0.236:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[*] hxxp://192.168.0.238:80 hxxp://192.168.0.238:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[-] Auxiliary failed: NoMethodError undefined method `code' for nil:NilClass
[-] Call stack:
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:50:in `block in run_host'
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:39:in `each'
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:39:in `run_host'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/auxiliary/scanner.rb:92:in `block in run'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/thread_manager.rb:64:in `call'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/thread_manager.rb:64:in `block in
Here is the Program:
require 'rex/proto/http'
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::WmapScanDir
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'ScriptResource Scanner',
'Description' => %q{
This module Will scan for the 302/500 response codes associated
with ScriptResource.axd on a traget machine or network. This
file is required for ASP.Net Oracle Padding attack.
},
'Author' => [ 'MyChickenNinja' ],
'License' => BSD_LICENSE,))
register_options(
[
OptString.new('PATH', [ true, "The path to identify vulnerable files", '/',
]
)
], self.class)
end
def run_host(ip)
cypher = ['scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1']
conn = false
spath = datastore['PATH']
cypher.each do |cy|
queue << cy.strip
begin
crypt = cy
res = send_request_cgi({
'uri' => spath+crypt,
'method' => 'GET',
'ctype' => 'text/plain'
}, 20)
if res.code == 500 or res.code == 302
print_status("#{wmap_base_url} #{wmap_base_url}#{spath}#{crypt} #{res.code}")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end
end
Now its referring to the "res.code". I see that, but I was under the impression that Metasploit handled res.code. Isn't this confirmed by the fact I am getting res.code output before the program crashes? So now I am at a loss... Yes I looked at other Questions on the site here but usually the answer is that they are not defined. But Metasplot defines this variable.. So... ??
As I said, I'm new to Ruby so if I can get a kinda detailed answer, I would be greatly appreciate it.
Thanks!
Figured it out.
Just needed a blank rescue to handle nil responses.
Related
I'm trying to pass in certain values and headers via Ruby but not sure how to do it. What I have so far:
uri = URI.parse('http://jira.test.local/rest/zapi/latest/execution')
req = Net::HTTP::Get.new(uri)
req.basic_auth 'userid', 'password'
res = Net::HTTP.start(uri.hostname, uri.port) {|http| http.request(req)}
puts res.body
values = "{\n \"issueId\": 32640,\n \"versionId\": \"11163\",\n \"cycleId\": \"5\",\n \"projectId\": 10460\n,\n \"status\": \"1\"}"
headers = {:content_type => "application/json"}
Net::HTTP.start(uri.hostname, uri.port) do | http |
response = http.post(req, values)
puts response.body
end
I'm getting this error right now:
{"status":{"1":{"id":1,"color":"#75B000","description":"Test was executed and passed successfully.","name":"PASS"},"2":{"id":2,"color":"#CC3300","description":"Test was executed and failed.","name":"FAIL"},"3":{"id":3,"color":"#F2B000","description":"Test execution is a work-in-progress.","name":"WIP"},"4":{"id":4,"color":"#6693B0","description":"The test execution of this test was blocked for some reason.","name":"BLOCKED"},"-1":{"id":-1,"color":"#A0A0A0","description":"The test has not yet been executed.","name":"UNEXECUTED"}},"executions":[],"currentlySelectedExecutionId":""}
undefined method `empty?' for #<Net::HTTP::Get GET> (NoMethodError)
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http/generic_request.rb:27:in `initialize'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http/request.rb:14:in `initialize'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1390:in `new'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1390:in `send_entity'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1179:in `post'
./features/step_definitions/zapi_farooq.rb:32:in `block (2 levels) in <top (required)>'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:852:in `start'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:582:in `start'
./features/step_definitions/zapi_farooq.rb:31:in `/^I test zapi update$/'
features/zapi_farooq.feature:4:in `* I test zapi update'
The first line of the output is good, it's giving me the proper outpul from the res.body, but after that is the error.
Summary: I want to go to the uri, authenticate with creds and post with the values provided and with the proper headers (all using Ruby).
I'm trying to create a new execution as per this API: http://docs.getzephyr.apiary.io/#executionresourceapis (Create a new Execution)
Playing around I got it to work with:
values = "{\n \"status\": 2\n}"
headers = {:content_type => "application/json"}
response = RestClient::Resource.new 'http://jira.test.local/rest/zapi/latest/execution/343/execute', 'username', 'password'
response.put values, headers
puts response
puts response.body
Gives output of:
http://jira.test.local/rest/zapi/latest/execution/343/execute
<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body></body></html>
Also it changes the value of the issue in Jira (intended goal).
I just used RestClient b/c the original docs (http://docs.getzephyr.apiary.io/#executionresourceapis) were using it and got some help here too: https://github.com/rest-client/rest-client
I made a simple SOAP-Request using Savon.
require 'savon'
client = Savon.client(:wsdl => 'https://url?wsdl', :ssl_verify_mode => :none,
wsse_auth: ["username", "password"],pretty_print_xml: true)
trackingnumber = 'anyNumber'
response = client.call(:shipment_status) do
message(Id: trackingnumber)
end
puts response
The problem is, if I get a "Error-Response", for instance if the trackingnumber don`t exists, then my program is crashing. But I dont want the program to crash, I want to keep the response. Here is the error:
c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/response.rb:85:in `raise_soap_and_http_errors!': (soap:Server) Fault occurred while processing. (Savon::SOAPFault)
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/response.rb:14:in `initialize'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:64:in `new'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:64:in `create_response'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:55:in `call'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/client.rb:36:in `call'
Is there a solution for this problem?
I think your syntax is off. Do you use Savon 2.x?
You should guard the call with an Exception handler.
require 'savon'
client = Savon.client(
:wsdl => 'https://url?wsdl',
:ssl_verify_mode => :none,
wsse_auth: ["username", "password"],
:raise_errors => true, # false if you don't want to see exceptions
pretty_print_xml: true)
trackingnumber = 'anyNumber'
begin
response = client.call(
:shipment_status,
:messageId => {:trackingnumber => trackingnumber}
)
rescue Savon::Error => soap_fault
print "Error: #{soap_fault}\n"
end
puts response
You can also set the parameter :raise_errors to false when creating your client. then you have to handle the return values accordingly.
I think my issue is the same as that in Having problems with Ruby file from Dashing which as to date no answer.
Full problem is when I start dashing I get.
scheduler caught exception:
undefined method `[]' for nil:NilClass
/home/bhladmin/Shopify-dashing-e672d84/dashboard/jobs/twitter_user.rb:19:in `block in <top (required)>'
/usr/lib64/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.23/lib/rufus/sc/jobs.rb:230:in `call'
/usr/lib64/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.23/lib/rufus/sc/jobs.rb:230:in `trigger_block'
/usr/lib64/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.23/lib/rufus/sc/jobs.rb:204:in `block in trigger'
/usr/lib64/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.23/lib/rufus/sc/scheduler.rb:430:in `call'
/usr/lib64/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.23/lib/rufus/sc/scheduler.rb:430:in `block in trigger_job'
Something isn't right on line 19, but I can't work out what...
The full section of code is below...
#!/usr/bin/env ruby
require 'net/http'
# Track public available information of a twitter user like follower, follower
# and tweet count by scraping the user profile page.
# Config
# ------
twitter_username = ENV['TWITTER_USERNAME'] || 'foobugs'
SCHEDULER.every '2m', :first_in => 0 do |job|
http = Net::HTTP.new("twitter.com", Net::HTTP.https_default_port())
http.use_ssl = true
response = http.request(Net::HTTP::Get.new("/#{twitter_username}"))
if response.code != "200"
puts "twitter communication error (status-code: #{response.code})\n#{response.body}"
else
tweets = /profile["']>[\n\t\s]*<strong>([\d.,]+)/.match(response.body)[1].delete('.,').to_i
following = /following["']>[\n\t\s]*<strong>([\d.,]+)/.match(response.body)[1].delete('.,').to_i
followers = /followers["']>[\n\t\s]*<strong>([\d.,]+)/.match(response.body)[1].delete('.,').to_i
send_event('twitter_user_tweets', current: tweets)
send_event('twitter_user_followers', current: followers)
send_event('twitter_user_following', current: following)
end
end
From the previous question it looks like the way of extracting the data from the webpage is the problem, but I don't know Ruby well enough. I've tried removing the ENV['TWITTER_USERNAME'] section to make sure the username I used (not the one above) is being used. If I dump out the raw html data then it contains the info I'm searching for so I know that part is working.
I think I've solved this myself, by going about it a different way. I've changed the code to use the twitter API rather than page scraping. Details below... The auth checking and timeout isn't great so if anyone has hints on making that better they'd be welcome...
#### Get your twitter keys & secrets:
#### https://dev.twitter.com/docs/auth/tokens-devtwittercom
Twitter.configure do |config|
config.consumer_key = 'YOUR_CONSUMER_KEY'
config.consumer_secret = 'YOUR_CONSUMER_SECRET'
config.oauth_token = 'YOUR_OAUTH_TOKEN'
config.oauth_token_secret = 'YOUR_OAUTH_SECRET'
end
twitter_username = 'foobugs'
MAX_USER_ATTEMPTS = 10
user_attempts = 0
SCHEDULER.every '10m', :first_in => 0 do |job|
begin
tw_user = Twitter.user("#{twitter_username}")
if tw_user
tweets = tw_user.statuses_count
followers = tw_user.followers_count
following = tw_user.friends_count
send_event('twitter_user_tweets', current: tweets)
send_event('twitter_user_followers', current: followers)
send_event('twitter_user_following', current: following)
end
rescue Twitter::Error => e
user_attempts = user_attempts +1
puts "Twitter error #{e}"
puts "\e[33mFor the twitter_user widget to work, you need to put in your twitter API keys in the jobs/twitter_user.rb file.\e[0m"
sleep 5
retry if(user_attempts < MAX_USER_ATTEMPTS)
end
end
[5040:6784:0906/150930:FATAL:platform_canvas.cc(70)] SK_CRASH ] 55%
C:/Ruby193/lib/ruby/1.9.1/net/protocol.rb:146:in `rescue in rbuf_fill': Timeout::Error (Ti
meout::Error)
from letsmt_rr_filetype_uploader.rb:43:in `block in <main>'
from letsmt_rr_filetype_uploader.rb:39:in `each'
from letsmt_rr_filetype_uploader.rb:39:in `<main>'
This is an rbuf-fill timout error on file uploading progress. Is there any different method to avoid this by *NOT*using sleep ?
This is the script im using for file upload:
puts "Tiek veikta atlasīto failu ielāde..."
progress = ProgressBar.create(:title => "Failu ielāde:", :progress_mark => "|", :format => "%t [%B] %p%%", :total => kolekcija.length)
kolekcija.each do |fails|
#fails = fails[0]
#b.div(:id, "pageHeader").link(:text, "Corpora").click
#b.span(:class => "btnText", :text => "Upload corpus").when_present.click
#b.text_field(:id, "corp_save_field_title").set("TestAuto #{File.basename(#fails)}") # Name / Title
#b.frame(:id, "uploadManagerFrame").frame(:index, 0).file_field(:id, "FileUploadHTML").set(#fails) # File absolute path
#b.frame(:id, "uploadManagerFrame").frame(:index, 0).span(:text, "Upload").click
#b.frame(:id, "uploadManagerFrame").table(:id, "ctrlGetUploadedFiles_gvUploadedFiles").wait_until_present
#b.frame(:id, "uploadManagerFrame").select_list(:id, "ctrlGetUploadedFiles_gvUploadedFiles_ctl02_ddlChooseType").option(:value, "#{fails[1]}").select
#b.send_keys :tab
if #b.frame(:id, "uploadManagerFrame").select_list(:id, "ctrlGetUploadedFiles_gvUploadedFiles_ctl02_ddlChooseLanguage").enabled?
#b.frame(:id, "uploadManagerFrame").select_list(:id, "ctrlGetUploadedFiles_gvUploadedFiles_ctl02_ddlChooseLanguage").select("English")
# #b.frame(:id, "uploadManagerFrame").select_list(:id, "ctrlGetUploadedFiles_gvUploadedFiles_ddlChooseLanguage_0").option(:value, "#{#filelang}".select
end
#b.send_keys :tab
#b.span(:class => "btnText", :text => "Save", :index => 1).when_present.click
#b.frame(:id, "uploadManagerFrame").table(:id, "ctrlGetUploadedFiles_gvUploadedFiles").wait_until_present
sleep 15
progress.increment
end
I have seen this problem before and it was caused by elements on the page that were being loaded via ajax where not responding hence causing the page to timeout in the same manner.
Eventually the only way to fix it was to wrap that particular call in a try catch. in addition to the try catch, try changing your sleep to a wait_until_present on any confirmation that comes up after the file upload. If there isnt one there, it may be worth adding one behind the scenes you can hook in to to confirm the file has completed uploading.
I recently switched from Ruby's Net:HTTP class to rest-client 1.6.7.
I find it a lot easier to form requests, but unlike Net:HTTP request, when rest-client gets anything other than a 200, the request dies. I've tried putting a breakpoint directly after the RestClient.get, and it never gets hit - so I'm doing something wrong.
def get_member_using_card
resource = "#{#settings_app_uri}api/v1/card/#{self.member_card_num}?token=#{#settings.api_key}"
response = RestClient.get resource
if response.code == 200
card = JSON.parse(response.body)
self.customer_id = card['card']['customer_id']
else
return 0
end
end
Which results in this stacktrace:
RestClient::ResourceNotFound - 404 Resource Not Found:
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/abstr
act_response.rb:48:in `return!'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:230:in `process_result'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:178:in `block in transmit'
/Users/tim/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/http.rb:627:in `start'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:172:in `transmit'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:64:in `execute'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:33:in `execute'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient.rb:68
:in `get'
Can someone tell me how to properly evaluate the response code and keep this exception from happening...?
See heading Exceptions on http://rubydoc.info/gems/rest-client/
for results code between 200 and 207 a RestClient::Response will be returned
for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
for result code 303 the redirection will be followed and the request transformed into a get
for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes
RestClient.get 'http://example.com/resource'
➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound`
begin
RestClient.get 'http://example.com/resource'
rescue => e
e.response
end
➔ 404 Resource Not Found | text/html 282 bytes
Also in the same documentation #wich pointed to, you can pass a block to RestClient.get such that it will not throw an exception on non-200 response codes:
# Don't raise exceptions but return the response
RestClient.get('http://example.com/resource'){|response, request, result| response }
See the "Result Handling" section from the documentation.
rescue RestClient::ExceptionWithResponse => err
There are several errors that could happen, specific exception types like Errno::EHOSTUNREACH or the more generic ExceptionWithResponse. Check the readme for more info.
I believe the best way to handle exceptions of an API client is to get the original error message thrown by the API endpoint. Here is an example code to handle that with RestClient
require 'json'
def get_call
begin
standard_response = {body: nil, success: false, message: ''}
response = RestClient.get('https://example.com/api/v1/xx', headers={'Authorization' => 'AbcDef xxx'})
standard_response[:success] = true
standard_response[:body] = JSON.parse(response.body)
rescue RestClient::ExceptionWithResponse => e
http_body = JSON.parse(e.http_body) # This is the original response from the API endpoint. e.g. {'message': 'Reason for the failure'}
meaningful_error_message = http_body['message'].nil? ? e.message : http_body['message'] # if {'message': 'error message'} is the format of your API
standard_response[:message] = meaningful_error_message
end
standard_response
end
Beautiful way to handle the exceptions in rest client.
For more info do check rest-client#response-callbacks-error-handling
RestClient.get('http://example.com/resource') { |response, request, result, &block|
case response.code
when 200
p "It worked !"
response
when 423
raise SomeCustomExceptionIfYouWant
else
response.return!(&block)
end
}