请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,猫哥的秋刀鱼回忆录及文章作者不为此承担任何责任。猫哥的秋刀鱼回忆录公众号均不发表带原创标志的文章,转载请附带公众号出处!本文主要参考AresX师傅(https://ares-x.com)与暗月师傅(微信公众号moonsec)的文章进行总结合并,并且加以浅修改与补充。
一个在域中的服务器通过路由来做端口映射的方式以此来对外提供web服务,在我们拿到该主机的system权限后,如果想做进一步的内网渗透的话,那么这个范畴就该归属于为域渗透。本文旨在浅浅叙述新手在学习域渗透时中应着重注意的一些话题,所以我们应以更直白易懂的话语去带动知识。在阅读本文前,我默认你已然了解域的基本概念,域环境与工作组环境的区别。鲁迅《伤逝》中写道:
我愿意真有所谓鬼魂,真有所谓地狱,那么,即使在孽风怒吼之中,我也将寻觅子君,当面说出我的悔恨和悲哀,祈求她的饶恕;否则,地狱的毒焰将围绕我,猛烈地烧尽我的悔恨和悲哀。
对于域渗透的一个认知问题,就是我们做到什么程度才算是对域的一个渗透?在基于WINDOWS与环境的渗透中,我们常常涉及到一些技术,比如说
这些技术的应用,实际上都是与域环境下的认证机制息息相关。在了解这些技术的本质之前,我们就必须对WINDOWS的认证机制有一个很清晰的了解。WINDOWS的认证的主要包括3个部分:
对于本地认证,我们就可以理解为当我们输入密码的时候,系统收到密码后将用户输入的密码计算成NTLM 哈希值然后与SAM(%SystemRoot%\system32\config\sam)数据库中的该用户哈希数值进行一个比对,如果匹配成功就登陆,匹配不成功的就登录失败,在本地认证中用来处理用户输入密码的进程是lsass.exe,用户密码会储存在这个进程中明文保存,供该进程将密码计算成NTLM哈希与SAM进行比对。我们使用的mimikatz来获取的明文密码就是在这个进程中读取到的。
网络认证即在工作组环境下远程登陆另一台电脑所采用的认证机制,NTLM是一种基于质询/应答消息交换模式的认证机制,常用于工作组和域环境下登录场景的身份认证。NTLM协议的认证过程分为三步,也叫挑战相应机制:
在质询环节,因为工作组环境和域环境下Net NTLM认证过程因为有DC(域控制器)的参与流程略有差异,这里图示为有DC参与下的Net NTLM认证过程,如下:
简单的来说:客户端向服务器请求使用某个用户进行验证,服务端判断该用户是否存在,存在的话使用这个用户密码的哈希值来加密一个随机字符串,并且将这个随机字符串返回给客户端,客户端再把自己提供的密码进行哈希处理后也来加密这串随机字符串,然后再把结果发送给服务器,服务器把从客户端发送的加密结果与自己本地的加密结果进行比较,相同的话便通过认证。其中的关键点在于:第二步中客户端发送的是NTLM哈希值与随机字符串加密的结果,而这个NTLM哈希是由用户输入的密码本地计算得出的,所以在这个步骤中,只要能提供正确的NTLM哈希即使不知道正确的密码也可通过认证。当然了,这个NTLM认证机制,从整个认证过程来看安全确实不太到位,也就是说只需要拿到一个系统管理员的哈希,直接给DC去认证就好了,反正账户名和域名都知道,psexec横向移动就是通过这种方式来进行的,如果本地管理员的账号密码相同,其实都不用密码一样也可以被认证,我们所以要做的就是去不断的通过这种方式来尝试拓展攻击内网的其他机器,直到去控制整个域。
验证:在质询完成后,服务端收到客户端发送的Response后,与之前保存在内存中的()混合hash比较,如果相等认证通过。
哈希传递攻击便是利用了NTLM认证机制的缺陷而导致的
域内身份认证是采用的Kerberos协议,在上面的NTLM认证机制中我们认识到了哈希传递攻击便是利用了认证机制的缺陷,相信大家对票据攻击也是耳熟能详的。Kerberos实际是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。Kerberos 是一种网络认证协议,其设计目标是通过密钥系统为客户机 / 服务器应用程序提供强大的认证服务。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos 作为一种可信任的第三方认证服务,是通过传统的密码技术(如:共享密钥)执行认证服务的。
简单来说,域内认证即是采用了Kerberos协议的认证机制,与前面两种认证机制相比最大的一个区别,就是它有一个可信的第三方机构KDC的参与。在域认证体系中存在着3个角色:
这里的AD账户数据库主要来存储域中所有用户的用户名以及他对应的NTLM哈希值,可以理解为域中的一个 SAM数据库,KDC可以从AD中去提取域中所有用户的NTLM哈希值,这是Kerberos协议能够成功实现的基础。从另一种角度来看,AD+AS+TGS均可以认为是域控制器DC。我们仍然需要对Kerberos认证协议做一些基础概念的认识,比如:
相对于NTLM而言,kerberos认证方式就要复杂的多,因为它提供了一个集中式的认证方式,在整个认证过程中总共要涉及到三方:客户端,服务端和KDC [密钥分发中心], 在Windows域环境中,KDC的角色由DC[域控]来担任,Kerberos是一种基于票据的认证方式,票据(Ticket)是用来安全的在认证服务器和用户请求的服务之间传递用户的身份,同时也会传递一些附加信息,用来保证使用票据的用户必须是票据中指定的用户,票据一旦生成,在生存时间内可以被客户端多次使用来申请同一个Server的服务(这就是票据窃取导致票据传递问题)
我们为了更好的理解,分析这几个阶段:
用户输入用户名和密码信息后,在客户端用户输入的密码通过计算生成NTLM哈希作做为CLIENT密钥
客户端向AS(身份认证服务)发送认证请求:客户端向AS发送认证请求,请求中带有明文的用户名信息,但是此时并未发送密码或密钥信息
AS确认Client端登录者用户身份
AS收到用户认证请求之后,根据请求中的用户名信息,从数据库中查找该用户名是否存在。如果用户名存在,则根据该用户名去提取NTLM Hash做为AS生成的CLIENT密钥,如果第1步中用户提供的密码信息正确,那么该秘钥与用户登录中的CLIENT密钥是相等的。
AS为Client响应如下消息:
TGT黄金票据中包含如下信息:
Client收到AS的响应消息以后,利用自身的 CLIENT密钥 可以对Msg A进行解密,这样可以获取到 CLIENT/TGS SESSIONKEY 。但由于Msg B是使用TGS密钥加密的,Client无法对其解密。
总的来说:AS响应的消息中有一条是属于客户端的,但是另外一条却属于TGS。Client/TGS SessionKey出现了两个均匀复制,一个给客户端,一个给TGS端。还有就是在认证过程中的加密除哈希外均采用的是对称加密算法。
客户端向TGS发送请求服务授权请求
客户端发送的请求中包含如下两个消息:
KDC接收到TGT与其他内容后,会首先使用KDC 的NTLM Hash解密TGT,只有KDC可以解密TGT,从TGT中提取到 CLIENT/TGS SESSIONKEY ,再使用 CLIENT/TGS SESSIONKEY 解密Authenticator 1,获取到{Client ID, Timestamp} 并与通过解密TGT获取到的{Client ID, 有效时间}进行对比
TGS为Client响应服务授权票据:
TGS为Client响应的消息包括:
Msg F使用了 CLIENT/TGS SESSIONKEY 加密,因此,该消息对Client可见。Client对其解密以后可获取到 CLIENT/SERVER SESSIONKEY。而Msg E使用了 [SERVICE密钥] 加密,该消息可视作是TGS给Service Server的消息,只不过由Client一起携带发送给Service Server
Client向Service Server发送服务请求
发送的消息中包括:
总结一下就是:CLIENT/SERVER SESSIONKEY 并非直接传输,而是被包含在使用[Service密钥]加密的Msg E中。既然 [CLIENT/SERVER SESSIONKEY] 并不直接明文传输, Client需要向Service Server证明自己拥有正确的 CLIENT/SERVER SESSIONKEY ,所以,Authenticator 2使用了 CLIENT/SERVER SESSIONKEY 加密。
SS响应Client:SS收到客户端的服务请求之后,先利用自身的 [SERVICE密钥] 对Msg E进行解密,提取出Client-To-Server Ticket, 在3.2步骤中,提到了该Ticket中包含了 CLIENT/SERVER SESSIONKEY 以及Client ID信息。
SS使用 CLIENT/SERVER SESSIONKEY 解密Msg G,提取Client ID信息,而后将该Client ID与Client-To-Server Ticket中的Client ID进行比对,如果匹配则说明Client拥有正确的 CLIENT/SERVER SESSIONKEY 。
而后,SS向Client响应Msg H(包含使用 CLIENT/SERVER SESSIONKEY 加密的Timestamp信息)。Client收到SS的响应消息Msg H之后,再使用 CLIENT/SERVER SESSIONKEY 对其解密,提取Timestamp信息,然后确认该信息与Client发送的Authenticator 2中的Timestamp信息一致。如上信息可以看出来,该交互过程起到了Client与SS之间的“双向认证”作用。
Client 密钥 TGS密钥 和 Service 密钥 均为对应用户的NTLM Hash
TGS密钥 == KDC Hash == krbtgt用户的NTLM Hash,这几个可能有时候叫法不一样但是是一个东西,Server 和 Service 也可以当作一个东西,就是Client想要访问的服务器或者服务。Client/(TGS/Server) Sessionkey 可以看作客户端与TGS服务和尝试登陆的Server之间会话时用来加密的密钥,而(Client/TGS/Service)密钥(上面提到的三个实际为NTLM Hash的密钥)是用来加密会话密钥的密钥,为了保证会话密钥的传输安全,这些加密方式均为对称加密。也就是说,参与认证的三个角色的NTLM Hash是三个密钥,这三个NTLM Hash的唯一作用是确保会话密钥Sessionkey的安全传输
然后Service 和 TGS 通过对TGT 和 Ticket (TGT 和 Ticket中包含会话密钥Sessionkey和客户端的身份信息)使用自己的NTLM Hash进行解密获取到会话密钥,再使用这个会话密钥解密客户端通过这个会话密钥加密发来的验证信息
通过解密客户端发来的验证信息,可以得到客户端的身份验证信息,再与使用自己的NTLM Hash进行解密TGT或者Ticket得到的客户端身份信息进行比较来完成对客户端身份的验证
TGT或Ticket 是由KDC使用TGS密钥和Service密钥进行加密的(上文讲到KDC可以从AD数据库中提取这三个东西),但是Client因为没有这两个密钥所以无法解密与修改。KDC将一份会话密钥通过Client的密钥加密发送给Client,另一份放在TGT中和客户端身份信息一起通过TGS的密钥进行加密也发送给Client
Client可以使用自己的密钥解密第一份会话密钥,然后用这个会话密钥来加密一份自己的身份信息,再把加密的身份信息和TGT一起发送给KDC,KDC此时如果能使用自己的TGS密钥来成功解密TGT,说明这个TGT是可信任的,因为Client无法修改TGT,然后再用这个TGT中的会话密钥来解密客户端发来的身份信息,与解密TGT得到的身份信息进行比对,如果能成功解密并且比对成功,说明这个Client是可信任的
Server端认证跟上面是一样的
某公司遭到竞争对手的渗透,大量公司员工账号被盗,公司领导瑟瑟发抖,因为现在不知道聊天窗对面是自己的员工还是竞争对手,在这种情况下怎么来保证员工和老板间的对话是安全并且互相可信的呢?
这时候就引入了一个第三者,HR,由于公司施行工资保密制度,员工之间不知道彼此工资的具体数字,但是HR知道全公司员工的工资数字,现在假定每个员工的工资都是不同的,我们用员工,老板,和HR来完成一个安全可信的加密机制,(假定HR是可信任的)
员工,老板和HR便是Kerberos认证中的三个角色俗称地狱三头犬
那么继续说,公司目前处在这样一个人与人之间毫无信任可言的情况下,还是要继续运转
某天,员工张二狗需要从老板大黄那里取得一份公司机密信息,但是如果二狗直接给老板发消息索要信息,那老板肯定不会给他,因为公司聊天工具里的人现在都是不可信任的,二狗不知道网线那边是不是真的老板,老板也不知道给自己发消息的是不是真的二狗,这时候就尴尬了
然后这时,聪明的老王出现了,老王是个国外读了10年本科的密码学砖家,他就给公司提出来一套流程,鉴于目前大家都没有办法确定某个人就是某个人,那么我们来用密码学的手段确定彼此的身份吧
这个流程是什么呢,如果二狗想给老板发消息,就要先通过HR来确定二狗就是二狗,怎么确定呢,二狗知道自己的工资,HR也知道二狗的工资,那么二狗就先给HR发个消息,我要找老板谈话,帮我弄个身份鉴定证书吧,但是二狗不能直接找HR要这个鉴定证书,因为二狗要先证明二狗就是二狗本人
于是二狗先给HR发了个消息,我是二狗,我要证明我就是二狗!
HR收到了二狗的消息,然后从公司数据库中一查,果然有二狗这个人,但是即使有这个人,又怎么确定二狗就是二狗本人呢,HR就用二狗的工资作为加密密钥,对一串非常复杂的数字(12345)进行加密作为消息A,然后又把这个数字12345和当前跟二狗聊天窗口的截图还有聊天的时间记到一个文件中,再用自己的工资对这个文件进行加密作为消息B
之后HR把用二狗工资加密的消息A和用自己工资加密的消息B一起发送给二狗,为什么要这样做呢,二狗如果能成功解密消息A,就能得到12345,因为只有真正的二狗知道自己的工资,假二狗不知道,消息B又是用来做什么的呢,我们继续看
二狗发送完消息之后,盯着聊天窗,然后钉,钉,响了两声,HR发来了两串东西,二狗看不懂,但是二狗想起来之前老王提出来的认证流程,先用自己的工资解密了第一个消息,得到了那串数字12345,然后用这串12345把跟HR聊天窗口的截图和时间放在一起进行了加密,作为消息D,那么消息C是什么呢,消息C就是HR发来的第二个消息,消息B,不过这次消息C中还要多一个东西,就是老板的名字大黄,大黄和消息B合在一起就组成了消息C
为什么呢,因为二狗这次发送的消息C和D就是为了证明他就是二狗本人,二狗自然确定自己就是真二狗,那么自然也要把老板的名字加到消息中,因为他要HR给他用来跟老板对话的身份鉴定证书,如果不加上老板的名字,HR即便确定了二狗是二狗,也不知道二狗要跟谁对话
现在消息C(消息B和老板的名字大黄)和消息D(二狗用12345加密的聊天窗口截图和聊天时间)就发到了HR那里
HR收到了消息C和D,得到了三个东西,原来用自己工资加密的消息B,老板的名字,和之前自己随便想出来的12345加密的消息D
这里就来到了第一个关键点,HR怎么通过这几个东西来确定二狗就是二狗呢,HR首先用自己的工资解密了消息C,得到了之前的聊天窗截图和聊天时间,还有自己之前随便想出来的12345,然后用这个12345来解密消息D,又得到了二狗对他们两个的聊天窗的截图和聊天时间,通过对比这两个聊天窗截图和时间是否都匹配,HR就确定了这个二狗是真的二狗(假二狗不知道真二狗的工资,所以就无法解密得到12345,也就没法用12345加密消息D,HR自然也没办法解密了),并且就是之前跟自己聊天的那个二狗(因为之前发过去的用自己工资加密的消息B原封不动的发回来了,而这个消息B除了自己谁都无法解密修改)
这里有人要问了,那HR直接用自己想出来的12345解密消息D不是也可以确定二狗就是真二狗吗,这个怎么解释呢,这个公司有一百万个员工,每个员工时不时都想跟老板说说话,而HR脑子存储量不够大,记不住12345这么复杂的数字,更何况是一百万个12345,那脑子不得爆炸了,所以把12345用自己的密钥加密发过去,再收回来用自己的密钥解密取出来,这样就不用记了
现在HR确定了二狗就是二狗,那么看看二狗想跟谁聊天吧,消息C中写的是老板大黄的名字,HR就从公司数据库中查,老板大黄:工资4块3毛1角
然后HR又用老板的工资,加密了和二狗聊天窗口的截图,聊天时间和另一串非常复杂的数字45678 作为消息E(也就是鉴定证书),和用从消息C中找到12345加密了新的复杂数字45678作为消息F
又回到二狗这里,二狗收到这两个消息,用12345解密了第二个消息F,得到了45678,然后用45678加密了自己和HR的聊天窗截图和聊天时间作为消息G,之后把消息E和消息G发给老板,是不是和之前很像
这时老板收到了二狗的消息,老板先用自己的工资解密了消息E(HR用老板工资加密的截图,聊天时间还有45678),得到了45678,然后用这串复杂的数字成功解密了消息G,得到二狗的截图和聊天时间,再对比这两个聊天截图和聊天时间是不是一样的,一样的话老板才能确定二狗是真二狗,经过HR权威认定的二狗,可以充满信任的聊天了,这里其实也有对老板身份的鉴别,因为假老板不会知道真老板的工资,自然也就没有办法解密消息E
至此整个认证流程基本结束,我们将其中的几个关键信息提取出来,换成正常含义下对应的词语
看懂了上面的故事,Kerberos的认证流程也就了解的差不多了,不过是细节上会有些差异
看了这么多发现是不是头都大了?简单来说:
在AS去确认客户端登陆者的身份时,KDC返回的Msg B:使用TGS密钥(KDCHASH/KRBTGT用户NTLMHASH) 加密的TGT,当我们获取到krbtgt用户的NTLM哈希后,便可主动使用krbtgt用户的NTLM哈希做为TGS密钥来生成TGT发送给KDC,这样KDC如果通过解密伪造TGT获取到伪造的 [CLIENT/TGS SESSIONKEY] 可以成功解密 Authenticator 1 并完成与TGT中的数据进行比对,便成功骗过了KDC,也就是成功伪造了黄金票据。
假设这么一种情况,原先已拿到的域内所有的账户hash,包括krbtgt账户,由于有些原因导致域管权限丢失,但好在你还有一个普通域用户权限,碰巧管理员在域内加固时忘记重置krbtgt密码,基于此条件,我们还能利用该票据重新获得域管理员权限,利用krbtgt的HASH值可以伪造生成任意的TGT(mimikatz),能够绕过对任意用户的账号策略,让用户成为任意组的成员,可用于Kerberos认证的任何服务。
所以说黄金票据就是伪造krbtgt用户的TGT票据,krbtgt用户是域控中用来管理发放票据的用户,拥有了该用户的权限,就可以伪造系统中的任意用户。
在Client向SS(Service Server)发送服务请求时,客户端向服务器发送的为使用 SERVICE密钥(服务器的NTLMHASH)加密的 CLIENT-TO-SERVER TICKET,Ticket中包含用来供服务器解密Authenticator 2的 CLIENT/SERVER SESSIONKEY。如果获取到了Service Server的NTLM Hash,便可伪造Ticket,和Authenticator 2 ,Service Server在接收到Ticket和Authenticator 2后可以使用自己的NTLM Hash正常解密完成比对,也就是成功伪造了白银票据。
通过观察Kerberos协议的认证过程不难发现,如果我们获取了Server秘钥Ks(服务器口令散列值),就可以跳过KDC的认证,直接伪造票据和目标Server通信。
所以黄金票据可以比作是伪造TGT(门票发放票),而白银票据则是伪造ST(门票),这样的好处是门票不会经过KDC,从而更加隐蔽,但是伪造的门票只对部分服务起作用。
黄金票据 伪造TGT,可以获取任何Kerberos服务权限
白银票据 伪造TGS,只能访问指定的服务,白银票据的权限就远不如黄金票据的权限
黄金票据 由Kerberos的NTLM Hash加密
白银票据 由服务账号(通常为计算机账户)NTLM Hash加密,更加隐蔽
黄金票据 利用过程需要访问域控DC
白银票据 不经过KDC,因此白银票据日志相对于黄金票据会更少,同时白银票据的日志都在目标服务器上,域控上不会有日志
在客户端向服务器上的某个服务发送服务请求时,客户端向服务器发送的为使用service密钥(服务器的NTLM HASH)加密的client TO server Ticket,票据中包含用来供服务器解密 Authenticator2 的 CLIENT/SERVER SESSIONKEY
如果获取到了服务器上的某个服务的NTLM Hash,便可伪造票据和Authenticator2,服务器上的某个服务在接收到票据和Authenticator2后可以使用自己的NTLM Hash正常解密完成比对,也就是成功伪造了白银票据。
再次值得提及的是:白银票据伪造的是TGS票据,不需要和域控DC打交道。白银票据使用要访问服务的hash,而不是krbtgt账户的hash。需要注意的一点是,伪造的白银票据没有带有有KDC签名的PAC,如果目标主机配置为验证KDC PAC签名,则白银票据将不起作用。所以白银票据只能访问指定的服务,权限比较低。
在AS去确认客户端登陆者的身份时,KDC返回的Msg B:
使用TGS密钥(kdc hash/krbtgt用户的NTLM HASH) 加密的TGT,当我们获取到krbtgt用户的NTLM哈希后,便可主动使用krbtgt用户的NTLM哈希做为TGS密钥来生成TGT发送给KDC,如果知道了krbtgt用户的密码hash可以直接伪造任意用户的TGT出来,这样KDC如果通过解密伪造TGT获取到伪造的[CLIENT/TGS SESSIONKEY]可以成功解密 Authenticator 1 并完成与TGT中的数据进行比对,便成功骗过了KDC,也就是成功伪造了黄金票据。
黄金票据和钻石票据都需要Krbgtg密钥。黄金票据攻击利用了从头开始伪造TGT,而钻石票据攻击利用了对域控制器请求的真实TGT进行解密和重新加密的能力。