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
HTTP PDF Authors Gather Module: Use Msf::Exploit::Remote::HttpClient #8686
HTTP PDF Authors Gather Module: Use Msf::Exploit::Remote::HttpClient #8686
Conversation
Replace Net::HTTP usage with proper Rex::Proto::Http::Client via the Msf module mixin. Generate the request opts from the same URI parsed URL string, execute a one shot GET request, disconencting after reciept of results. Depending on the response code, either pass back an empty StringIO or if its 200, a StringIO(res.body).
To address the complexity which comes with the flexibility offered by Rex::Proto::Http::Client and its Msf mixin descendant, a simple process needs to be implemented for issuing a request using only the URL string in order to provide ease of access to users who may not have the time to study how these clients work in detail. Implement :request_opts_from_url in Msf's HttpClient mixin such as to extract the options required for :send_request_* from a URL string passed into the method. This approach reduces HTTP requests in the mixin to `send_request_raw(request_opts_from_url(url))` when `url` is just a string. Implement this approach in the http_pdf_authors gather module to further reduce infrastructure complexity around the simple need to acquire PDF files via HTTP/S. Testing: Local to this module only, and in Pry of course. Seems to work...
ping @bcook-r7 @egypt: the last commit before this comment addresses a need you guys mentioned for "simple access to complex HTTP subsystems" by just parsing out a URL string into the opts needed to send_request_* |
To round out implementation of a simple path for users to access HttpClient like Open or Net::HTTP, create :request_url method which takes a single URL parameter, uses :request_opts_from_url to build the request configuration for Rex::Proto::Http::Client, executes a GET request with it, and disconnects the client unless keepalive is specified as the second parameter to :request_url. Example usage of functionality is implemented in http_pdf_authors.
I like the library changes. Worth noting that each module that makes use of Edit: Based on the appletv_display_image.rb module as an example, the following options should probably be de-registered in each module that makes use of
|
lib/msf/core/exploit/http/client.rb
Outdated
# | ||
# Returns response from a simple URL call | ||
def request_url(url, keepalive = false) | ||
res = send_request_raw(request_options_from_url(url)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request_opts_from_url
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, OK. This is why I may not be ideally suited to working at the interface level. Wilco
# Returns a hash of request opts from a URL string | ||
def request_opts_from_url(url) | ||
tgt = URI.parse(url) | ||
opts = { 'rhost' => tgt.host, 'rport' => tgt.port, 'uri' => tgt.request_uri } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably this method will always expect an absolute URL.
A URL of /
is valid input for URI.parse
, but tgt
will have no scheme
or host
attributes.
Perhaps error handling should be performed here?
begin
tgt = URI.parse(url)
raise 'Invalid URL' unless tgt.scheme =~ %r{https?}
raise 'Invalid URL' if tgt.host.to_s.eql? ''
rescue => e
print_error "Could not parse URL: #{e}"
return
end
... or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're entirely right, I should have pulled the full validation block you had going. Will adjust as requested, thx.
@bcoles: since your module is being used as a guinea pig for this, do you want me to continue abusing it in this PR, or turn this into another nightmare for Egypt and Sinn3r to dig thru in lib with no explicit exposure in a module? Didn't mean to hijack your efforts on improving this. |
@sempervictus I'm happy for you to keep using this module as a guinea pig. I've re-written my module to make use of your library changes and patch a few other things. The code is much cleaner. My only concern is that there's some issues in the underlying pdf-reader library, which I've since patched in my local repo, but will cause merge conflicts with this PR. One of the underlying issues is a hang with 100% CPU usage which is rather poor user experience. |
Let's add your repo to the gemfile until the author adopts or replaces your fixes. Again, big ups on keeping the user base safe. Client side exploits against MSF are to be avoided at most costs. |
Ah, to clarify, I mean I've patched by rescuing. I haven't actually patched the lib. Using
def read(data)
Timeout.timeout(10) do
reader = PDF::Reader.new data
return parse reader
end
rescue PDF::Reader::MalformedPDFError
print_error "Could not parse PDF: PDF is malformed (MalformedPDFError)"
return
rescue PDF::Reader::UnsupportedFeatureError
print_error "Could not parse PDF: PDF contains unsupported features (UnsupportedFeatureError)"
return
rescue SystemStackError
print_error "Could not parse PDF: PDF is malformed (SystemStackError)"
return
rescue SyntaxError
print_error "Could not parse PDF: PDF is malformed (SyntaxError)"
return
rescue Timeout::Error
print_error "Could not parse PDF: PDF is malformed (Timeout)"
return
rescue => e
print_error "Could not parse PDF: Unhandled exception: #{e}"
return
end |
… client mixin Updated PDF author metadata downloader to support the new methods.
Thanks @bcoles and @sempervictus. I added an additional commit and some error handling here based on @bcoles' updated work on this PR: 5d05ca1 - added http client 'download' method and updates to pdf author module from @bcoles |
Release NotesThis improves error handling in the |
Replace Net::HTTP usage with proper Rex::Proto::Http::Client via
the Msf module mixin. Generate the request opts from the same URI
parsed URL string, execute a one shot GET request, disconencting
after reciept of results. Depending on the response code, either
pass back an empty StringIO or if its 200, a StringIO(res.body).
Verification
Before this commit:
After: