Merge commit 'dc7867b6bc1193e3b5d54a9c7368c0647c39b663' into test/373-native-registry-sacl-lifecycle

# Conflicts:
#	.gitattributes
#	.github/workflows/release.yml
#	CHANGELOG-Japanese.md
#	CHANGELOG.md
#	website/docs/resources/changelog.ja.md
#	website/docs/resources/changelog.md
This commit is contained in:
Shirofune-Security committed 2026-09-22 09:35:07 +09:00
commit ac45e8f72f
27 files changed
+1285 -5

No files matched your search

+2
View File
@@ -90,3 +90,5 @@ RSoP schema references: [registry policy](https://learn.microsoft.com/en-us/prev
Targeted file/registry SACL prerequisites are included as a read-only companion plan. See [targeted SACL planning](targeted-sacl-planning.md) for per-user gaps, source distinctions and `-SaclMode Skip`.
The stronger profile's optional IPsec Main Mode control additionally requires positive local native prerequisite evidence during shared planning/configuration. See [conditional IPsec prerequisites](ipsec-prerequisites.md) for scope, statuses and fresh pre-write checks.
A separate [public custom-profile native acceptance fixture](custom-audit-profiles.md#verification-and-recovery) exercises the shared configuration/precedence engine with actual writes on disposable Server 2022/2025 hosts. It verifies all 59 effective masks and exact cleanup without claiming full baseline, GPO, event or Sigma acceptance.
+40
View File
@@ -0,0 +1,40 @@
# Reviewed native channel recovery
`channel-recovery` restores **one completed `channel-settings` operation** on one exact channel from the bundled Microsoft WEF Appendix C profile. It can restore the original enabled state and size, and remove only the exact Event Log Readers read ACE that operation added. It does not restore other configuration commands, partially completed original writes, event records, subscriptions or arbitrary channels. Sysmon is excluded.
```powershell
./WELA.ps1 channel-recovery -ChannelRecoveryJournalPath C:\WELA\original\before.jsonl `
-ChannelRecoveryOriginalResultsPath C:\WELA\original-results.json `
-ChannelRecoveryChannel 'Microsoft-Windows-CAPI2/Operational' `
-ChannelRecoveryOutputPath C:\WELA\recovery-plan
# Inspect plan.json and manifest.json; independently retain manifest PlanHash.
./WELA.ps1 channel-recovery -ChannelRecoveryAction Restore `
-ChannelRecoveryPlanPath C:\WELA\recovery-plan\plan.json `
-ChannelRecoveryPlanHash REVIEWED_SHA256 `
-ChannelRecoveryOutputPath C:\WELA\recovery-run `
-ChannelRecoveryAllowShrink -ChannelRecoveryAllowDisable -ChannelRecoveryAllowRevoke
```
Supply only the consent switches the reviewed plan requires. **Shrinking can discard records; disabling stops channel generation; removing a read grant can interrupt collection.** These are separate decisions. Plan is read-only apart from new protected evidence files. Restore accepts a reviewed plan/hash and a new output directory; `-Auto`, `-DryRun`, `-WhatIf` and unrelated command options are rejected. There is no automatic rollback or continuation after a partial failure.
The original journal must contain exactly one matching entry, with the same typed `Before`, `Desired` and target as one `Applied` result. The command independently rebuilds the enable/minimum-size/read-grant transformation from the current bundled profile. Unknown schemas, Boolean values in text/size fields, duplicate JSON properties, mismatched journals, unexplained post-write changes, missing read-grant authorization and unchanged operations are refused. The selected operation may be recovered even when another channel failed during the original invocation; it must itself be completed and fully consistent.
Current settings must exactly match the original confirmed after-state. For descriptors, equality means the complete binary descriptor, including owner, group, SACL, DACL, resource-manager control and all ACE bytes/order. The canonical read-grant planner must reproduce the exact original addition, and SDDL conversion must round-trip without loss. An unrelated new ACE or another changed setting requires manual review; recovery never removes it. A previous read grant that was already present is preserved.
Only originally changed fields are written, in size, descriptor, then enablement order. Each write has a flushed pending receipt, a fresh complete settings/metadata check and actual primary-token check, native `wevtutil` exit validation, independent readback, and a confirmed receipt. Other channel properties, including retention, path, provider parameters and isolation, must remain unchanged. A final read checks the full target. Recovery changes no other channel, audit policy, group membership, service or forwarding configuration.
| Result | Meaning |
| --- | --- |
| `ReviewRequired` | A new plan and hash were retained; no native write occurred. |
| `Refused` | Evidence, consent or current context did not authorize a write. |
| `RestoredAndVerified` | Every selected original field was restored and observed with preservation checks. |
| `RestoreAttemptedUnverified` | At least one native write was attempted; inspect pending, observed, confirmed and failure-state receipts before manual action. |
`ConfirmedFields` identifies steps whose immediate readback succeeded; a later failure does not establish that those settings stayed unchanged. Loss of power, process termination or output-storage failure can leave pending evidence without a final manifest. A read-grant removal could succeed even if the caller subsequently cannot read metadata; that remains unverified, without rollback. There is no atomic Windows compare-and-set, so another administrator can race the final check.
Inputs and outputs must use ordinary local paths supported by WELA's protected recovery artifact helpers. Current host identity, actual operator/logon, source files and native executable/reader assembly hashes are bound to the plan. Plan and Restore must use the same installed implementation and PowerShell version. **Old version-1 journals contain only historical ComputerName; current guards do not authenticate historical ownership.** Treat original evidence as trusted operator records. Updating WELA invalidates older review plans; create and review a new plan rather than editing its fingerprints.
Windows validation uses explicit disposable GitHub-hosted Server 2022/2025 fixtures under Windows PowerShell 5.1 and PowerShell 7. The fixture calls public Configure then Plan/Restore for actual CAPI2 enable/size changes, with and without the optional read ACE. It tests each missing consent, actual later size drift, replay, unsupported preview options, other-channel preservation, retained hashes, and exact original fixture configuration/all audit masks at cleanup. Shrinking during fixture cleanup can discard intervening records. Windows 11, domain/DC/CA forwarding identities, event generation, persistence through policy refresh, retention duration and backend Sigma evaluation remain separate acceptance work. No rule-readiness credit is granted.
See [native channel configuration](native-channel-access.md) for original journal creation and [actual channel reads](channel-read.md) for separate current-token query evidence. [Microsoft's `wevtutil` contract](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/wevtutil) documents channel enablement, maximum size and channel access; buffer configuration is not a retention guarantee.
+10 -3
View File
@@ -110,7 +110,14 @@ undo partially applied changes, restore a GPO, or invoke policy refresh. Re-run
assessment after GPO/MDM refresh to verify effective state.
Tests exercise malformed files, preservation modes, validation ordering, mocked
writes, prompt-time file changes and final drift. Windows CI performs real read-only
custom-profile audits on Server 2022/2025 with PowerShell 5.1/7. Configuration and
benign event/backend acceptance on Windows 11, DC and AD CS labs remain separate;
writes, prompt-time file changes and final drift. Windows CI also exercises the actual public Plan, DryRun, Configure and Audit
commands on disposable Server 2022/2025 hosts with PowerShell 5.1/7. A fixture-owned
custom file selects four canonical controls: minimum and exact masks, an explicit
optional control, and Not Configured preservation. Tests compare all 59 masks,
typed precedence, source fingerprints, native channels and original journals,
then verify exact fixture restoration. Invalid role selection is refused before
configuration, and repeated configuration makes no further native change.
These are hosted standalone servers classified by the shared profile engine as
MemberServer; no domain join or GPO refresh is simulated. Configuration and
benign event/backend acceptance on Windows 11, domain-joined servers, DC and AD CS labs remain separate;
no clean-install or detection-coverage claim is made.
+1 -1
View File
@@ -30,7 +30,7 @@ The planner uses [RawSecurityDescriptor](https://learn.microsoft.com/en-us/dotne
The shared configuration runner writes `before.jsonl` before each native mutation, capturing the original enabled state, exact size, full descriptor and retention mode. A fresh read must match both the plan and the journal snapshot before `wevtutil sl` executes. Only changed `/e:true`, `/ms:...` and explicitly authorized `/ca:...` arguments are sent. Native failure, failed readback, descriptor mismatch and final drift produce a nonzero result. There is no atomic Windows compare-and-set; another writer can still race the final check. Re-run after policy refresh to check persistence. No automatic rollback occurs.
Recovery is manual: review each journal `Before` against the current settings, identify the affected channel, and restore only the intended previous values using `wevtutil sl "CHANNEL" /e:true|false /ms:ORIGINAL_BYTES /ca:"ORIGINAL_SDDL"`. Pass the descriptor as one argument in PowerShell, for example `& wevtutil.exe sl $entry.Target.Channel ("/ca:" + $entry.Before.SecurityDescriptor)` after loading and reviewing the relevant JSONL entry. Restoring a smaller limit can discard events. Existing retention is not intentionally modified; investigate any changed mode before choosing recovery actions. Use a new backup directory for each run.
For a completed `channel-settings` operation, use [reviewed single-channel recovery](channel-recovery.md) to reconstruct the original changed fields, require exact current after-state and request separate shrink/disable/read-revocation consent. Partially completed originals and later drift still require manual review. For manual recovery, review each journal `Before` against the current settings, identify the affected channel, and restore only the intended previous values using `wevtutil sl "CHANNEL" /e:true|false /ms:ORIGINAL_BYTES /ca:"ORIGINAL_SDDL"`. Pass the descriptor as one argument in PowerShell, for example `& wevtutil.exe sl $entry.Target.Channel ("/ca:" + $entry.Before.SecurityDescriptor)` after loading and reviewing the relevant JSONL entry. Restoring a smaller limit can discard events. Existing retention is not intentionally modified; investigate any changed mode before choosing recovery actions. Use a new backup directory for each run.
## Native WEF prerequisites and validation
+29
View File
@@ -0,0 +1,29 @@
# Reviewed WEC source authorization
`wec-authorization` plans and applies the explicit source SID allow list of one **already disabled**, existing source-initiated HTTP/native-event subscription. This supplies the authorization update missing from the create-only collector command, query/description updater and separate Enabled transition. Related to #368; built-in Windows only, with no Sysmon.
```powershell
# Invoke the PowerShell script directly when supplying an array of SIDs.
.\WELA.ps1 wec-authorization -WecAuthorizationId 'Reviewed subscription' `
-WecAuthorizationSourceSid 'S-1-5-21-111-222-333-1234','S-1-5-21-111-222-333-1235' `
-WecAuthorizationOutputPath C:\Evidence\authorization-plan
# Review plan.json, including its complete original XML and desired source list.
# Retain its PlanHash from manifest.json before applying those exact bytes.
.\WELA.ps1 wec-authorization -WecAuthorizationAction Apply `
-WecAuthorizationPlanPath C:\Evidence\authorization-plan\plan.json `
-WecAuthorizationPlanHash '<reviewed SHA256>' `
-WecAuthorizationOutputPath C:\Evidence\authorization-apply
```
Plan reads native configuration and writes review artifacts. Apply takes the subscription and desired list only from the reviewed plan. Both require a new private evidence directory on a local fixed drive. The actual elevated, non-impersonated reader, supported patched Server 2022/2025 standalone/member host, running Wecsvc/WMI/EventLog services, destination channel settings and implementation sources are observed and bound. No service is started, subscription enabled, channel changed or AD membership modified. Unknown options, mixed Plan/Apply inputs, `-Auto`, `-DryRun` and `-WhatIf` are refused; use Plan for review.
The desired list contains 1–32 unique canonical `S-1-5-21-A-B-C-RID` strings with native-range subauthorities. Order is normalized; duplicate SIDs, aliases, arbitrary SDDL, null/empty/default authorization and non-domain/certificate settings are refused. The existing descriptor must already be the same supported explicit allow-list form. WELA neither resolves these strings nor verifies that they identify domain computer accounts or groups. Obtain and independently verify intended identities and group membership before review. Adding a SID can broaden future authorization; removing one entry does not establish that a machine lacks access through another allowed group.
Apply checks the complete original definition and current context, flushes a pending receipt, opens only an existing native subscription and uses one `EcSubscriptionAllowedSourceDomainComputers` setter followed by save. The native adapter rechecks disabled/source-initiated state and selected native fields through a fresh handle. Native readback must match the desired list while all other observed XML fields, actual token, services and destination settings stay unchanged. Matching authorization returns `AlreadyMatches` without a save. Successful changes report `AuthorizationChangedAndVerified`; failures before save report `Refused`. Once save has been attempted, incomplete readback or preservation reports `SaveAttemptedUnverified` and retains available native after-XML.
An enabled subscription is refused, including a no-op request. Use the separately reviewed [Enabled transition](wec-state.md) when an intentional interruption or activation is required. To restore an authorization list, make a fresh plan against the current disabled definition using the original retained SIDs. There is no automatic rollback or native compare-and-swap: another administrator can race the pre-save observations. Coordinate changes and inspect retained evidence after partial results. Plan hashes check consistency and do not authenticate an untrusted evidence author.
The native CI fixture creates one uniquely named disabled subscription with inert SIDs, exercises public no-op/add/remove/restore, wrong-hash/stale/enabled refusals and a native fresh-handle drift check, then verifies original subscription inventory, service startup/state and complete channel restoration. Temporary service/channel changes belong only to explicitly opted-in disposable fixtures. These tests do not resolve or authenticate a source, change AD groups, verify forwarding or bookmarks, or award Sigma readiness credit.
Microsoft documents the [authorization property](https://learn.microsoft.com/en-us/windows/win32/api/evcoll/ne-evcoll-ec_subscription_property_id), [source-initiated subscription settings](https://learn.microsoft.com/en-us/windows/win32/wec/creating-a-source-initiated-subscription), [existing-only open flags](https://learn.microsoft.com/en-us/windows/win32/api/evcoll/nf-evcoll-ecopensubscription) and [activation on saving enabled subscriptions](https://learn.microsoft.com/en-us/windows/win32/api/evcoll/nf-evcoll-ecsavesubscription).
+2
View File
@@ -58,6 +58,8 @@ Readback equality covers ID, enabled state, selected delivery preset, ReadExisti
JSON retains exact filters, disabled flags, local channel enablement/mode/ACL, local configuration results, native `wecutil gr` output and its errors, and unverified prerequisites. A separate [`TypedRuntime`](wec-runtime.md) object adds native activity/error/time fields and bounded per-source observations; its Unknown/Partial status stays independent of local configuration success. On collectors, local channel metadata is explicitly labeled **collector only**; it does not describe remote source states. Localized runtime text is preserved as evidence without inferring connected-source counts or arrival success. `LocalConfigurationStatus: RequestedSettingsMatch` describes the selected local settings only. A non-dry-run with unmet prerequisites, failed writes or mismatched final settings exits nonzero and is incomplete.
Use the separate [reviewed authorization update](wec-authorization.md) to change an explicit source SID list on an already disabled existing subscription. It preserves the other observed fields and supplies no SID-resolution or forwarding proof.
## Recovery and lab acceptance
`before.jsonl` is written before each mutation. Review its exact Target/Before/Desired and the results before recovery. For a newly created subscription, it records absence and stores the prepared XML; remove that exact ID only after verifying its current definition still belongs to this run. Existing subscriptions are never edited. For the new SubscriptionManager value, compare the current value with Desired before removing only that value; keep other list entries and parent keys. Restore WSMan values and service start/running states only after verifying their present state and current policy authority. Remove only the newly added group SID after comparing the full membership snapshot; DC membership is never changed by this workflow. For channel restoration, use the channel journal and descriptor-preservation guidance. Recovery is deliberately manual so a newer operator/GPO change is not overwritten.