From c4184ce3148131b61d3fc51f7a816e3cf9e88540 Mon Sep 17 00:00:00 2001 From: Matteo Mara Date: Thu, 29 Sep 2022 15:44:17 +0200 Subject: [PATCH] SONAR-17399 add mapping between requirements and levels for owasp asvs 40 --- .../server/security/SecurityStandards.java | 50 ++++++++++++++++++- .../security/SecurityStandardsTest.java | 28 +++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java index b06a72461a4..171991db872 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java @@ -23,6 +23,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Ordering; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -30,6 +32,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion; @@ -77,11 +80,11 @@ public final class SecurityStandards { // https://cwe.mitre.org/top25/archive/2019/2019_cwe_top25.html public static final List CWE_TOP25_2019 = List.of("119", "79", "20", "200", "125", "89", "416", "190", "352", "22", "78", "787", "287", "476", - "732", "434", "611", "94", "798", "400", "772", "426", "502", "269", "295"); + "732", "434", "611", "94", "798", "400", "772", "426", "502", "269", "295"); // https://cwe.mitre.org/top25/archive/2020/2020_cwe_top25.html public static final List CWE_TOP25_2020 = List.of("79", "787", "20", "125", "119", "89", "200", "416", "352", "78", "190", "22", "476", "287", - "434", "732", "94", "522", "611", "798", "502", "269", "400", "306", "862"); + "434", "732", "94", "522", "611", "798", "502", "269", "400", "306", "862"); // https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html public static final List CWE_TOP25_2021 = List.of("787", "79", "125", "20", "78", "89", "416", "22", "352", "434", "306", "190", "502", "287", "476", @@ -92,6 +95,40 @@ public final class SecurityStandards { "2020", CWE_TOP25_2020, "2021", CWE_TOP25_2021); + public static final List OWASP_ASVS_40_LEVEL_1 = List.of("2.1.1", "2.1.10", "2.1.11", "2.1.12", "2.1.2", "2.1.3", "2.1.4", "2.1.5", "2.1.6", "2.1.7", "2.1.8", "2.1.9", + "2.10.1", "2.10.2", "2.10.3", "2.10.4", "2.2.1", "2.2.2", "2.2.3", "2.3.1", "2.5.1", "2.5.2", "2.5.3", "2.5.4", "2.5.5", "2.5.6", "2.7.1", "2.7.2", "2.7.3", "2.7.4", "2.8.1", + "3.1.1", "3.2.1", "3.2.2", "3.2.3", "3.3.1", "3.3.2", "3.4.1", "3.4.2", "3.4.3", "3.4.4", "3.4.5", "3.7.1", "4.1.1", "4.1.2", "4.1.3", "4.1.4", "4.1.5", "4.2.1", "4.2.2", + "4.3.1", "4.3.2", "5.1.1", "5.1.2", "5.1.3", "5.1.4", "5.1.5", "5.2.1", "5.2.2", "5.2.3", "5.2.4", "5.2.5", "5.2.6", "5.2.7", "5.2.8", "5.3.1", "5.3.10", "5.3.2", "5.3.3", + "5.3.4", "5.3.5", "5.3.6", "5.3.7", "5.3.8", "5.3.9", "5.5.1", "5.5.2", "5.5.3", "5.5.4", "6.2.1", "7.1.1", "7.1.2", "7.4.1", "8.2.1", "8.2.2", "8.2.3", "8.3.1", "8.3.2", + "8.3.3", "8.3.4", "9.1.1", "9.1.2", "9.1.3", "10.3.1", "10.3.2", "10.3.3", "11.1.1", "11.1.2", "11.1.3", "11.1.4", "11.1.5", "12.1.1", "12.3.1", "12.3.2", "12.3.3", "12.3.4", + "12.3.5", "12.4.1", "12.4.2", "12.5.1", "12.5.2", "12.6.1", "13.1.1", "13.1.2", "13.1.3", "13.2.1", "13.2.2", "13.2.3", "13.3.1", "14.2.1", "14.2.2", "14.2.3", "14.3.1", + "14.3.2", "14.3.3", "14.4.1", "14.4.2", "14.4.3", "14.4.4", "14.4.5", "14.4.6", "14.4.7", "14.5.1", "14.5.2", "14.5.3"); + + public static final List OWASP_ASVS_40_LEVEL_2 = Collections.unmodifiableList(Stream.concat(Stream.of("1.1.1", "1.1.2", "1.1.3", "1.1.4", "1.1.5", "1.1.6", + "1.1.7", "1.10.1", "1.11.1", "1.11.2", "1.12.1", "1.12.2", "1.14.1", "1.14.2", "1.14.3", "1.14.4", "1.14.5", "1.14.6", "1.2.1", "1.2.2", "1.2.3", "1.2.4", "1.4.1", "1.4.2", + "1.4.3", "1.4.4", "1.4.5", "1.5.1", "1.5.2", "1.5.3", "1.5.4", "1.6.1", "1.6.2", "1.6.3", "1.6.4", "1.7.1", "1.7.2", "1.8.1", "1.8.2", "1.9.1", "1.9.2", "2.3.2", "2.3.3", + "2.4.1", "2.4.2", "2.4.3", "2.4.4", "2.4.5", "2.5.7", "2.6.1", "2.6.2", "2.6.3", "2.7.5", "2.7.6", "2.8.2", "2.8.3", "2.8.4", "2.8.5", "2.8.6", "2.9.1", "2.9.2", "2.9.3", + "3.2.4", "3.3.3", "3.3.4", "3.5.1", "3.5.2", "3.5.3", "4.3.3", "5.4.1", "5.4.2", "5.4.3", "6.1.1", "6.1.2", "6.1.3", "6.2.2", "6.2.3", "6.2.4", "6.2.5", "6.2.6", "6.3.1", + "6.3.2", "6.4.1", "6.4.2", "7.1.3", "7.1.4", "7.2.1", "7.2.2", "7.3.1", "7.3.2", "7.3.3", "7.3.4", "7.4.2", "7.4.3", "8.1.1", "8.1.2", "8.1.3", "8.1.4", "8.3.5", "8.3.6", + "8.3.7", "8.3.8", "9.2.1", "9.2.2", "9.2.3", "9.2.4", "10.2.1", "10.2.2", "11.1.6", "11.1.7", "11.1.8", "12.1.2", "12.1.3", "12.2.1", "12.3.6", "13.1.4", "13.1.5", "13.2.4", + "13.2.5", "13.2.6", "13.3.2", "13.4.1", "13.4.2", "14.1.1", "14.1.2", "14.1.3", "14.1.4", "14.2.4", "14.2.5", "14.2.6", "14.5.4"), OWASP_ASVS_40_LEVEL_1.stream()) + .collect(Collectors.toList())); + + public static final List OWASP_ASVS_40_LEVEL_3 = Collections.unmodifiableList(Stream + .concat(Stream.of("1.11.3", "2.2.4", "2.2.5", "2.2.6", "2.2.7", "2.8.7", "3.6.1", "3.6.2", "6.2.7", "6.2.8", "6.3.3", "8.1.5", + "8.1.6", "9.2.5", "10.1.1", "10.2.3", "10.2.4", "10.2.5", "10.2.6", "14.1.5"), OWASP_ASVS_40_LEVEL_2.stream()) + .collect(Collectors.toList())); + + public static final Map> OWASP_ASVS_40_REQUIREMENTS_BY_LEVEL = Map.of( + 1, OWASP_ASVS_40_LEVEL_1, + 2, OWASP_ASVS_40_LEVEL_2, + 3, OWASP_ASVS_40_LEVEL_3); + + public static final Map OWASP_ASVS_40_LEVEL_BY_REQUIREMENT = Collections.unmodifiableMap(getLevelByRequirementMap()); + + public static final Map>> OWASP_ASVS_REQUIREMENTS_BY_LEVEL = Map.of( + OwaspAsvsVersion.V4_0, OWASP_ASVS_40_REQUIREMENTS_BY_LEVEL); + public enum VulnerabilityProbability { HIGH(3), MEDIUM(2), @@ -296,6 +333,14 @@ public final class SecurityStandards { return new SecurityStandards(standards, cwe, sqCategory, ignoredSQCategories); } + private static Map getLevelByRequirementMap() { + Map levelByRequirement = new HashMap<>(); + OWASP_ASVS_40_LEVEL_3.forEach(req -> levelByRequirement.put(req, 3)); + OWASP_ASVS_40_LEVEL_2.forEach(req -> levelByRequirement.put(req, 2)); + OWASP_ASVS_40_LEVEL_1.forEach(req -> levelByRequirement.put(req, 1)); + return levelByRequirement; + } + private static Set getMatchingStandards(Set securityStandards, String prefix) { return securityStandards.stream() .filter(s -> s.startsWith(prefix)) @@ -336,4 +381,5 @@ public final class SecurityStandards { .collect(toList()); return result.isEmpty() ? singletonList(SQCategory.OTHERS) : result; } + } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java index c61c4106a31..a9d6a045923 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.junit.Test; +import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion; import org.sonar.server.security.SecurityStandards.OwaspAsvs; import org.sonar.server.security.SecurityStandards.PciDss; import org.sonar.server.security.SecurityStandards.SQCategory; @@ -33,7 +34,11 @@ import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.stream.Collectors.toSet; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.sonar.server.security.SecurityStandards.CWES_BY_SQ_CATEGORY; +import static org.sonar.server.security.SecurityStandards.OWASP_ASVS_40_LEVEL_BY_REQUIREMENT; +import static org.sonar.server.security.SecurityStandards.OWASP_ASVS_REQUIREMENTS_BY_LEVEL; import static org.sonar.server.security.SecurityStandards.SQ_CATEGORY_KEYS_ORDERING; import static org.sonar.server.security.SecurityStandards.fromSecurityStandards; @@ -133,4 +138,27 @@ public class SecurityStandardsTest { assertThat(owaspAsvsCategories).hasSize(14).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"); } + + @Test + public void owaspAsvs40_requirements_distribution_by_level_check() { + assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.containsKey(OwaspAsvsVersion.V4_0)); + assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).containsKey(1)); + assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).containsKey(2)); + assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).containsKey(3)); + assertEquals(135, OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).get(1).size()); + assertEquals(266, OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).get(2).size()); + assertEquals(286, OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).get(3).size()); + } + + @Test + public void owaspAsvs40_level_by_requirements_check() { + assertEquals(286, OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.keySet().size()); + assertEquals(Integer.valueOf(1), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("2.1.1")); + assertEquals(Integer.valueOf(1), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("14.5.3")); + assertEquals(Integer.valueOf(2), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("1.1.1")); + assertEquals(Integer.valueOf(2), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("14.5.4")); + assertEquals(Integer.valueOf(3), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("1.11.3")); + assertEquals(Integer.valueOf(3), OWASP_ASVS_40_LEVEL_BY_REQUIREMENT.get("14.1.5")); + } + } -- 2.39.5