canweriotnow / rpam-ruby19

PAM auth for Ruby - 1.9 compat version
https://rubygems.org/gems/rpam-ruby19
GNU General Public License v2.0
9 stars 5 forks source link

trouble authenticating other user than <me> #5

Open tboyko opened 11 years ago

tboyko commented 11 years ago

I'm experiencing the same issue as #2 , even after using suid. This is happening on an Ubuntu server running a Rails app with Passenger. I am using a custom PAM service which is a copy of /etc/pam.d/login. Authentication works for the user running the Rails app, but no others.

Could this be a problem brought about by Rails/Passenger?

tboyko commented 11 years ago

Here is some additional info:

# ls -la /sbin/unix_chkpwd
-rwsr-sr-x 1 root shadow 35488 2011-10-18 08:26 /sbin/unix_chkpwd

# ls -la /etc/shadow
-rw-r----- 1 root shadow 1181 2012-12-20 11:30 /etc/shadow

# tail -f /var/log/auth.log
Dec 20 11:56:13 ubuntu unix_chkpwd[15662]: check pass; user unknown
Dec 20 11:56:13 ubuntu unix_chkpwd[15662]: password check failed for user (testuser)
Dec 20 11:56:13 ubuntu ruby: pam_unix(rpam:auth): authentication failure; logname=appuser uid=1001 euid=1001 tty= ruser= rhost=  user=testuser

I experience this problem simply running a ruby script with the library. The issue is not restricted to the domain of Apache/Rails. Any help is appreciated!

canweriotnow commented 11 years ago

Can you post the contents of /etc/pam.d/login (or your copied service)?

Also, are you passing hte name of the service to Rpam? The default is to use the /etc/pam.d/rpam service, an alternate service needs to be passed in to Rpam.auth(). My first guess would be it has something to do with the service definition.

I'm running rpam in production on Debian 6.06 and locally on OS X 10.8, the latter required some monkeying with the PAM definitions, but on Debian it always Just Works®, not sure why Ubuntu would be that different...

tboyko commented 11 years ago

I'm pretty dumbfounded myself. I even looked into SELinux but it doesn't appear to be installed.

I am not specifying a service name. I tried this, but it didn't seem to make a difference. I do not have an rpam service defined in my /etc/pam.d/ folder, and I think PAM is selecting some default instead. Copying login to rpam didn't make any difference.

I did find that setting /etc/shadow to world readable band-aided the problem. Adding my user to the shadow group, curiously enough, did not work.

Here is the vanilla contents of login:

#
# The PAM configuration file for the Shadow `login' service
#

# Enforce a minimal delay in case of failure (in microseconds).
# (Replaces the `FAIL_DELAY' setting from login.defs)
# Note that other modules may require another minimal delay. (for example,
# to disable any delay, you should add the nodelay option to pam_unix)
auth       optional   pam_faildelay.so  delay=3000000

# Outputs an issue file prior to each login prompt (Replaces the
# ISSUE_FILE option from login.defs). Uncomment for use
# auth       required   pam_issue.so issue=/etc/issue

# Disallows root logins except on tty's listed in /etc/securetty
# (Replaces the `CONSOLE' setting from login.defs)
# Note that it is included as a "required" module. root will be
# prompted for a password on insecure ttys.
# If you change it to a "requisite" module, make sure this does not leak
# user name information.
auth       required  pam_securetty.so

# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth       requisite  pam_nologin.so

# SELinux needs to be the first session rule. This ensures that any 
# lingering context has been cleared. Without out this it is possible 
# that a module could execute code in the wrong domain.
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close

# This module parses environment configuration file(s)
# and also allows you to use an extended config
# file /etc/security/pam_env.conf.
# 
# parsing /etc/environment needs "readenv=1"
session       required   pam_env.so readenv=1
# locale variables are also kept into /etc/default/locale in etch
# reading this file *in addition to /etc/environment* does not hurt
session       required   pam_env.so readenv=1 envfile=/etc/default/locale

# Standard Un*x authentication.
@include common-auth

# This allows certain extra groups to be granted to a user
# based on things like time of day, tty, service, and user.
# Please edit /etc/security/group.conf to fit your needs
# (Replaces the `CONSOLE_GROUPS' option in login.defs)
auth       optional   pam_group.so

# Uncomment and edit /etc/security/time.conf if you need to set
# time restrainst on logins.
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
# as well as /etc/porttime)
# account    requisite  pam_time.so

# Uncomment and edit /etc/security/access.conf if you need to
# set access limits.
# (Replaces /etc/login.access file)
# account  required       pam_access.so

# Sets up user limits according to /etc/security/limits.conf
# (Replaces the use of /etc/limits in old login)
session    required   pam_limits.so

# Prints the last login info upon succesful login
# (Replaces the `LASTLOG_ENAB' option from login.defs)
session    optional   pam_lastlog.so

# Prints the motd upon succesful login
# (Replaces the `MOTD_FILE' option in login.defs)
session    optional   pam_motd.so

# Prints the status of the user's mailbox upon succesful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). 
#
# This also defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user 
# also removes the user's mail spool file.
# See comments in /etc/login.defs
session    optional   pam_mail.so standard

# Standard Un*x account and session
@include common-account
@include common-session
@include common-password

# SELinux needs to intervene at login time to ensure that the process
# starts in the proper default security context. Only sessions which are
# intended to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
canweriotnow commented 11 years ago

Huh... your login looks identical to mine (on Debian 6.06, so pretty much expected)... The default behavior is typically for PAM to look at /etc/pam.d/other when a service isn't specified (or not found; I don't have an /etc/pam.d/rpam either, typicall only needed on BSD-like Unixes such as OS X), and /etc/pam.d/other is usually just a bunch of @include directives to fall back to /etc/pam.d/common-* I would look at other and common-auth, because Rpam.auth() should only ever get that far, as you're not asking to open a session, just for credential authentication.

I'm kind of at a loss, at this point, though... might be worth asking on ServerFault or SO, maybe someone else will see something we're missing?

tboyko commented 11 years ago

Good thoughts. Glad to know that I'm not the only one that this is stumping. I'll take those routes and repost if I come to any conclusions. Thanks again!

On Dec 21, 2012, at 6:41 AM, Jason Lewis notifications@github.com wrote:

Huh... your login looks identical to mine (on Debian 6.06, so pretty much expected)... The default behavior is typically for PAM to look at /etc/pam.d/other when a service isn't specified (or not found; I don't have an /etc/pam.d/rpam either, typicall only needed on BSD-like Unixes such as OS X), and /etc/pam.d/other is usually just a bunch of @include directives to fall back to /etc/pam.d/common-* I would look at other and common-auth, because Rpam.auth() should only ever get that far, as you're not asking to open a session, just for credential authentication.

I'm kind of at a loss, at this point, though... might be worth asking on ServerFault or SO, maybe someone else will see something we're missing?

— Reply to this email directly or view it on GitHub.

augustf commented 11 years ago

I ran into this problem as well. I tried all of the aforementioned as well as randomly monkeying with the /etc/pam.d/rpam to read: @include common-auth, to no avail. Whatever the latest Ubuntu is doing with PAM, it doesn't seem to work with something like rpam.

canweriotnow commented 11 years ago

I've got the latest Ubuntu installed on my home workstation, I'll try playing with it on there this weekend. Thanks for the feedback :smile:

felipelo commented 11 years ago

Hello,

I'm trying to configure Rpam and.. the same issue. Even with a simple script I can't authenticate any user but me.

Just to give some add information, here is my auth.log log out when the login fails:

unix_chkpwd[17744]: check pass; user unknown unix_chkpwd[17744]: password check failed for user (xxxxx) ruby: pam_unix(rpam:auth): authentication failure; logname=idealogic uid=1000 euid=1000 tty= ruser= rhost= user=xxxxx ruby: pam_winbind(rpam:auth): getting password (0x00000388) ruby: pam_winbind(rpam:auth): pam_get_item returned a password ruby: pam_winbind(rpam:auth): request wbcLogonUser failed: WBC_ERR_AUTH_ERROR, PAM error: PAM_USER_UNKNOWN (10), NTSTATUS: NT_STATUS_NO_SUCH_USER, Error message was: No such user

Please let me know if have any further information.

Thanks, Felipe

canweriotnow commented 11 years ago

Was finally able to reproduce on an Ubuntu system... now that I've reproduced it I should be able to look into it more. I'll keep you posted with what I find.

felipelo commented 11 years ago

Hey, any news about it?

Thanks.

canweriotnow commented 11 years ago

I think I've found the issue... I'm not sure why I'm not seeing this issue on some fo by Debian systems, unless there was a change between libpam0g 1.1.1 and 1.1.3, but apparently the issue encountered on Ubuntu 12.10 is the correct behavior for PAM (specifically, for /sbin/unixchkpwd). When the euid of the user invoking unix_chkpwd > 0, unix_chkpwd defaults to the real uid of the calling user, only allowing the current user to attempt to authenticate themselves.

I found this forum thread which explains the issue in detail, possible workarounds, and hte security issues posed by those workarounds. Specifically:

The bottom line for Hudson users using UNIX authentication via PAM on Linux with shadow password database is this. If you run Hudson as root, pam_unix will never even bother calling unix_chkpwd because it does not need to. Voila...your users get authenticated. If you run Hudson with uid > 0, then the only user you can authenticate successfully is the username whose uid matches the process running Hudson. Clearly this is not acceptable for most usages since only one user can log in. To fix this, you can do one the following things in order of increasing security.

  1. Run Hudson as root. This is unacceptable in many enterprise environments that have internal IT SOPs against this. It can be a major security issue based on the configuration of the underlying Java policy.
  2. Create a special group (say shadow) that can read /etc/shadow and assign the user running Hudson to that group. This is better, but does allow enhanced access to the password hash file to anyone running code in Hudson, or who gains access to any kind of Hudson user process (such as a shell).
  3. Hack /sbin/unix_chkpwd (or provide a different helper binary) so that it does not change euid from 0 to real uid when it detects that the real uid does not match the authenticating username.

This last option represents a reduced yet real security risk by potentially allowing the setuid binary to be used in brute force password crack attacks such as those that can be performed when not using a shadow file. However, the source code to the binary does reveal that the designers added some additional features to ward this off such as not allowing the password you are testing to come from standard input generated by a TTY. The switch euid to real uid when the authenticating username does not match real uid is an additional measure. It restricts the attacker from using brute force attack to obtain the password for a user they do not already have access to. Anyone who considers hacking the binary to remove the euid swich should probably disallow an authenticating username that is root or any other system-privileged user.

The best solution is to use a PAM auth strategy that doesn't hit /etc/shadow; I use rpam-ruby19 with PowerBroker Open for ActiveDirectory bridging, so the pam_auth call never invokes unix_chkpwd to read /etc/shadow.

The fact that rpam works at all on Unixes other than the latest Ubuntu is probably a security flaw... not sure if it's worthy of a CVE, but I'll investigate...

FWIW, there's a relevant thread on the pam mailing list addressing this issue as well: https://www.redhat.com/archives/pam-list/2012-August/msg00001.html

Sorry I don't have better news for those who wanted to authenticate local users, but at least we know what's going on better now.

I think the 'resolution' for this will probably be to update the README... leaving open until I have a chance to do that, but will probably close after I document the limitation.

felipelo commented 11 years ago

hummm... this is bad! I agree with all your point of view and understand the problem. But it is still disappointing. Linux is so flexible in some points to allow users do everything they want, but some times, I think the caprices from the community overrides the Linux way to think!

Lets hope to find a solution! I really would enjoy to have this kind of authentication.