SPN是什么?
在我们了解SPN之前,我们需要了解Active Drietcory域中的服务是什么?
服务我们已经很熟悉了,比如说SMB服务,Web服务,HTTP服务,FTP服务,DNS服务,MYSQL服务等等这些我们都称之为服务!!!
那么同一个服务可以在不同的主机下运行,比如说打印机服务,它不是一个专属于任何人的服务,它可以应用于多个主机,可以给多个主机提供打印的服务,所以我们需要指定主机,而一台计算机是可以承载多个服务的,所以我们还需要去指定服务,这样的话,我们就可以准确的指定服务给那些计算机服务。
这两个合起来就是服务主体名称或者也可以叫做SPN。
我们来举一个现实中的例子。
当某个用户去访问数据库服务的时候,比如sqlserver或mysql服务,系统会以当前用户的身份向域控查询SPN为Mysql的记录,当找到该SPN的记录后,用户再次与KDC通信,将TGT发送给KDC,并将需要访问的SPN发送给KDC,KDC的TGS服务对TGT进行解密,解密之后确定无误的话,由TGS将一张允许访问该SPN所对应的服务的ST服务票据和该SPN所对应的服务的地址发送给用户,用户使用该ST服务票据来访问数据库服务。
那么我们再来看下SPN是如何命名的。
服务类/主机名或者域名
这里的服务类实际上就是服务的一个通用名称,例如所有的web服务都归于www类,sql服务都归于Sqlserver类等等。
如果服务在自定义端口上运行的话,你可以将这个端口加到主机的后面。
例如:
服务类/主机名或者域名:端口
或者也可以命名SPN。
如果我们在上面指定了一个web服务,比如说主机名为:WEB-SERVER-01。
那么它的SPN就是这样的。这里的www就是服务类。这是以主机名进行命名的。
www/WEB-SERVER-01
如果以域名命名的话,那么将是这样的。
www/WEB-SERVER-01.relaysec.com
有大量的服务类,我们可以在微软这里进行参考:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc772815(v=ws.10)#service-principal-names
这里服务类中有例如CIFS与文件共享的服务,DNS 域名解析服务,spooler打印服务等等,但是这里面并不详细,例如没有SQLserver或者Ldap目录服务类。这些类通常可以在AD环境中找到。
SPN两种类型
SPN分为两种类型,一种是注册在活动目录的机器帐户(Computers)下,当一个服务的权限为 Local System 或 Network Service。一种是注册在活动目录的域用户帐户(Users)下,当一个服务的权限为一个域用户,则SPN注册在域用户帐户(Users)下。
在Windows域里,默认普通机器账号有权注册SPN:
比如说我们拿到一个机器将其提升到system权限之后,我们就有权注册SPN了。
setspn -A MSSQL/win2016.relaysec.com win2016
现在我们来到win2016机器的servicePrincipalNames属性查看
如上图可以看到已经注册进来了。
但是普通域内用户是不能注册SPN的。这样就会导致一个问题,如果SqlServer使用 Local SysTem account来启动的话,kerberos就能认证成功,这时候就可以在DC上注册SPN,如果用一个普通用户的话,kerberos就不能成功,因为这时候SPN注册不上去。
我们可以在DC中赋予域账号Read servicePrincipalName和WriteserverPrincipalName的权限,只要有这两个权限就可以注册。
现在我们已经知道了SPN是什么。我们来查找一下域内存在的SPN。
查找域内的SPN
使用过滤器进行查找(servicePrincipalName=*),也就是servicePrincipalName属性,也可以使用setSpn。
Setspn -Q */*
使用GetUsersSPNS.py
这个工具也可以查找SPN,这个工具可以说很舒服了,包括我们查找出来的SPN进行kerberoasting攻击都可以用到。
BloodHound
BloodHound我们前面一直在用,但是也一直没说,因为BloodHound有时候很不稳定,为什么说他不稳定,因为有时候你使用官方提供的exe导出的域内信息,我们无法将它导入到BloodHound中来解析。
所以这里我推荐一个方式,很简单不需要落地exe文件,我们直接使用python来进行导出。
这里直接使用kali的bloodhound-python
来导出即可。
需要注意的是-ns这个参数,这个参数非常重要,指定的是DNS服务器的地址,如果不指定这个参数肯定是导不出来的。
bloodhound-python -u win2016 -p 'Admin123..' -d relaysec.com -ns 10.10.211.130 -c All
导出之后我们开启neo4j数据库,如果没有下载的话直接apt install即可。
sudo neo4j console
然后我们直接打开bloodhound即可,还是一样如果没有安装直接apt instll安装即可。
打开之后我们点击List All kerberoastable Accounts 就可以列出可以kerberoastable 攻击的账户了,可以看到如下图有3个账户,krbtgt账户我们肯定是不会考虑的,它生成的密码是非常复杂的,所以我们可以考虑剩余下来的两个账户。
kerberoasting攻击
kerberoastring攻击是出在TGS_REP阶段的,由于ST服务票据是使用服务账户的Hash进行加密的,所以如果我们能获取到ST服务票据,就可以对该ST服务票据进行暴力破解,得到服务的Hash,在TGS_REP这一阶段不会验证客户端是否有权限访问服务端,因此这一步无论用户也没有访问服务的权限,只要TGT正确,都会返回ST服务票据,这也就是kerberoasting能利用的原因,任何一个域内用户都是去请求任何一个服务的ST服务票据。
我们直接上实例来看下。
为了测试环境我将ceshi这个用户作为服务账户注册了一个SPN。
setspn -A MYSQL/dc.relaysec.com ceshi
然后我们使用impacket-GetUserSPNs
进行枚举。
可以看到并没有枚举出来机器账户,只枚举出来了两个域用户。这是因为机器账户的密码非常复杂是破解不开的。所以一般都是使用域用户来进行kerberoasting攻击。
然后我们加上-request
参数,它将申请一个ST服务票据,因为ST服务票据是使用服务账户的Hash进行加密的,所以我们可以直接使用hashcat进行破解。
可以看到成功获取到两个ST票据。
然后我们将第二个服务账户,也就是ceshi这个账户放到一个hash.txt文件中。
这里简单做了一个字典,里面的Admin123..是正确密码。
所以让我们使用hashcat对其进行破解把。
hashcat hash.txt password.txt --force
可以看到成功破解。
结束语
本次学习就先到这里 期待和您的下次相遇!!!