Maison  >  Questions et réponses  >  le corps du texte

Connexion LDAP sans mot de passe et obtenir des informations utilisateur à l'aide du ticket Kerberos en PHP

J'essaie de mettre en œuvre le SSO sur certains des sites intranet de notre entreprise en utilisant FreeIPA/Kerberos. Mais il existe très peu d’informations sur ce sujet.

J'ai trois machines en cours d'exécution dans mon réseau de test :

  1. Serveur FreeIPA v4.9.8 sur Centos 8 Stream
  2. Serveur Web sur Debian 11 (Apache v2.4.53, PHP v7.4.28)
  3. Client Xubuntu 22.04 avec Kinit et Firefox

Kinit, la connexion Unix et l'authentification Apache Kerberos fonctionnent. Le navigateur Firefox sur le système client peut se connecter à FreeIPA WebConfig sans mot de passe (à l'aide du ticket Kerberos). Je souhaite maintenant déplacer cette fonctionnalité vers notre page intranet. Jusqu'à présent, les connexions à ces pages étaient basées sur les connexions LDAP traditionnelles. Avec un léger ajustement du script de connexion, les utilisateurs peuvent désormais se connecter au nouveau serveur FreeIPA. Cependant, il a toujours besoin d'un mot de passe, mais grâce au ticket Kerberos, le mot de passe n'est en réalité plus nécessaire.

La question est : à quoi ressemble la connexion sans mot de passe ?

Extrait fonctionnel du script de connexion :

<?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);
  }
}
?>

Maintenant, j'ai deux pensées :

  1. Je pourrais utiliser ldap_sasl_bind() au lieu de ldap_bind(), mais cette fonction n'est pas documentée sur php.net (https://www.php.net/manual/en/function.ldap-sasl-bind.php). Si quelqu'un sait comment utiliser cette fonctionnalité, je lui en serais reconnaissant.
  2. Je serais également heureux si je pouvais exécuter ldap_search() sans mot de passe pour obtenir des informations sur l'utilisateur (nom complet, e-mail, etc.).

Merci beaucoup d'avance.

Éditeur :

La VM du serveur Web et la VM client sont initialisées via "ipa-client-install". De plus, le serveur Web a enregistré le service Apache (ipa service-add HTTP/ebook.exampletest.de).

La configuration d'Apache reflète également ceci :

<Directory /var/www/ebook/>
        AuthType                GSSAPI
        AuthName                "eBook Login"
        GssapiCredStore         keytab:/etc/apache2/http.keytab
        GssapiAllowedMech       krb5
        GssapiBasicAuthMech     krb5
        GssapiImpersonate       On
        GssapiDelegCcacheDir    /run/apache2/clientcaches
        GssapiLocalName         On
        
        # for production set to on:
        GssapiSSLonly           Off
        GssapiNegotiateOnce     Off
        
        GssapiUseSessions       On
        Session                 On
        SessionCookieName       gssapi_session path=/private;httponly;secure;
        Require                 valid-user
    </Directory>
Comme je l'ai déjà mentionné, l'authentification des utilisateurs semble fonctionner comme ceci (client(自己的票) > web 服务(自己的票) > ipa server). Sinon, le serveur Apache ne renverra pas mon nom d'utilisateur ldap/kerberos. Ou est-ce que j'ai raté quelque chose d'important ici ? Existe-t-il un autre moyen d'appliquer cette authentification ?

Sortie : <?php print_r($_SERVER) ?> (interceptée)

[GSS_MECH] => Negotiate/krb5
[GSS_NAME] => test@EXAMPLETEST.DE
[REMOTE_USER] => test
[AUTH_TYPE] => Negotiate
[PHP_AUTH_USER] => test

P粉071743732P粉071743732230 Il y a quelques jours459

répondre à tous(1)je répondrai

  • P粉614840363

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

    Assurez-vous que votre serveur Web dispose du correct ticket Kerberos.

    En règle générale, l'authentification Kerberos transmet uniquement les tickets valables uniquement pour ce serveur, plutôt qu'une couverture de « tous » les tickets. Lorsqu'un client s'authentifie auprès de votre application Web, tout ce que vous obtenez est un ticket pour le HTTP/webapp.example.tld et vous ne pouvez pas réellement l'utiliser pour accéder à LDAP au nom de l'utilisateur.

    Si vous besoinaccéder à LDAP au nom d'un utilisateur, vous disposez de plusieurs options :

    • Les applications Web peuvent avoir leurs propres informations d'identification d'annuaire LDAP. C'est probablement le moyen le plus simple. Les applications Web peuvent utiliser la liaison de mot de passe standard ou la liaison Kerberos (SASL) à l'aide de leurs propres tickets obtenus à partir d'un fichier keytab.

      • LDAP prend également en charge "l'usurpation d'identité", où l'application Web s'authentifiera à l'aide de ses propres informations d'identification, mais également spécifiez un "ID d'autorisation" (authzid) pour déterminer à quel compte vous aurez accès.

        Par exemple, si vous vous authentifiez en tant que "webapp" mais spécifiez l'identifiant d'authentification "myuser" (et si le serveur LDAP l'autorise ), alors vous obtiendrez les autorisations que "myuser" aurait normalement - et non "webapp" parmi celles-ci. .

    • L'authentification par négociation HTTP (SPNEGO) pour les applications Web peut permettre la « délégation ». La délégation transfère le ticket maître krbtgt au serveur Web, qui le place ensuite dans un cache de tickets temporaire et le met à la disposition de votre environnement d'application Web.

      Cependant, il y a quelques problèmes avec la délégation :

      1. Cela ralentira chaque requête HTTP car le client devra demander un nouveau krbtgt ticket avec l'indicateur "forward" (à moins que le serveur Web puisse utiliser par exemple des cookies pour éviter de demander une authentification négociée) pour d'autres requêtes, par exemple avec Il y a mod_auth_gssapi dans. mode "séance").

      2. Cela nécessite que l'application Web soit hautement fiable, car elle stockera des tickets génériques pour chaque utilisateur qui y accède (y compris les administrateurs) - même si l'application Web elle-même est fiable pour ne pas en abuser, ils peuvent toujours être compromis par le serveur.

      3. La plupart des API qui utilisent Kerberos (y compris ldap_sasl_bind()) s'attendent à ce que KRB5CCNAME les variables d'environnement pointent vers le cache de tickets. Mais les variables d'environnement sont limitées au processus, elles peuvent donc être divulguées dans des requêtes non liées chaque fois que PHP réutilise le même processus (ou pire, si vous utilisez mod_php pour exécuter votre application Web dans le processus Apache).

      Dans AD, cela est spécifiquement appelé « délégation sans contrainte » puisque AD ​​a introduit d'autres variantes.

    • Les applications Web peuvent utiliser S4U2Proxy, également appelée « délégation contrainte » pour créer des tickets au nom des utilisateurs pour certains ensembles limités de services (par exemple, FreeIPA peut les restreindre uniquement à l'accès ldap/foo.example.com).

      C'est un peu compliqué (PHP n'a pas d'API pour cela - vous devrez peut-être la générer avec les bons indicateurs kinit), et présente toujours les mêmes problèmes potentiels que la fuite de requêtes croisées KRB5CCNAME. < /p>

    Pour l'authentification Kerberos standard, l'utilisation est la suivante :

    ldap_sasl_bind($conn, null, null, "GSSAPI");

    C'est tout. Le mécanisme GSSAPI SASL s'attend à ce que l'environnement dispose déjà d'un ticket Kerberos disponible (par exemple via $KRB5CCNAME ou via gss-proxy), et il utilisera le ticket qu'il y trouvera pour l'authentification.

    Si vous souhaitez utiliser l'usurpation d'identité (en supposant une configuration sur le serveur LDAP), vous devez spécifier authz_id :

    ldap_sasl_bind($conn, null, null, "GSSAPI", null, null, $theuser);

    La plupart des ldap_*() fonctions PHP sont des wrappers directs de la bibliothèque C libldap, sa documentation peut donc être utilisée comme référence partielle.

    Il semble que votre exemple spécifie déjà le DN exact de l'utilisateur, donc transmettre mail 进行额外过滤 - 只需在读取邮件时使用 objectClass=*un DN spécifique ne semble pas être nécessaire. De plus, lorsque vous souhaitez lire un DN spécifique, utilisez ldap_read() pour une recherche « de base » plutôt que pour une recherche de sous-arborescence.

    Non, ce n’est pas ce qui s’est passé. Votre nom d'utilisateur (c'est-à-dire le principal Kerberos du client) est stocké dans le ticket client, de sorte que le serveur Web le connaît immédiatement après avoir déchiffré le ticket sans avoir à parler à l'IPA.

    répondre
    0
  • Annulerrépondre