Разбор ldap sid в узле - PullRequest
       3

Разбор ldap sid в узле

0 голосов
/ 23 января 2020

Я пытаюсь получить все группы пользователя, включая вложенные группы, чтобы ускорить запрос. Я пытаюсь использовать атрибут tokenGroups, чтобы не выполнять рекурсивный запрос групп групп.

Я получил tokenGroups с содержит sid всех групп пользователя. Проблема в том, что entry.object дает мне массив странных строк, которые я не могу использовать, а object.raw дает мне массив jsons с типом: "buffer" и данными, содержащими массив с числами, которые я не знаю, что делать с.

Учитывая, что у меня есть, как мне разобрать sid или получить больше информации о каждой группе?

Ответы [ 2 ]

0 голосов
/ 24 января 2020

tokenGroups - двоичный атрибут, возвращаемый в строке в кодировке base64. Чтобы использовать его в запросе, вам нужно будет его декодировать и преобразовать в экранированную строку, которую можно использовать в запросе . Чтобы уменьшить нагрузку на сеть и повысить производительность, вы можете запросить все группы в одном запросе, и, поскольку индекс objectSid проиндексирован, результат быстро растет.

Позвольте мне привести пример командной строки:

# Preparation

# Domain controller
$ ad_host=w2k8-dc.internal.local

# Get domain context automatically (or set manually)
$ base_dn=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -s base defaultNamingContext | grep '^defaultNamingContext:' | cut -f2- -d\ )
$ echo $base_dn
DC=internal,DC=local

# User to check
$ user=Administrator
$ user_dn=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" sAMAccountName=$user dn | grep '^dn:' | cut -f2- -d\ )
$ echo $user_dn
CN=Administrator,CN=Users,DC=internal,DC=local

# Actual query

# Get token groups
$ token_groups=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$user_dn" -s base tokenGroups | grep '^tokenGroups:' | cut -f2- -d\ )
$ echo $token_groups
AQIAAAAAAAUgAAAAIQIAAA== AQIAAAAAAAUgAAAAIAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3PAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3BgIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3BwIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3AQIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3CAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3AAIAAA==

# Decode SIDs and prepare query
$ sid_query=$(for sid in $token_groups; do printf "(objectSid=%s)" $(echo $sid | base64 -d | hexdump -ve '"\\" /1 "%02x"'); done)
$ echo $sid_query
(objectSid=\01\02\00\00\00\00\00\05\20\00\00\00\21\02\00\00)(objectSid=\01\02\00\00\00\00\00\05\20\00\00\00\20\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\3c\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\06\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\07\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\01\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\08\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\00\02\00\00)

# Get group information
$ ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(|$sid_query)" dn cn
dn: CN=Schema Admins,CN=Users,DC=internal,DC=local
cn: Schema Admins

dn: CN=Enterprise Admins,CN=Users,DC=internal,DC=local
cn: Enterprise Admins

dn: CN=Administrators,CN=Builtin,DC=internal,DC=local
cn: Administrators

dn: CN=Users,CN=Builtin,DC=internal,DC=local
cn: Users

dn: CN=Domain Admins,CN=Users,DC=internal,DC=local
cn: Domain Admins

dn: CN=Domain Users,CN=Users,DC=internal,DC=local
cn: Domain Users

dn: CN=Group Policy Creator Owners,CN=Users,DC=internal,DC=local
cn: Group Policy Creator Owners

dn: CN=Denied RODC Password Replication Group,CN=Users,DC=internal,DC=local
cn: Denied RODC Password Replication Group

Обратите внимание, что использование tokenGroups не предоставляет информацию о группах рассылки. Однако он включает основную группу пользователя (скорее всего, Domain Users), которая НЕ включена в memberOf (а пользователь не включен в атрибут member группы).

Это может повлиять на результаты, так как обычный рекурсивный запрос member не будет возвращать ни первичную группу, ни группы, в которых пользователь будет являться членом своей первичной группы. Например, если основная группа пользователя - Domain Users, а Domain Users является членом группы my-security-group, последняя не будет найдена в запросе member:1.2.840.113556.1.4.1941:, но будет возвращена в tokenGroups.

И последнее, но не менее важное: member:1.2.840.113556.1.4.1941: может быть очень дорогим в вычислительном отношении, и в зависимости от размера домена, базового DN и нагрузки контроллера домена может потребоваться много времени для разрешения. Для домена моей реальной компании это примерно в 3 раза больше, чем для запроса SID:

$ time ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=$user_dn))" dn | grep '^dn:' | wc -l
92

real    0m11.038s
user    0m0.017s
sys     0m0.024s

$ time ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(|$sid_query)" dn | grep '^dn:' | wc -l
111

real    0m2.851s
user    0m0.014s
sys     0m0.033s

Обратите внимание на разницу в количестве результатов; запрос SID возвращает некоторые встроенные группы и те группы, членами которых является пользователь, через Domain Users.

0 голосов
/ 23 января 2020

Если вам нужна помощь в разборе tokenGroups, вам придется показать свой код и какой вывод вы на самом деле получаете.

Но да, tokenGroups дает вам SID каждого security группа, членом которой должен считаться пользователь (рекурсивно). Но есть предостережения:

  • Если вы хотите, чтобы название каждой группы, вы должны искать группу на основе SID. Это в основном один сетевой запрос на группу. Если хочешь «быстрее», то это плохо. Больше сетевых запросов = медленнее.
  • Он не будет включать группы рассылки (группы, где тип группы - «Распространение»). Это может иметь или не иметь значения для вас.

Мой первый вопрос всегда таков: почему вы хотите это знать? Вы действительно должны перечислить каждую группу, членом которой является пользователь? Или вы ищете одну конкретную c группу. Если вы ищете одну группу, то вы можете найти SID этой группы и найти этот SID в tokenGroups.

Если вы действительно хотите, чтобы название каждой группы или вам нужно включите группы рассылки, тогда вам лучше делать это по-другому. Вы можете выполнить поиск всех групп, в которых этот пользователь является участником:

(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=userDN))

Где userDN - это distinguishedName пользователя. Это странно выглядящее число - идентификатор объекта (OID) для LDAP_MATCHING_RULE_IN_CHAIN, о котором вы можете прочитать подробнее на этой странице . В основном, это говорит AD сделать рекурсивный поиск. Таким образом, он будет возвращать каждую группу, в которой пользователь является прямым или вложенным.

Я написал пару статей на моем веб-сайте об этом, которые вы могли бы прочитать, особенно если у вас их больше одного. домен в вашей среде. Мои примеры кода C#, но в любом случае это просто LDAP в фоновом режиме, поэтому принципы можно применять к любому языку.

...