PAM 인가 우회 (PAM Authorization Bypass)

PAM 인증 성공 후 계정 상태와 접근 정책을 확인하세요.

설명

PAM(Pluggable Authentication Modules)의 pam_authenticate()는 자격 증명을 검증하지만 계정 관리 정책 확인을 대신하지 않습니다. 인증 후 pam_acct_mgmt()의 결과를 확인하지 않으면 계정 만료나 접근 제한 같은 정책을 놓칠 수 있습니다.

잠재적 영향

  • 계정 관리 정책에서 금지한 사용자가 로그인할 수 있습니다.
  • 계정 또는 비밀번호의 만료 조건을 적절히 처리하지 못할 수 있습니다.
  • 실제 영향은 서비스에 구성된 PAM 모듈과 계정 정책에 따라 달라집니다.

해결 방법

  1. 인증 성공 후 pam_acct_mgmt()로 계정 상태와 접근 조건을 확인하세요. 성공하지 않으면 그대로 접근을 허용하지 마세요.
  2. PAM_NEW_AUTHTOK_REQD는 비밀번호 교체가 필요한 상태입니다. 허용된 교체 절차를 완료하기 전에는 접근을 거부하세요.
  3. 서비스에 필요한 인증·계정 관리 모듈과 최소 권한 정책을 구성하고, 비밀번호를 남기지 않도록 로그인 성공·실패를 기록하세요.

예시

PAM 바인딩의 흐름을 보여 주는 일부 코드입니다. pam_start, handle_conv의 바인딩, 비밀번호 전달과 pam_end 정리는 생략했습니다. 실제 구현에서는 초기화 성공 여부를 확인하고, 성공적으로 시작한 트랜잭션은 모든 종료 경로에서 정리하세요.

변경 전

python
from pam import PamHandle, PamConv
from ctypes import CDLL, c_int, byref
from ctypes.util import find_library

libpam = CDLL(find_library("pam"))

pam_authenticate = libpam.pam_authenticate
pam_authenticate.argtypes = [PamHandle, c_int]
pam_authenticate.restype = c_int

def authenticate(username, password, service='login'):
    handle = PamHandle()
    conv = PamConv(handle_conv, 0)
    retval = pam_start(service, username, byref(conv), byref(handle))
    if retval != 0:
        return False
    # 인증만 수행 (보안 취약)
    return pam_authenticate(handle, 0) == 0

변경 후

python
from pam import PamHandle, PamConv
from ctypes import CDLL, c_int, byref
from ctypes.util import find_library

libpam = CDLL(find_library("pam"))

pam_authenticate = libpam.pam_authenticate
pam_authenticate.argtypes = [PamHandle, c_int]
pam_authenticate.restype = c_int

pam_acct_mgmt = libpam.pam_acct_mgmt
pam_acct_mgmt.argtypes = [PamHandle, c_int]
pam_acct_mgmt.restype = c_int

def authenticate(username, password, service='login'):
    handle = PamHandle()
    conv = PamConv(handle_conv, 0)
    retval = pam_start(service, username, byref(conv), byref(handle))
    if retval != 0:
        return False

    # 계정 상태 검증 추가 (안전)
    return pam_authenticate(handle, 0) == 0 and pam_acct_mgmt(handle, 0) == 0

설명:

  • 변경 전: 인증 결과만 확인하고 계정 관리 정책의 결과는 확인하지 않습니다.
  • 변경 후: 인증과 계정 상태 검사가 모두 성공한 경우에만 True를 반환합니다.

참조