This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Custom RTA: Alert when member is added from ForestA to ForestB.

I thought I'd post this while I started working on this. Basic logic for this custom rule would be:

If member or group from "ForestA" is added to any group in "ForestB", send alert.

Any help, greatly appreciated.

Thanks,

jrcusa

Parents
  • Hi JC,
    There are many concerns here. Inside the event we have only domain\member, but there may be domains and members with the same names in other forests, so we might not have 100% true results. However, the example rule follows that works in normal cases, maybe need some improvement. It takes event 4732 and checks whether there is a domain with a given name in the forest where InTrust is installed, and whether a member belongs to this domain. If not, it will send an alert. To set up, create a rule of "Custom" type, choose "Windows Security Log", on Alert tab set Name=%RuleName%, set Description=Member %String32% likely from another forest added to group %String35%, and in Matching|Advanced paste the text:

    <rule type="REL" version="1.0" language="jscript">
    <arguments>
    </arguments>
    <prefilter>
    </prefilter>
    <body>
    function MemberFoundInThisForest(dom,mem)
    {
    var strFilter = "(nETBIOSName=" + dom + ")";
    var dnsRoot = "";
    var strFilter2 = "";
    var returnValue = false;
    var nETBIOSNames = [];
    var nCNames = [];
    try
    {
    var objConnection = new ActiveXObject("ADODB.Connection");
    objConnection.Provider = "ADsDSOObject";
    objConnection.Open("Active Directory Provider");
    var objRootDSE = GetObject("LDAP://RootDSE");
    print("This line is a workaround fixing access to RootDSE object, do not remove it: " + objRootDSE.InvokePropertyGet("Description"));
    print("Search in Forest: &lt;LDAP://" + objRootDSE.InvokePropertyGet("configurationNamingContext") + "&gt;;" + strFilter + ";nETBIOSName,nCName;subtree");
    var objRecordSet = objConnection.Execute("&lt;LDAP://" + objRootDSE.InvokePropertyGet("configurationNamingContext") + "&gt;;" + strFilter + ";nETBIOSName,nCName;subtree");
    print("Number of domains found (objRecordSet.RecordCount): " + objRecordSet.RecordCount);
    if(!objRecordSet.EOF)
    {
    nETBIOSNames = objRecordSet.GetRows( -1, 1, "nETBIOSName" ).toArray();
    nCNames = objRecordSet.GetRows( -1, 1, "nCName" ).toArray();
    }
    for (var i = 0; i&lt;nETBIOSNames.length; i++)
    {
    print(nETBIOSNames[i].toUpperCase());
    print(nCNames[i].toUpperCase());
    dnsRoot = nCNames[i].toUpperCase().split(',').join('.').split('DC=').join('');
    strFilter2 = "(sAMAccountName=" + mem + ")";
    print("Search in Domain: &lt;LDAP://" + dnsRoot + "&gt;;" + strFilter2 + ";sAMAccountName;subtree");
    var objRecordSet2 = objConnection.Execute("&lt;LDAP://" + dnsRoot + "&gt;;" + strFilter2 + ";sAMAccountName;subtree");
    if (!objRecordSet2.EOF)
    {
    print("Member found, will now quit.");
    returnValue = true;
    break;
    }
    }
    return returnValue;
    }
    catch( e )
    {
    print( e.message + ", " + e.number);
    }
    }
    function MemberDomainResolved(securityId)
    {
    return securityId.split('\\').slice( 0, -1 ).toString().toUpperCase();
    }
    function MembersAMAccountNameResolved(securityId)
    {
    return securityId.split('\\').slice( -1 ).toString().toUpperCase();
    }
    function OnEvent(e)
    {
    intEventId = 4732;
    strLogName = "Security";

    print("OnEvent::e.EventID: " + e.EventID);
    if (e.EventID == intEventId)
    {
    print("OnEvent::DataSourceName: " + e._DataSourceName);
    if (e._DataSourceName.toUpperCase() == strLogName.toUpperCase())
    {
    var memberDomain = "";
    var MembersAMAccountName = "";
    print("OnEvent::Member: " + e.String32);
    memberDomain = MemberDomainResolved(e.String32);
    print("OnEvent::MemberDomain: " + memberDomain);
    MembersAMAccountName = MembersAMAccountNameResolved(e.String32);
    print("OnEvent::MembersAMAccountName: " + MembersAMAccountName);
    if (memberDomain &amp;&amp; MembersAMAccountName)
    {
    if (!MemberFoundInThisForest(memberDomain,MembersAMAccountName))
    {
    match (e);
    }
    }
    else
    {
    print("OnEvent::Cannot resolve Domain name or Member name, will now quit.");
    }
    }
    }
    }
    </body>
    </rule>
Reply
  • Hi JC,
    There are many concerns here. Inside the event we have only domain\member, but there may be domains and members with the same names in other forests, so we might not have 100% true results. However, the example rule follows that works in normal cases, maybe need some improvement. It takes event 4732 and checks whether there is a domain with a given name in the forest where InTrust is installed, and whether a member belongs to this domain. If not, it will send an alert. To set up, create a rule of "Custom" type, choose "Windows Security Log", on Alert tab set Name=%RuleName%, set Description=Member %String32% likely from another forest added to group %String35%, and in Matching|Advanced paste the text:

    <rule type="REL" version="1.0" language="jscript">
    <arguments>
    </arguments>
    <prefilter>
    </prefilter>
    <body>
    function MemberFoundInThisForest(dom,mem)
    {
    var strFilter = "(nETBIOSName=" + dom + ")";
    var dnsRoot = "";
    var strFilter2 = "";
    var returnValue = false;
    var nETBIOSNames = [];
    var nCNames = [];
    try
    {
    var objConnection = new ActiveXObject("ADODB.Connection");
    objConnection.Provider = "ADsDSOObject";
    objConnection.Open("Active Directory Provider");
    var objRootDSE = GetObject("LDAP://RootDSE");
    print("This line is a workaround fixing access to RootDSE object, do not remove it: " + objRootDSE.InvokePropertyGet("Description"));
    print("Search in Forest: &lt;LDAP://" + objRootDSE.InvokePropertyGet("configurationNamingContext") + "&gt;;" + strFilter + ";nETBIOSName,nCName;subtree");
    var objRecordSet = objConnection.Execute("&lt;LDAP://" + objRootDSE.InvokePropertyGet("configurationNamingContext") + "&gt;;" + strFilter + ";nETBIOSName,nCName;subtree");
    print("Number of domains found (objRecordSet.RecordCount): " + objRecordSet.RecordCount);
    if(!objRecordSet.EOF)
    {
    nETBIOSNames = objRecordSet.GetRows( -1, 1, "nETBIOSName" ).toArray();
    nCNames = objRecordSet.GetRows( -1, 1, "nCName" ).toArray();
    }
    for (var i = 0; i&lt;nETBIOSNames.length; i++)
    {
    print(nETBIOSNames[i].toUpperCase());
    print(nCNames[i].toUpperCase());
    dnsRoot = nCNames[i].toUpperCase().split(',').join('.').split('DC=').join('');
    strFilter2 = "(sAMAccountName=" + mem + ")";
    print("Search in Domain: &lt;LDAP://" + dnsRoot + "&gt;;" + strFilter2 + ";sAMAccountName;subtree");
    var objRecordSet2 = objConnection.Execute("&lt;LDAP://" + dnsRoot + "&gt;;" + strFilter2 + ";sAMAccountName;subtree");
    if (!objRecordSet2.EOF)
    {
    print("Member found, will now quit.");
    returnValue = true;
    break;
    }
    }
    return returnValue;
    }
    catch( e )
    {
    print( e.message + ", " + e.number);
    }
    }
    function MemberDomainResolved(securityId)
    {
    return securityId.split('\\').slice( 0, -1 ).toString().toUpperCase();
    }
    function MembersAMAccountNameResolved(securityId)
    {
    return securityId.split('\\').slice( -1 ).toString().toUpperCase();
    }
    function OnEvent(e)
    {
    intEventId = 4732;
    strLogName = "Security";

    print("OnEvent::e.EventID: " + e.EventID);
    if (e.EventID == intEventId)
    {
    print("OnEvent::DataSourceName: " + e._DataSourceName);
    if (e._DataSourceName.toUpperCase() == strLogName.toUpperCase())
    {
    var memberDomain = "";
    var MembersAMAccountName = "";
    print("OnEvent::Member: " + e.String32);
    memberDomain = MemberDomainResolved(e.String32);
    print("OnEvent::MemberDomain: " + memberDomain);
    MembersAMAccountName = MembersAMAccountNameResolved(e.String32);
    print("OnEvent::MembersAMAccountName: " + MembersAMAccountName);
    if (memberDomain &amp;&amp; MembersAMAccountName)
    {
    if (!MemberFoundInThisForest(memberDomain,MembersAMAccountName))
    {
    match (e);
    }
    }
    else
    {
    print("OnEvent::Cannot resolve Domain name or Member name, will now quit.");
    }
    }
    }
    }
    </body>
    </rule>
Children
No Data