Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • lemonldap-ng lemonldap-ng
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 331
    • Issues 331
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 10
    • Merge requests 10
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • LemonLDAP NGLemonLDAP NG
  • lemonldap-nglemonldap-ng
  • Issues
  • #2290
Closed
Open
Issue created Aug 24, 2020 by Maxime Besson@maxbes🔧Maintainer

[security:high, CVE-2020-24660] Lack of URL normalization by Nginx may lead to authorization bypass when URL access rules are used

Environment

LemonLDAP::NG version: 2.0.8

Operating system: Debian Stretch, Debian Buster, probably RHEL

Web server: nginx/1.10.3, nginx/1.14.2

Summary

When using Nginx, regexp-based access rules may not be correctly enforced by the handler.

I am doing a CVE request for this bug

Logs

  • Content of test vhost:
# cat /var/lib/lemonldap-ng/test/admin
SECRET ADMIN FILE
  • Handler configuration:

image

  • Proof of exploitation:
GET -S  http://test1.example.com/admin/secretfile 
GET http://test1.example.com/admin/secretfile
302 Moved Temporarily //AS EXPECTED

$ GET -S  http://test1.example.com/%61dmin/secretfile 
GET http://test1.example.com/%61dmin/secretfile
200 OK
SECRET ADMIN FILE  //SHOULD BE PROTECTED

GET -S  http://test1.example.com/x/../admin/secretfile
GET http://test1.example.com/x/../admin/secretfile
200 OK
SECRET ADMIN FILE //SHOULD BE PROTECTED

I have also successfully tested this in a reverse proxy configuration, which is a very common, if not the most common use case. I have also tested this without the "skip" keyword, in such a cas, a normal user may be granted access to admin-only resources.

Cause

The problem comes from the fact that the handler tests regexp against the REQUEST_URI variable. Unlike Apache, Nginx does not normalize REQUEST_URI. Because of this, it becomes extremely hard for an admin to write a regexp that correctly catches all of the possible URLs that can be used to target a protected resource (such as /admin).

Solutions

URI::Normalize

Nginx transmits the original URL in a X_ORIGINAL_URL header. We could use this fact to trigger special processing in the handler:

    $self->env->{REQUEST_URI} = $self->env->{X_ORIGINAL_URI}
      if ( $self->env->{X_ORIGINAL_URI} );

would change to

    $self->env->{REQUEST_URI} = normalize_url($self->env->{X_ORIGINAL_URI})
      if ( $self->env->{X_ORIGINAL_URI} );

Using normalize_url from URI::Normalize which is not in distros but easily embeddable.

Nginx config

We could also make Nginx normalize the URL, with something like this:

location / {
    ...
    # Save the normalized URI here
    set $original_uri $uri$is_args$args;
    ...
}

location = /lmauth {
    ...
    fastcgi_param X_ORIGINAL_URI  $original_uri;
    ...
}

But that means each webserver we ever want to support will probably have it's own, distinct solution

Edited Aug 26, 2020 by Maxime Besson
Assignee
Assign to
Time tracking