diff --git a/pkg/security/risks/builtin/container_platform_escape_rule_test.go b/pkg/security/risks/builtin/container_platform_escape_rule_test.go index 378495b9..bd203f7c 100644 --- a/pkg/security/risks/builtin/container_platform_escape_rule_test.go +++ b/pkg/security/risks/builtin/container_platform_escape_rule_test.go @@ -7,8 +7,8 @@ import ( "github.com/threagile/threagile/pkg/security/types" ) -func TestContainerPlatformEscapeRuleGenerateRisksEmptyModelNotRisksCreated(t *testing.T) { - rule := NewContainerPlatformEscapeRule() +func TestCrossSiteRequestForgeryRuleGenerateRisksEmptyModelNotRisksCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() risks, err := rule.GenerateRisks(&types.Model{}) @@ -16,8 +16,8 @@ func TestContainerPlatformEscapeRuleGenerateRisksEmptyModelNotRisksCreated(t *te assert.Empty(t, risks) } -func TestContainerPlatformEscapeRuleGenerateRisksOutOfScopeNotRisksCreated(t *testing.T) { - rule := NewContainerPlatformEscapeRule() +func TestCrossSiteRequestForgeryRuleGenerateRisksOutOfScopeNotRisksCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() risks, err := rule.GenerateRisks(&types.Model{ TechnicalAssets: map[string]*types.TechnicalAsset{ @@ -31,8 +31,8 @@ func TestContainerPlatformEscapeRuleGenerateRisksOutOfScopeNotRisksCreated(t *te assert.Empty(t, risks) } -func TestContainerPlatformEscapeRuleRuleGenerateRisksTechAssetNotContainerPlatformNotRisksCreated(t *testing.T) { - rule := NewContainerPlatformEscapeRule() +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetNotWebApplicationNotRisksCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() risks, err := rule.GenerateRisks(&types.Model{ TechnicalAssets: map[string]*types.TechnicalAsset{ @@ -41,7 +41,7 @@ func TestContainerPlatformEscapeRuleRuleGenerateRisksTechAssetNotContainerPlatfo { Name: "tool", Attributes: map[string]bool{ - types.ContainerPlatform: false, + types.WebApplication: false, }, }, }, @@ -53,66 +53,208 @@ func TestContainerPlatformEscapeRuleRuleGenerateRisksTechAssetNotContainerPlatfo assert.Empty(t, risks) } -func TestContainerPlatformEscapeRuleGenerateRisksTechAssetContainerPlatformRisksCreated(t *testing.T) { - rule := NewContainerPlatformEscapeRule() +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetWebApplicationWithoutIncomingCommunicationNotRisksCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() risks, err := rule.GenerateRisks(&types.Model{ TechnicalAssets: map[string]*types.TechnicalAsset{ "ta1": { - Id: "ta1", - Title: "Docker", + Technologies: types.TechnologyList{ + { + Name: "web-app", + Attributes: map[string]bool{ + types.WebApplication: true, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetWebApplicationIncomingRequestNotWebAccessProtocolNotRiskCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "web-app": { + Id: "web-app", + Technologies: types.TechnologyList{ + { + Name: "web-app", + Attributes: map[string]bool{ + types.WebApplication: true, + }, + }, + }, + }, + "file-scrapper": { Technologies: types.TechnologyList{ { Name: "tool", + }, + }, + }, + }, + IncomingTechnicalCommunicationLinksMappedByTargetId: map[string][]*types.CommunicationLink{ + "web-app": { + { + Protocol: types.LocalFileAccess, + SourceId: "file-scrapper", + TargetId: "web-app", + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetWebApplicationIncomingRequestWebAccessProtocolRiskCreated(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "web-app": { + Id: "web-app", + Title: "Web Application", + Technologies: types.TechnologyList{ + { + Name: "web-app", + Attributes: map[string]bool{ + types.WebApplication: true, + }, + }, + }, + }, + "user": { + Title: "user", + Technologies: types.TechnologyList{ + { + Name: "user", + }, + }, + }, + }, + IncomingTechnicalCommunicationLinksMappedByTargetId: map[string][]*types.CommunicationLink{ + "web-app": { + { + Title: "HTTP", + Protocol: types.HTTP, + SourceId: "user", + TargetId: "web-app", + }, + }, + }, + }) + + assert.Nil(t, err) + assert.NotEmpty(t, risks) + assert.Equal(t, "Cross-Site Request Forgery (CSRF) risk at Web Application via HTTP from user", risks[0].Title) + assert.Equal(t, types.VeryLikely, risks[0].ExploitationLikelihood) + assert.Equal(t, types.LowImpact, risks[0].ExploitationImpact) +} + +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetWebApplicationIncomingRequestWebAccessProtocolViaDevOpsRiskCreatedWithLikelyLikelihood(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "web-app": { + Id: "web-app", + Title: "Web Application", + Technologies: types.TechnologyList{ + { + Name: "web-app", Attributes: map[string]bool{ - types.ContainerPlatform: true, + types.WebApplication: true, }, }, }, - Machine: types.Container, + }, + "ci/cd": { + Title: "ci/cd", + Technologies: types.TechnologyList{ + { + Name: "ci/cd", + }, + }, + }, + }, + IncomingTechnicalCommunicationLinksMappedByTargetId: map[string][]*types.CommunicationLink{ + "web-app": { + { + Title: "HTTP", + Protocol: types.HTTP, + SourceId: "ci/cd", + TargetId: "web-app", + Usage: types.DevOps, + }, }, }, }) assert.Nil(t, err) assert.NotEmpty(t, risks) - assert.Equal(t, "Container Platform Escape risk at Docker", risks[0].Title) - assert.Equal(t, types.MediumImpact, risks[0].ExploitationImpact) - assert.NotEmpty(t, risks[0].DataBreachTechnicalAssetIDs) - assert.Equal(t, "ta1", risks[0].DataBreachTechnicalAssetIDs[0]) + assert.Equal(t, "Cross-Site Request Forgery (CSRF) risk at Web Application via HTTP from ci/cd", risks[0].Title) + assert.Equal(t, types.Likely, risks[0].ExploitationLikelihood) + assert.Equal(t, types.LowImpact, risks[0].ExploitationImpact) } -func TestContainerPlatformEscapeRuleGenerateRisksTechAssetProcessStrictlyConfidentialDataAssetHighImpactRiskCreated(t *testing.T) { - rule := NewContainerPlatformEscapeRule() +func TestCrossSiteRequestForgeryRuleGenerateRisksTechAssetWebApplicationIncomingRequestWebAccessProtocolRiskCreatedWithMediumImpactWhenIntegrityIsMissionCritical(t *testing.T) { + rule := NewCrossSiteRequestForgeryRule() risks, err := rule.GenerateRisks(&types.Model{ TechnicalAssets: map[string]*types.TechnicalAsset{ - "ta1": { - Id: "ta1", - Title: "Docker", + "web-app": { + Id: "web-app", + Title: "Web Application", Technologies: types.TechnologyList{ { - Name: "tool", + Name: "web-app", Attributes: map[string]bool{ - types.ContainerPlatform: true, + types.WebApplication: true, }, }, }, - Machine: types.Container, - DataAssetsProcessed: []string{"strictly-confidential-data-asset"}, + }, + "user": { + Title: "user", + Technologies: types.TechnologyList{ + { + Name: "user", + }, + }, }, }, DataAssets: map[string]*types.DataAsset{ - "strictly-confidential-data-asset": { - Confidentiality: types.StrictlyConfidential, + "mission-critical-data": { + Id: "mission-critical-data", + Title: "Mission Critical Data", + Integrity: types.MissionCritical, + }, + }, + + IncomingTechnicalCommunicationLinksMappedByTargetId: map[string][]*types.CommunicationLink{ + "web-app": { + { + Title: "HTTP", + Protocol: types.HTTP, + SourceId: "user", + TargetId: "web-app", + DataAssetsReceived: []string{"mission-critical-data"}, + }, }, }, }) assert.Nil(t, err) assert.NotEmpty(t, risks) - assert.Equal(t, "Container Platform Escape risk at Docker", risks[0].Title) - assert.Equal(t, types.HighImpact, risks[0].ExploitationImpact) - assert.NotEmpty(t, risks[0].DataBreachTechnicalAssetIDs) - assert.Equal(t, "ta1", risks[0].DataBreachTechnicalAssetIDs[0]) + assert.Equal(t, "Cross-Site Request Forgery (CSRF) risk at Web Application via HTTP from user", risks[0].Title) + assert.Equal(t, types.VeryLikely, risks[0].ExploitationLikelihood) + assert.Equal(t, types.MediumImpact, risks[0].ExploitationImpact) } diff --git a/pkg/security/risks/builtin/cross_site_request_forgery_rule_test.go b/pkg/security/risks/builtin/cross_site_request_forgery_rule_test.go new file mode 100644 index 00000000..378495b9 --- /dev/null +++ b/pkg/security/risks/builtin/cross_site_request_forgery_rule_test.go @@ -0,0 +1,118 @@ +package builtin + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/threagile/threagile/pkg/security/types" +) + +func TestContainerPlatformEscapeRuleGenerateRisksEmptyModelNotRisksCreated(t *testing.T) { + rule := NewContainerPlatformEscapeRule() + + risks, err := rule.GenerateRisks(&types.Model{}) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestContainerPlatformEscapeRuleGenerateRisksOutOfScopeNotRisksCreated(t *testing.T) { + rule := NewContainerPlatformEscapeRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + OutOfScope: true, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestContainerPlatformEscapeRuleRuleGenerateRisksTechAssetNotContainerPlatformNotRisksCreated(t *testing.T) { + rule := NewContainerPlatformEscapeRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Technologies: types.TechnologyList{ + { + Name: "tool", + Attributes: map[string]bool{ + types.ContainerPlatform: false, + }, + }, + }, + }, + }, + }) + + assert.Nil(t, err) + assert.Empty(t, risks) +} + +func TestContainerPlatformEscapeRuleGenerateRisksTechAssetContainerPlatformRisksCreated(t *testing.T) { + rule := NewContainerPlatformEscapeRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Docker", + Technologies: types.TechnologyList{ + { + Name: "tool", + Attributes: map[string]bool{ + types.ContainerPlatform: true, + }, + }, + }, + Machine: types.Container, + }, + }, + }) + + assert.Nil(t, err) + assert.NotEmpty(t, risks) + assert.Equal(t, "Container Platform Escape risk at Docker", risks[0].Title) + assert.Equal(t, types.MediumImpact, risks[0].ExploitationImpact) + assert.NotEmpty(t, risks[0].DataBreachTechnicalAssetIDs) + assert.Equal(t, "ta1", risks[0].DataBreachTechnicalAssetIDs[0]) +} + +func TestContainerPlatformEscapeRuleGenerateRisksTechAssetProcessStrictlyConfidentialDataAssetHighImpactRiskCreated(t *testing.T) { + rule := NewContainerPlatformEscapeRule() + + risks, err := rule.GenerateRisks(&types.Model{ + TechnicalAssets: map[string]*types.TechnicalAsset{ + "ta1": { + Id: "ta1", + Title: "Docker", + Technologies: types.TechnologyList{ + { + Name: "tool", + Attributes: map[string]bool{ + types.ContainerPlatform: true, + }, + }, + }, + Machine: types.Container, + DataAssetsProcessed: []string{"strictly-confidential-data-asset"}, + }, + }, + DataAssets: map[string]*types.DataAsset{ + "strictly-confidential-data-asset": { + Confidentiality: types.StrictlyConfidential, + }, + }, + }) + + assert.Nil(t, err) + assert.NotEmpty(t, risks) + assert.Equal(t, "Container Platform Escape risk at Docker", risks[0].Title) + assert.Equal(t, types.HighImpact, risks[0].ExploitationImpact) + assert.NotEmpty(t, risks[0].DataBreachTechnicalAssetIDs) + assert.Equal(t, "ta1", risks[0].DataBreachTechnicalAssetIDs[0]) +}