LDAP(Light Directory Access Portocol)轻型目录访问协议,通过IP协议提供访问控制和维护分布式信息的目录信息。通常使用ldap来实现访问控制、权限管理、资源管理等,Microsoft Active Directory即使用ldap协议来做域控用户登录认证,而OpenLDAP则是利用ldap协议实现开源的统一认证服务。本文OpenLDAP的搭建基于简书博主小尛酒窝的文章,因其文章代码存在一个小错误,该错误在此处可解决,所以我把完整搭建过程再记录一遍。

关于LDAP协议的介绍可以看LDAP Wiki
搭建环境:centos7

一、OpenLDAP服务器搭建

0x01 安装openldap服务

yum install -y epel-release openldap compat-openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel migrationtools

0x02 初始化openldap服务管理权限

[root@localhost ~]# slappasswd -s 123456 #设置LDAP管理员密码,此处生成的SSHA密码需要记住,后面需要用到
{SSHA}gJyJiCg+suM1r1oKOQc5i6WUk2YZgjIZ
[root@localhost ~]# sed -i 's/cn=Manager/cn=admin/g' /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif #修改配置文件,替换cn为admin,cn表示OpenLDAP管理员用户名
[root@localhost ~]# sed -i 's/dc=my-domain,dc=com/dc=ldaptest,dc=com,dc=cn/g'  /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif #修改配置文件,替换dc为ldaptest.com.cn,dc为LDAP服务器的域名
[root@localhost ~]# vim /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
olcSuffix: dc=ldaptest,dc=com,dc=cn
olcRootDN: cn=admin,dc=ldaptest,dc=com,dc=cn
olcRootPW: {SSHA}gJyJiCg+suM1r1oKOQc5i6WUk2YZgjIZ #新增一行,把之前生成的SSHA密码填入
[root@localhost ~]# sed -i 's/cn=Manager,dc=my-domain,dc=com/cn=admin,dc=ldaptest,dc=com,dc=cn/g' /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif #修改配置文件的cn和dc
[root@localhost ~]# vim /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{1\}monitor.ldif #检测是否修改正确
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth" read by dn.base="cn=admin,dc=ldaptest,dc=com,dc=cn" read by * none
[root@localhost ~]# slaptest -u #配置文件测试
6022a998 ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={1}monitor.ldif"
6022a998 ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif"
config file testing succeeded #看到成功便没有问题
[root@localhost ~]# systemctl restart slapd

0x03 配置OpenLDAP数据库

OpenLDAP默认使用的数据库是BerkeleyDB,/var/lib/ldap/就是BerkeleyDB数据库默认存储的路径。

[root@localhost ~]# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
[root@localhost ~]# chown ldap.ldap -R /var/lib/ldap/
[root@localhost ~]# chmod 700 -R /var/lib/ldap/
[root@localhost ~]# ll /var/lib/ldap/
总用量 324
-rwx------ 1 ldap ldap     2048 2月   9 23:27 alock
-rwx------ 1 ldap ldap   262144 2月   9 23:27 __db.001
-rwx------ 1 ldap ldap    32768 2月   9 23:27 __db.002
-rwx------ 1 ldap ldap    49152 2月   9 23:27 __db.003
-rwx------ 1 ldap ldap      845 2月  10 00:02 DB_CONFIG
-rwx------ 1 ldap ldap     8192 2月   9 23:27 dn2id.bdb
-rwx------ 1 ldap ldap    32768 2月   9 23:27 id2entry.bdb
-rwx------ 1 ldap ldap 10485760 2月   9 23:27 log.0000000001
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif #导入基本Schema
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=cosine,cn=schema,cn=config"
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=nis,cn=schema,cn=config"
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=inetorgperson,cn=schema,cn=config"

0x4 初始化组织架构及添加初始用户和组

[root@localhost ~]# vim /usr/share/migrationtools/migrate_common.ph
$DEFAULT_MAIL_DOMAIN = "ldaptest.com.cn";
$DEFAULT_BASE = "dc=ldaptest,dc=com,dc=cn";
$EXTENDED_SCHEMA = 1;
[root@localhost ~]# groupadd OPS
[root@localhost ~]# groupadd HR
[root@localhost ~]# useradd -g OPS charles
[root@localhost ~]# useradd -g HR fiona
[root@localhost ~]# echo "cha123" | passwd --stdin charles
更改用户 charles 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# echo "fio123" | passwd --stdin fiona
更改用户 fiona 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# grep "OPS" /etc/group > groups
[root@localhost ~]# grep "HR" /etc/group >> groups
[root@localhost ~]# grep "charles" /etc/passwd > users
[root@localhost ~]# grep "fiona" /etc/passwd >> users
[root@localhost ~]# /usr/share/migrationtools/migrate_passwd.pl users > users.ldif
[root@localhost ~]# /usr/share/migrationtools/migrate_group.pl groups > groups.ldif
[root@localhost ~]# vim base.ldif #此处即是原博代码有问题的地方,首行为dn行,其他dn的行前留一空行
dn: dc=ldaptest,dc=com,dc=cn
o: ldaptest.com.cn
dc: ldaptest 
objectClass: top
objectClass: dcObject
objectclass: organization

dn: cn=admin,dc=ldaptest,dc=com,dc=cn
cn: admin
objectClass: organizationalRole
description: Directory Manager

dn: ou=People,dc=ldaptest,dc=com,dc=cn
ou: People
objectClass: top
objectClass: organizationalUnit

dn: ou=Group,dc=ldaptest,dc=com,dc=cn
ou: Group
objectClass: top
objectClass: organizationalUnit
[root@localhost ~]# ldapadd -x -w "123456" -D "cn=admin,dc=ldaptest,dc=com,dc=cn" -f base.ldif
[root@localhost ~]# ldapadd -x -w "123456" -D "cn=admin,dc=ldaptest,dc=com,dc=cn" -f users.ldif
[root@localhost ~]# ldapadd -x -w "123456" -D "cn=admin,dc=ldaptest,dc=com,dc=cn" -f groups.ldif

0x05 启用Openldap服务的日志记录功能

[root@localhost ~]# vim loglevel.ldif
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats
[root@localhost ~]# ldapmodify -Y EXTERNAL -H ldapi:/// -f loglevel.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
[root@localhost ~]# vim /etc/rsyslog.conf
local4.* /var/log/slapd/slapd.log
[root@localhost ~]# systemctl restart rsyslog
[root@localhost ~]# systemctl restart slapd
[root@localhost ~]# tail -f /var/log/slapd/slapd.log #查看配置好的日志,即可观察到关于slapd的运行信息
Feb 10 00:41:46 localhost slapd[1745]: daemon: shutdown requested and initiated.
Feb 10 00:41:46 localhost slapd[1745]: slapd shutdown: waiting for 0 operations/tasks to finish
Feb 10 00:41:46 localhost slapd[1745]: slapd stopped.

0x06 禁止用户匿名登录

[root@localhost ~]# vim disable_anon.ldif
dn: cn=config
changetype: modify
add: olcDisallows
olcDisallows: bind_anon

dn: cn=config
changetype: modify
add: olcRequires
olcRequires: authc

dn: olcDatabase={-1}frontend,cn=config
changetype: modify
add: olcRequires
olcRequires: authc
[root@localhost ~]# ldapadd -Y EXTERNAL -H ldapi:/// -f /root/disable_anon.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"

modifying entry "cn=config"

modifying entry "olcDatabase={-1}frontend,cn=config"

二、centos客户端LDAP认证登录

0x07 安装nslcd服务

[root@localhost ~]# yum -y install nss-pam-ldapd

0x08 修改nslcd配置文件

[root@localhost ~]# vim /etc/nslcd.conf
uri ldap://192.168.1.188/
base dc=ldaptest,dc=com,dc=cn
binddn cn=admin,dc=ldaptest,dc=com,dc=cn #若服务器开启了禁止匿名用户访问,需要在客户端配置具有读权限的账号和密码才能验证成功。
bindpw 123456 #同上
rootpwmoddn cn=admin,dc=ldaptest,dc=com,dc=cn
rootpwmodpw 123456
ssl no
tls_cacertdir /etc/openldap/cacerts

0x09 修改system-auth配置文件

[root@localhost ~]# vim /etc/pam.d/system-auth
1)在auth required pam_deny.so这行上面加上"auth sufficient pam_ldap.so use_first_pass" 
2)在account required pam_permit.so这行上面加上account [default=bad success=ok user_unknown=ignore] pam_ldap.so 
3)在password required pam_deny.so这行上面加上password sufficient pam_ldap.so use_authtok
4)在最后一行加上session optional pam_ldap.so 
5)在session块中的第二行下面添加session optional pam_mkhomedir.so skel=/etc/skel/ umask=0022
注意:含有pam_sss.so的行要注释掉

0x0a 修改nsswitch.conf 配置文件

[root@localhost ~]# vim /etc/nsswitch.conf
passwd: files ldap
shadow: files ldap
group: files ldap

0x0b 修改authconfig配置文件

[root@localhost ~]# vim /etc/sysconfig/authconfig
USELDAP=yes
USELDAPAUTH=yes
USELOCAUTHORIZE=yes
USESHADOW=yes

0x0c 编辑sshd_config文件

[root@localhost ~]# vim /etc/ssh/sshd_config
UsePAM yes #确保此为yes

0x0d 编辑sshd文件

[root@localhost ~]# vim /etc/pam.d/sshd
1)在最后面添加session required pam_mkhomedir.so 
2)在account块中添加account required pam_access.so(后续控制用户使用)

0x0e 编辑password-auth

1)auth块中倒数第二行添加auth sufficient pam_ldap.so use_first_pass
2)account块中倒数第二行添加account [default=bad success=ok user_unknown=ignore] pam_ldap.so
3)password块中倒数第二行添加password sufficient pam_ldap.so use_authtok
4)session块中最后一行添加session optional pam_ldap.so 
注意:包含pam_sss.so的行对其进行注释

0x0f 重启服务

[root@localhost ~]# systemctl restart sshd
[root@localhost ~]# systemctl restart nslcd

三、LDAP流量分析

0x10 登录认证流量

环境已经创建好,在配置好LDAP的客户端通过ssh登录测试用户,同时在LDAP服务端抓LDAP客户端流量。
ssh -l charles 192.168.1.189
[email protected]'s password: cha123
客户端首先发送searchRequest,查询是否存在charles用户
查询是否存在charles用户
服务器对请求响应searchResEntry,当用户存在,服务器返回uiduidNumber。同时,服务器还会响应searchResDone success,表明响应成功。
服务器返回charles用户存在消息
登录认证流量在wireshark中为bindRequest,uid为登录用户名,simple为登录密码,当LDAP客户端向服务端认证成功时,LDAP服务器向客户端发送binResponse success,表明认证成功。
LDAP登录认证流量
当登录密码错误时,LDAP服务器响应invalidCredentials,表示密码错误。
LDAP登录密码错误时流量
而当用户名错误,即LDAP服务器中不存在此用户时,在客户端向服务器searchRequest阶段,服务器无searchResEntry响应,只有searchResDone,表明LDAP上不存在该用户。
服务器无searchResEntry响应

0x11 ldapsearch信息收集

当拿到ldap其中一个用户的密码后,可以使用ldapsearch工具进行信息收集,kali中默认集成了该工具。
以charles用户密码泄露为例,分析使用ldapsearch向LDAP服务器发送的流量情况。具体ldapsearch用法可参考此处

ldapsearch -x -H ldap://192.168.1.188:389 -D "uid=charles,ou=People,DC=ldaptest,DC=com,DC=cn" -w "cha123" -b "DC=ldaptest,DC=com,DC=cn" #查询域内所有信息

抓包看到,首先经过bindRequest认证,认证成功后,进行searchRequest(2) "DC=ldaptest,DC=com,DC=cn" wholeSubtree,查询整个ldaptest.com.cn域内所有项目信息
认证成功后,查询wholeSubtree

参考文档:
https://www.jianshu.com/p/ce3bb45585d1
https://www.cnblogs.com/cy0917/p/10178898.html
https://blog.csdn.net/liumiaocn/article/details/83990918
Last modification:February 13th, 2021 at 09:18 pm