
=====================================================================

                               CERT-Renater

                    Note d'Information No. 2023/VULN144

_____________________________________________________________________

DATE                : 05/04/2023

HARDWARE PLATFORM(S): /

OPERATING SYSTEM(S): Systems running Mastodon versions prior to
                                     4.1.2, 4.0.4, 3.5.8.

=====================================================================
https://github.com/mastodon/mastodon/security/advisories/GHSA-38g9-pfm9-gfqv
_____________________________________________________________________


Blind LDAP injection in login allows the attacker to leak arbitrary
attributes from LDAP database

High
Gargron published GHSA-38g9-pfm9-gfqv
Package
No package listed

Affected versions
>= 2.5.0

Patched versions
4.1.2, 4.0.4, 3.5.8


Description

Summary

Mastodon allows configuration of LDAP for authentication. The LDAP query 
made during login is insecure and the attacker can perform LDAP
injection attack to leak arbitrary attributes from LDAP database.


Details

These are the default variables initiated if LDAP is configured:

mastodon/config/initializers/devise.rb

Lines 398 to 414 in 94cbd80
  if ENV['LDAP_ENABLED'] == 'true'    config.ldap_authentication = true 
   config.check_at_sign       = true    config.ldap_host           = 
ENV.fetch('LDAP_HOST', 'localhost')    config.ldap_port           = 
ENV.fetch('LDAP_PORT', 389).to_i    config.ldap_method         = 
ENV.fetch('LDAP_METHOD', :simple_tls).to_sym    config.ldap_base 
   = ENV.fetch('LDAP_BASE')    config.ldap_bind_dn        = 
ENV.fetch('LDAP_BIND_DN')    config.ldap_password       = 
ENV.fetch('LDAP_PASSWORD')    config.ldap_uid            = 
ENV.fetch('LDAP_UID', 'cn')    config.ldap_mail           = 
ENV.fetch('LDAP_MAIL', 'mail')    config.ldap_tls_no_verify  = 
ENV['LDAP_TLS_NO_VERIFY'] == 'true'    config.ldap_search_filter  = 
ENV.fetch('LDAP_SEARCH_FILTER', 
'(|(%{uid}=%{email})(%{mail}=%{email}))') 
config.ldap_uid_conversion_enabled  = ENV['LDAP_UID_CONVERSION_ENABLED'] 
== 'true'    config.ldap_uid_conversion_search   = 
ENV.fetch('LDAP_UID_CONVERSION_SEARCH', '.,- ') 
config.ldap_uid_conversion_replace  = 
ENV.fetch('LDAP_UID_CONVERSION_REPLACE', '_')  end
Then, during the authentication, this line is executed:

mastodon/app/models/concerns/ldap_authenticable.rb

Lines 7 to 14 in 94cbd80
  def authenticate_with_ldap(params = {})    ldap   = 
Net::LDAP.new(ldap_options)    filter = 
format(Devise.ldap_search_filter, uid: Devise.ldap_uid, mail: 
Devise.ldap_mail, email: params[:email])      if (user_info = 
ldap.bind_as(base: Devise.ldap_base, filter: filter, password: 
params[:password]))      ldap_get_user(user_info.first)    end  end
So this query is filled with untrusted input, namely user's login:

(|(cn=%{email})(mail=%{email}))

User can inject LDAP query here. I didn't find a way to login as
arbitrary user because there are two queries - one for fetching
the user object and the second one for authentication and the
injection exists in the first one.

However, the attacker can use blind injection technique to
exfiltrate one bit of information at a time.


PoC

     Set up Mastodon and LDAP authentication

     Create a user admin with any password. The information that we
want to leak is the description=LDAP Administrator attribute but it
can be any (I'm not yet able to leak password hash but I'm working
on it).

     Now, as the attacker, create a new account. In my case it's
adminmalicious and password test.

     Now when we try to log in with the login 
adminmalicious)(&(cn=admin)(description=A*) and password test. The full 
query will look like this: 
(|(cn=adminmalicious)(&(cn=admin)(description=A*))(mail=adminmalicious)(&(cn=admin)(description=A*))). 
In plain english this query means "If the description of the user
admin starts with A, the query will return both admin and
adminmalicious". In my example, the admin description does not
start with A so only adminmalicious will be returned from the
LDAP query and we'll be logged in as adminmalicious.

     When we try to log in with 
adminmalicious)(&(cn=admin)(description=L*), the query will
return both admin and adminmalicious but admin will be first
and the app will try to login to user admin with the password
test which will fail and we will see Invalid E-mail address or
password..


Impact

This way we've leaked one bit of information of other user from the
database. Of course, this is easy to script and leak whole
attribute values.


Severity
High

7.7/ 10

CVSS base metrics

Attack vector
Network

Attack complexity
Low

Privileges required
Low

User interaction
None

Scope
Changed

Confidentiality
High

Integrity
None

Availability
None

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

CVE ID
CVE-2023-28853

Weaknesses
CWE-90


Credits

     @gregxsunday gregxsunday


=========================================================
+ CERT-RENATER        |    tel : 01-53-94-20-44         +
+ 23/25 Rue Daviel    |    fax : 01-53-94-20-41         +
+ 75013 Paris         |   email:cert@support.renater.fr +
=========================================================
