diff --git a/Framework/Configurations/SVT/AAD/AAD.Tenant.json b/Framework/Configurations/SVT/AAD/AAD.Tenant.json index e54f1ab..570f5a9 100644 --- a/Framework/Configurations/SVT/AAD/AAD.Tenant.json +++ b/Framework/Configurations/SVT/AAD/AAD.Tenant.json @@ -365,6 +365,23 @@ "Privacy" ], "Enabled": false + }, + { + "ControlID": "EntraID_Tenant_CAP_AuthN_Setup_Policies", + "Description": "Ensure that Conditional Access Policies are setup for tenant", + "Id": "Tenant280", + "ControlSeverity": "High", + "Automated": "Yes", + "MethodName": "CheckCAPAuthNPolicySetup", + "Rationale": "CAP allows to prevent malicious attacks on tenants by reducing conditions that compromise user accounts and prevent further compromise by taking approprate actions ", + "Recommendation": "1. Go to entra admin center --> 2. Navigate to conditonal access under Protection --> 3. Under policies, create all policies (i) Block all legacy sign ins (Users - all, Target Resources - All cloud apps, Conditions - Client Apps - Legacy auth clients, Block Access) (ii) Require MFA and a password change when high-risk users are detected (Users - all, Target Resources - All cloud apps, Conditions - User risk - high, Grant Access - Require MFA and Require password change) (iii) Require MFA for all users (Users - all, Target Resources - All cloud apps,, Grant Access - Require MFA or Require MFA/Passwordless authentication strength) (iv) Require MFA when risky sign ins are detected (Users - all, Target Resources - All cloud apps, Conditions - sign in risk - high, medium, Grant Access - Require MFA or Require MFA/Passwordless authentication strength) or enable security defaults", + "Tags": [ + "SDL", + "TCP", + "Automated", + "Privacy" + ], + "Enabled": true } ] } \ No newline at end of file diff --git a/Framework/Configurations/SVT/AAD/AAD.User.json b/Framework/Configurations/SVT/AAD/AAD.User.json index 9362024..5269ca4 100644 --- a/Framework/Configurations/SVT/AAD/AAD.User.json +++ b/Framework/Configurations/SVT/AAD/AAD.User.json @@ -53,6 +53,40 @@ "AuthN" ], "Enabled": false + }, + { + "ControlID": "EntraID_User_AuthZ_Disable_Guest_Self_Service_Signup_Flow", + "Description": "Do not enable guest self-service sign up via user flows", + "Id": "User140", + "ControlSeverity": "High", + "Automated": "Yes", + "MethodName": "CheckGuestSelfServiceSignupFlow", + "Rationale": "Enabling guest self service signup flow, would mean any application could use flows to create guest accounts in the owning tenant.", + "Recommendation": "1. Navigate to 'Users' in Entra admin center --> 2. Select 'User Settings', navigate to 'External users' section and select 'Manage external collaboration settings' --> 3. Navigate to 'Guest Invite settings' to find 'Enable guest self-service sign up via user flows' and set it to 'No'", + "Tags": [ + "SDL", + "TCP", + "Automated", + "AuthN" + ], + "Enabled": true + }, + { + "ControlID": "EntraID_User_AuthZ_Limit_Invite_Permissions_To_Admins", + "Description": "Limit guest invite permissions to admins", + "Id": "User150", + "ControlSeverity": "High", + "Automated": "Yes", + "MethodName": "CheckGuestInviteSettings", + "Rationale": "Inviting guests is mainly used for business collaboration and should generally be done either by the global admin or by a user assigned with appropriate role, otherwise malicious actors can invite any number of guests to potentially bloat the directory.", + "Recommendation": "1. Navigate to 'Users' in Entra admin center --> 2. Select 'User Settings', navigate to 'External users' section and select 'Manage external collaboration settings' --> 3. Navigate to 'Guest Invite settings' to find 'Guest Invite restrictions' --> 4. Configure the restrictions such that its set to one of the below mentioned values: i) Member users and users assigned to specific admin roles can invite guest users including guests with member permissions ii) Only users assigned to specific admin roles can invite guest users iii) No one in the organization can invite guest users including admins (most restrictive)", + "Tags": [ + "SDL", + "TCP", + "Automated", + "AuthN" + ], + "Enabled": true } ] } \ No newline at end of file diff --git a/Framework/Core/SVT/AAD/AAD.Tenant.ps1 b/Framework/Core/SVT/AAD/AAD.Tenant.ps1 index 6a6167a..3541eb5 100644 --- a/Framework/Core/SVT/AAD/AAD.Tenant.ps1 +++ b/Framework/Core/SVT/AAD/AAD.Tenant.ps1 @@ -692,4 +692,89 @@ class Tenant: SVTBase } return $controlResult; } + + hidden [ControlResult] CheckCAPAuthNPolicySetup([ControlResult] $controlResult) + { + # Connect-MgGraph -Scopes "Policy.Read.All" + #(This need the admin access of the tenant and it is necessary to run this command before running the below commands to check that security default is enabled or not) + + #It is used to find that Security default is Enabled or not + $SecurityDefault=Get-MgBetaPolicyIdentitySecurityDefaultEnforcementPolicy| Select-Object IsEnabled + + if($SecurityDefault.IsEnabled -eq $true){ + #If the Security Default is enabled then it will return the passed message + $controlResult.AddMessage([VerificationResult]::Passed, + [MessageData]::new("Security Default is enabled.")); + return $controlResult; + } + + #It is used to get all the CAP Policies + $policy=Get-MgBetaIdentityConditionalAccessPolicy + + #It is used to store the Conditional Access Policies + $BlockLegacyAuth=$null + $MFAforAllUsers=$null + $PasswordChangeForHishRiskUser=$null + $MFAforRiskySignIns=$null + + #Checks if any Conditional Access Policy is added + foreach($obj in $policy){ + #Checks if Block legacy authentication policy is added + if($obj.DisplayName -eq "Block legacy authentication"){ + $BlockLegacyAuth=$obj + } + #Checks if Require multifactor authentication for all users policy is added + elseif($obj.DisplayName -eq "Require multifactor authentication for all users"){ + $MFAforAllUsers=$obj + } + #Checks if Require password change for high-risk users policy is added + elseif($obj.DisplayName -eq "Require password change for high-risk users"){ + $PasswordChangeForHishRiskUser=$obj + } + #Checks if Require multifactor authentication for risky sign-ins policy is added + elseif($obj.DisplayName -eq "Require multifactor authentication for risky sign-ins"){ + $MFAforRiskySignIns=$obj + } + } + + #Checks if any of the policy is not added + if($BlockLegacyAuth -eq $null -or $MFAforAllUsers -eq $null-or $PasswordChangeForHishRiskUser-eq $null -or $MFAforRiskySignIns -eq $null){ + $controlResult.AddMessage([VerificationResult]::Failed, + [MessageData]::new("Conditional Access Policy is not configured.")); + } + else { + #checks if Block Legacy Authentication policy is enabled and configured correctly + if ($BlockLegacyAuth.State -eq "enabled" -and $BlockLegacyAuth.Conditions.Users.IncludeUsers -contains "All" -and $BlockLegacyAuth.Conditions.Applications.IncludeApplications -contains "All" -and $BlockLegacyAuth.GrantControls.BuiltInControls -contains "block") { + # checks if Require multifactor authentication for all users policy is enabled and configured correctly + if ($MFAforAllUsers.State -eq "enabled" -and $MFAforAllUsers.Conditions.Users.IncludeUsers -contains "All" -and $MFAforAllUsers.Conditions.Applications.IncludeApplications -contains "All" -and $MFAforAllUsers.GrantControls.BuiltInControls -contains "mfa") { + # checks if Require password change for high-risk users policy is enabled and configured correctly + if ($PasswordChangeForHishRiskUser.State -eq "enabled" -and $PasswordChangeForHishRiskUser.Conditions.Users.IncludeUsers -contains "All" -and $PasswordChangeForHishRiskUser.Conditions.Applications.IncludeApplications -contains "All" -and $PasswordChangeForHishRiskUser.Conditions.UserRiskLevels -contains "high" -and $PasswordChangeForHishRiskUser.GrantControls.BuiltInControls -contains "mfa" -and $PasswordChangeForHishRiskUser.GrantControls.BuiltInControls -contains "passwordChange") { + #Checks if Require multifactor authentication for risky sign-ins policy is enabled and configured correctly + if ($MFAforRiskySignIns.State -eq "enabled" -and $MFAforRiskySignIns.Conditions.Users.IncludeUsers -contains "All" -and $MFAforRiskySignIns.Conditions.Applications.IncludeApplications -contains "All" -and $MFAforRiskySignIns.Conditions.SignInRiskLevels -contains "medium" -and $MFAforRiskySignIns.Conditions.SignInRiskLevels -contains "high" -and $MFAforRiskySignIns.GrantControls.BuiltInControls -contains "mfa" ) { + $controlResult.AddMessage([VerificationResult]::Passed, + [MessageData]::new("Conditional Access Policy is configured correctly.")); + } + else { + $controlResult.AddMessage([VerificationResult]::Failed, + [MessageData]::new("Conditional Access Policy is not configured.")); + } + } + else { + $controlResult.AddMessage([VerificationResult]::Failed, + [MessageData]::new("Conditional Access Policy is not configured.")); + } + } + else { + $controlResult.AddMessage([VerificationResult]::Failed, + [MessageData]::new("Conditional Access Policy is not configured.")); + } + } + else { + $controlResult.AddMessage([VerificationResult]::Failed, + [MessageData]::new("Conditional Access Policy is not configured.")); + } + } + return $controlResult; + } + }#class \ No newline at end of file diff --git a/Framework/Core/SVT/AAD/AAD.User.ps1 b/Framework/Core/SVT/AAD/AAD.User.ps1 index b40c853..1f94d86 100644 --- a/Framework/Core/SVT/AAD/AAD.User.ps1 +++ b/Framework/Core/SVT/AAD/AAD.User.ps1 @@ -72,4 +72,45 @@ class User: SVTBase return $controlResult; } -} \ No newline at end of file + + hidden [ControlResult] CheckGuestSelfServiceSignupFlow([ControlResult] $controlResult) + { + # Connect-MgGraph -Scopes "Policy.Read.All" + # (This need the admin access of the tenant and it is necessary to run this command before running the below commands) + + #Get the self-service sign up policy + $property=Get-MgBetaPolicyAuthenticationFlowPolicy | Select-Object selfServiceSignUp + #Check if self-service sign up is enabled + if($property.SelfServiceSignUp.IsEnabled -eq $true) + { + $controlResult.AddMessage([VerificationResult]::Failed, + "Guest self-service sign up via user flows is enabled. Please review!"); + } + #If self-service sign up is disabled + else + { + $controlResult.AddMessage([VerificationResult]::Passed, + "Guest self-service sign up via user flows is disabled."); + } + return $controlResult; + } + + hidden [ControlResult] CheckGuestInviteSettings([ControlResult] $controlResult) + { + # Check if anyone in the organization is allowed to invite guests + $inviteRestrictions=Get-MgBetaPolicyAuthorizationPolicy | Select-Object allowInvitesFrom + #If everyone is allowed to invite guests + if($inviteRestrictions.AllowInvitesFrom -eq "everyone") + { + $controlResult.AddMessage([VerificationResult]::Failed, + "Anyone in the organization is allowed to invite guests. Please review!"); + } + #If only specific people are allowed to invite guests + else + { + $controlResult.AddMessage([VerificationResult]::Passed, + "Only specific people are allowed to invite guests."); + } + return $controlResult; + } +}