>  Q&A  >  본문

비밀번호 없는 LDAP 로그인 및 PHP에서 Kerberos 티켓을 사용하여 사용자 정보 가져오기

FreeIPA/Kerberos를 사용하여 우리 회사의 일부 인트라넷 사이트에 SSO를 구현하려고 합니다. 그러나 이 주제에 대한 정보는 거의 없습니다.

테스트 네트워크에는 세 대의 머신이 실행되고 있습니다.

  1. Centos 8 Stream의 FreeIPA v4.9.8 서버
  2. Debian 11의 웹 서버(Apache v2.4.53, PHP v7.4.28)
  3. Kinit 및 Firefox를 사용하는 Xubuntu 22.04 클라이언트

Kinit, Unix 로그인 및 Apache Kerberos 인증이 작동합니다. 클라이언트 시스템의 Firefox 브라우저는 비밀번호 없이(Kerberos 티켓 사용) FreeIPA WebConfig에 로그인할 수 있습니다. 이제 이 기능을 인트라넷 페이지로 옮기고 싶습니다. 지금까지 이러한 페이지에 대한 로그인은 기존 LDAP 로그인을 기반으로 했습니다. 로그인 스크립트를 약간 조정하면 이제 사용자는 새로운 FreeIPA 서버에 로그인할 수 있습니다. 그러나 여전히 비밀번호가 필요하지만 Kerberos 티켓 덕분에 비밀번호는 실제로 더 이상 필요하지 않습니다.

질문은 비밀번호 없는 로그인이 어떤 모습이냐는 것입니다.

로그인 스크립트의 기능 조각:

으아아아

이제 내 생각에는 두 가지가 있습니다.

  1. ldap_bind() 대신 ldap_sasl_bind()를 사용할 수 있지만 해당 함수는 php.net(https://www.php.net/manual/en/function.ldap-sasl-bind.php)에 문서화되어 있지 않습니다. 혹시 이 기능을 사용하는 방법을 아시는 분이 계시다면 감사하겠습니다.
  2. 사용자 정보(이름, 이메일 등)를 얻기 위해 어떻게든 비밀번호 없이 ldap_search()를 실행할 수 있다면 기쁠 것입니다.

미리 감사드립니다.

편집자:

웹 서버 VM과 클라이언트 VM 모두 "ipa-client-install"을 통해 초기화됩니다. 또한 웹 서버에는 Apache 서비스(ipa service-add HTTP/ebook.exampletest.de)가 등록되어 있습니다.

아파치 구성에는 다음 사항도 반영됩니다.

으아아아 아까도 말씀드렸듯이 사용자 인증은 이런 식으로 되는 것 같아요(client(自己的票) > web 服务(自己的票) > ipa server). 그렇지 않으면 Apache 서버가 내 ldap/kerberos 사용자 이름을 반환하지 않습니다. 아니면 여기서 중요한 것을 놓치고 있는 걸까요? 이 인증을 시행하는 다른 방법이 있습니까?

출력: <?php print_r($_SERVER) ?>(가로채기)

<?php
$username = $_SERVER['PHP_AUTH_USER'];
$password = 'password';

$ldap_rdn  = 'uid='.$username.',cn=users,cn=accounts,dc=exampletest,dc=de';
$ldap_server = ldap_connect('ldap://ipa.exampletest.de:389');

ldap_set_option($ldap_server, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_server, LDAP_OPT_REFERRALS, 0);

if ($ldap_server) {
  $ldap_bind = @ldap_bind($ldap_server, $ldap_rdn, $password);
  if ($ldap_bind) {
    $search = array("uid","givenname","sn","mail","uidnumber","gidnumber");
    $result = ldap_search($ldap_server, $ldap_rdn, "mail=$username*", $search);
    $info = ldap_get_entries($ldap_server, $result);

    print_r($info);
  }
}
?>

P粉071743732P粉071743732181일 전382

모든 응답(1)나는 대답할 것이다

  • P粉614840363

    P粉6148403632024-03-27 09:46:20

    웹 서버에 올바른 Kerberos 티켓이 있는지 확인하세요.

    일반적으로 Kerberos 인증은 "모든" 티켓을 전송하는 것이 아니라 해당 서버에만 유효한 티켓만 전송합니다. 클라이언트가 웹 앱에 인증하면 HTTP/webapp.example.tld에 대한 티켓만 얻을 수 있으며 실제로 사용자를 대신하여 LDAP에 액세스하는 데 사용할 수는 없습니다.

    사용자를 대신하여 LDAP에 액세스해야 하는 필요한 경우 몇 가지 옵션이 있습니다.

    • 웹 애플리케이션은 자체 LDAP 디렉터리 자격 증명을 가질 수 있습니다. 아마도 이것이 가장 쉬운 방법일 것입니다. 웹 애플리케이션은 키탭에서 얻은 자체 티켓을 사용하여 표준 비밀번호 바인딩 또는 Kerberos(SASL) 바인딩을 사용할 수 있습니다.

      • LDAP는 웹 애플리케이션이 자체 자격 증명을 사용하여 인증하는 "가장"도 지원하지만 또한 "인증 ID"(authzid)를 지정하여 액세스 권한을 부여받을 계정을 결정합니다.

        예를 들어, "webapp"으로 인증했지만 authzid "myuser"를 지정하는 경우(그리고 LDAP 서버가 이를 허용하는 경우 ) "webapp"이 아닌 "myuser"가 일반적으로 갖는 권한을 얻게 됩니다. .

    • 웹 애플리케이션에 대한 HTTP 협상(SPNEGO) 인증은 "위임"을 활성화할 수 있습니다. 위임 은 마스터 티켓을 웹 서버로 krbtgt 전송한 다음 이를 임시 티켓 캐시에 저장하고 웹 응용 프로그램 환경에서 사용할 수 있도록 합니다.

      그러나 위임에는 몇 가지 문제가 있습니다.

      1. 추가 요청을 위해 클라이언트가 "전달" 플래그를 사용하여 새 krbtgt 티켓을 요청해야 하기 때문에(예: 협상된 인증 요청을 피하기 위해 쿠키를 사용할 수 없는 경우) 모든 HTTP 요청 속도가 느려집니다. "세션" 모드).

      2. 웹 애플리케이션에 액세스하는 모든 사용자(관리자 포함)에 대해 와일드카드 티켓을 저장하므로 웹 애플리케이션의 신뢰도가 높아야 합니다. 웹 애플리케이션 자체가 이를 남용하지 않을 것으로 신뢰되더라도 여전히 서버에 의해 손상될 수 있습니다.

      3. Kerberos(ldap_sasl_bind() 포함)를 사용하는 대부분의 API는 KRB5CCNAME 환경 변수가 티켓 캐시를 가리킬 것으로 예상합니다. 그러나 환경 변수는 프로세스 범위이므로 PHP가 동일한 프로세스를 재사용할 때마다(또는 더 나쁜 경우 mod_php를 사용하여 Apache 프로세스 내에서 웹 애플리케이션을 실행하는 경우) 관련 없는 요청에서 누출될 수 있습니다.

      AD에서는 AD가 다른 변형을 도입했기 때문에 이를 구체적으로 "무제한 위임"이라고 합니다.

    • 웹 애플리케이션은 S4U2Proxy(일명 "제한된 위임")를 사용하여 사용자를 대신하여 특정 제한된 서비스 세트에 대한 티켓을 생성할 수 있습니다(예: FreeIPA는 액세스만 ldap/foo.example.com하도록 제한할 수 있습니다).

      이것은 약간 복잡하며(PHP에는 이에 대한 API가 없습니다. 올바른 플래그를 사용하여 생성해야 할 수도 있습니다 kinit) 여전히 KRB5CCNAME 교차 요청 누출과 동일한 잠재적인 문제가 있습니다. < /p>

    일반 Kerberos 인증의 경우 사용법은 다음과 같습니다.

    으아아아

    그게 다예요. GSSAPI SASL 메커니즘은 환경에 이미 사용 가능한 Kerberos 티켓이 있을 것으로 예상하고(예: $KRB5CCNAME 또는 gss-proxy를 통해) 거기에서 발견된 티켓을 사용하여 인증합니다.

    가장을 사용하려면(LDAP 서버에 설정되어 있다고 가정) authz_id를 지정해야 합니다:

    으아아아

    대부분의 ldap_*() PHP 함수는 C libldap 라이브러리의 직접 래퍼이므로 해당 문서를 부분 참조로 사용할 수 있습니다.

    귀하의 예에서는 이미 사용자의 정확한 DN을 지정하고 있으므로 mail 进行额外过滤 - 只需在读取邮件时使用 objectClass=*특정 DN을 전달할 필요는 없는 것 같습니다. 또한 특정 DN을 읽으려면 하위 트리 검색보다는 "기본" 검색을 위해 ldap_read()를 사용하세요.

    아니요, 그런 일은 일어나지 않았습니다. 귀하의 사용자 이름(예: 클라이언트 Kerberos 주체)은 클라이언트 티켓에 저장되므로 웹 서버는 IPA와 통신할 필요 없이 티켓을 해독한 후 즉시 이를 알 수 있습니다.

    회신하다
    0
  • 취소회신하다