Skip to content

Commit

Permalink
Cover sql no sql injection rule with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Yevhen Zavhorodnii committed Jun 3, 2024
1 parent 18acc52 commit c7e3a83
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 2 deletions.
7 changes: 5 additions & 2 deletions pkg/security/risks/builtin/sql_nosql_injection_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ func (r *SqlNoSqlInjectionRule) GenerateRisks(input *types.Model) ([]*types.Risk
if input.TechnicalAssets[incomingFlow.SourceId].OutOfScope {
continue
}
if incomingFlow.Protocol.IsPotentialDatabaseAccessProtocol(true) && technicalAsset.Technologies.GetAttribute(types.IsVulnerableToQueryInjection) ||
incomingFlow.Protocol.IsPotentialDatabaseAccessProtocol(false) {
potentialDatabaseAccessProtocol := incomingFlow.Protocol.IsPotentialDatabaseAccessProtocol(true)
isVulnerableToQueryInjection := technicalAsset.Technologies.GetAttribute(types.IsVulnerableToQueryInjection)
potentialLaxDatabaseAccessProtocol := incomingFlow.Protocol.IsPotentialDatabaseAccessProtocol(false)
if potentialDatabaseAccessProtocol && isVulnerableToQueryInjection ||
potentialLaxDatabaseAccessProtocol {
risks = append(risks, r.createRisk(input, technicalAsset, incomingFlow))
}
}
Expand Down
155 changes: 155 additions & 0 deletions pkg/security/risks/builtin/sql_nosql_injection_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package builtin

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/threagile/threagile/pkg/security/types"
)

func TestSqlNoSqlInjectionRuleGenerateRisksEmptyModelNotRisksCreated(t *testing.T) {
rule := NewSqlNoSqlInjectionRule()

risks, err := rule.GenerateRisks(&types.Model{})

assert.Nil(t, err)
assert.Empty(t, risks)
}

func TestSqlNoSqlInjectionRuleGenerateRisksOutOfScopeNoRisksCreated(t *testing.T) {
rule := NewSqlNoSqlInjectionRule()
risks, err := rule.GenerateRisks(&types.Model{
TechnicalAssets: map[string]*types.TechnicalAsset{
"ta1": {
Title: "Test Technical Asset",
OutOfScope: true,
Technologies: types.TechnologyList{
{
Name: "service-registry",
Attributes: map[string]bool{
types.ServiceRegistry: true,
},
},
},
},
},
})

assert.Nil(t, err)
assert.Empty(t, risks)
}

type SqlNoSqlInjectionRuleTest struct {
confidentiality types.Confidentiality
integrity types.Criticality
usage types.Usage

protocol types.Protocol
isVulnerableToQueryInjection bool

expectRiskCreated bool
expectedLikelihood types.RiskExploitationLikelihood
expectedImpact types.RiskExploitationImpact
}

func TestSqlNoSqlInjectionRuleCreateRisks(t *testing.T) {
testCases := map[string]SqlNoSqlInjectionRuleTest{
"not database protocol": {
protocol: types.SmbEncrypted,
expectRiskCreated: false,
isVulnerableToQueryInjection: true,
},
// TODO: understand
// "not vulnerable to query injection": {
// protocol: types.JdbcEncrypted,
// expectRiskCreated: false,
// isVulnerableToQueryInjection: false,
// },
"database protocol and vulnerable to query injection": {
protocol: types.JdbcEncrypted,
expectRiskCreated: true,
isVulnerableToQueryInjection: true,
expectedLikelihood: types.VeryLikely,
expectedImpact: types.MediumImpact,
},
"strictly confidential tech asset high impact": {
protocol: types.JdbcEncrypted,
expectRiskCreated: true,
isVulnerableToQueryInjection: true,
confidentiality: types.StrictlyConfidential,
integrity: types.Critical,
expectedLikelihood: types.VeryLikely,
expectedImpact: types.HighImpact,
},
"mission critical integrity tech asset high impact": {
protocol: types.JdbcEncrypted,
expectRiskCreated: true,
isVulnerableToQueryInjection: true,
confidentiality: types.Confidential,
integrity: types.MissionCritical,
expectedLikelihood: types.VeryLikely,
expectedImpact: types.HighImpact,
},
"devops usage likely likelihood": {
protocol: types.JdbcEncrypted,
expectRiskCreated: true,
isVulnerableToQueryInjection: true,
usage: types.DevOps,
confidentiality: types.Confidential,
integrity: types.Critical,
expectedLikelihood: types.Likely,
expectedImpact: types.MediumImpact,
},
}

for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
rule := NewSqlNoSqlInjectionRule()
risks, err := rule.GenerateRisks(&types.Model{
TechnicalAssets: map[string]*types.TechnicalAsset{
"ta1": {
Id: "ta1",
Title: "Test Technical Asset",
OutOfScope: false,
Technologies: types.TechnologyList{
{
Name: "service-registry",
Attributes: map[string]bool{
types.IsVulnerableToQueryInjection: testCase.isVulnerableToQueryInjection,
},
},
},
Confidentiality: testCase.confidentiality,
Integrity: testCase.integrity,
},
"ta2": {
Id: "ta2",
Title: "Caller Technical Asset",
OutOfScope: false,
},
},
IncomingTechnicalCommunicationLinksMappedByTargetId: map[string][]*types.CommunicationLink{
"ta1": {
{
Title: "Incoming Flow",
TargetId: "ta1",
SourceId: "ta2",
Protocol: testCase.protocol,
Usage: testCase.usage,
},
},
},
})

assert.Nil(t, err)
if testCase.expectRiskCreated {
assert.Len(t, risks, 1)
assert.Equal(t, testCase.expectedImpact, risks[0].ExploitationImpact)
assert.Equal(t, testCase.expectedLikelihood, risks[0].ExploitationLikelihood)
assert.Equal(t, "<b>SQL/NoSQL-Injection</b> risk at <b>Caller Technical Asset</b> against database <b>Test Technical Asset</b> via <b>Incoming Flow</b>", risks[0].Title)
} else {
assert.Empty(t, risks)
}
})
}
}

0 comments on commit c7e3a83

Please sign in to comment.