public static JProperty AssessGrpMemberItem(string rawMember) { string memberDisplayName = rawMember; string memberSid = "unknown"; // if it's a SID if (rawMember.StartsWith("*")) { // clean it up memberSid = rawMember.Trim('*'); if (GlobalVar.OnlineChecks) { // look it up memberDisplayName = LDAPstuff.GetUserFromSid(memberSid); } else { // see if it's well known JToken checkedMemberSid = Utility.CheckSid(memberSid); if (checkedMemberSid != null) { memberDisplayName = checkedMemberSid["displayName"].ToString(); } } } return(new JProperty(memberDisplayName, memberSid)); }
private JObject GetAssessedGroupMember(JToken member) { List <JToken> memberProps = new List <JToken> { JUtil.GetSafeJProp("Name", member, "@name"), JUtil.GetSafeJProp("Action", member, "@action"), JUtil.GetSafeJProp("SID", member, "@sid") }; string memberSid = JUtil.GetSafeString(member, "@sid"); if (!string.IsNullOrEmpty(memberSid)) { string resolvedSID = LDAPstuff.GetUserFromSid(memberSid); memberProps.Add(new JProperty("Display Name From SID", resolvedSID)); } JObject assessedMember = new JObject(); foreach (JProperty memberProp in memberProps) { if (memberProp != null) { assessedMember.Add(memberProp); } } if (assessedMember.HasValues) { return(assessedMember); } return(null); }
static JProperty GetTrustee(string trustee) { string displayName = ""; // clean up the trustee SID string resolvedSid = LDAPstuff.GetUserFromSid(trustee); displayName = resolvedSid; return(new JProperty(trustee, displayName)); }
private JObject GetAssessedGroupMember(JToken member) { JObject assessedMember = new JObject { { "Name", Utility.GetSafeString(member, "@name") }, { "Action", Utility.GetSafeString(member, "@action") } }; string memberSid = Utility.GetSafeString(member, "@sid"); if (memberSid.Length > 0) { assessedMember.Add("SID", memberSid); if (GlobalVar.OnlineChecks) { string resolvedSID = LDAPstuff.GetUserFromSid(memberSid); assessedMember.Add("Display Name From SID", resolvedSID); } } return(assessedMember); }
public Sid(string sid) { Raw = sid; string alias = Match.OneByRegex(sid, KnownSidsDict) ?? Match.OneByPrefix(sid, KnownAliasesDict, out var _); if (alias == null) { // ERROR Unknown SID. if (GlobalVar.OnlineChecks) { alias = LDAPstuff.GetUserFromSid(sid); } else { alias = Format.Unknown(sid); } } Alias = alias; }
static JProperty GetTrustee(string trustee) { string displayName = ""; // clean up the trustee SID try { string resolvedSid = LDAPstuff.GetUserFromSid(trustee); displayName = resolvedSid; } catch (IdentityNotMappedException) { displayName = "Unable to resolve SID."; // check if it's a well known trustee in our JankyDB JToken checkedSid = Utility.CheckSid(trustee); if (checkedSid != null) { displayName = (string)checkedSid["displayName"]; } } return(new JProperty(trustee, displayName)); }
public JObject ToJObject() { bool anyFlags = Flags != null && Flags.Any(); bool anyAces = Aces != null && Aces.Any(); JObject parsedAcl = new JObject(); if (anyFlags) { //parsedAcl.Add("Flags", JArray.FromObject(Flags)); } if (anyAces) { int inc = 0; foreach (Ace ace in Aces) { JObject parsedAce = new JObject(); JArray aceFlagsJArray = new JArray(); if (ace.AceFlags != null) { aceFlagsJArray = JArray.FromObject(ace.AceFlags); } string aceSidAlias = ace.AceSid.Alias; string aceSidRaw = ace.AceSid.Raw; string aceType = ""; if (ace.AceType == "ACCESS_ALLOWED") { aceType = "Allow"; } else if (ace.AceType == "ACCESS_DENIED") { aceType = "Deny"; } else { aceType = ace.AceType; } JArray aceRights = JArray.FromObject(ace.Rights); string displayName = LDAPstuff.GetUserFromSid(aceSidRaw); parsedAce.Add("SID", aceSidRaw); parsedAce.Add("Name", displayName); parsedAce.Add("Type", aceType); if (aceRights.Count > 1) { parsedAce.Add("Rights", aceRights); } else if (aceRights.Count == 1) { parsedAce.Add("Rights", aceRights[0].ToString()); } if (aceFlagsJArray.Count > 1) { parsedAce.Add("Flags", aceFlagsJArray); } else if (aceFlagsJArray.Count == 1) { parsedAce.Add("Flags", aceFlagsJArray[0].ToString()); } parsedAcl.Add(new JProperty(inc.ToString(), parsedAce)); inc++; } } return(parsedAcl); }
public static JObject AssessPrivRights(JToken privRights) { JObject jsonData = JankyDb.Instance; JArray intPrivRights = (JArray)jsonData["privRights"]["item"]; // create an object to put the results in JObject assessedPrivRights = new JObject(); //set an intentionally non-matchy domainSid value unless we doing online checks. string domainSid = "X"; if (GlobalVar.OnlineChecks) { domainSid = LDAPstuff.GetDomainSid(); } //iterate over the entries foreach (JProperty privRight in privRights.Children <JProperty>()) { // our interest level always starts at 1. Everything is boring until proven otherwise. int interestLevel = 1; foreach (JToken intPrivRight in intPrivRights) { // if the priv is interesting if ((string)intPrivRight["privRight"] == privRight.Name) { //create a jobj to put the trustees into JObject trustees = new JObject(); //then for each trustee it's granted to foreach (string trustee in privRight.Value) { string displayName = "unknown"; // clean up the trustee SID string trusteeClean = trustee.Trim('*'); // check if it's a well known trustee in our JankyDB JToken checkedSid = Utility.CheckSid(trusteeClean); // extract some info if they match. if (checkedSid != null) { displayName = (string)checkedSid["displayName"]; } // if they don't match, try to resolve the sid with the domain. // tbh it would probably be better to do this the other way around and prefer the resolved sid output over the contents of jankydb. @liamosaur? else { if (GlobalVar.OnlineChecks) { try { if (trusteeClean.StartsWith(domainSid)) { string resolvedSid = LDAPstuff.GetUserFromSid(trusteeClean); displayName = resolvedSid; } } catch (IdentityNotMappedException) { displayName = "Failed to resolve SID with domain."; } } } trustees.Add(trusteeClean, displayName); } // add the results to our jobj of trustees if they are interesting enough. string matchedPrivRightName = privRight.Name; if (interestLevel >= GlobalVar.IntLevelToShow) { assessedPrivRights.Add(matchedPrivRightName, trustees); } } } } return(assessedPrivRights); }
public JObject ToJObject() { bool anyFlags = Flags != null && Flags.Any(); bool anyAces = Aces != null && Aces.Any(); JObject parsedAcl = new JObject(); if (anyFlags) { //parsedAcl.Add("Flags", JArray.FromObject(Flags)); } if (anyAces) { int inc = 0; foreach (Ace ace in Aces) { JObject parsedAce = new JObject(); JArray aceFlagsJArray = new JArray(); if (ace.AceFlags != null) { aceFlagsJArray = JArray.FromObject(ace.AceFlags); } string aceSidAlias = ace.AceSid.Alias; string aceSidRaw = ace.AceSid.Raw; string aceType; if ((ace.AceType == "ACCESS_ALLOWED") || (ace.AceType == "OBJECT_ACCESS_ALLOWED")) { aceType = "Allow"; } else if ((ace.AceType == "ACCESS_DENIED") || (ace.AceType == "OBJECT_ACCESS_DENIED")) { aceType = "Deny"; } else { aceType = ace.AceType; } Dictionary <string, string> boringRights = new Dictionary <string, string>() { { "READ_CONTROL", "Read ACL" }, { "SYNCHRONIZE", "Synchronize" }, { "GENERIC_EXECUTE", "Execute" }, { "GENERIC_READ", "Read" }, { "READ_PROPERTY", "Read Property" }, { "LIST_CHILDREN", "List Children" }, { "LIST_OBJECT", "List Object" } }; Dictionary <string, string> interestingRights = new Dictionary <string, string>() { { "KEY_ALL", "Full Control" }, { "DELETE_TREE", "Delete Tree" }, { "STANDARD_DELETE", "Delete" }, { "CREATE_CHILD", "Create Child" }, { "DELETE_CHILD", "Delete Child" }, { "WRITE_PROPERTY", "Write Property" }, { "GENERIC_ALL", "Full Control" }, { "GENERIC_WRITE", "Write" }, { "WRITE_DAC", "Write ACL" }, { "WRITE_OWNER", "Write Owner" }, { "STANDARD_RIGHTS_ALL", "Full Control" }, { "STANDARD_RIGHTS_REQUIRED", "Delete, Write DACL, Write Owner" }, { "CONTROL_ACCESS", "Extended Rights" }, { "SELF_WRITE", "Self Write" } }; JArray aceRightsJArray = new JArray(); foreach (string right in ace.Rights) { // if the right is interesting, we'll take it if (interestingRights.ContainsKey(right)) { aceRightsJArray.Add(interestingRights[right]); continue; } // if it's boring and we're not showing defaults, we'll skip it. else if ((boringRights.ContainsKey(right)) && (GlobalVar.IntLevelToShow > 0)) { continue; } else if ((boringRights.ContainsKey(right)) && (GlobalVar.IntLevelToShow == 0)) { aceRightsJArray.Add(boringRights[right]); continue; } else { // KEY_READ will land here. not sure what to do with it cos reading the right registry key is of course very interesting, but those cases are going to be pretty rare. // Might have to handle further downstream? Utility.Output.DebugWrite(right + " was not defined as either boring or interesting. Consider adding it to the dicts in Acl.cs?"); aceRightsJArray.Add(right); } } string displayName = LDAPstuff.GetUserFromSid(aceSidRaw); parsedAce.Add("SID", aceSidRaw); parsedAce.Add("Name", displayName); parsedAce.Add("Type", aceType); if (aceRightsJArray.Count > 1) { parsedAce.Add("Rights", aceRightsJArray); } else if (aceRightsJArray.Count == 1) { parsedAce.Add("Rights", aceRightsJArray[0].ToString()); } if (aceFlagsJArray.Count > 1) { parsedAce.Add("Flags", aceFlagsJArray); } else if (aceFlagsJArray.Count == 1) { parsedAce.Add("Flags", aceFlagsJArray[0].ToString()); } parsedAcl.Add(new JProperty(inc.ToString(), parsedAce)); inc++; } } return(parsedAcl); }
public static JObject AssessGroupMembership(JToken parsedGrpMemberships) { // base interest level int interestLevel = 4; // really not sure about this one at all. Think it's ok now but could use a recheck. // output object JObject assessedGrpMemberships = new JObject(); // cast input object JEnumerable <JToken> parsedGrpMembershipsEnumerable = parsedGrpMemberships.Children(); foreach (JToken parsedGrpMembership in parsedGrpMembershipsEnumerable) { JProperty parsedGrpMembershipJProp = (JProperty)parsedGrpMembership; // break immediately if there's no value. if (parsedGrpMembershipJProp.Value.ToString() == "") { continue; } // strip the asterisk off the front of the line string cleanedKey = parsedGrpMembershipJProp.Name.Trim('*'); // split out the sid from the 'memberof' vs 'members' bit. string[] splitKey = cleanedKey.Split('_'); // get the sid string cleanSid = splitKey[0]; // get the type of entry string memberWhat = splitKey[2]; // check if the Key SID is a well known sid and get some info about it if it is. JToken checkedSid = Utility.CheckSid(cleanSid); string displayName = ""; // if we're online, try to look up the Key SID if (GlobalVar.OnlineChecks) { displayName = LDAPstuff.GetUserFromSid(cleanSid); } // otherwise try to get it from the well known sid data else if (checkedSid != null) { displayName = checkedSid["displayName"].ToString(); } else { displayName = cleanSid; } if (memberWhat == "Memberof") { JProperty assessedGrpMemberKey = AssessGrpMemberItem(parsedGrpMembershipJProp.Name.Split('_')[0]); if (parsedGrpMembershipJProp.Value is JArray) { foreach (string rawGroup in parsedGrpMembershipJProp.Value) { JProperty assessedGrpMemberItem = AssessGrpMemberItem(rawGroup); if (!(assessedGrpMemberships.ContainsKey(assessedGrpMemberItem.Name))) { assessedGrpMemberships.Add( new JProperty(assessedGrpMemberItem.Name, new JObject( new JProperty("SID", assessedGrpMemberItem.Value), new JProperty("Members", new JObject()))) ); } JObject targetJObject = (JObject)assessedGrpMemberships[assessedGrpMemberItem.Name]["Members"]; targetJObject.Add(assessedGrpMemberKey); } } else { // get a cleaned up version of the memberof JProperty assessedGrpMemberValue = AssessGrpMemberItem(parsedGrpMembershipJProp.Value.ToString()); if (!(assessedGrpMemberships.ContainsKey(assessedGrpMemberValue.Name))) { // create one assessedGrpMemberships.Add( new JProperty(assessedGrpMemberValue.Name, new JObject( new JProperty("SID", assessedGrpMemberValue.Value), new JProperty("Members", new JObject()))) ); } JObject targetJObject = (JObject)assessedGrpMemberships[assessedGrpMemberValue.Name]["Members"]; targetJObject.Add(assessedGrpMemberKey); } } else { // if we don't have an entry for this group yet //Utility.DebugWrite(displayName); if (!(assessedGrpMemberships.ContainsKey(displayName))) { assessedGrpMemberships.Add( new JProperty(displayName, new JObject( new JProperty("SID", cleanSid), new JProperty("Members", new JObject()))) ); } JObject targetJObject = (JObject)assessedGrpMemberships[displayName]["Members"]; // iterate over members and put them in the appropriate JArray if (parsedGrpMembershipJProp.Value is JArray) { foreach (string rawMember in parsedGrpMembershipJProp.Value) { JProperty assessedGrpMember = AssessGrpMemberItem(rawMember); try { targetJObject.Add(assessedGrpMember); } catch (Exception e) { Utility.DebugWrite(e.ToString()); } } } else { JProperty assessedGrpMember = AssessGrpMemberItem(parsedGrpMembershipJProp.Value.ToString()); try { //Utility.DebugWrite(assessedGrpMember.ToString()); targetJObject.Add(assessedGrpMember); } catch (Exception e) { Utility.DebugWrite(e.ToString()); } } } // if the resulting interest level of this shit is sufficient, add it to the output JObject. if (GlobalVar.IntLevelToShow <= interestLevel) { return(assessedGrpMemberships); } } return(null); }
public static JObject GetFileDaclJObject(string filePathString) { int inc = 0; string[] interestingTrustees = new string[] { "Everyone", "BUILTIN\\Users", "Authenticated Users", "Domain Users", "INTERACTIVE", }; string[] boringTrustees = new string[] { "TrustedInstaller", "Administrators", "NT AUTHORITY\\SYSTEM", "Domain Admins", "Enterprise Admins", "Domain Controllers" }; string[] interestingRights = new string[] { "FullControl", "Modify", "Write", "AppendData", "TakeOwnership" }; string[] boringRights = new string[] { "Synchronize", "ReadAndExecute" }; if (!GlobalVar.OnlineChecks) { return(null); } // object for result JObject fileDaclsJObject = new JObject(); FileSecurity filePathSecObj; try { filePathSecObj = File.GetAccessControl(filePathString); } catch (ArgumentException e) { Utility.Output.DebugWrite("Tried to check file permissions on invalid path: " + filePathString); Utility.Output.DebugWrite(e.ToString()); return(null); } catch (UnauthorizedAccessException e) { Utility.Output.DebugWrite(e.ToString()); return(null); } AuthorizationRuleCollection fileAccessRules = filePathSecObj.GetAccessRules(true, true, typeof(SecurityIdentifier)); foreach (FileSystemAccessRule fileAccessRule in fileAccessRules) { // get inheritance and access control type values string isInheritedString = "False"; if (fileAccessRule.IsInherited) { isInheritedString = "True"; } string accessControlTypeString = "Allow"; if (fileAccessRule.AccessControlType == AccessControlType.Deny) { accessControlTypeString = "Deny"; } // get the user's SID string sid = fileAccessRule.IdentityReference.ToString(); string displayNameString = LDAPstuff.GetUserFromSid(sid); // do some interest level analysis bool trusteeBoring = false; bool trusteeInteresting = false; // check if our trustee is boring foreach (string boringTrustee in boringTrustees) { // if we're showing everything that's fine, keep going if (GlobalVar.IntLevelToShow == 0) { break; } // otherwise if the trustee is boring, set the interest level to 0 if (displayNameString.ToLower().EndsWith(boringTrustee.ToLower())) { trusteeBoring = true; // and don't bother comparing rest of array break; } } // skip rest of access rule if trustee is boring and we're not showing int level 0 if ((GlobalVar.IntLevelToShow != 0) && trusteeBoring) { continue; } // see if the trustee is interesting foreach (string interestingTrustee in interestingTrustees) { if (displayNameString.ToLower().EndsWith(interestingTrustee.ToLower())) { trusteeInteresting = true; break; } } // get the rights string fileSystemRightsString = fileAccessRule.FileSystemRights.ToString(); // strip spaces fileSystemRightsString = fileSystemRightsString.Replace(" ", ""); // turn them into an array string[] fileSystemRightsArray = fileSystemRightsString.Split(','); // then do some 'interest level' analysis // JArray for output JArray fileSystemRightsJArray = new JArray(); foreach (string right in fileSystemRightsArray) { bool rightInteresting = false; bool rightBoring = false; foreach (string boringRight in boringRights) { if (right.ToLower() == boringRight.ToLower()) { rightBoring = true; break; } } foreach (string interestingRight in interestingRights) { if (right.ToLower() == interestingRight.ToLower()) { rightInteresting = true; break; } } // if we're showing defaults, just add it to the result and move on if (GlobalVar.IntLevelToShow == 0) { fileSystemRightsJArray.Add(right); continue; } // if we aren't, and it's boring, skip it and move on. if (rightBoring) { continue; } // if it's interesting, add it and move on. if (rightInteresting) { fileSystemRightsJArray.Add(right); continue; } // if it's neither boring nor interesting, add it if the 'interestlevel to show' value is low enough else if (GlobalVar.IntLevelToShow < 3) { Utility.Output.DebugWrite(right + " was not labelled as boring or interesting."); fileSystemRightsJArray.Add(right); } else { Utility.Output.DebugWrite("Shouldn't hit here, label FS right as boring or interesting." + right); } } // no point continuing if no rights to show if (fileSystemRightsJArray.HasValues) { // if the trustee isn't interesting and we're excluding low-level findings, bail out if ((!trusteeInteresting) && (GlobalVar.IntLevelToShow > 4)) { return(null); } // build the object string rightsString = fileSystemRightsJArray.ToString().Trim('[', ']').Trim().Replace("\"", ""); JObject fileDaclJObject = new JObject { { accessControlTypeString, displayNameString }, { "Inherited?", isInheritedString }, { "Rights", rightsString } }; // add the object to the array. fileDaclsJObject.Add(inc.ToString(), fileDaclJObject); inc++; } } //DebugWrite(fileDaclsJObject.ToString()); return(fileDaclsJObject); }