-
Notifications
You must be signed in to change notification settings - Fork 119
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
ssl_peer_fingerprint_verification for self-signed certs #150
Changes from all commits
25302d6
7c2164a
3ef3cdf
33a26d4
24b01a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,12 +40,13 @@ def initialize(endpoint) | |
# @param [String] The XML SOAP message | ||
# @returns [REXML::Document] The parsed response body | ||
def send_request(message) | ||
ssl_peer_fingerprint_verification! | ||
log_soap_message(message) | ||
hdr = { | ||
'Content-Type' => 'application/soap+xml;charset=UTF-8', | ||
'Content-Length' => message.length } | ||
hdr = { 'Content-Type' => 'application/soap+xml;charset=UTF-8', | ||
'Content-Length' => message.length } | ||
resp = @httpcli.post(@endpoint, message, hdr) | ||
log_soap_message(resp.http_body.content) | ||
verify_ssl_fingerprint(resp.peer_cert) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need a |
||
handler = WinRM::ResponseHandler.new(resp.http_body.content, resp.status) | ||
handler.parse_to_xml | ||
end | ||
|
@@ -67,6 +68,34 @@ def no_ssl_peer_verification! | |
@httpcli.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE | ||
end | ||
|
||
# SSL Peer Fingerprint Verification prior to connecting | ||
def ssl_peer_fingerprint_verification! | ||
return unless @ssl_peer_fingerprint && ! @ssl_peer_fingerprint_verified | ||
connection_cert = shady_ssl_connection.peer_cert_chain.last | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't hurt. |
||
verify_ssl_fingerprint(connection_cert) | ||
@logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n") | ||
@ssl_peer_fingerprint_verified = true | ||
no_ssl_peer_verification! | ||
end | ||
|
||
# Connect without verification to retrieve untrusted ssl context | ||
def shady_ssl_connection | ||
noverify_peer_context = OpenSSL::SSL::SSLContext.new | ||
noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE | ||
tcp_connection = TCPSocket.new(@endpoint.host, @endpoint.port) | ||
shady_ssl_connection = OpenSSL::SSL::SSLSocket.new(tcp_connection, | ||
noverify_peer_context) | ||
shady_ssl_connection.connect | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ssl_fingerprint_verification! will make an outbound tcp connection before sending any traffic to verify our cert fingerprint. See #151 |
||
shady_ssl_connection | ||
end | ||
|
||
# compare @ssl_peer_fingerprint to current ssl context | ||
def verify_ssl_fingerprint(cert) | ||
conn_fingerprint = OpenSSL::Digest::SHA1.new(cert.to_der).to_s | ||
return unless @ssl_peer_fingerprint.casecmp(conn_fingerprint) != 0 | ||
fail "ssl fingerprint mismatch!!!!\n" | ||
end | ||
|
||
# HTTP Client receive timeout. How long should a remote call wait for a | ||
# for a response from WinRM? | ||
def receive_timeout=(sec) | ||
|
@@ -112,6 +141,7 @@ def initialize(endpoint, user, pass, ca_trust_path = nil, opts) | |
no_sspi_auth! if opts[:disable_sspi] | ||
basic_auth_only! if opts[:basic_auth_only] | ||
no_ssl_peer_verification! if opts[:no_ssl_peer_verification] | ||
@ssl_peer_fingerprint = opts[:ssl_peer_fingerprint] | ||
end | ||
end | ||
|
||
|
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.
At the time of this call to POST our first message, we don't know if the fingerprint will match, but we go ahead and send the http request.
We have already connected once in ssl_peer_fingerprint_verification! but if we had a complex malicious-in-the-middle scenario, they could wait for the initial verify then redirect all subsequent connections.
I'm not sure of all the initial http soap requests winrm makes, but I'd like to verify that we could fail after that first request and still be safe. It's obviously fine for negotiate and kerberos, but I'm unsure if the first request for plaintext would send anything.