Skip to content

Commit

Permalink
Merge pull request #2 from rapid7/feature/MSP-12777/pass-the-hash
Browse files Browse the repository at this point in the history
add pass-the-hash capability
  • Loading branch information
trosen-r7 committed Jun 9, 2015
2 parents a78c718 + 38928da commit b08e88b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
29 changes: 27 additions & 2 deletions lib/net/ntlm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ module NTLM

class << self

# Valid format for LAN Manager hex digest portion: 32 hexadecimal characters.
LAN_MANAGER_HEX_DIGEST_REGEXP = /[0-9a-f]{32}/i
# Valid format for NT LAN Manager hex digest portion: 32 hexadecimal characters.
NT_LAN_MANAGER_HEX_DIGEST_REGEXP = /[0-9a-f]{32}/i
# Valid format for an NTLM hash composed of `'<LAN Manager hex digest>:<NT LAN Manager hex digest>'`.
DATA_REGEXP = /\A#{LAN_MANAGER_HEX_DIGEST_REGEXP}:#{NT_LAN_MANAGER_HEX_DIGEST_REGEXP}\z/

# Takes a string and determines whether it is a valid NTLM Hash
# @param [String] the string to validate
# @return [Boolean] whether or not the string is a valid NTLM hash
def is_ntlm_hash?(data)
decoded_data = data.dup
decoded_data = EncodeUtil.decode_utf16le(decoded_data)
if DATA_REGEXP.match(decoded_data)
true
else
false
end
end

# Conver the value to a 64-Bit Little Endian Int
# @param [String] val The string to convert
def pack_int64le(val)
Expand Down Expand Up @@ -129,10 +149,15 @@ def ntlm_hash(password, opt = {})
# Generate a NTLMv2 Hash
# @param [String] user The username
# @param [String] password The password
# @param [String] target The domain or workstaiton to authenticate to
# @param [String] target The domain or workstation to authenticate to
# @option opt :unicode (false) Unicode encode the domain
def ntlmv2_hash(user, password, target, opt={})
ntlmhash = ntlm_hash(password, opt)
if is_ntlm_hash? password
decoded_password = EncodeUtil.decode_utf16le(password)
ntlmhash = [decoded_password.upcase[33,65]].pack('H32')
else
ntlmhash = ntlm_hash(password, opt)
end
userdomain = user.upcase + target
unless opt[:unicode]
userdomain = EncodeUtil.encode_utf16le(userdomain)
Expand Down
8 changes: 8 additions & 0 deletions spec/lib/net/ntlm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@
expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
end

context 'when a user passes an NTLM hash for pass-the-hash' do
let(:passwd) { Net::NTLM::EncodeUtil.encode_utf16le('ff3750bcc2b22412c2265b23734e0dac:cd06ca7c7e10c99b1d33b7485a2ed808') }

it 'should return the correct ntlmv2 hash' do
expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
end
end

it 'should generate an lm_response' do
expect(Net::NTLM::lm_response(
{
Expand Down
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require 'simplecov'
require 'pathname'

SimpleCov.start do
add_filter '/spec/'
add_filter '/config/'
Expand Down

0 comments on commit b08e88b

Please sign in to comment.