[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1006371: bullseye-pu: package lemonldap-ng/2.0.11+ds-4+deb11u1



Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu

[ Reason ]
lemonldap-ng is vulnerable to password bypass (impact critical) in a very
unlikely setup (probability very low). CVE-2021-40874

[ Impact ]
In such configuration, a remote lemonldap-ng system that queries the
main lemonldap-ng system using internal lemonldap-ng protocol instead of
SAML/OpenID-Connect, accepts user with _wrong password; if and only if_
main lemonldap-ng system is configured to use both Kerberos and LDAP
authentication.

[ Tests ]
Tests passed and upstream patch adds a new test

[ Risks ]
Low risk, test coverage proves that package isn't broken with such
change (trivial for a lemonldap-ng dev ;-))

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]
Instead of setting login/password into result variables ($req->user),
RESTServer stores them in form and launch the whole authentication
process ($self->p->authProcess) instead of selected steps.
Same change is applied to CheckState plugin (no major risk here, this
plugin is reserved to LLNG administrators).

Cheers,
Yadd
diff --git a/debian/changelog b/debian/changelog
index a56d54279..f6be653a8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+lemonldap-ng (2.0.11+ds-4+deb11u1) bullseye; urgency=medium
+
+  * Fix auth process in password-testing plugins (Closes: CVE-2021-20874)
+
+ -- Yadd <yadd@debian.org>  Thu, 24 Feb 2022 15:16:09 +0100
+
 lemonldap-ng (2.0.11+ds-4) unstable; urgency=high
 
   * Import security fixes from 2.0.12
diff --git a/debian/patches/CVE-2021-40874.patch b/debian/patches/CVE-2021-40874.patch
new file mode 100644
index 000000000..a333d3260
--- /dev/null
+++ b/debian/patches/CVE-2021-40874.patch
@@ -0,0 +1,238 @@
+Description: Fix auth process in password-testing plugins (#2611)
+Author: Maxime Besson <maxime.besson@worteks.com>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/commit/66946e8
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2612
+Forwarded: not-needed
+Reviewed-By: Yadd <yadd@debian.org>
+Last-Update: 2022-01-14
+
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/_WebForm.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/_WebForm.pm
+@@ -73,7 +73,10 @@
+     my $res            = PE_OK;
+ 
+     # 1. No user defined at all -> first access
+-    unless ( $defUser and $req->method =~ /^POST$/i ) {
++    # _pwdCheck is a workaround to make CheckUser work while using a GET
++    unless ( $defUser
++        and ( uc( $req->method ) eq "POST" or $req->data->{_pwdCheck} ) )
++    {
+         $res = PE_FIRSTACCESS;
+     }
+ 
+@@ -170,6 +173,7 @@
+ 
+ sub setSecurity {
+     my ( $self, $req ) = @_;
++    return if $req->data->{skipToken};
+ 
+     # If captcha is enable, prepare it
+     if ( $self->captcha ) {
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
+@@ -41,16 +41,22 @@
+ 
+     if ( my $user = $req->param('user') and my $pwd = $req->param('password') )
+     {
+-        $req->user($user);
+-        $req->data->{password} = $pwd;
++        $req->parameters->{user}     = ($user);
++        $req->parameters->{password} = $pwd;
++        $req->data->{skipToken}      = 1;
++
++        # This makes Auth::Choice use authChoiceAuthBasic if defined
++        $req->data->{_pwdCheck} = 1;
+ 
+         # Not launched methods:
+-        #  - "extractFormInfo" due to "token"
+         #  - "buildCookie" useless here
+         $req->steps( [
+-                'getUser',                         'authenticate',
+-                @{ $self->p->betweenAuthAndData }, $self->p->sessionData,
+-                @{ $self->p->afterData },          'storeHistory',
++                @{ $self->p->beforeAuth },
++                $self->p->authProcess,
++                @{ $self->p->betweenAuthAndData },
++                $self->p->sessionData,
++                @{ $self->p->afterData },
++                'storeHistory',
+                 @{ $self->p->endAuth }
+             ]
+         );
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm
+@@ -681,11 +681,13 @@
+             400 );
+     }
+ 
+-    $req->user($user);
+-    $req->data->{password} = $password;
++    $req->parameters->{user}     = $user;
++    $req->parameters->{password} = $password;
++    $req->data->{_pwdCheck}      = 1;
++    $req->data->{skipToken}      = 1;
+ 
+     if ( $self->p->_userDB ) {
+-        $req->steps( [ 'getUser', 'authenticate' ] );
++        $req->steps( [ $self->p->authProcess ] );
+         my $result = $self->p->process($req);
+         if ( $result == PE_PASSWORD_OK or $result == PE_OK ) {
+             return $self->p->sendJSONresponse( $req,
+--- /dev/null
++++ b/lemonldap-ng-portal/t/35-REST-auth-password-server.t
+@@ -0,0 +1,126 @@
++use Test::More;
++use strict;
++use IO::String;
++use MIME::Base64;
++use JSON;
++
++require 't/test-lib.pm';
++
++my $res;
++
++my $client = LLNG::Manager::Test->new( {
++        ini => {
++            logLevel           => 'error',
++            useSafeJail        => 1,
++            requireToken       => 1,
++            restAuthServer     => 1,
++            restPasswordServer => 1,
++            authentication     => 'Combination',
++            userDB             => 'Same',
++
++            combination => '[K,Dm] or [Dm]',
++            combModules => {
++                K => {
++                    for  => 1,
++                    type => 'Kerberos',
++                },
++                Dm => {
++                    for  => 0,
++                    type => 'Demo',
++                },
++            },
++            krbKeytab => '/etc/keytab',
++            krbByJs   => 1,
++        }
++    }
++);
++
++# Test pwdConfirm endpoint
++
++my $res = expectJSON(
++    postJSON(
++        $client,
++        "/proxy/pwdConfirm",
++        {
++            user     => "dwho",
++            password => "dwho",
++        }
++    )
++);
++
++is( $res->{result}, 1, "Correct password is accepted" );
++count(1);
++
++my $res = expectJSON(
++    postJSON(
++        $client,
++        "/proxy/pwdConfirm",
++        {
++            user     => "waldo",
++            password => "dwho",
++        }
++    )
++);
++
++is( $res->{result}, 0, "Incorrect user is rejected" );
++count(1);
++
++my $res = expectJSON(
++    postJSON(
++        $client,
++        "/proxy/pwdConfirm",
++        {
++            user     => "dwho",
++            password => "wrongpass",
++        }
++    )
++);
++
++is( $res->{result}, 0, "Incorrect password is rejected" );
++count(1);
++
++# Test getUser endpoint
++# Existing user
++my $res = expectJSON(
++    postJSON(
++        $client,
++        "/proxy/getUser",
++        {
++            user => "dwho",
++        }
++    )
++);
++is( $res->{result},               1,            "Correct result" );
++is( $res->{info}->{cn},           "Doctor Who", "Correct attributes" );
++is( $res->{info}->{_whatToTrace}, "dwho",       "Correct macro" );
++count(3);
++
++# Missing user
++my $res = expectJSON(
++    postJSON(
++        $client,
++        "/proxy/getUser",
++        {
++            user => "notfound",
++        }
++    )
++);
++is( $res->{result}, 0,     "Correct result" );
++is( $res->{info},   undef, "No attributes" );
++count(2);
++
++clean_sessions();
++
++done_testing( count() );
++
++sub postJSON {
++    my ( $portal, $url, $payload ) = @_;
++    my $string_payload = to_json($payload);
++    return $portal->_post(
++        $url,
++        IO::String->new($string_payload),
++        accept => 'application/json',
++        type   => 'application/json',
++        length => length($string_payload)
++    );
++}
+--- a/lemonldap-ng-portal/t/65-CheckState.t
++++ b/lemonldap-ng-portal/t/65-CheckState.t
+@@ -8,10 +8,25 @@
+ my $client = LLNG::Manager::Test->new( {
+         ini => {
+             logLevel         => 'error',
+-            authentication   => 'Demo',
++            requireToken     => 1,
+             checkStateSecret => 'x',
+             checkState       => 1,
++            authentication   => 'Combination',
+             userDB           => 'Same',
++
++            combination => '[K,Dm] or [Dm]',
++            combModules => {
++                K => {
++                    for  => 1,
++                    type => 'Kerberos',
++                },
++                Dm => {
++                    for  => 0,
++                    type => 'Demo',
++                },
++            },
++            krbKeytab => '/etc/keytab',
++            krbByJs   => 1,
+         }
+     }
+ );
diff --git a/debian/patches/series b/debian/patches/series
index a1245fc76..644277be7 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -8,3 +8,4 @@ fix-trusted-domain-wildcard.patch
 fix-trusted-domain-regex.patch
 fix-xss-on-register-form.patch
 dont-display-totp-secret.patch
+CVE-2021-40874.patch

Reply to: