pinepain / ldap-auth-proxy

A simple drop-in HTTP proxy for transparent LDAP authentication which is also a HTTP auth backend.
MIT License
75 stars 16 forks source link

Authenticate without password #8

Closed kumy closed 5 years ago

kumy commented 5 years ago

I've just installed ldap-auth-proxy in proxy mode, during my tests I've found that while authenticating, if I just give the login without entering a password, the authentication is validated :(

Am I missing something?

pinepain commented 5 years ago

Hi, thanks for reporting. There was such bug/feature during early development stage, afair, however it supposed to be fixed now. Can you please clarify what was your steps to set up the proxy?

kumy commented 5 years ago

@pinepain sure, here is how I setup things.

Note: As we sign our certificates with a custom CA (used for example on openldap-server), I've built an intermediate image.

$ cat Dockerfile
FROM ubuntu:xenial AS ubuntu
ADD https://somehost/CA1.crt /usr/share/ca-certificates/here/
ADD https://somehost/CA2.crt /usr/share/ca-certificates/here/
RUN apt-get update \
  && apt-get install --no-install-recommends -y ca-certificates \
  && echo here/CA1.crt >> /etc/ca-certificates.conf \
  && echo here/CA2.crt >> /etc/ca-certificates.conf \
  && update-ca-certificates

FROM pinepain/ldap-auth-proxy:0.0.5
COPY --from=ubuntu /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

$ docker build -t ldap-auth-proxy:0.0.5-custom .

$ cat http-proxy-test.yml
---
# vim:set ts=2 sw=2 ai et bg=dark:
version: "3"

services:

  ldap-auth-proxy:
    image: "ldap-auth-proxy:0.0.5-custom"
    environment:
      LOG_LEVEL: "debug"
      LISTEN: ":80"
      LDAP_SERVER: "ldaps://myldapserver"
      LDAP_BASE: "DC=test,DC=test"
      LDAP_BIND_DN: "CN=test,DC=test,DC=test"
      LDAP_BIND_PASSWORD: "mypassword"
      LDAP_USER_FILTER: "(sAMAccountName=%s)"
      HEADERS_MAP: "X-LDAP-Mail:mail,X-LDAP-UID:sAMAccountName,X-LDAP-CN:cn"
      UPSTREAM: "http://http-exports:80"
    deploy:
      labels:
        traefik.enable: "true"
        traefik.docker.network: "traefik_public"
        traefik.frontend.rule: "Host:myhost; PathPrefixStrip: /exports"
        traefik.port: "80"
      placement:
        constraints:
          - "node.labels.disk == gluster"
    networks:
      traefik_public:
      default:

  http-exports:
    image: "myregistry/nginx-autoindex:latest"
    command: [ "nginx", "-g", "daemon off;" ]
    deploy:
      labels:
        traefik.enable: "false"
      placement:
        constraints:
          - "node.labels.disk == gluster"
    volumes:
      - /somepath/data/export:/usr/share/nginx/html
    networks:
      default:

networks:
  default:
  traefik_public:
    external: true
...

# launch stack using docker swarm
$ docker stack deploy --with-registry-auth -c http-proxy-test.yml http-proxy-test

Then access https://myhost/exports and fill username with no password, lead to a valid authentication. I expect here an invalid authentication like if I used an invalid password.

kumy commented 5 years ago

Please note, the example above use an Active Directory server.

I've setup the stack on another infrastructure, with an openldap backend, and I obtain Failed to authenticate: LDAP Result Code 53 \"Unwilling To Perform\": unauthenticated bind (DN with no password) disallowed. But this is a response from the openldap backend, not ldap-auth-proxy.

pinepain commented 5 years ago

Thanks a lot for extra detauls, it's definitely weird and it's not something that is expected. Does AD allow user to have empty password, by chance? I know it sounds ridiculous but just to double check (have no AD here, unfortunately). I will double-check the code later today and will give it a try with OpenLDAP too. FTR, I use JumpCloud atm so example configs and all tests was done using their endpoint (I'm not affiliated with them though). For now I think it may be a good idea to reject immediately any credentials with empty username or password, in the end, it shouldn't work at LDAP anyway.

kumy commented 5 years ago

Thanks for taking time to look into this.

Does AD allow user to have empty password

It may, but my account has a password of course... I've tested with a few other apps, and the authentication is rejected when password is not given.

pinepain commented 5 years ago

Can you please also post debug logs from both ldap-auth-proxy as well from traefik (I see that you use traefik in front of services, right?) and relevant web server config (at least the part that proxies auth to ldap-auth-proxy)?

kumy commented 5 years ago

Here are the requested logs ldap-auth-proxy.log traefik.log

Regarding webserver, I didn't add specific config, just used ldap-auth-proxy as proxy like https://github.com/pinepain/ldap-auth-proxy#proxy

pinepain commented 5 years ago

@microsoft This is why I do not bother supporting your products - screen shot 2018-11-06 at 9 11 56 pm

kumy commented 5 years ago

@pinepain does this message come from Github???

pinepain commented 5 years ago

Nope, I tried to register Azure account to be able to reproduce the issue you are having and apparently, if a user reside in Ukraine, they have to print, sign and send that agreement to Ireland. I'm just curious why printing and not writing it by hand? But never mind, I think the chance MS read and do sth is close to zero (from the negative side).

PS: But I got your irony 🤣

pinepain commented 5 years ago

@kumy am I right that with openldap you are unable to authenticate with empty password and it's only possible with AD, is it correct?

kumy commented 5 years ago

Exact, but I think the restriction in openldap can be adjusted via config.

pinepain commented 5 years ago

@kumy hm, I double-checked ldap-auth-proxy code as well as jtblin/go-ldap-client which is used under the hood and i think it's LDAP server-specific configuration, here's a similar issue discussed - https://github.com/Pylons/pyramid_ldap/issues/9#issuecomment-20543667. For now I'll make zero-length username or password to trigger auth failure immediately without contacting LDAP server, I see no good fit for empty usernameo password in in real world.

pinepain commented 5 years ago

Here is another issue/report - https://github.com/go-ldap/ldap/issues/93 (just linking for the reference purpose).

kumy commented 5 years ago

For now I'll make zero-length username or password to trigger auth failure immediately without contacting LDAP server

I also feel this may be a nice default. For the general use, may it be switchable via a config option?

pinepain commented 5 years ago

@kumy as per LDAP rfc, it may be, however in real life the reason people are putting auth is to avoid anonymous access and both anonymous and unauthenticated authentications do quite the opposite, so I see little or no this use case to applicable to the real world.

pinepain commented 5 years ago

@kumy could you please give 0.1.0 docker image tag a try?

kumy commented 5 years ago

Sure, but have to wait tomorrow :disappointed: And thanks @pinepain for the quick fix!

kumy commented 5 years ago

@pinepain just tested. I can see the rejection in the logs, so basically it works. However, we get an http 400 response code. Would be better to send back a 401, so users are requested to fill credentials again. Actually the session is "stalled", we have to clear the browser cache to have the opportunity to authenticate again.

pinepain commented 5 years ago

Indeed, makes sense to me, pushed a fix and tagged as 0.1.1, thanks for the feedback.