top of page

What a Compromised Account Can See in Your Microsoft 365 Tenant

Writer: Derek Morgan
Derek Morgan
5 minutes ago
7 min read

After an incident, the review opens with the same question: what could that account see?


The answer is rarely in one place. It is spread across directory role assignments, Conditional Access scope, sign-in and alert visibility, consent grants, and other settings that sit in separate admin pages.


Verizon's 2026 Data Breach Investigations Report found that 31% of breaches now start with a software vulnerability, ahead of stolen passwords as the top way in. Entry points vary: an exploited edge device, a phished user, a reused password. After entry, the behavior repeats. The foothold account starts reading.


Rejewski is the open-source toolkit I built to ask that question on purpose, against a tenant you own or are authorized to assess. It launched on October 26.


Infographic showing a yellow compromised account connected to six blue boxes: users, roles, access, logs, apps, devices.
Diagram illustrating the six areas accessed by a compromised account, highlighting vulnerabilities in users and groups, directory roles, conditional access, sign-in logs, apps and consent grants, and devices and sensors.

What Rejewski is

Rejewski emulates the discovery phase of an attack, the part that happens once an adversary has a working account. It reads and never writes.


Version 1.0 ships with 15 tools. Each one is a Microsoft Graph read call. Together they cover users, groups, applications, service principals, directory role assignments, PIM-eligible role assignments, OAuth consent grants, Conditional Access policies, Defender for Identity sensor health, Intune devices, Purview sensitivity labels, sign-in logs, Defender XDR alerts, SharePoint sites, and inbox rules. The threat model maps 20 MITRE ATT&CK techniques. Thirteen have a working tool behind them, and 7 are catalogued for later.


Four rules apply to every run:

  • Read-only. GET requests only. Nothing in the tenant's configuration is created, changed, or deleted. The reads do generate sign-in and activity logs, which is what makes them a detection test. The tools sign in as a test account with delegated permissions.

  • One consented tenant. A run can target only the tenant named in its consent record. The check runs before the first sign-in, so a run without a record never starts.

  • No app registration. Nothing is registered in the target tenant.

  • Evidence for every call. Each call writes a replay-log entry. Tokens and secrets are scrubbed before anything is written to the log.


Together these rules keep a test from becoming an incident: it reads, it records every call, and it runs only where the tenant's owner consented.


Each run starts with a consent record, and no tool signs in without one. The record is the first entry in the replay log, and every later entry carries the same run ID. After the run, an analyst triages each finding: a severity from the rubric and a specific control, such as a Conditional Access policy or a directory role. The HTML report lists every triaged finding with its severity and an ROI line.


The agent layer is early. The runtime is built on the Claude Agent SDK and routes steps between Sonnet for routine enumeration and Opus for multi-hop analysis. In this release the operator runs the discovery tools directly, and the routing layer runs offline. Connecting the agent to the tools live is not part of version 1.0.


Other tools exist in this space. Scripted toolkits for Microsoft 365 and Entra include ROADtools, AADInternals, GraphRunner, and MAAD-AF. Configuration checkers include CISA's ScubaGear and Maester, which compare a tenant to a baseline. I searched for an LLM-driven option for Microsoft 365 tenant assessment in May and again in October, and I did not find one. Rejewski's agent layer is the start of one. In version 1.0, each discovery step ends in a rated, control-mapped finding.


The name honors Marian Rejewski, the Polish mathematician who reconstructed the wiring of the German Enigma machine in 1932 without a captured device.


Infographic titled From consent to report with five blue step boxes: consent record, tools, replay log, findings, HTML report.
"Step-by-step process from consent to report generation: Step 1 starts with recording consent, Step 2 utilizes 15 tools for read-only graph calls, Step 3 involves replay logging with scrubbing of secrets, Step 4 maps findings by control and rates them using a rubric, culminating in Step 5 with an HTML report showcasing severity badges and ROI."

What it found in the sandbox

I ran all 15 tools in one consented session against my sandbox tenant, cloudharbordemo. The run is R017. It produced 10 distinct findings: 5 high and 5 medium. The next two runs, R018 and R019, returned the same 10 findings.


The 14 surfaces that returned data produce 8 findings, because six read directory objects and map to account discovery (T1087.004) and two read sign-in and alert logs and map to log enumeration (T1654). The other 2 come from authentication: the sign-in itself (T1078.004) and the silent reuse of its token for the other 14 tools (T1550.001). I count by technique and do not split findings to make the number larger.


Identity. The run's first step signed in with the test account's password through the ROPC flow, which cannot satisfy MFA, and received a token. No policy blocked it. That is the T1078.004 finding, rated high, and its control is a Conditional Access policy that requires MFA for all users.


The PIM-eligible tool found 2 principals eligible to activate Global Administrator, both time-bound and tenant-wide. A review built on active role assignments cannot see them, because eligibility is not an assignment until someone activates it. An eligible principal is one activation away from full control, gated only by the role's activation rules, such as MFA, approval, and justification. Permanent eligibility would remove even the time limit.


Threat detection. The Conditional Access inventory returned 27 policies. The Defender for Identity check returned 3 sensors. Both rate high. The rubric treats a read of the defender's own coverage as high severity, because it tells an adversary which signals exist and where the gaps are.


One tool returned an error. With the delegated Mail.Read scope, the inbox-rules tool reaches only the signed-in user's own mailbox, and the sandbox operator account has no mailbox enabled for the REST API. I record that as a boundary of the method and leave it out of the finding count.


All of these results come from a sandbox with seeded accounts.


Rejewski Run Report table listing 31 findings, with MITRE techniques and severity badges like medium and high, all triage open
Rejewski Run Report highlights high-severity vulnerabilities in cloud systems, requiring urgent attention.

Table of Graph Calls: Account Discovery showing multiple successful cloud account queries; yellow-highlighted PIM eligible roles row.
Graph API Calls for Account Discovery Success: This table showcases a series of API calls made for cloud account discovery using technique T1087.004. Each call, such as listing users, applications, and role assignments, successfully retrieves specific data, with highlighted focus on the tool_list_pim_eligible_roles endpoint, returning 2 rows successfully.

Anatomy of one finding

The Conditional Access finding shows how a result moves from a read to a report line.


The read. The tool calls the Conditional Access policies endpoint in Microsoft Graph. It needs the Policy.Read.All scope and a supported directory role such as Security Reader, Global Reader, or Conditional Access Administrator. In R017 it returned 27 policies.


The mapping. The finding maps to a preventive control: least privilege on the roles that can read policy. The reason is concrete. Whoever reads that inventory learns which user groups have no MFA requirement, which locations are trusted, and which applications have no coverage.


The severity. High, under the rubric's rule for a map of the defender's own coverage.


The ROI line. The report's line for this finding says that least privilege on policy reads limits an adversary's map of where MFA and Conditional Access coverage is thin.


Every step is a record you can open: the replay-log entry, the finding record, the control mapping, and the report row.


The business case

Three published figures give the scale. IBM's 2026 Cost of a Data Breach report puts the global average breach at $4.99M, up 12% and a record. Mandiant's M-Trends 2026 puts median dwell time at 14 days, up from 11. Microsoft's research puts multifactor authentication at blocking more than 99.2% of account compromise attacks.


MFA blocks those attacks only where a policy requires it. In R017, the test account's password alone produced a token, because no policy required MFA for that sign-in. Where MFA is required, it leaves two paths open. One is the share it does not block. The other is every entry path that does not start at a sign-in prompt. Vulnerability exploitation is one of those paths, and the 2026 DBIR puts it at 31% of breaches.


Assume-breach testing measures what a working account can reach after any of those paths. It asks one question: given a working account, how much of the tenant can it read?


The cost link is dwell time. Mandiant's median is 14 days. During those days, an intruder in the discovery phase can read your privileged roles, policies, and detection coverage, and picks the next step with good information. Cut what an ordinary account can read, and discovery takes longer and gives your detection more chances to fire. A shorter dwell time touches fewer systems, which leaves less to clean up before containment. That is how these controls reduce the cost of a breach. IBM's $4.99M average gives the scale.


Each finding in the report carries an ROI line. The line names a risk category, the control that reduces the risk, and the direction of the effect. It carries no dollar figure, because breach-cost data does not support one per finding.


Severity follows a written rubric tied to CIS Controls v8, so a reader can challenge any rating against a public source. High means a finding gave an adversary credential material, sensitive data, a way past a control, or a map of the defender's own coverage. Medium means a tenant-wide list of accounts, groups, roles, or a data-classification scheme.


What to do this quarter

You can act on this without running Rejewski.

  1. Audit PIM eligibility. In Privileged Identity Management, open the eligible assignments for Microsoft Entra roles. List who can activate Global Administrator and the other high-privilege roles. Flag any assignment with no end date, require approval and MFA on activation, and keep the list short and named.

  2. Review the read roles. Check who holds Reports Reader, Security Reader, and Global Reader. Each one can read part of your detection and policy map.

  3. Close the MFA exceptions. Look for user accounts that run scripts or integrations with a stored password. They are a common exception to an MFA requirement. Microsoft's guidance is to migrate them to managed identities or service principals. Then confirm a Conditional Access policy requires MFA for all users, which also makes password-only flows such as ROPC fail.

  4. Run the question yourself. If you try Rejewski, start in a sandbox, complete the consent step, and read the replay log before the report.


For the executive, ask for one number: the count of Global Administrator assignments with no end date. Track it each quarter.


If an account in your tenant is compromised tomorrow, the next step depends on what it can read. Rejewski does that reading ahead of time, writes down what it found, and rates each result. The repository, the threat model, and the sample reports are public on GitHub.

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page