Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MS.AAD.3.1v1 phishing resistant mfa for all users #433

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
70f6a73
Structural baseline updates (cleaned up) (#334)
ahuynhMITRE May 15, 2023
49b95c7
Initial drop of secure baseline automation (#336)
crutchfield May 25, 2023
b82249a
Add quiet mode for invoke-scuba (#357)
crutchfield Jun 2, 2023
825861d
Invert Stance on Defender Preset Policies in Markdown (#355)
adhilto Jun 7, 2023
2c950f0
Substantiative changes to Sharepoint Baseline minus Rationale (#360)
Sloane4 Jun 7, 2023
f7a6e75
Fix test location file path (#367)
schrolla Jun 8, 2023
5ad473b
Enhanced smoke test - check for missing results (#356)
crutchfield Jun 13, 2023
d423116
One drive baseline (#370)
Dylan-MITRE Jun 16, 2023
99081e7
DLP policy group additions and updates (#381)
schrolla Jun 26, 2023
b023ecb
Adjudicate Substantive AAD Baseline Comments (#379)
ssatyapal123 Jun 29, 2023
4572307
Added SharePoint to MS.DEFENDER.4.2v1 locations (#402)
schrolla Jun 30, 2023
a04eb7b
Update aad scubagear code to align to revised baseline (#408)
Sloane4 Jul 3, 2023
2ade0e4
Differentiate policy id vs implementation (#414)
crutchfield Jul 5, 2023
38ea3ea
WIP
Jul 11, 2023
27e3958
Updated ReportDetails on tests to match patch results (#426)
schrolla Jul 11, 2023
3a029ae
Address Power Platform pilot comments and substantive changes in the …
buidav Jul 11, 2023
7f3822d
wip
Jul 13, 2023
fbdf897
Implemented AAD 3.1
Jul 13, 2023
f9b3398
WIP
Jul 11, 2023
24decbb
wip
Jul 13, 2023
d7cbbf7
Implemented AAD 3.1
Jul 13, 2023
f39411f
Update Rego/AADConfig.rego
crutchfield Jul 13, 2023
e6d68cb
Update Smoke Test to handle CAP (#418)
crutchfield Jul 13, 2023
f73e96c
update MS.AAD.7.6v1 to only check for global admin (#428)
adhilto Jul 13, 2023
d195e00
Merge branch '351-implement-new-scubagear-rego-check-for-msaad31v1-ph…
Jul 14, 2023
34037da
Combine Sharepoint with OneDrive and address feedback from review per…
tkol2022 Jul 14, 2023
fa9c0b6
Adjudicate review comments
Jul 14, 2023
6e1ad9a
Merge branch 'emerald' into 351-implement-new-scubagear-rego-check-fo…
crutchfield Jul 14, 2023
cc764c0
WIP
Jul 11, 2023
18862f8
wip
Jul 13, 2023
07a4cbe
Implemented AAD 3.1
Jul 13, 2023
98f35a9
WIP
Jul 11, 2023
b243639
wip
Jul 13, 2023
39e0536
Update Rego/AADConfig.rego
crutchfield Jul 13, 2023
3f34b60
Adjudicate review comments
Jul 14, 2023
86a6cde
Merge branch '351-implement-new-scubagear-rego-check-for-msaad31v1-ph…
Jul 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions PowerShell/ScubaGear/RequiredVersions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $ModuleList = @(
},
@{
ModuleName = 'ExchangeOnlineManagement' # includes Defender
ModuleVersion = [version] '3.2.0'
ModuleVersion = [version] '3.1.0'
MaximumVersion = [version] '3.99.99999'
},
@{
Expand Down Expand Up @@ -38,7 +38,7 @@ $ModuleList = @(
@{
ModuleName = 'Microsoft.Graph.Authentication'
ModuleVersion = [version] '1.14.0'
MaximumVersion = [version] '1.99.99999'
MaximumVersion = [version] '1.27.0'
},
@{
ModuleName = 'Microsoft.Graph.DeviceManagement' #TODO: Verify is needed
Expand Down
40 changes: 30 additions & 10 deletions Rego/AADConfig.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import future.keywords
import data.report.utils.NotCheckedDetails
import data.report.utils.Format
import data.report.utils.ReportDetailsBoolean
import data.policy.utils.IsEmptyContainer
import data.policy.utils.Contains
import data.policy.utils.Count

#############################################################################
# The report formatting functions below are generic and used throughout AAD #
Expand Down Expand Up @@ -268,18 +271,35 @@ tests[{
#
# MS.AAD.3.1v1
#--
# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods
# Awaiting API changes and feature updates from Microsoft for automated checking

MS_AAD_3_1v1_CAP[Cap.DisplayName] {
Cap := input.conditional_access_policies[_]

Cap.State == "enabled"
Contains(Cap.Conditions.Users.IncludeUsers, "All")
IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications)
Contains(Cap.Conditions.Applications.IncludeApplications, "All")
GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true
UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true

# Strength must be at least one of acceptable with no unacceptable strengths
Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]}
AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"}
MinusSet := Strengths - AcceptableMFA
Count(MinusSet) == 0
Count(Strengths) > 0
}

tests[{
"PolicyId" : PolicyId,
"Criticality" : "Shall/Not-Implemented",
"Commandlet" : [],
"ActualValue" : [],
"ReportDetails" : NotCheckedDetails(PolicyId),
"RequirementMet" : false
"PolicyId" : "MS.AAD.3.1v1",
"Criticality" : "Shall",
"Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"],
"ActualValue" : MS_AAD_3_1v1_CAP,
"ReportDetails" : concat(". ", [ReportFullDetailsArray(MS_AAD_3_1v1_CAP, DescriptionString), CapLink]),
"RequirementMet" : Status
}] {
PolicyId := "MS.AAD.3.1v1"
true
DescriptionString := "conditional access policy(s) found that meet(s) all requirements"
Status := count(MS_AAD_3_1v1_CAP) > 0
}
#--

Expand Down
30 changes: 30 additions & 0 deletions Rego/Utils/PolicyUtils.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package policy.utils
import future.keywords

IsEmptyContainer(null) = true
IsEmptyContainer(container) := true if {
Temp := {Item | Item := container[_]}
count(Temp) == 0
}

IsAllUsers(null) = false
IsAllUsers(array) := true if {
not IsEmptyContainer(array)
array[_] == "All"
} else = false {true}

Contains(null, _) = false
Contains(array, item) := true if {
not IsEmptyContainer(array)
array[_] == item
} else = false {
true
}

Count(null) = 0
Count(container) := Result if {
not IsEmptyContainer(container)
Result := count(container)
} else = 0 {
true
}
267 changes: 264 additions & 3 deletions Testing/Unit/Rego/AAD/AADConfig_03_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,277 @@ import data.report.utils.NotCheckedDetails
#
# MS.AAD.3.1v1
#--
test_NotImplemented_Correct_V1 if {
test_PhishingResistantAllMFA_Correct if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as { }
Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"windowsHelloForBusiness",
"fido2",
"x509CertificateMultiFactor"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:<br/>Test name. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantSingleMFA_Correct if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"x509CertificateMultiFactor"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:<br/>Test name. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantExtraMFA_Incorrect if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"x509CertificateMultiFactor",
"SuperStrength"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId)
#RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantNoneMFA_Incorrect if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": null
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
#RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantMFAExcludeApp_Incorrect if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : ["Some App"]
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"windowsHelloForBusiness",
"fido2",
"x509CertificateMultiFactor"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantMFAExcludeUser_Incorrect if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : ["me"],
"ExcludeGroups" : [],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"windowsHelloForBusiness",
"fido2",
"x509CertificateMultiFactor"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. <a href='#caps'>View all CA policies</a>."
}

test_PhishingResistantMFAExcludeGroup_Incorrect if {
PolicyId := "MS.AAD.3.1v1"

Output := tests with input as {
"conditional_access_policies" : [
{
"Conditions" : {
"Applications" : {
"IncludeApplications" : ["All"],
"ExcludeApplications" : []
},
"Users" : {
"IncludeUsers" : ["All"],
"ExcludeUsers" : [],
"ExcludeGroups" : ["some"],
"ExcludeRoles" : []
}
},
"GrantControls" : {
"AuthenticationStrength" : {
"AllowedCombinations": [
"windowsHelloForBusiness",
"fido2",
"x509CertificateMultiFactor"
]
}
},
"State" : "enabled",
"DisplayName" : "Test name"
}
]
}

RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId]

count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. <a href='#caps'>View all CA policies</a>."
}
#--

Expand Down