Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/spec/lib/rex/proto/ldap/auth_spec.rb
Views: 11789
# frozen_string_literal: true12require 'rex/text'3require 'rex/proto/ntlm/message'45RSpec.describe Rex::Proto::LDAP::Auth do6subject(:nil_parameter_auth) do7described_class.new(nil, nil, nil, nil, nil)8end910subject(:parameter_auth) do11described_class.new('1122334455667788', 'my_domain', 'my_server', 'my_dnsname', 'my_dnsdomain')12end1314before do15@type3 = "0\x82\x01D\x02\x01\x01`\x82\x01=\x02\x01\x03\x04\x00\xA3\x82\x014\x04\nGSS-SPNEGO\x04\x82\x01$NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00@"\16"\x00\x00\x00\x92\x00\x92\x00X\x00\x00\x00\f\x00\f\x00\xEA\x00\x00\x00\b\x00\b\x00\xF6\x00\x00\x00\x16\x00\x16\x00\xFE\x00\x00\x00\x10\x00\x10"\17"\x00\x14\x01\x00\x00\x05\x02\x80BN\x98\xF8\x84,\x8At\b\x98\xEC\xB7\xC8\x15\x12l\x01\x92\xDDO\x88<\xFA\x0F\xF4Q\x9AA\x12\xC4\x991\xE2\xA0\xCETk"\18"\x83\x00\xCA\x8D\x01\x01\x00\x00\x00\x00\x00\x00\x80\x15sIU\t\xDA\x01\x92\xDDO\x88<\xFA\x0F\xF4\x00\x00\x00\x00\x02\x00\f\x00D\x00O\x00M\x00A\x00I\x00N"\19"\x00\x01\x00\f\x00S\x00E\x00R\x00V\x00E\x00R\x00\x04\x00\x16\x00e\x00x\x00a\x00m\x00p\x00l\x00e\x00.\x00c\x00o\x00m\x00\x03\x00$\x00S\x00E\x00R\x00V"\20"\x00E\x00R\x00.\x00e\x00x\x00a\x00m\x00p\x00l\x00e\x00.\x00c\x00o\x00m\x00\x00\x00\x00\x00D\x00O\x00M\x00A\x00I\x00N\x00U\x00s\x00e\x00r\x00W\x00O\x00R"\21"\x00K\x00S\x00T\x00A\x00T\x00I\x00O\x00N\x00\xFD\xF0\x01l#bF\xD2\x87\x14\x119#c*\xBA"22end2324let(:user_login) { OpenStruct.new }25let(:ntlm_type1) do26ntlm1 = Net::NTLM::Message::Type1.new.serialize2728sasl = ['GSS-SPNEGO'.to_ber, ntlm1.to_ber].to_ber_contextspecific(3)29br = [30Net::LDAP::Connection::LdapVersion.to_ber, ''.to_ber, sasl31].to_ber_appsequence(Net::LDAP::PDU::BindRequest)3233type1 = [0.to_ber, br, nil].compact.to_ber_sequence.read_ber(Net::LDAP::AsnSyntax)34pdu = Net::LDAP::PDU.new(type1)35pdu.bind_parameters36end37let(:ntlm_type3) do38pdu = Net::LDAP::PDU.new(@type3.read_ber(Net::LDAP::AsnSyntax))39pdu.bind_parameters40end4142context '#initialize' do43it 'sets default values when called with nil arguments' do44expect(nil_parameter_auth.instance_variable_get(:@domain)).to eq('DOMAIN')45expect(nil_parameter_auth.instance_variable_get(:@server)).to eq('SERVER')46expect(nil_parameter_auth.instance_variable_get(:@dnsname)).to eq('server')47expect(nil_parameter_auth.instance_variable_get(:@dnsdomain)).to eq('example.com')48expect(nil_parameter_auth.instance_variable_get(:@challenge).length).to eq(8)49end5051it 'sets provided values when called with arguments' do52expect(parameter_auth.instance_variable_get(:@domain)).to eq('my_domain')53expect(parameter_auth.instance_variable_get(:@server)).to eq('my_server')54expect(parameter_auth.instance_variable_get(:@dnsname)).to eq('my_dnsname')55expect(parameter_auth.instance_variable_get(:@dnsdomain)).to eq('my_dnsdomain')56expect(parameter_auth.instance_variable_get(:@challenge).length).to eq(8)57end58end5960context '#handle_anonymous_request' do61before do62user_login.name = ''63user_login.authentication = ''64end6566it 'returns a hash with expected values for anonymous requests' do67result = parameter_auth.handle_anonymous_request(user_login)6869expect(result[:user]).to eq('')70expect(result[:pass]).to eq('')71expect(result[:domain]).to be_nil72expect(result[:auth_type]).to eq('Anonymous')73expect(result[:result_code]).to eq(Net::LDAP::ResultCodeSuccess)74end75end7677context '#handle_simple_request' do78it 'handles requests with an username and domain in a DN object' do79user_login.name = 'cn=username,dc=domain,dc=com'80user_login.authentication = 'password'8182result = parameter_auth.handle_simple_request(user_login)8384expect(result[:user]).to eq('username')85expect(result[:domain]).to eq('domain.com')86expect(result[:private]).to eq('password')87expect(result[:private_type]).to eq(:password)88expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)89expect(result[:auth_type]).to eq('Simple')90end9192it 'handles requests with an username and multiple DC components for domain in a DN object' do93user_login.name = 'cn=username,dc=domain1,dc=domain2,dc=domain3'94user_login.authentication = 'password'9596result = parameter_auth.handle_simple_request(user_login)9798expect(result[:user]).to eq('username')99expect(result[:domain]).to eq('domain1.domain2.domain3')100expect(result[:private]).to eq('password')101expect(result[:private_type]).to eq(:password)102expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)103expect(result[:auth_type]).to eq('Simple')104end105106it 'handles requests with information in the form of username@domain' do107user_login.name = '[email protected]'108user_login.authentication = 'password'109110result = parameter_auth.handle_simple_request(user_login)111112expect(result[:user]).to eq('username')113expect(result[:domain]).to eq('domain.com')114expect(result[:private]).to eq('password')115expect(result[:private_type]).to eq(:password)116expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)117expect(result[:auth_type]).to eq('Simple')118end119120it 'handles requests with invalid DN and CN components' do121user_login.name = 'cn=user,name,mydomain,dc=com'122user_login.authentication = 'password'123124expect { parameter_auth.handle_simple_request(user_login) }.to raise_error(Net::LDAP::InvalidDNError)125end126127it 'handles requests with username and domain in NETBIOS format' do128user_login.name = 'domain\\username'129user_login.authentication = 'password'130131result = parameter_auth.handle_simple_request(user_login)132133expect(result[:user]).to eq('username')134expect(result[:domain]).to eq('domain')135expect(result[:private]).to eq('password')136expect(result[:private_type]).to eq(:password)137expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)138expect(result[:auth_type]).to eq('Simple')139end140141it 'handles authentication requests with incorrect request format' do142user_login.name = 'username'143user_login.authentication = 'password'144145result = parameter_auth.handle_simple_request(user_login)146147expect(result[:user]).to eq('username')148expect(result[:domain]).to be_nil149expect(result[:private]).to eq('password')150expect(result[:private_type]).to eq(:password)151expect(result[:result_code]).to eq(Net::LDAP::ResultCodeInvalidCredentials)152expect(result[:auth_type]).to eq('Simple')153end154end155156context '#handle_sasl_request' do157context 'using GSS-SPNEGO mechanism' do158context 'using LM/NTLM authentication' do159it 'handles NTLM Type1 requests with an NTLM type2 response' do160result = parameter_auth.handle_sasl_request(ntlm_type1)161162expect(result[:server_creds]).to be_a(String)163expect(Net::NTLM::Message.parse(result[:server_creds])).to(be_a(Net::NTLM::Message::Type2))164expect(result[:result_code]).to eq(Net::LDAP::ResultCodeSaslBindInProgress)165expect(result[:auth_type]).to eq('SASL')166end167168it 'handles NTLM Type3 requests containing client information' do169result = parameter_auth.handle_sasl_request(ntlm_type3)170171expect(result[:domain]).to eq('DOMAIN')172expect(result[:user]).to eq('User')173expect(result[:private]).not_to be_nil174expect(result[:private_type]).to eq(:ntlm_hash)175expect(result[:auth_type]).to eq('SASL')176expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)177expect(result[:auth_type]).to eq('SASL')178end179end180181context 'unsupprted SASL value' do182let(:request) do183auth_message = 'INVALIDSSP'184sasl = ['GSS-SPNEGO'.to_ber, auth_message.to_ber].to_ber_contextspecific(3)185br = [186Net::LDAP::Connection::LdapVersion.to_ber, ''.to_ber, sasl187].to_ber_appsequence(Net::LDAP::PDU::BindRequest)188189type1 = [0.to_ber, br, nil].compact.to_ber_sequence.read_ber(Net::LDAP::AsnSyntax)190pdu = Net::LDAP::PDU.new(type1)191pdu.bind_parameters192end193it 'hanldes and unknown SASL header as unsuppoted' do194result = parameter_auth.handle_sasl_request(request)195expect(result[:auth_type]).to eq('SASL')196expect(result[:result_code]).to eq(Net::LDAP::ResultCodeAuthMethodNotSupported)197end198end199end200end201202context 'private methods' do203context '#generate_type2_response' do204it 'returns a valid NTLM Type2 message from NTLM Type1 message' do205message = Net::NTLM::Message.parse(ntlm_type1.authentication[1])206result = parameter_auth.send(:generate_type2_response, message)207208expect(result).to be_a(String)209end210end211212context '#handle_type3_message' do213it 'handles NTLM Type3 message and returns the expected authentication information' do214message = Net::NTLM::Message.parse(ntlm_type3.authentication[1])215result = parameter_auth.send(:handle_type3_message, message)216217expect(result[:domain]).to eq('DOMAIN')218expect(result[:user]).to eq('User')219expect(result[:private]).not_to be_nil220expect(result[:private_type]).to eq(:ntlm_hash)221expect(result[:ntlm_ver]).not_to be_nil222end223end224225context '#process_ntlm_hash' do226it 'processes NTLM hash from Type3 message and returns the expected information' do227ntlm_info = {228ntlm_ver: NTLM_CONST::NTLM_V2_RESPONSE,229lm_hash: '054ab6f7f2d60c068bf03a4e27d99834',230lm_cli_challenge: '2464587cc5ef2d6c',231nt_hash: '93d3aa55263a1d37931a67a5b54710b8',232nt_cli_challenge: '0101000000000000006e8eed5507da012464587cc5ef2d6c0000000002000c0042334004f004d00410049004e0001000c00530045005200560045005200040016006523400780061006d0070006c0065002e0063006f006d00030024005300450052005602350450052002e006500780061006d0070006c0065002e0063006f006d0000000000',236domain: "D\x00O\x00M\x00A\x00I\x00N\x00",237user: "U\x00s\x00e\x00r\x00",238host: "W\x00O\x00R\x00K\x00S\x00T\x00A\x00T\x00I\x00O\x00N\x00"239}240241result = parameter_auth.send(:process_ntlm_hash, ntlm_info)242243expect(result[:domain]).to eq('DOMAIN')244expect(result[:user]).to eq('User')245expect(result[:private]).not_to be_nil246expect(result[:private_type]).to eq(:ntlm_hash)247expect(result[:ntlm_ver]).not_to be_nil248end249end250end251end252253254