ldap windows安装_关于windows空会话的一些研究

建议点击

前言

在这篇文章中我们探讨一下windows空会话

参考链接:

  • https://sensepost.com/blog/2018/a-new-look-at-null-sessions-and-user-enumeration/

抓包分析

使用rpcclient尝试建立空连接并调用querydispinfo方法

rpcclient -U'%' 192.168.60.160 -c querydispinfo

返回NT_STATUS_ACCESS_DENIED

从抓包结果上分析,认证和授权这两个部分是分开的

你可以认证到ipc$共享上,也可以打开ipc$共享,但是你没办法在这个管道上调用LsaOpenPolicy方法

也就是说你可以建立空连接,但是你无法执行特定的RPC方法

使用nmap的 smb-enum-users脚本可以枚举出远程系统的所有用户,有时间我要研究一下这个脚本是怎么回事

6ca5222bcccc8de17106719560950b6c.png

但是我本地复现时无法枚举远程系统的用户,网上搜了一下,说是需要使用比较老的nmap版本

我尝试找了一下哪些管道可以进行匿名连接,还有就是在这些管道上可以调用哪些方法

最后我锁定了netlogon管道上的GetDcName, DsrGetDcName, DsrGetDcNameExDsrGetDcNameEx2这些方法

这些方法可以被用来检测在DC中是否存在特定的用户

直接调用DsrGetDcNameEx2RPC方法

先用rpcclient工具执行如下命令调用DsrGetDcNameEx2方法

rpcclient 192.168.60.160 -U'%' -c 'dsr_getdcnameex2 Administrator 512 domain2.com'
  • 192.168.60.160是DC

  • domain2.com是域名

  • Administrator 是我们要验证是否存在的用户名

  • 512 是AllowableAccountControlBits的值(参考https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/fb8e1146-a045-4c31-98d1-c68507ad5620?redirectedfrom=MSDN),0000000000000000000001000000000代表域用户

可以根据响应结果来进行判断:

  • 存在则返回一个结构体

  • 不存在则返回WERR_NO_SUCH_USER

下面看抓包情况

下面是DsrGetDcNameEx2请求的参数,16进制的200就是512,代表域用户

de685e0187e43fce8910eaff95338231.png

用户存在会返回success

1c64b7db55ca7dd6f521fa26c068ab1d.png

用户不存在则返回unknown5eaf034c1223751d0ff99f47334a80d6.png在抓取到的数据包中,可以看到如下数据包:

49680a0399896ce6d910d823d6f2b091.png

可以看到空连接建立之后我们可以通过调用LsarQueryInformationPolicy2方法来获取域的SID

root@ubuntu:/# rpcclient 192.168.60.160 -U'%' -c 'lsaquery'Domain Name: DOMAIN2Domain Sid: S-1-5-21-1986246999-2617435358-1981060215

根据上面的分析编写一个脚本,功能如下:

使用impacket框架调用DsrGetDcNameEx2方法,接收一个用户名列表,然后依次使用该列表中的用户针对远程主机(DC)调用DsrGetDcNameEx2方法,根据返回结果来进行枚举

构造数据包进行枚举

为了加速枚举,我调查了一下DsrGetDcNameEx2是如何工作的,该方法和GetDcName, DsrGetDcName, DsrGetDcNameEx都可以根据提供的域名来定位到该域的DC

这些方法会使用DNS、LDAP或者NetBIOS等方法获取域控制器在域内的位置,它们的工作方式大致如下所述:

  • 1、通过DNS查询或者NetBIOS广播提供的域名获取到域控制器的IP

  • 2、如果通过DNS获取到了域控制器的IP,则请求端会向DC发送一个LDAP ping报文,如果通过NetBIOS获取到了DC的IP,会向DC发送一个mailslot ping报文,这两个数据包都是通过UDP协议进行发送的,这两个报文中都有一个Filter,其实就是请求的一些参数

  • 3、DC检查自己是否符合这些要求并发送响应报文

  • 4、最后调用方法的系统会处理发送回来的响应报文

LDAP ping

发起调用的主机会向远程主机发送一个CLDAP报文(基于UDP,无连接),对于用户存在的情况,DC会向源主机返回操作码为23的报文,如果用户不存在则返回操作码25

因此我需要自己构造出CLDAP报文,Samba源代码中有一个示例脚本,该脚本可以构造出这样的CLDAP报文

根据那个示例脚本我写出了下面这个脚本:https://github.com/sensepost/UserEnum/blob/master/UserEnum_LDAP.py

安装这个工具需要asn1tools模块,安装的时候有需要安装diskcache模块,但是使用python2安装的时候他会出现错误,因为默认安装的是针对python3的模块,因此需要指定diskcache模块的版本

pip install diskcache==4.1.0

还有就是上面安装好之后还是会报错ImportError: cannot import name WordCompleter

然后我们使用如下方式解决

python2 -m pip install scapy==2.4.0

python2 -m pip install asn1tools==0.55.0

pip install prompt_toolkit==1 .0.15

如果运行的时候报下面的错误

asn1tools.codecs.EncodeError: protocolOp: typesOnly: Expected data of type bool, but got 0.

则使用如下方法解决

pip install asn1tools==0.100.0

之前写的脚本是直接调用的rpc方法,这种调用方法的方式相比较直接构造数据包发送请求的方式要慢很多

我测试了一下,1万多个用户名,只用了10秒左右

下面是抓的请求包

7d62663cbd5ebf49d898a637946afc07.png

这里acc进行了映射,映射表是下面这俩:

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/10bf6c8e-34af-4cf9-8dff-6b6330922863?redirectedfrom=MSDN

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8a193181-a7a2-49df-a8b1-f689aaa6987c?redirectedfrom=MSDN

从第一个表中我们可以找到普通域用户也就是16进制的200,对应的是UF_NORMAL_ACCOUNT

从第二个表中我们可以看到UF_NORMAL_ACCOUNT对应的是USER_NORMAL_ACCOUNT

USER_ACCOUNT在这里可以找到, 可以看到USER_NORMAL_ACCOUNT的值是0x00000010

从上面wireshark抓的包我们可以看到显示的是10:00:00:00

这个不能直接读,细心的话你可以发现这里没有加0x前缀,我们就必须将网络序(大端)转换成小端来读,转换之后就是00:00:00:10,正好符合上面的映射

后面我又在想我可以使用通配符来猜解用户名,比如B*Bo*等,但是当我这样写的时候,构造出来的CLDAP包就无法正常响应

我又捣鼓了一会儿,发现确实没办法实现这种功能,不过既然CLDAP可以达到这种爆破用户名的效果,那么NetBIOS呢?

首先我使用rpcclient发起了一个DsrGetDcNameEx2方法的调用,然后再wireshark中,我捕捉到了如下数据包:

这里发起请求的机器为DC01(192.168.57.2),目标机器为black(192.168.57.120)

  • 1、57.2发送NBNS广播报文,查询black这个名称

  • 2、12057.2返回NBNS响应报文,其中包含自己的IP(192.168.57.120)

  • 3、57.2发送SMB_NETLOGON广播报文(UDP),这里明明已经知道了black域的DC的IP却还要发送广播,我也不知道为啥

  • 4、120发送NBNS广播报文,查询DC01这个名称

  • 5、57.2向120发送SMB_NETLOGON报文

  • 6、57.2向120返回NBNS报文,报告自己的IP

  • 7、12057.2返回SMB_NETLOGON响应报文

从以上的报文我们可以看出来,通信双方都发起了NBNS查询,而且查询的名称我们是可以控制的,响应的IP地址我们也可以控制(这个我们只能控制DC01),但是通信过程一直都是UDP,没有SMB TCP报文,我们无法使用Responder来利用,但是我发现至少可以利用这个来方法来中毒目标系统的NETBIOS名称-ip对应表缓存

mailslot ping

看完了ldap之后我们再来看一下NetBIOS

可以使用这个脚本枚举

在运行该脚本的时候可能会遇到如下错误:

from scapy.all import *ImportError: No module named scapy.all

解决方法

pip install scapy==2.4.3

使用方法:

Python2 UserEnum_NBS.py 192.168.60.148 192.168.60.160 DOMAIN2 userlist.txt

注意这里域名是NetBIOS名称,也就是大写字母,比如domain.local在这里应该写成DOMAIN,注意这里写的并不是FQDN

可以看到netlogon的响应包

3a5a79819ac4d60447923a8067ce295f.png

参考对照表,0x17 (十进制的23)表示LOGON_SAM_LOGON_RESPONSE_EX而并不是user unknown,这里应该是wireshark的问题,LOGON_SAM_USER_UNKNOWN_EX应该是0x19

因此操作码为0x17说明用户存在

后记

以上提到的三种方式中,CLDAP是最快的,其实次NetBIOS,最慢的是直接调用DsrGetDcNameEx2 方法,且前两者不会产生日志,最后一种方法会产生匿名登录日志

这个是直接调用rpc方法产生的日志

fbfc416c7b45f014dc2c4a4b61495994.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值