域滲透——Local Administrator Password Solution

wyzsk發表於2020-08-19
作者: 三好學生 · 2015/11/13 15:18

0x00 前言


在域滲透中,有關域內主機的本地管理員的安全介紹還很少,對於LAPS大都比較陌生,所以這次就和我一起學習一下吧。

這裡寫圖片描述

0x01 簡介


在實際的域環境中,域內主機的本地管理員賬戶往往被忽視,再加上統一的配置,域內主機的本地管理員密碼往往相同,這就帶來了一個問題,如果獲得一臺域內主機的本地管理員密碼,其他域內主機的本地管理員密碼自然就知道了,解決這個問題最好的辦法就是確保每臺域內主機有不同的密碼,並且定期更換。

所以微軟在今年3月1號釋出了LAPS(Local Administrator Password Solution)協議。

0x02 學習目標


站在滲透的角度,在研究之初設立了以下目標:

>     1、如果域內主機本地管理員賬戶密碼相同,如何利用?
>     2、LAPS是如何配置使用的?
>     3、如果安裝了LAPS,有沒有利用方法?

對於問題1,如果賬戶許可權配置不當,可以利用pass-the-hash嘗試獲取其他域內主機許可權,mimikatz的操作命令之前有介紹,本文不做重點介紹,暫時忽略。
連結:
/tips/?id=7547

0x03 測試環境


域控:server 2008 r2 x64
域內主機: win7 x64

0x04 配置LAPS


1、安裝LAPS

域控:

-1)下載LAPS

https://www.microsoft.com/en-us/download/details.aspx?id=46899

-2)安裝

選擇全部功能

如圖

這裡寫圖片描述

域內主機:

下載安裝,方法同上

Tips:

域內主機批次安裝可使用組策略安裝的方法
參考連結如下:
https://4sysops.com/archives/install-32-bit-and-64-bit-applications-with-group-policy-and-sccm/

2、域控LAPS配置

對於這部分可以理解為域的配置以LDAP(Lightweight Directory Access Protocol)協議儲存,現在需要新增兩個屬性來儲存LAPS資訊:

ms-MCS-AdmPwd:儲存密碼
ms-MCS-AdmPwdExpirationTime:儲存過期時間

我們可以開啟C:\Program Files\LAPS\AdmPwd.Utils看到LAPS的安裝配置:

如圖

這裡寫圖片描述

-1)在域控上執行以下Powershell命令(需要使用域管許可權登入)

#!powershell
import-module AdmPwd.PS
Get-Command -Module AdmPwd.PS
Update-AdmPwdADSchema

如圖

這裡寫圖片描述

server2008 預設Powershell 版本2.0
執行import-module AdmPwd.PS會出現如下錯誤:
下載powershell3.0,安裝後重啟再次執行即可

如圖

這裡寫圖片描述

-2)配置活動目錄許可權

(1)檢視可以訪問儲存密碼的使用者組:

powershell執行:

#!powershell
import-module AdmPwd.PS
Find-AdmPwdExtendedRights -OrgUnit "CN=Computers,DC=test,DC=local"

如圖

這裡寫圖片描述

(2)取消使用者組訪問儲存密碼的許可權:

開啟ADSIEdit.msc,右鍵連線,如圖

這裡寫圖片描述

這裡寫圖片描述

選擇對應的組,右鍵-屬性,如圖

這裡寫圖片描述

選擇安全-高階,如圖

這裡寫圖片描述

選中取消許可權的使用者-編輯-勾中拒絕所有擴充套件許可權,如圖

這裡寫圖片描述

(3)增加使用者組讀取和重置儲存密碼的許可權:

powershell執行:

#!powershell
import-module AdmPwd.PS
Set-AdmPwdReadPasswordPermission -OrgUnit "CN=Computers,DC=test,DC=local" -AllowedPrincipals test\administrator
Set-AdmPwdResetPasswordPermission -OrgUnit "CN=Computers,DC=test,DC=local" -AllowedPrincipals test\administrator

如圖

這裡寫圖片描述

(4)為域內主機新增可以更新密碼的許可權:

#!powershell
import-module AdmPwd.PS
Set-AdmPwdComputerSelfPermission -OrgUnit "CN=Computers,DC=test,DC=local"

如圖

這裡寫圖片描述

-3)配置LAPS密碼組策略

gpedit.msc-管理模板-LAPS,設定對應的密碼策略

如圖

這裡寫圖片描述

0x05 檢視LAPS儲存的密碼


共有以下三種方法

1、屬性編輯器

開啟Active Directory 使用者和計算機

檢視-選中高階功能,如圖

這裡寫圖片描述

選中對應計算機-右鍵-屬性-屬性編輯器-找到

ms-Mcs-AdmPwd:儲存密碼
ms-Mcs-AdmPwdExpirationTime:儲存過期時間

如圖

這裡寫圖片描述

2、LAPS UI

安裝LAPS時可以選擇安裝LAPS UI,啟動後輸入計算機名,查詢,如圖

這裡寫圖片描述

3、Powershell

(1)查詢某主機

#!powershell
Import-Module AdmPwd.PS 
Get-AdmPwdPassword –ComputerName testf

或者

#!powershell
Get-ADComputer testf -Properties ms-Mcs-AdmPwd | select name, ms-Mcs-AdmPwd

如圖

這裡寫圖片描述

這裡寫圖片描述

(2)查詢所有主機

#!powershell
function Get-LAPSPasswords
{

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$false,
        HelpMessage="Credentials to use when connecting to a Domain Controller.")]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,

        [Parameter(Mandatory=$false,
        HelpMessage="Domain controller for Domain and Site that you want to query against.")]
        [string]$DomainController,

        [Parameter(Mandatory=$false,
        HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000.")]
        [int]$Limit = 1000,

        [Parameter(Mandatory=$false,
        HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")]
        [ValidateSet("Subtree","OneLevel","Base")]
        [string]$SearchScope = "Subtree",

        [Parameter(Mandatory=$false,
        HelpMessage="Distinguished Name Path to limit search to.")]

        [string]$SearchDN
    )
    Begin
    {
        if ($DomainController -and $Credential.GetNetworkCredential().Password)
        {
            $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password
            $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain
        }
        else
        {
            $objDomain = [ADSI]""  
            $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain
        }
    }

    Process
    {
        # Status user
        Write-Verbose "[*] Grabbing computer accounts from Active Directory..."

        # Create data table for hostnames, and passwords from LDAP
        $TableAdsComputers = New-Object System.Data.DataTable 
        $TableAdsComputers.Columns.Add('Hostname') | Out-Null
        $TableAdsComputers.Columns.Add('Stored') | Out-Null
        $TableAdsComputers.Columns.Add('Readable') | Out-Null
        $TableAdsComputers.Columns.Add('Password') | Out-Null
        $TableAdsComputers.Columns.Add('Expiration') | Out-Null

        # ------------------------------------------------
        # Grab computer account information from Active Directory via LDAP
        # ------------------------------------------------
        $CompFilter = "(&(objectCategory=Computer))"
        $ObjSearcher.PageSize = $Limit
        $ObjSearcher.Filter = $CompFilter
        $ObjSearcher.SearchScope = "Subtree"

        if ($SearchDN)
        {
            $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)")
        }

        $ObjSearcher.FindAll() | ForEach-Object {

            # Setup fields
            $CurrentHost = $($_.properties['dnshostname'])
            $CurrentUac = $($_.properties['useraccountcontrol'])
            $CurrentPassword = $($_.properties['ms-MCS-AdmPwd'])
            if ($_.properties['ms-MCS-AdmPwdExpirationTime'] -ge 0){$CurrentExpiration = $([datetime]::FromFileTime([convert]::ToInt64($_.properties['ms-MCS-AdmPwdExpirationTime'],10)))}
            else{$CurrentExpiration = "NA"}

            $PasswordAvailable = 0
            $PasswordStored = 1

            $CurrentUacBin = [convert]::ToString($CurrentUac,2)

            # Check the 2nd to last value to determine if its disabled
            $DisableOffset = $CurrentUacBin.Length - 2
            $CurrentDisabled = $CurrentUacBin.Substring($DisableOffset,1)

            # Set flag if stored password is not available
            if ($CurrentExpiration -eq "NA"){$PasswordStored = 0}


            if ($CurrentPassword.length -ge 1){$PasswordAvailable = 1}


            # Add computer to list if it's enabled
            if ($CurrentDisabled  -eq 0){
                # Add domain computer to data table
                $TableAdsComputers.Rows.Add($CurrentHost,$PasswordStored,$PasswordAvailable,$CurrentPassword, $CurrentExpiration) | Out-Null
            }

            # Display results
            $TableAdsComputers | Sort-Object {$_.Hostname} -Descending
         }
    }
    End
    {
    }
}
Get-LAPSPasswords -DomainController 192.168.40.132 -Credential test.local\Administrator | Format-Table -AutoSize

如圖

這裡寫圖片描述

注:

如果配置不當,我們可以在域內一臺普通主機,檢視域內其他主機本地管理員賬號

如圖

這裡寫圖片描述

這裡寫圖片描述

0x06 防禦


1、如果未使用LAPS

一定要留意域內主機的本地管理員賬號

對於域內本地管理員嘗試pass-the-hash雖未做詳細介紹,但如果滿足條件,操作簡單、威力無窮

2、使用LAPS

(1)注意使用者許可權配置是否存在問題,是否普通使用者可以讀取域內其他主機的本地管理員密碼
(2)為了便於管理域內主機本地管理員賬號,一般大規模的域都會使用LAPS
這種情況下在安裝程式列表裡面會出現Local Administrator Password Solution
(3)如果域控被入侵過,記得更新所有LAPS配置

0x07 小結


在域滲透中,對域內主機的本地管理員的嘗試利用,往往會有出其不意的效果。 我們知道,LAPS是在LDAP中儲存,那麼LDAP在域滲透中有多大作用呢?值得研究。

參考資料:

本文由三好學生原創並首發於烏雲drops,轉載請註明

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章