Audit Active Directory changes
Audit Active Directory changes

Purpose :
Audit Active Directory changes (user/group creation, deletion, changes and GPO changes)

Pre-requesites :

  • Windows 2003 or 2008 domain controllers
  • Install powershell on the Windows 2003 DCs
  • A web site with http,ftp and php features enabled

Powershell script to schedule daily on each Windows 2003 domain controllers :

$log_path = "c:\Temp\"
$computer = gc env:computername
$result = "result_" + (get-date (get-date).AddDays(-1) -uFormat "%Y-%m-%d") + "_" + $computer + ".log"

get-eventlog -LogName Security -After (get-date).adddays(-1) -EntryType SuccessAudit `
| where {($_.eventid -eq "630") -or ($_.eventid -eq "632") -or ($_.eventid -eq "633") -or ($_.eventid -eq "642") -or ($_.eventid -eq "660") -or (($_.eventid -eq "566") -and ($_.message.Contains("f30e3bc2-9ff0-11d1-b603-0000f80367c1")))} `
| Foreach-Object {    ($_.timegenerated).tostring() + ";" + `
($_.eventid).tostring() + ";" + `
$_.username + ";" + `
((($_.message -replace "`n", ";") -replace ";`t","") -replace "`r","")} `
| Out-File -FilePath ($log_path + $result) -encoding ASCII -append -Width 1000

# Upload using ftp the log results
$file = ($log_path + $result)
$filenewname = $result

$FtpUploadCommand = "PUT `"" + $file + "`"";
$FtpCommandFilePath = [System.IO.Path]::GetFullPath("FTPCommand.tmp");
$FtpCommands = @( "ftpuser", "ftppassword", "bin", "quote pasv", $FtpUploadCommand, "quit" );
$FtpCommand = [String]::Join( "`r`n", $FtpCommands );
set-content $FtpCommandFilePath $FtpCommand;
ftp "-s:$FtpCommandFilePath" 10.1.1.1;
remove-item $FtpCommandFilePath;

# Downloaded files removal
Remove-Item ($log_path + "*.log")

 

 

Powershell script to schedule daily on each Windows 2008 domain controllers :

$log_path = "c:\Temp\"
$computer = gc env:computername
$result = "result_" + (get-date (get-date).AddDays(-1) -uFormat "%Y-%m-%d") + "_" + $computer + ".log"

get-eventlog -LogName Security -After (get-date).adddays(-1) -EntryType SuccessAudit `
| where {($_.eventid -eq "5141") -or (($_.eventid -eq "5136") -and ($_.message.Contains("groupPolicyContainer"))) -or ($_.eventid -eq "4720") -or ($_.eventid -eq "4738") -or ($_.eventid -eq "4728") -or ($_.eventid -eq "4729")} `
| Foreach-Object {    ($_.timegenerated).tostring() + ";" + `
($_.eventid).tostring() + ";" + `
((($_.message -replace "`n", ";") -replace ";`t","") -replace "`r",";")}`
| Out-File -FilePath ($log_path + $result) -encoding ASCII -append -Width 1000

# Upload using ftp the log results
$file = ($log_path + $result)
$filenewname = $result

$FtpUploadCommand = "PUT `"" + $file + "`"";
$FtpCommandFilePath = [System.IO.Path]::GetFullPath("FTPCommand.tmp");
$FtpCommands = @( "ftpuser", "ftppassword", "bin", "quote pasv", $FtpUploadCommand, "quit" );
$FtpCommand = [String]::Join( "`r`n", $FtpCommands );
set-content $FtpCommandFilePath $FtpCommand;
ftp "-s:$FtpCommandFilePath" 10.1.1.1;
remove-item $FtpCommandFilePath;

# Downloaded files removal
Remove-Item ($log_path + "*.log")

 

 


PHP code to display Active Directory changes (auditad.php) :

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<title>Active Directory Audit</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link href="index.css" rel="stylesheet" type="text/css">
<LINK REL="SHORTCUT ICON" href="favicon.ico">
</head>
<body>

<center><table class = "sample"><tr><th> Active Directory Change Audit </table><br><br><br>
<table>
<form action="<?php echo $url; ?>" method="get" name="myform">
<th><input type="text" name="text_search" value="<?php echo $text_search; ?>" onblur="if(this.value=='') this.value='<?php echo $text_search; ?>';" onfocus="if(this.value=='<?php echo $text_search; ?>') this.value='';"/></th>
<th><input type="submit" value="Search" /></th>
<th><input name=type type=button value="Show All" onclick="window.open('auditad.php?text_search=All','_self')"/></th>
</form>
</table>
<i><font size=1>(Search criteria : date / event id / change type / modified by) </font>
<br><br>

<?php
//Hide Warning messages
error_reporting(0);

$folder = "/var/www/dashboard/auditad_log";
$d = array_diff( scandir($folder,1), array(".", "..") );

echo "<TABLE class = \"sample\">";
echo "<TR><TH><font Size=1,5> Date ";
echo "<TH><font Size=1,5> Event ID ";
echo "<TH><font Size=1,5> Change type ";
echo "<TH><font Size=1,5> Modified by ";

foreach($d as $filename){
$octet = filesize($folder."/".$filename);
if ($octet==0) {
continue;
}
else {
$text = file($folder."/".$filename);
}

$search_string = $_GET['text_search'];

if ($search_string == "All" || $search_string == "" || $search_string == null){
$search_string = "";
SearchString($search_string,$text);
}
else {
SearchString($search_string,$text);
}
}

function SearchString($stringtosearch,$text){
$gpolist = "/var/www/dashboard/gpolist.txt";
foreach($text as $line)
{
if (strpos(strtolower($line),strtolower($stringtosearch))!==false || $stringtosearch == "") {
$columns = explode(";", $line);
$targetaccount = explode(":", $columns[6]);
switch ($columns[1]) {
case 4738:
$mod_properties = Propmod2008($line);
if (strpos($columns[8],"\$")===false && !preg_match("/anonymous/i",$columns[8]) && $mod_properties<>""){
$username = explode(":",$columns[8]);
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>Properties has been changed for $columns[16] <br>$mod_properties";
echo "<TD>$username[1]";
}
break;
case 4729:
$username = explode(":",$columns[8]);
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>$columns[16] has been has been removed from $columns[22]";
echo "<TD>$username[1]";
break;
case 4728:
$username = explode(":",$columns[8]);
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>$columns[16] has been has been added to $columns[22]";
echo "<TD>$username[1]";
break;
case 4720:
$username = explode(":",$columns[8]);
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>$columns[16] has been created";
echo "<TD>$username[1]";
break;
case 5141:
$username = explode(":",$columns[7]);
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>$columns[18] has been deleted";
echo "<TD>$username[1]";
break;
case 5136:
$username = explode(":",$columns[7]);
$gponame = ResolveGPOSID($line,$gpolist);
if ($gponame=="" && $columns[6]=="Object Type:    %{f30e3bc2-9ff0-11d1-b603-0000f80367c1}"){
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>The Group policy name cannot be resolved. Please update the configuration file gpolist.txt";
echo "<TD>$username[1]";
}
elseif ($gponame<>"") {
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>GPO $gponame has been modified";
echo "<TD>$username[1]";
}
break;
case 566:
$gpoguid = explode("%", $columns[7]);
$gpoguid_mod = str_replace('}','',str_replace('{','',$gpoguid[1]));
$gponame = ResolveGPOGUID($gpoguid_mod,$gpolist);
if ($gponame=="" && $columns[6]=="Object Type:    %{f30e3bc2-9ff0-11d1-b603-0000f80367c1}"){
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>The Group policy name cannot be resolved. Please update the configuration file gpolist.txt";
echo "<TD>$columns[2]";
}
elseif ($gponame<>"") {
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>GPO $gponame has been modified";
echo "<TD>$columns[2]";
}
break;
case 630:
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
$accountdeleted = explode(":", $columns[4]);
echo "<TD>$accountdeleted[1] has been deleted";
echo "<TD>$columns[2]";
break;
case 660:
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
if ($columns[3]=="Member Name: -"){
echo "<TD>Primary group $columns[7] has been set for user $columns[4]";
}
else {
echo "<TD>$columns[4] has been added to $targetaccount[1] group";
}
echo "<TD>$columns[2]";
break;
case 632:
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
if ($columns[3]=="Member Name: -"){
echo "<TD>Primary group $columns[7] has been set for user $columns[4]";
}
else {
echo "<TD>$columns[4] has been added to $targetaccount[1] group";
}
echo "<TD>$columns[2]";
break;
case 633:
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
if ($columns[3]=="Member Name: -"){
echo "<TD>Primary group $columns[7] has been removed for user $columns[4]";
}
else {
echo "<TD>$columns[4] has been removed from $targetaccount[1] group";
}
echo "<TD>$columns[2]";
break;
case 642:
$mod_properties = Propmod($line);
if (strpos($columns[2],"\$")===false && !preg_match("/anonymous/i",$columns[2]) && $mod_properties<>""){
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>Properties has been changed for $columns[4] <br>$mod_properties";
echo "<TD>$columns[2]";
}
elseif (strpos($columns[2],"\$")===false && $columns[18]=="Password Last Set: <never>" ){
echo "<TR><TD>$columns[0]";
echo "<TD>$columns[1]";
echo "<TD>User account created : $columns[5]";
echo "<TD>$columns[2]";
}
break;
default:
}
}
}
}

$d->close();

function Propmod2008($event){
$result = "";
for ($i=22;$i<41;$i++) {
$field = explode(";", $event);
$field_prop = explode(':',$field[$i]);
$field_prop_clean = trim($field_prop[1]);
if ($field_prop_clean<>"-" && $result=="") {
$result = $field[$i];
}
elseif ($field_prop_clean<>"-" && $result<>"") {
$result = $result."<br>".$field[$i];
}
}
return $result;
}

function Propmod($event){
$result = "";
for ($i=13;$i<28;$i++) {
$field = explode(";", $event);
$field_prop = explode(":\t",$field[$i]);
if ($field_prop[1]<>"-" && $result=="") {
$result = $field[$i];
}
elseif ($field_prop[1]<>"-" && $result<>"") {
$result = $result."<br>".$field[$i];
}
}
return $result;
}

function ResolveGPOGUID($GUID,$gpo_list){
$gpotext = file($gpo_list);
foreach($gpotext as $gpoline) {
$columns = explode(";", $gpoline);
if ($columns[1] <> $GUID) {
continue;
}
else {
return $columns[2];
}
}
}

function ResolveGPOSID($SID,$gpo_list){
$gpotext = file($gpo_list);
foreach($gpotext as $gpoline) {
$columns = explode(";", $gpoline);
if (strpos($SID,$columns[0])) {
return $columns[2];
}
else {
continue;
}
}
}

?>
<>

My Powershell script categories

Audit Active Directory changes

One thought on “Audit Active Directory changes

  • June 10, 2014 at 4:49 am
    Permalink

    I every time spent my half an hour to read this web site’s content every day along with a cup of coffee.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *