diff --git a/e2e/analysis/test_case.go b/e2e/analysis/test_case.go index 375bdeeb1..eda6877ef 100644 --- a/e2e/analysis/test_case.go +++ b/e2e/analysis/test_case.go @@ -77,10 +77,10 @@ func NewTestCase() []*TestCase { fmt.Sprintf(messages.MsgPrintFinishAnalysisWithStatus, analysis.Success), messages.MsgDebugVulnHashToFix, messages.MsgWarnAnalysisFoundVulns[16:], - "In this analysis, a total of 73 possible vulnerabilities were found and we classified them into:", + "In this analysis, a total of 61 possible vulnerabilities were found and we classified them into:", "Total of Vulnerability CRITICAL is: 22", "Total of Vulnerability HIGH is: 24", - "Total of Vulnerability MEDIUM is: 24", + "Total of Vulnerability MEDIUM is: 12", "Total of Vulnerability LOW is: 3", fmt.Sprintf("{HORUSEC_CLI} Running %s - %s", tools.HorusecEngine, languages.CSharp), fmt.Sprintf("{HORUSEC_CLI} Running %s - %s", tools.HorusecEngine, languages.Dart), diff --git a/internal/services/engines/swift/rules.go b/internal/services/engines/swift/rules.go index 2e7cc9f0f..c2cdf6774 100644 --- a/internal/services/engines/swift/rules.go +++ b/internal/services/engines/swift/rules.go @@ -48,14 +48,13 @@ func NewCoreDataDatabase() *text.Rule { Metadata: engine.Metadata{ ID: "HS-SWIFT-2", Name: "CoreData Database", - Description: "App uses CoreData Database. Sensitive Information should be encrypted.", + Description: "App uses CoreData Database. Sensitive Information should be encrypted. For more information checkout the CWE-311 (https://cwe.mitre.org/data/definitions/311.html) advisory.", Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.AndMatch, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ - regexp.MustCompile(`NSManagedObjectContext`), - regexp.MustCompile(`\.save\(\)`), + regexp.MustCompile(`(?i)(NSManagedObjectContext)(([^C]|C[^r]|Cr[^y]|Cry[^p]|Cryp[^t])*)(\.save\(\))`), }, } } @@ -64,15 +63,14 @@ func NewDTLS12NotUsed() *text.Rule { return &text.Rule{ Metadata: engine.Metadata{ ID: "HS-SWIFT-3", - Name: "DTLS 1.2 not used", - Description: "DTLS 1.2 should be used. Detected old version - DTLS 1.0.", + Name: "DTLS 1.0 or 1.1 not used", + Description: "DTLS 1.2 should be used. Detected old version - DTLS 1.0. For more information checkout the CWE-295 (https://cwe.mitre.org/data/definitions/295.html) advisory.", Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.AndMatch, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ - regexp.MustCompile(`\.TLSMinimumSupportedProtocolVersion`), - regexp.MustCompile(`tls_protocol_version_t\.DTLSv10`), + regexp.MustCompile(`tls_protocol_version_t\.DTLSv[0-1][0-1]`), }, } } @@ -81,15 +79,14 @@ func NewTLS13NotUsed() *text.Rule { return &text.Rule{ Metadata: engine.Metadata{ ID: "HS-SWIFT-4", - Name: "TLS 1.3 not used", - Description: "Older versions of SSL/TLS protocol like \"SSLv3\" have been proven to be insecure. This rule raises an issue when an SSL/TLS context is created with an insecure protocol version (ie: a protocol different from \"TLSv1.2\", \"TLSv1.3\", \"DTLSv1.2\" or \"DTLSv1.3\"). For more information checkout the CWE-326 (https://cwe.mitre.org/data/definitions/326.html) and CWE-327 (https://cwe.mitre.org/data/definitions/327.html) advisory.", + Name: "TLS 1.0 or TLS 1.1 not be used", + Description: "TLS 1.2 should be used. Older versions of SSL/TLS protocol like \"SSLv3\" have been proven to be insecure. This rule raises an issue when an SSL/TLS context is created with an insecure protocol version (ie: a protocol different from \"TLSv1.2\", \"TLSv1.3\", \"DTLSv1.2\" or \"DTLSv1.3\"). For more information checkout the CWE-326 (https://cwe.mitre.org/data/definitions/326.html) and CWE-327 (https://cwe.mitre.org/data/definitions/327.html) advisory.", Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.AndMatch, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ - regexp.MustCompile(`\.TLSMinimumSupportedProtocolVersion`), - regexp.MustCompile(`tls_protocol_version_t\.TLSv12`), + regexp.MustCompile(`tls_protocol_version_t\.TLSv(0|1[0-1])`), }, } } @@ -99,7 +96,7 @@ func NewReverseEngineering() *text.Rule { Metadata: engine.Metadata{ ID: "HS-SWIFT-5", Name: "Reverse engineering", - Description: "This App may have Reverse engineering detection capabilities.", + Description: "This App may have Reverse engineering detection capabilities. For more information checkout the OWASP-M9 (https://owasp.org/www-project-mobile-top-10/2016-risks/m9-reverse-engineering) advisory.", Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, @@ -108,7 +105,6 @@ func NewReverseEngineering() *text.Rule { regexp.MustCompile(`"FridaGadget"`), regexp.MustCompile(`"cynject"`), regexp.MustCompile(`"libcycript"`), - regexp.MustCompile(`"/usr/sbin/frida-server"`), }, } } @@ -226,6 +222,7 @@ func NewSha1Collision() *text.Rule { }, Type: text.OrMatch, Expressions: []*regexp.Regexp{ + regexp.MustCompile(`(?i)\.SHA1\.hash`), regexp.MustCompile(`(?i)SHA1\(`), regexp.MustCompile(`CC_SHA1\(`), }, @@ -305,8 +302,7 @@ func NewLoadHTMLString() *text.Rule { }, Type: text.OrMatch, Expressions: []*regexp.Regexp{ - regexp.MustCompile(`loadHTMLString`), - regexp.MustCompile(`webView`), + regexp.MustCompile(`loadHTMLString\(((.*["|']\+.*\+["|'])|([^"]\w*,?))`), }, } } @@ -337,7 +333,7 @@ func NewRealmDatabase() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`realm\.write`), }, @@ -353,7 +349,7 @@ func NewTLSMinimum() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`\.tlsMinimumSupportedProtocol`), }, @@ -369,7 +365,7 @@ func NewUIPasteboard() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`UIPasteboard`), }, @@ -385,7 +381,7 @@ func NewFileProtection() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`(?i)\.noFileProtection`), }, @@ -401,9 +397,9 @@ func NewWebViewSafari() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ - regexp.MustCompile(`UIWebView|SFSafariViewController`), + regexp.MustCompile(`UIWebView\(\)|SFSafariViewController`), }, } } @@ -417,7 +413,7 @@ func NewKeyboardCache() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`.autocorrectionType = .no`), }, @@ -433,7 +429,7 @@ func NewMD4Collision() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`CC_MD4\(`), }, @@ -449,7 +445,7 @@ func NewMD2Collision() *text.Rule { Severity: severities.Medium.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`CC_MD2\(`), }, @@ -465,7 +461,7 @@ func NewSQLInjection() *text.Rule { Severity: severities.High.ToString(), Confidence: confidence.Low.ToString(), }, - Type: text.Regular, + Type: text.OrMatch, Expressions: []*regexp.Regexp{ regexp.MustCompile(`(?i)((sqlite3_exec|executeChange|raw)\(.?((.*|\n)*)?)(select|update|insert|delete)((.*|\n)*)?.*((["|']*)(\s?)(\+))`), }, diff --git a/internal/services/engines/swift/rules_test.go b/internal/services/engines/swift/rules_test.go index be0ca36de..5463763bf 100644 --- a/internal/services/engines/swift/rules_test.go +++ b/internal/services/engines/swift/rules_test.go @@ -26,18 +26,378 @@ import ( func TestRulesVulnerableCode(t *testing.T) { tmpDir := t.TempDir() testcases := []*testutil.RuleTestCase{ + { + Name: "HS-SWIFT-2", + Rule: NewCoreDataDatabase(), + Src: SampleVulnerableHSSWIFT2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-2.test"), + Findings: []engine.Finding{ + { + CodeSample: `var mainContext: NSManagedObjectContext {`, + SourceLocation: engine.Location{ + Line: 13, + Column: 21, + Filename: filepath.Join(tmpDir, "HS-SWIFT-2.test"), + }, + }, + }, + }, + { + Name: "HS-SWIFT-3", + Rule: NewDTLS12NotUsed(), + Src: SampleVulnerableHSSWIFT3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-3.test"), + Findings: []engine.Finding{ + { + CodeSample: `var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.DTLSv11`, + SourceLocation: engine.Location{ + Line: 3, + Column: 40, + Filename: filepath.Join(tmpDir, "HS-SWIFT-3.test"), + }, + }, + }, + }, + { + Name: "HS-SWIFT-4", + Rule: NewTLS13NotUsed(), + Src: SampleVulnerableHSSWIFT4, + Filename: filepath.Join(tmpDir, "HS-SWIFT-4.test"), + Findings: []engine.Finding{ + { + CodeSample: `var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.TLSv11`, + SourceLocation: engine.Location{ + Line: 3, + Column: 40, + Filename: filepath.Join(tmpDir, "HS-SWIFT-4.test"), + }, + }, + }, + }, + { + Name: "HS-SWIFT-5", + Rule: NewReverseEngineering(), + Src: SampleVulnerableHSSWIFT5, + Filename: filepath.Join(tmpDir, "HS-SWIFT-5.test"), + Findings: []engine.Finding{ + { + CodeSample: `.library(name: "FridaGadget", targets: ["FridaGadget"]),`, + SourceLocation: engine.Location{ + Line: 8, + Column: 25, + Filename: filepath.Join(tmpDir, "HS-SWIFT-5.test"), + }, + }, + }, + }, { Name: "HS-SWIFT-6", Rule: NewWeakMD5CryptoCipher(), Src: SampleVulnerableHSSWIFT6, - Filename: filepath.Join(tmpDir, "HS-SWIFT-6"), + Filename: filepath.Join(tmpDir, "HS-SWIFT-6.test"), Findings: []engine.Finding{ { CodeSample: `import CryptoSwift`, SourceLocation: engine.Location{ - Filename: filepath.Join(tmpDir, "HS-SWIFT-6"), Line: 1, Column: 0, + Filename: filepath.Join(tmpDir, "HS-SWIFT-6.test"), + }, + }, + }, + }, + { + Name: "HS-SWIFT-7", + Rule: NewWeakCommonDesCryptoCipher(), + Src: SampleVulnerableHSSWIFT7, + Filename: filepath.Join(tmpDir, "HS-SWIFT-7.test"), + Findings: []engine.Finding{ + { + CodeSample: `import CommonCrypto`, + SourceLocation: engine.Location{ + Line: 2, + Column: 0, + Filename: filepath.Join(tmpDir, "HS-SWIFT-7.test"), + }, + }, + }, + }, + { + Name: "HS-SWIFT-8", + Rule: NewWeakIDZDesCryptoCipher(), + Src: SampleVulnerableHSSWIFT8, + Filename: filepath.Join(tmpDir, "HS-SWIFT-8.test"), + Findings: []engine.Finding{ + { + CodeSample: `import IDZSwiftCommonCrypto`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-8.test"), + Column: 0, + }, + }, + }, + }, + { + Name: "HS-SWIFT-9", + Rule: NewWeakBlowfishCryptoCipher(), + Src: SampleVulnerableHSSWIFT9, + Filename: filepath.Join(tmpDir, "HS-SWIFT-9.test"), + Findings: []engine.Finding{ + { + CodeSample: `import CryptoSwift`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-9.test"), + Column: 0, + }, + }, + }, + }, + { + Name: "HS-SWIFT-10", + Rule: NewMD6Collision(), + Src: SampleVulnerableHSSWIFT10, + Filename: filepath.Join(tmpDir, "HS-SWIFT-10.test"), + Findings: []engine.Finding{ + { + CodeSample: `MD6( cStr, strlen(cStr), result );`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-10.test"), + Column: 0, + }, + }, + }, + }, + { + Name: "HS-SWIFT-11", + Rule: NewMD5Collision(), + Src: SampleVulnerableHSSWIFT11, + Filename: filepath.Join(tmpDir, "HS-SWIFT-11.test"), + Findings: []engine.Finding{ + { + CodeSample: `MD5( cStr, strlen(cStr), result );`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-11.test"), + Column: 0, + }, + }, + }, + }, + { + Name: "HS-SWIFT-12", + Rule: NewSha1Collision(), + Src: SampleVulnerableHSSWIFT12, + Filename: filepath.Join(tmpDir, "HS-SWIFT-12.test"), + Findings: []engine.Finding{ + { + CodeSample: `let digest = Insecure.SHA1.hash(data: data)`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-12.test"), + Column: 21, + }, + }, + }, + }, + { + Name: "HS-SWIFT-13", + Rule: NewJailbreakDetect(), + Src: SampleVulnerableHSSWIFT13, + Filename: filepath.Join(tmpDir, "HS-SWIFT-13.test"), + Findings: []engine.Finding{ + { + CodeSample: `if(fm.fileExists(atPath: "/private/var/lib/apt")) || (fm.fileExists(atPath: "/Applications/Cydia.app")) {`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-13.test"), + Column: 78, + }, + }, + { + CodeSample: `if(fm.fileExists(atPath: "/private/var/lib/apt")) || (fm.fileExists(atPath: "/Applications/Cydia.app")) {`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-13.test"), + Column: 27, + }, + }, + { + CodeSample: `if(fm.fileExists(atPath: "/private/var/lib/apt")) || (fm.fileExists(atPath: "/Applications/Cydia.app")) {`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-13.test"), + Column: 35, + }, + }, + }, + }, + { + Name: "HS-SWIFT-14", + Rule: NewLoadHTMLString(), + Src: SampleVulnerableHSSWIFT14, + Filename: filepath.Join(tmpDir, "HS-SWIFT-14.test"), + Findings: []engine.Finding{ + { + CodeSample: `webView1.loadHTMLString("

"+content+"

", baseURL: nil)`, + SourceLocation: engine.Location{ + Line: 4, + Filename: filepath.Join(tmpDir, "HS-SWIFT-14.test"), + Column: 10, + }, + }, + }, + }, + { + Name: "HS-SWIFT-15", + Rule: NewWeakDesCryptoCipher(), + Src: SampleVulnerableHSSWIFT15, + Filename: filepath.Join(tmpDir, "HS-SWIFT-15.test"), + Findings: []engine.Finding{ + { + CodeSample: `crypt.CryptAlgorithm = "3des"`, + SourceLocation: engine.Location{ + Line: 5, + Filename: filepath.Join(tmpDir, "HS-SWIFT-15.test"), + Column: 9, + }, + }, + }, + }, + { + Name: "HS-SWIFT-16", + Rule: NewRealmDatabase(), + Src: SampleVulnerableHSSWIFT16, + Filename: filepath.Join(tmpDir, "HS-SWIFT-16.test"), + Findings: []engine.Finding{ + { + CodeSample: `try! realm.write {`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-16.test"), + Column: 5, + }, + }, + }, + }, + { + Name: "HS-SWIFT-17", + Rule: NewTLSMinimum(), + Src: SampleVulnerableHSSWIFT17, + Filename: filepath.Join(tmpDir, "HS-SWIFT-17.test"), + Findings: []engine.Finding{ + { + CodeSample: `config.tlsMinimumSupportedProtocol = .tlsProtocol12`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-17.test"), + Column: 6, + }, + }, + }, + }, + { + Name: "HS-SWIFT-18", + Rule: NewUIPasteboard(), + Src: SampleVulnerableHSSWIFT18, + Filename: filepath.Join(tmpDir, "HS-SWIFT-18.test"), + Findings: []engine.Finding{ + { + CodeSample: `let content = UIPasteboard.general.string`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-18.test"), + Column: 14, + }, + }, + }, + }, + { + Name: "HS-SWIFT-19", + Rule: NewFileProtection(), + Src: SampleVulnerableHSSWIFT19, + Filename: filepath.Join(tmpDir, "HS-SWIFT-19.test"), + Findings: []engine.Finding{ + { + CodeSample: `try data?.write(to: documentURL, options: .noFileProtection)`, + SourceLocation: engine.Location{ + Line: 3, + Filename: filepath.Join(tmpDir, "HS-SWIFT-19.test"), + Column: 50, + }, + }, + }, + }, + { + Name: "HS-SWIFT-20", + Rule: NewWebViewSafari(), + Src: SampleVulnerableHSSWIFT20, + Filename: filepath.Join(tmpDir, "HS-SWIFT-20.test"), + Findings: []engine.Finding{ + { + CodeSample: `let config = SFSafariViewController.Configuration()`, + SourceLocation: engine.Location{ + Line: 4, + Filename: filepath.Join(tmpDir, "HS-SWIFT-20.test"), + Column: 14, + }, + }, + { + CodeSample: `let vc = SFSafariViewController(url: url, configuration: config)`, + SourceLocation: engine.Location{ + Line: 7, + Filename: filepath.Join(tmpDir, "HS-SWIFT-20.test"), + Column: 10, + }, + }, + }, + }, + { + Name: "HS-SWIFT-21", + Rule: NewKeyboardCache(), + Src: SampleVulnerableHSSWIFT21, + Filename: filepath.Join(tmpDir, "HS-SWIFT-21.test"), + Findings: []engine.Finding{ + { + CodeSample: `textField.autocorrectionType = .no`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-21.test"), + Column: 9, + }, + }, + }, + }, + { + Name: "HS-SWIFT-22", + Rule: NewMD4Collision(), + Src: SampleVulnerableHSSWIFT22, + Filename: filepath.Join(tmpDir, "HS-SWIFT-22.test"), + Findings: []engine.Finding{ + { + CodeSample: `CC_MD4( cStr, strlen(cStr), result );`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-22.test"), + Column: 0, + }, + }, + }, + }, + { + Name: "HS-SWIFT-23", + Rule: NewMD2Collision(), + Src: SampleVulnerableHSSWIFT23, + Filename: filepath.Join(tmpDir, "HS-SWIFT-23.test"), + Findings: []engine.Finding{ + { + CodeSample: `CC_MD2( cStr, strlen(cStr), result );`, + SourceLocation: engine.Location{ + Line: 2, + Filename: filepath.Join(tmpDir, "HS-SWIFT-23.test"), + Column: 0, }, }, }, @@ -46,12 +406,12 @@ func TestRulesVulnerableCode(t *testing.T) { Name: "HS-SWIFT-24", Src: SampleVulnerableHSSWIFT24, Rule: NewSQLInjection(), - Filename: filepath.Join(tmpDir, "HS-SWIFT-24"), + Filename: filepath.Join(tmpDir, "HS-SWIFT-24.test"), Findings: []engine.Finding{ { CodeSample: `let err = SD.executeChange("SELECT * FROM User where user="+ valuesFromInput) {`, SourceLocation: engine.Location{ - Filename: filepath.Join(tmpDir, "HS-SWIFT-24"), + Filename: filepath.Join(tmpDir, "HS-SWIFT-24.test"), Line: 2, Column: 13, }, @@ -66,23 +426,149 @@ func TestRulesVulnerableCode(t *testing.T) { func TestRulesSafeCode(t *testing.T) { tmpDir := t.TempDir() testcases := []*testutil.RuleTestCase{ + { + Name: "HS-SWIFT-2", + Rule: NewCoreDataDatabase(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-2.test"), + Src: SampleSafeHSSWIFT2, + }, + { + Name: "HS-SWIFT-3", + Rule: NewDTLS12NotUsed(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-3.test"), + Src: SampleSafeHSSWIFT3, + }, + { + Name: "HS-SWIFT-4", + Rule: NewTLS13NotUsed(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-4.test"), + Src: SampleSafeHSSWIFT4, + }, + { + Name: "HS-SWIFT-5", + Rule: NewReverseEngineering(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-5.test"), + Src: SampleSafeHSSWIFT5, + }, { Name: "HS-SWIFT-6", Rule: NewWeakMD5CryptoCipher(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-6.test"), Src: SampleSafeHSSWIFT6, - Filename: filepath.Join(tmpDir, "HS-SWIFT-6"), + }, + { + Name: "HS-SWIFT-7", + Rule: NewWeakCommonDesCryptoCipher(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-7.test"), + Src: SampleSafeHSSWIFT7, + }, + { + Name: "HS-SWIFT-8", + Rule: NewWeakIDZDesCryptoCipher(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-8.test"), + Src: SampleSafeHSSWIFT8, + }, + { + Name: "HS-SWIFT-9", + Rule: NewWeakBlowfishCryptoCipher(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-9.test"), + Src: SampleSafeHSSWIFT9, + }, + { + Name: "HS-SWIFT-10", + Rule: NewMD6Collision(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-10.test"), + Src: SampleSafeHSSWIFT10, + }, + { + Name: "HS-SWIFT-11", + Rule: NewMD5Collision(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-11.test"), + Src: SampleSafeHSSWIFT11, + }, + { + Name: "HS-SWIFT-12", + Rule: NewSha1Collision(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-12.test"), + Src: SampleSafeHSSWIFT12, + }, + { + Name: "HS-SWIFT-13", + Rule: NewJailbreakDetect(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-13.test"), + Src: SampleSafeHSSWIFT13, + }, + { + Name: "HS-SWIFT-14", + Rule: NewLoadHTMLString(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-14.test"), + Src: SampleSafeHSSWIFT14, + }, + { + Name: "HS-SWIFT-15", + Rule: NewWeakDesCryptoCipher(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-15.test"), + Src: SampleSafeHSSWIFT15, + }, + { + Name: "HS-SWIFT-16", + Rule: NewRealmDatabase(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-16.test"), + Src: SampleSafeHSSWIFT16, + }, + { + Name: "HS-SWIFT-17", + Rule: NewTLSMinimum(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-17.test"), + Src: SampleSafeHSSWIFT17, + }, + { + Name: "HS-SWIFT-18", + Rule: NewUIPasteboard(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-18.test"), + Src: SampleSafeHSSWIFT18, + }, + { + Name: "HS-SWIFT-19", + Rule: NewFileProtection(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-19.test"), + Src: SampleSafeHSSWIFT19, + }, + { + Name: "HS-SWIFT-20", + Rule: NewWebViewSafari(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-20.test"), + Src: SampleSafeHSSWIFT20, + }, + { + Name: "HS-SWIFT-21", + Rule: NewKeyboardCache(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-21.test"), + Src: SampleSafeHSSWIFT21, + }, + { + Name: "HS-SWIFT-22", + Rule: NewMD4Collision(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-22.test"), + Src: SampleSafeHSSWIFT22, + }, + { + Name: "HS-SWIFT-23", + Rule: NewMD2Collision(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-23.test"), + Src: SampleSafeHSSWIFT23, }, { Name: "HS-SWIFT-24", - Rule: NewSQLInjection(), Src: SampleSafeHSSWIFT24, - Filename: filepath.Join(tmpDir, "HS-SWIFT-24"), + Rule: NewSQLInjection(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-24.test"), }, { Name: "HS-SWIFT-24", - Rule: NewSQLInjection(), Src: Sample2SafeHSSWIFT24, - Filename: filepath.Join(tmpDir, "HS-SWIFT-24"), + Rule: NewSQLInjection(), + Filename: filepath.Join(tmpDir, "HS-SWIFT-2.test"), }, } testutil.TestSafeCode(t, testcases) diff --git a/internal/services/engines/swift/samples_test.go b/internal/services/engines/swift/samples_test.go index 64e0717ed..cd1a9a4fd 100644 --- a/internal/services/engines/swift/samples_test.go +++ b/internal/services/engines/swift/samples_test.go @@ -15,9 +15,155 @@ package swift const ( + SampleVulnerableHSSWIFT2 = ` +class CoreDataManager { + static let shared = CoreDataManager() + private init() {} + private lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "PillReminder") + container.loadPersistentStores(completionHandler: { _, error in + _ = error.map { fatalError("Unresolved error \($0)") } + }) + return container + }() + + var mainContext: NSManagedObjectContext { + return persistentContainer.viewContext + } + + func backgroundContext() -> NSManagedObjectContext { + return persistentContainer.newBackgroundContext() + } +} +... +func savePill(pass: String) throws { + let context = CoreDataManager.shared.backgroundContext() + context.perform { + let entity = Pill.entity() + let pill = Pill(entity: entity, insertInto: context) + pill.pass = pass + pill.amount = 2 + pill.dozePerDay = 1 + pill.lastUpdate = Date() + try context.save() + } +} +` + SampleVulnerableHSSWIFT3 = ` +... +var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.DTLSv11 +` + SampleVulnerableHSSWIFT4 = ` +... +var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.TLSv11 +` + SampleVulnerableHSSWIFT5 = `import PackageDescription +let package = Package(name: "Alamofire", + platforms: [.macOS(.v10_12), + .iOS(.v10), + .tvOS(.v10), + .watchOS(.v3)], + products: [.library(name: "Alamofire", targets: ["Alamofire"]), + .library(name: "FridaGadget", targets: ["FridaGadget"]), + .library(name: "cynject", targets: ["cynject"]), + .library(name: "libcycript", targets: ["libcycript"])], + targets: [.target(name: "Alamofire", + path: "Source", + exclude: ["Info.plist"], + linkerSettings: [.linkedFramework("CFNetwork", + .when(platforms: [.iOS, + .macOS, + .tvOS, + .watchOS]))]), + .testTarget(name: "AlamofireTests", + dependencies: ["Alamofire"], + path: "Tests", + exclude: ["Resources", "Info.plist"])], + swiftLanguageVersions: [.v5])` SampleVulnerableHSSWIFT6 = `import CryptoSwift "SwiftSummit".md5() +` + SampleVulnerableHSSWIFT7 = ` +import CommonCrypto + +let algorithm = CCAlgorithm(kCCAlgorithmDES) // Noncompliant: 64 bits block size +` + SampleVulnerableHSSWIFT8 = ` +import IDZSwiftCommonCrypto + +let cryptor = Cryptor(operation: .encrypt, algorithm: .des, options: [.ECBMode, .PKCS7Padding], key: key, iv:[UInt8]()) +` + SampleVulnerableHSSWIFT9 = ` +import CryptoSwift + +Blowfish(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(message) +` + SampleVulnerableHSSWIFT10 = ` +MD6( cStr, strlen(cStr), result ); +` + SampleVulnerableHSSWIFT11 = ` +MD5( cStr, strlen(cStr), result ); +` + SampleVulnerableHSSWIFT12 = ` +let digest = Insecure.SHA1.hash(data: data) +` + SampleVulnerableHSSWIFT13 = ` + let fm = FileManager.default + if(fm.fileExists(atPath: "/private/var/lib/apt")) || (fm.fileExists(atPath: "/Applications/Cydia.app")) { + ... + } +` + SampleVulnerableHSSWIFT14 = ` +func loadPage(content) { + let webView1 = UIWebView() + webView1.loadHTMLString("

"+content+"

", baseURL: nil) +} +` + SampleVulnerableHSSWIFT15 = ` + let crypt = CkoCrypt2() + + // Specify 3DES for the encryption algorithm: + crypt.CryptAlgorithm = "3des" +` + SampleVulnerableHSSWIFT16 = ` +try! realm.write { + ... +} +` + SampleVulnerableHSSWIFT17 = ` +let config = URLSessionConfiguration.default +config.tlsMinimumSupportedProtocol = .tlsProtocol12 +` + SampleVulnerableHSSWIFT18 = ` +// read from clipboard +let content = UIPasteboard.general.string +` + SampleVulnerableHSSWIFT19 = ` + do { + try data?.write(to: documentURL, options: .noFileProtection) + } catch { + print("Error...Cannot save data!!!See error:(error.localizedDescription)") + } +` + SampleVulnerableHSSWIFT20 = ` +import SafariServices +func showTutorial(url: String) { + let config = SFSafariViewController.Configuration() + config.entersReaderIfAvailable = true + + let vc = SFSafariViewController(url: url, configuration: config) + present(vc, animated: true) +} +` + SampleVulnerableHSSWIFT21 = ` +textField.autocorrectionType = .no +` + SampleVulnerableHSSWIFT22 = ` +CC_MD4( cStr, strlen(cStr), result ); +` + SampleVulnerableHSSWIFT23 = ` +CC_MD2( cStr, strlen(cStr), result ); ` SampleVulnerableHSSWIFT24 = ` let err = SD.executeChange("SELECT * FROM User where user="+ valuesFromInput) { @@ -29,6 +175,62 @@ let err = SD.executeChange("SELECT * FROM User where user="+ valuesFromInput) { ) const ( + SampleSafeHSSWIFT2 = ` +class CoreDataManager { + static let shared = CoreDataManager() + private init() {} + private lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "PillReminder") + container.loadPersistentStores(completionHandler: { _, error in + _ = error.map { fatalError("Unresolved error \($0)") } + }) + return container + }() + + var mainContext: NSManagedObjectContext { + return persistentContainer.viewContext + } + + func backgroundContext() -> NSManagedObjectContext { + return persistentContainer.newBackgroundContext() + } +} +... +func savePill(pass: String) throws { + let context = CoreDataManager.shared.backgroundContext() + context.perform { + let entity = Pill.entity() + let pill = Pill(entity: entity, insertInto: context) + pill.password = EncryptedDATAStack(passphraseKey:pass, modelName:"MyAppModel") + pill.amount = 2 + pill.dozePerDay = 1 + pill.lastUpdate = Date() + try context.save() + } +} +` + SampleSafeHSSWIFT3 = `var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.DTLSv12` + SampleSafeHSSWIFT4 = `var tlsMinimumSupportedProtocolVersion: tls_protocol_version_t.TLSv12` + SampleSafeHSSWIFT5 = `import PackageDescription +let package = Package(name: "Alamofire", + platforms: [.macOS(.v10_12), + .iOS(.v10), + .tvOS(.v10), + .watchOS(.v3)], + products: [.library(name: "Alamofire", targets: ["Alamofire"])], + targets: [.target(name: "Alamofire", + path: "Source", + exclude: ["Info.plist"], + linkerSettings: [.linkedFramework("CFNetwork", + .when(platforms: [.iOS, + .macOS, + .tvOS, + .watchOS]))]), + .testTarget(name: "AlamofireTests", + dependencies: ["Alamofire"], + path: "Tests", + exclude: ["Resources", "Info.plist"])], + swiftLanguageVersions: [.v5])` SampleSafeHSSWIFT6 = `import Foundation import var CommonCrypto.CC_MD5_DIGEST_LENGTH import func CommonCrypto.CC_MD5 @@ -53,7 +255,94 @@ func MD5(string: String) -> Data { //Test: let md5Data = MD5(string:"Hello")` + SampleSafeHSSWIFT7 = ` +import Crypto + +let sealedBox = try AES.GCM.seal(input, using: key) // Compliant` + SampleSafeHSSWIFT8 = ` +import Crypto + +let sealedBox = try AES.GCM.seal(input, using: key) // Compliant` + SampleSafeHSSWIFT9 = ` +import Crypto + +let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7) +` + SampleSafeHSSWIFT10 = ` +import Crypto + +let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7)` + SampleSafeHSSWIFT11 = ` +import Crypto + +let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7)` + SampleSafeHSSWIFT12 = ` +func sha256(data : Data) -> Data { + var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) + data.withUnsafeBytes { + _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) + } + return Data(hash) +} +` + SampleSafeHSSWIFT13 = ` +do { + try jailBreakTestText.write(toFile:"/private/jailBreakTestText.txt", atomically:true, encoding:String.Encoding.utf8) + return true +} catch { + return false +} +` + SampleSafeHSSWIFT14 = ` +func loadPage() { + let webView1 = UIWebView() + webView1.loadHTMLString("

Hello!

", baseURL: nil) +} +` + SampleSafeHSSWIFT15 = ` +func sha256(data : Data) -> Data { + var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) + data.withUnsafeBytes { + _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) + } + return Data(hash) +} +` + SampleSafeHSSWIFT16 = ` +realm.beginWrite() +... +try! realm.commitWrite() +` + SampleSafeHSSWIFT17 = ` +let config = URLSessionConfiguration.default +` + SampleSafeHSSWIFT18 = ` +let content = "Static content" +` + SampleSafeHSSWIFT19 = ` + do { + try data?.write(to: documentURL, options: null) + } catch { + print("Error...Cannot save data!!!See error:(error.localizedDescription)") + } +` + SampleSafeHSSWIFT20 = ` +func showTutorial(url: String) { + let vc = UIApplication.shared.openURL(url) + present(vc, animated: true) +} +` + SampleSafeHSSWIFT21 = ` +textField.autocorrectionType = .yes +` + SampleSafeHSSWIFT22 = ` +import Crypto + +let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7)` + SampleSafeHSSWIFT23 = ` +import Crypto +let encryptedBytes = try AES(key: [1,2,3,...,32], blockMode: CBC(iv: [1,2,3,...,16]), padding: .pkcs7)` SampleSafeHSSWIFT24 = ` if let err = SD.executeChange("SELECT * FROM User where user=?", withArgs: [name, population, isWarm, foundedIn]) { //there was an error during the insert, handle it here