Skip to content
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

Patch LDAP for synchronous reads #16640

Merged
merged 1 commit into from
Jun 1, 2022

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Jun 1, 2022

This fixes an issue where the Net::LDAP library would fail due to the socket returning less data than was requested. Rex sockets use Rex::IO::Stream whose #read method calls read_nonblocking which will return less data than requested in more scenarios than just when an EoF was raised. The Net::LDAP library assumes that it will have received all of the data that it requested, and when that is not the case it will fail to parse it which causes an exception to be raised.

The proposed solution is to modify the socket that is passed to Net::LDAP to override it's #read method to behave in the correct way. An alternative solution would be to update Rex::IO::Stream#read however that will likely introduce additional issues from code that relies on it behaving in the way that it currently does.

Testing

This also possibly fixes #16498 but that has not been confirmed.

@gwillcox-r7 gwillcox-r7 self-assigned this Jun 1, 2022
@gwillcox-r7
Copy link
Contributor

gwillcox-r7 commented Jun 1, 2022

Before the changes
msf6 auxiliary(gather/query_ldap) > show options

Module options (auxiliary/gather/query_ldap):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   BASE_DN                     no        LDAP base DN if you already have it
   BIND_DN                     no        The username to authenticate to LDAP server
   BIND_PW                     no        Password for the BIND_DN
   LDAPQUERY                   no        Query to run against the target LDAP server
   RHOSTS     ##               yes       The target host(s), see https://github.com/rapid
                                         7/metasploit-framework/wiki/Using-Metasploit
   RPORT      389              yes       The target port
   SSL        false            no        Enable SSL on the LDAP connection


Auxiliary action:

   Name                  Description
   ----                  -----------
   ENUM_ALL_OBJECTCLASS  Dump all objects containing any objectClass field.


msf6 auxiliary(gather/query_ldap) > set RHOSTS *redacted*
RHOSTS => *redacted*
msf6 auxiliary(gather/query_ldap) > run
[*] Running module against *redacted*

[*] Discovering base DN automatically
[-] *redacted*:389 Empty namingContexts attribute
[-] *redacted*:389 Base DN cannot be determined
[!] Couldn't discover base DN!
[-] Auxiliary failed: Net::LDAP::PDU::Error Invalid Search Response length.
[-] Call stack:
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/pdu.rb:240:in `parse_search_return'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/pdu.rb:104:in `initialize'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:243:in `new'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:243:in `block in read'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/instrumentation.rb:19:in `instrument'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:242:in `read'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:201:in `queued_read'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:441:in `block (2 levels) in search'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:399:in `loop'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:399:in `block in search'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/instrumentation.rb:19:in `instrument'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/connection.rb:388:in `search'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:784:in `block (2 levels) in search'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:1305:in `use_connection'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:783:in `block in search'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/instrumentation.rb:19:in `instrument'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:782:in `search'
[-]   /home/gwillcox/git/metasploit-framework/modules/auxiliary/gather/query_ldap.rb:60:in `perform_ldap_query'
[-]   /home/gwillcox/git/metasploit-framework/modules/auxiliary/gather/query_ldap.rb:98:in `block in run'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:644:in `block in open'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:716:in `block in open'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap/instrumentation.rb:19:in `instrument'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:711:in `open'
[-]   /home/gwillcox/.rvm/gems/ruby-3.0.2@metasploit-framework/gems/net-ldap-0.17.0/lib/net/ldap.rb:644:in `open'
[-]   /home/gwillcox/git/metasploit-framework/lib/msf/core/exploit/remote/ldap.rb:68:in `ldap_connect'
[-]   /home/gwillcox/git/metasploit-framework/modules/auxiliary/gather/query_ldap.rb:73:in `run'
[*] Auxiliary module execution completed
msf6 auxiliary(gather/query_ldap) >
After the changes
 ~/git/metasploit-framework │ master *1 ?38  git checkout upstream/pr/16640 -b land-pr16640
Branch 'land-pr16640' set up to track remote branch 'pr/16640' from 'upstream'.
Switched to a new branch 'land-pr16640'
 ~/git/metasploit-framework │ land-pr16640:pr/16640 *1 ?38  ./msfconsole   ✔ │ 3.0.2 Ruby 
                                                  

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMM                MMMMMMMMMM
MMMN$                           vMMMM
MMMNl  MMMMM             MMMMM  JMMMM
MMMNl  MMMMMMMN       NMMMMMMM  JMMMM
MMMNl  MMMMMMMMMNmmmNMMMMMMMMM  JMMMM
MMMNI  MMMMMMMMMMMMMMMMMMMMMMM  jMMMM
MMMNI  MMMMMMMMMMMMMMMMMMMMMMM  jMMMM
MMMNI  MMMMM   MMMMMMM   MMMMM  jMMMM
MMMNI  MMMMM   MMMMMMM   MMMMM  jMMMM
MMMNI  MMMNM   MMMMMMM   MMMMM  jMMMM
MMMNI  WMMMM   MMMMMMM   MMMM#  JMMMM
MMMMR  ?MMNM             MMMMM .dMMMM
MMMMNm `?MMM             MMMM` dMMMMM
MMMMMMN  ?MM             MM?  NMMMMMN
MMMMMMMMNe                 JMMMMMNMMM
MMMMMMMMMMNm,            eMMMMMNMMNMM
MMMMNNMNMMMMMNx        MMMMMMNMMNMMNM
MMMMMMMMNMMNMMMMm+..+MMNMMNMNMMNMMNMM
        https://metasploit.com


       =[ metasploit v6.2.1-dev-0c481ed9c9                ]
+ -- --=[ 2224 exploits - 1172 auxiliary - 398 post       ]
+ -- --=[ 867 payloads - 45 encoders - 11 nops            ]
+ -- --=[ 9 evasion                                       ]

Metasploit tip: View advanced module options with 
advanced

msf6 payload(windows/x64/meterpreter/reverse_tcp) > use auxiliary/gather/query_ldap
msf6 auxiliary(gather/query_ldap) > set RHOSTS *redacted*
RHOSTS => *redacted*
msf6 auxiliary(gather/query_ldap) > run
[*] Running module against *redacted*

[*] Discovering base DN automatically
[-] *redacted*:389 Empty namingContexts attribute
[-] *redacted*:389 Base DN cannot be determined
[!] Couldn't discover base DN!
[*cut for brevity*, #<Net::LDAP::Entry:0x00007efdcd88eba0 @myhash={:dn=>["cn=Administrator"], :objectclass=>["Person"], :userclass=>["Regular"], :cn=>["Administrator"], :sn=>["Administrator"], :givenname=>[""], :mail=>["administrator@*redacted*", "administrator@*redacted*", "admin@*redacted*", "admin@*redacted*", "admin@*redacted*"], :url=>["*redacted*"], :uid=>["3"]}>, *cut for brevity*

Details should show the query now works and returns a lot of data. I've omitted a lot of it since its quite verbose, but above snippet should show this is now working as expected and returning the expected data.

@gwillcox-r7 gwillcox-r7 merged commit 44a22ab into rapid7:master Jun 1, 2022
@gwillcox-r7 gwillcox-r7 added library bug rn-fix release notes fix labels Jun 1, 2022
@gwillcox-r7
Copy link
Contributor

Release Notes

A bug has been fixed where the Net::LDAP library would fail due to the socket returning less data than was requested. This was addressed by introducing a custom read() method to appropriately handle cases where the socket may return less data than was expected.

@gwillcox-r7 gwillcox-r7 mentioned this pull request Jun 1, 2022
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug library rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

auxiliary/gather/vmware_vcenter_vmdir_ldap exploit broken by internal LDAP changes
2 participants