# T1098 - Account Manipulation

## SOC Recommendation
Any unexpected credential, permission, or delegation change on an account should be treated as a potential persistence mechanism established after compromise, especially when it grants broader access or a secondary path back into the account.

## D3FEND Mappings
| D3FEND Technique | Relationship | Practical SOC Action |
|---|---|---|
| Domain Account Monitoring | Detect | Review role assignments, group membership changes, and OAuth app consent grants for the account. |
| Credential Revocation | Evict | Reset credentials and remove any added authentication methods. |
| Multi-factor Authentication | Harden | Confirm MFA is enforced and no unrecognized authentication method was added. |

## Investigation Steps
1. Is the path in a temp folder, %APPDATA%, %PROGRAMDATA%, or C:\Users? → Almost certainly malicious
2. Is the binary signed? Submit the hash to VirusTotal
3. Does the path contain a strange name (random characters, looks like a legitimate system file)?

## Evidence to Collect
- Account affected
- Type of change (credential/permission/delegation/group)
- Initiating identity
- Timestamp of change
- Before/after state of the modified attribute

## Response Actions
| Action | Risk | Automation Safe | Approval Required |
|---|---|---|---|
| Delete the malicious run key via MDE Live Response | Low | No | Yes |
| Quarantine or delete the pointed binary (SHA256 block in MDE | Medium | No | Yes |
| Run full AV scan on the device | Low | No | Yes |
| Check for additional persistence: scheduled tasks, services, | Low | Yes | No |
| Trace the initiating process back to determine how the malwa | Low | No | Yes |

## KQL
```kql
let lookback = 1d;
let credentialOperations = dynamic([
    "Add service principal credentials",
    "Update service principal",
    "Add application",
    "Update application",
    "Add key credential to application",
    "Add password credential to application",
    "Add service principal delegated permission grant"
]);
let highRiskTerms = dynamic(["keyCredentials", "passwordCredentials", "servicePrincipal", "federatedIdentityCredentials", "AppRoleAssignment"]);
AuditLogs
| where TimeGenerated >= ago(lookback)
| where OperationName has_any (credentialOperations)
| extend Actor = tostring(InitiatedBy.user.userPrincipalName),
         AppDisplayName = tostring(TargetResources[0].displayName),
         TargetId = tostring(TargetResources[0].id),
         ModifiedProperties = tostring(TargetResources[0].modifiedProperties),
         Details = tostring(AdditionalDetails)
| where ModifiedProperties has_any (highRiskTerms) or Details has_any (highRiskTerms) or OperationName has_any ("credential", "permission grant")
| project
    TimeGenerated,
    Actor,
    AppDisplayName,
    TargetId,
    OperationName,
    Result,
    ModifiedProperties,
    Details
| extend timestamp = TimeGenerated,
         AccountCustomEntity = Actor
| order by TimeGenerated desc
```
```kql
let lookback = 1d;
let assignmentThreshold = 3;
AuditLogs
| where TimeGenerated >= ago(lookback)
| where OperationName in~ ("Add member to role", "Add eligible member to role")
| extend InitiatedByUPN = tostring(InitiatedBy.user.userPrincipalName)
| extend TargetRole = tostring(TargetResources[0].displayName)
| extend TargetUser = tostring(TargetResources[0].userPrincipalName)
| where isnotempty(InitiatedByUPN)
| summarize
    StartTime = min(TimeGenerated),
    EndTime = max(TimeGenerated),
    RoleAssignmentCount = count(),
    Roles = make_set(TargetRole, 20),
    TargetUsers = make_set(TargetUser, 50)
    by InitiatedByUPN
| where RoleAssignmentCount >= assignmentThreshold
| extend AccountName = tostring(split(InitiatedByUPN, "@")[0]),
         UPNSuffix = tostring(split(InitiatedByUPN, "@")[1])
| project StartTime, EndTime, InitiatedByUPN, AccountName, UPNSuffix,
          RoleAssignmentCount, Roles, TargetUsers
| extend timestamp = StartTime, AccountCustomEntity = InitiatedByUPN
| order by RoleAssignmentCount desc
```
```kql
Event
| where EventLog == "Microsoft-Windows-Sysmon/Operational" and EventID in (13)
| parse EventData with * 'ProcessId">' ProcessId "<"* 'Image">' Image "<" * 'TargetObject">' TargetObject "<" * 'Details">' Details "<" * 'User">' User "<" * 
| where TargetObject has ("HKLM\\System\\CurrentControlSet\\Control\\Lsa\\DsrmAdminLogonBehavior") and Details == "DWORD (0x00000002)"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, User, ProcessId, Image, TargetObject, Details, _ResourceId
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(User, "\\")[1]), AccountNTDomain = tostring(split(User, "\\")[0])
| extend ImageFileName = tostring(split(Image, "\\")[-1])
| extend ImageDirectory = replace_string(Image, ImageFileName, "")
| project-away DomainIndex
```

## Escalation Criteria
- Change grants privileged or admin-level access.
- Change adds a new authentication method not recognized by the user.
- Mailbox forwarding rule added to an external address.
- Change was made outside the normal change management process.

## False Positive Considerations
- Software installer creating a legitimate startup entry — Add the signed installer's SHA256 to the ApprovedInstallers watchlist
- Browser or application auto-updater — Add specific installer executables to the exclusion list in the query — verify they are from known vendor paths

Generated by SOC Response Atlas by Basyrix.
