امیرحسین کریم پور
مدیر ارشد توسینسو و متخصص سرویس های مایکروسافت

آموزش حذف گروپ پالیسی (GPO) های منسوخ شده از SYSVOL با پاورشل

در این آموزش بسیار بسیار کاربردی و عملی قصد داریم نحوه پیدا کردن Orphaned GPO ها را که درون پوشه SYSVOL قرار دارند را به شما عزیزان آموزش دهیم که در سازمان های بزرگ بسیار قطعا به کمک شما می آید. GPO های اکتیودایرکتوری اگر به درستی نگهداری نشوند میتوانند از محدوده کنترل ما خارج شوند مخصوصا در سازمان های بزرگ که تعدادی زیادی از افراد میتوانند روی GPO ها دسترسی داشته باشند و تغییرات خود را روی آنها انجام دهند.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

یکی از مشکلاتی که در این گونه مواقع در شبکه رخ میدهد وجود Orphaned GPO ها می باشد. همانطور که در مقالات قبلی نیز اشاره کردیم یک GPO خود از دو جزء GPT و GPC تشکیل می شود که GPC ها در دیتابیس اکتیودایرکتوری و GPT ها در پوشه SYSVOL Share قرار میگیرند. گاهی اوقات یک GPO از دیتابیس اکتیودایرکتوری پاک می شود و ممکن است در کنسول مدیریتی GPMC نشان داده نشوند اما با این وجود در پوشه SYSVOL Share همچنان وجود دارند در این حالت ما میگوییم که GPO های ما بصورت Orphaned در آمده است.

دانستن اینکه کجا و چگونه دیتابیس AD و پوشه SYSVOL را با هم مقایسه کنیم به ما کمک شایانی در پیدا کردن و پاک کردن Orphaned GPO ها می کند. چه راهی بهتر از استفاده از PowerShell ! در ابتدا ما نیاز داریم که یک لیست از تمام GPO های موجود در دیتابیس اکتیودایرکتوری را تهیه کنیم. به همین منظور ما از دستور Get-GPO در PowerShell استفاده می کنیم. دستور Get-GPO اطلاعات مختلفی را به ما میدهد اما ما فقط به دنبال GUID ها هستیم. ما به GUID ها به این خاطر نیاز داریم که با GUID های درون پوشه SYSVOL مقایسه کنیم. ما GUID ها را بوسیله دستور Get-GPO میتوانیم از داخل دییتابیس اکتیودایرکتوری با ریختن Id property در یک String بیرون بکشیم. به دستور زیر توجه کنید :

$gpoGuids = Get-GPO -All | Select-Object @{ n='GUID'; e = {$_.Id.ToString()}} | Select-Object -ExpandProperty GUID

با اجرای این Script تمامی GUID های موجود در AD در خروجی نمایش داده می شوند. حالا ما نیاز است تا مسیری را پیدا کنیم که به این GUID ها اشاره می کنند. هر GPO بایستی یک پوشه در هر دامین کنترلر داشته باشد که در مسیر زیر قرار دارد :

\\<DomainName>\SYSVOL\<DomainName>\Policies
وب سایت توسینسو

درون این پوشه ، پوشه هایی قرار دارند که با نام GUID ها نامگذاری شده اند و نشان دهنده همه GPO ها در دامین هستند. از آنجا که ما تنها به GUID ها نیاز داریم پس پوشه ای به نام PolicyDefinitions را Exclude می کنیم که خود درون پوشه Policies قرار دارد. به دستور زیر توجه کنید :

$polFolders = Get-ChildItem \\<DomainName>\SYSVOL\<DomainName>\Policies ‑Exclude 'PolicyDefinitions' | Select-Object -ExpandProperty name
وب سایت توسینسو

خروجی دستور شبیه به تصویر فوق است. حالا باید یکی یکی GUID ها را با هم مقایسه کنیم. اسم پوشه ها در انتهای خروجی دستور داخل آکولاد قرار دارند. ما با دستور زیر با ایجاد یک متغیر به نام sysvolGuids$ آنها را حذف می کنیم. به دستور زیر توجه کنید :

$sysvolGuids = @()
foreach ($folder in $polFolders) {
    $sysvolGuids += $folder -replace '{|}', ''
}

حالا ما دو لیست از GUID ها داریم که یکی از آنها در دیتابیس اکتیودایرکتوری و دیگری در پوشه SYSVOL قرار دارد. ما باید این دو لیست را با هم مقایسه کنیم و ببینیم که آیا پوشه SYSVOL ای وجود دارد که در دیتابیس AD وجود نداشته باشد ؟ یکی از این راه ها استفاده از دستور Compare-Object می باشد. همانطور که از اسم این دستور نیز مشخص است ما بوسیله این دستور میتوانیم دو لیست را با هم مقایسه کنیم و تفاوت های آنها را دربیاوریم. اگر تفاوتی وجود داشت خروجی Script زیر GUID ها را نشان خواهد داد و در اینجاست که میتوانید مطمئن شوید که Orphaned GPO ها در پوشه SYSVOL Share دامین کنترلر ها وجود دارد!

Compare-Object -ReferenceObject $sysvolGuids -DifferenceObject $gpoGuids | Select-Object -ExpandProperty InputObject

برای اینکه ساده تر از این دستورات بتوانید استفاده کنید یک Script آماده کرده ایم که تمامی دستوراتی که تا کنون اجرا کرده ایم را شامل می شود و شما در محیط های Multi-Domain میتوانید از آن براحتی استفاده کنید :

function Get-OrphanedGPO {
    
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$ForestName
    )
    try {
        ## Find all domains in the forest
        $domains = Get-AdForest -Identity $ForestName | Select-Object -ExpandProperty Domains
 
        $gpoGuids = @()
        $sysvolGuids = @()
        foreach ($domain in $Domains) {
            $gpoGuids += Get-GPO -All -Domain $domain | Select-Object @{ n='GUID'; e = {$_.Id.ToString()}} | Select-Object -ExpandProperty GUID
            foreach ($guid in $gpoGuids) {
                $polPath = "\\$domain\SYSVOL\$domain\Policies"
                $polFolders = Get-ChildItem $polPath -Exclude 'PolicyDefinitions' | Select-Object -ExpandProperty name
                foreach ($folder in $polFolders) {
                    $sysvolGuids += $folder -replace '{|}'
                }
            }
        }
 
        Compare-Object -ReferenceObject $sysvolGuids -DifferenceObject $gpoGuids | Select-Object -ExpandProperty InputObject
    } catch {
        $PSCmdlet.ThrowTerminatingError($_)
    }
}

برای پیدا کردن Orphaned GPO ها در Forest کافیست که دستور <Get-OrphanedGPO -ForestName <ForestName را اجرا کنید. امیدوارم مورد توجه شما قرار گرفته باشد.


امیرحسین کریم پور
امیرحسین کریم پور

مدیر ارشد توسینسو و متخصص سرویس های مایکروسافت

امیرحسین کریم پور ، مدیر ارشد توسینسو ، متخصص شبکه ، تخصص در حوزه سیستم عامل های کلاینت و سرور مایکروسافت و سرویس های مربوطه ، سیستم عامل لینوکس و... ، سابقه کار با سازمان ها و شرکت های مختلف در زمینه سرویس های مایکروسافت در قالب پروژه ، مشاوره و آموزش. علاقه مند به حوزه امنیت اطلاعات و تست نفوذ سنجی

نظرات