diff --git a/change-notes/1.19/analysis-csharp.md b/change-notes/1.19/analysis-csharp.md index 3b85b8f367c0..5a9e506a4eb0 100644 --- a/change-notes/1.19/analysis-csharp.md +++ b/change-notes/1.19/analysis-csharp.md @@ -8,7 +8,8 @@ | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| -| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* | +| Using a package with a known vulnerability (cs/use-of-vulnerable-package) | security, external/cwe/cwe-937 | Finds project build files that import packages with known vulnerabilities. This is included by default. | + ## Changes to existing queries diff --git a/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs b/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs index d49493c55480..1979dcdf5b9c 100644 --- a/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs +++ b/csharp/extractor/Semmle.Autobuild.Tests/BuildScripts.cs @@ -356,7 +356,7 @@ public void TestDefaultCSharpAutoBuilder() Actions.RunProcess["cmd.exe /C dotnet restore"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -375,7 +375,7 @@ public void TestLinuxCSharpAutoBuilder() Actions.RunProcess["dotnet restore"] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -486,7 +486,7 @@ public void TestLinuxBuildlessExtractionSuccess() { Actions.RunProcess[@"C:\odasa\tools\csharp\Semmle.Extraction.CSharp.Standalone --references:."] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -518,7 +518,7 @@ public void TestLinuxBuildlessExtractionSolution() { Actions.RunProcess[@"C:\odasa\tools\csharp\Semmle.Extraction.CSharp.Standalone foo.sln --references:."] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -562,7 +562,7 @@ public void TestLinuxBuildCommand() { Actions.RunProcess["C:\\odasa\\tools\\odasa index --auto \"./build.sh --skip-tests\""] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -587,7 +587,7 @@ public void TestLinuxBuildSh() Actions.RunProcess[@"C:\odasa\tools\odasa index --auto build/build.sh"] = 0; Actions.RunProcessWorkingDirectory[@"C:\odasa\tools\odasa index --auto build/build.sh"] = "build"; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; var autobuilder = CreateAutoBuilder("csharp", false); @@ -641,7 +641,7 @@ public void TestWindowsBuildBat() Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto build.bat"] = 0; Actions.RunProcessWorkingDirectory[@"cmd.exe /C C:\odasa\tools\odasa index --auto build.bat"] = ""; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; var autobuilder = CreateAutoBuilder("csharp", true); @@ -692,7 +692,7 @@ public void TestWindowCSharpMsBuild() Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\csharp\nuget\nuget.exe restore C:\Project\test2.sln"] = 0; Actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && C:\\odasa\\tools\\odasa index --auto msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; @@ -748,7 +748,7 @@ public void TestSkipNugetMsBuild() Actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && C:\\odasa\\tools\\odasa index --auto msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0; Actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && C:\\odasa\\tools\\odasa index --auto msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; @@ -776,7 +776,7 @@ public void TestSkipNugetBuildless() { Actions.RunProcess[@"C:\odasa\tools\csharp\Semmle.Extraction.CSharp.Standalone foo.sln --references:. --skip-nuget"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -796,7 +796,7 @@ public void TestSkipNugetDotnet() Actions.RunProcess["dotnet restore"] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false --no-restore"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -820,7 +820,7 @@ public void TestDotnetVersionNotInstalled() Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore"] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -845,7 +845,7 @@ public void TestDotnetVersionAlreadyInstalled() Actions.RunProcess[@"C:\Project\.dotnet\dotnet restore"] = 0; Actions.RunProcess[@"C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.RunProcess[@"C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; @@ -868,7 +868,7 @@ public void TestDotnetVersionWindows() Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false"] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\java\bin\java -jar C:\odasa\tools\extractor-asp.jar ."] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; Actions.GetEnvironmentVariable["TRAP_FOLDER"] = null; Actions.GetEnvironmentVariable["SOURCE_ARCHIVE"] = null; diff --git a/csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs b/csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs index 6b0a5b1cbb19..420fc508bfb7 100644 --- a/csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs +++ b/csharp/extractor/Semmle.Autobuild/XmlBuildRule.cs @@ -11,7 +11,7 @@ public BuildScript Analyse(Autobuilder builder) { var command = new CommandBuilder(builder.Actions). RunCommand(builder.Odasa). - Argument("index --xml --extensions config"); + Argument("index --xml --extensions config csproj props xml"); return command.Script; } } diff --git a/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll b/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll new file mode 100644 index 000000000000..13e2ea301bbc --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll @@ -0,0 +1,292 @@ +/** + * Provides a list of NuGet packages with known vulnerabilities. + * + * To add a new vulnerability follow the existing pattern. + * Create a new class that extends the abstract class `Vulnerability`, + * supplying the name and the URL, and override one (or both) of + * `matchesRange` and `matchesVersion`. + */ + +import csharp +import Vulnerability + +class MicrosoftAdvisory4021279 extends Vulnerability { + MicrosoftAdvisory4021279() { this = "Microsoft Security Advisory 4021279" } + + override string getUrl() { result = "https://github.com/dotnet/corefx/issues/19535" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + name = "System.Text.Encodings.Web" and ( + affected = "4.0.0" and fixed = "4.0.1" + or + affected = "4.3.0" and fixed = "4.3.1" + ) or + name = "System.Net.Http" and ( + affected = "4.1.1" and fixed = "4.1.2" + or + affected = "4.3.1" and fixed = "4.3.2" + ) or + name = "System.Net.Http.WinHttpHandler" and ( + affected = "4.0.1" and fixed = "4.0.2" + or + affected = "4.3.0" and fixed = "4.3.1" + ) or + name = "System.Net.Security" and ( + affected = "4.0.0" and fixed = "4.0.1" + or + affected = "4.3.0" and fixed = "4.3.1" + ) or ( + name = "Microsoft.AspNetCore.Mvc" + or + name = "Microsoft.AspNetCore.Mvc.Core" + or + name = "Microsoft.AspNetCore.Mvc.Abstractions" + or + name = "Microsoft.AspNetCore.Mvc.ApiExplorer" + or + name = "Microsoft.AspNetCore.Mvc.Cors" + or + name = "Microsoft.AspNetCore.Mvc.DataAnnotations" + or + name = "Microsoft.AspNetCore.Mvc.Formatters.Json" + or + name = "Microsoft.AspNetCore.Mvc.Formatters.Xml" + or + name = "Microsoft.AspNetCore.Mvc.Localization" + or + name = "Microsoft.AspNetCore.Mvc.Razor.Host" + or + name = "Microsoft.AspNetCore.Mvc.Razor" + or + name = "Microsoft.AspNetCore.Mvc.TagHelpers" + or + name = "Microsoft.AspNetCore.Mvc.ViewFeatures" + or + name = "Microsoft.AspNetCore.Mvc.WebApiCompatShim" + ) and ( + affected = "1.0.0" and fixed = "1.0.4" + or + affected = "1.1.0" and fixed = "1.1.3" + ) + } +} + +class CVE_2017_8700 extends Vulnerability { + CVE_2017_8700() { this = "CVE-2017-8700" } + + override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/279" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + ( + name = "Microsoft.AspNetCore.Mvc.Core" + or + name = "Microsoft.AspNetCore.Mvc.Cors" + ) and ( + affected = "1.0.0" and fixed = "1.0.6" + or + affected = "1.1.0" and fixed = "1.1.6" + ) + } +} + +class CVE_2018_0765 extends Vulnerability { + CVE_2018_0765() { this = "CVE-2018-0765" } + + override string getUrl() { result = "https://github.com/dotnet/announcements/issues/67" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + name = "System.Security.Cryptography.Xml" and + affected = "0.0.0" and + fixed = "4.4.2" + } +} + +class AspNetCore_Mar18 extends Vulnerability { + AspNetCore_Mar18() { this = "ASPNETCore-Mar18" } + + override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/300" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + ( + name = "Microsoft.AspNetCore.Server.Kestrel.Core" + or + name = "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" + or + name = "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" + ) and + affected = "2.0.0" and + fixed = "2.0.3" + or + name = "Microsoft.AspNetCore.All" and + affected = "2.0.0" and + fixed = "2.0.8" + } +} + +class CVE_2018_8409 extends Vulnerability { + CVE_2018_8409() { this = "CVE-2018-8409" } + + override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/316" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + name = "System.IO.Pipelines" and affected = "4.5.0" and fixed = "4.5.1" + or + (name = "Microsoft.AspNetCore.All" or name = "Microsoft.AspNetCore.App") and + affected = "2.1.0" and fixed = "2.1.4" + } +} + +class CVE_2018_8171 extends Vulnerability { + CVE_2018_8171() { this = "CVE-2018-8171" } + + override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/310" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + name = "Microsoft.AspNetCore.Identity" and ( + affected = "1.0.0" and fixed = "1.0.6" + or + affected = "1.1.0" and fixed = "1.1.6" + or + affected = "2.0.0" and fixed = "2.0.4" + or + affected = "2.1.0" and fixed = "2.1.2" + ) + } +} + +class CVE_2018_8356 extends Vulnerability { + CVE_2018_8356() { this = "CVE-2018-8356" } + + override string getUrl() { result = "https://github.com/dotnet/announcements/issues/73" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + ( + name = "System.Private.ServiceModel" + or + name = "System.ServiceModel.Http" + or + name = "System.ServiceModel.NetTcp" + ) and ( + affected = "4.0.0" and fixed = "4.1.3" + or + affected = "4.3.0" and fixed = "4.3.3" + or + affected = "4.4.0" and fixed = "4.4.4" + or + affected = "4.5.0" and fixed = "4.5.3" + ) + or + ( + name = "System.ServiceModel.Duplex" + or + name = "System.ServiceModel.Security" + ) and ( + affected = "4.0.0" and fixed = "4.0.4" + or + affected = "4.3.0" and fixed = "4.3.3" + or + affected = "4.4.0" and fixed = "4.4.4" + or + affected = "4.5.0" and fixed = "4.5.3" + ) + or + name = "System.ServiceModel.NetTcp" and ( + affected = "4.0.0" and fixed = "4.1.3" + or + affected = "4.3.0" and fixed = "4.3.3" + or + affected = "4.4.0" and fixed = "4.4.4" + or + affected = "4.5.0" and fixed = "4.5.1" + ) + } +} + +class ASPNETCore_Jul18 extends Vulnerability { + ASPNETCore_Jul18() { this = "ASPNETCore-July18" } + + override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/311" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + name = "Microsoft.AspNetCore.Server.Kestrel.Core" and ( + affected = "2.0.0" and fixed = "2.0.4" + or + affected = "2.1.0" and fixed = "2.1.2" + ) + or + name = "Microsoft.AspNetCore.All" and ( + affected = "2.0.0" and fixed = "2.0.9" + or + affected = "2.1.0" and fixed = "2.1.2" + ) + or + name = "Microsoft.AspNetCore.App" and + affected = "2.1.0" and + fixed = "2.1.2" + } +} + +class CVE_2018_8292 extends Vulnerability { + CVE_2018_8292() { this = "CVE-2018-8292" } + + override string getUrl() { result = "https://github.com/dotnet/announcements/issues/88" } + + override predicate matchesVersion(string name, Version affected, Version fixed) { + name = "System.Net.Http" and ( + affected = "2.0" or + affected = "4.0.0" or + affected = "4.1.0" or + affected = "1.1.1" or + affected = "4.1.2" or + affected = "4.3.0" or + affected = "4.3.1" or + affected = "4.3.2" or + affected = "4.3.3" + ) and + fixed = "4.3.4" + } +} + +class CVE_2018_0786 extends Vulnerability { + CVE_2018_0786() { this = "CVE-2018-0786" } + + override string getUrl() { result = "https://github.com/dotnet/announcements/issues/51" } + + override predicate matchesRange(string name, Version affected, Version fixed) { + ( + name = "System.ServiceModel.Primitives" + or + name = "System.ServiceModel.Http" + or + name = "System.ServiceModel.NetTcp" + or + name = "System.ServiceModel.Duplex" + or + name = "System.ServiceModel.Security" + or + name = "System.Private.ServiceModel" + ) and ( + affected = "4.4.0" and fixed = "4.4.1" + or + affected = "4.3.0" and fixed = "4.3.1" + ) + or ( + name = "System.ServiceModel.Primitives" + or + name = "System.ServiceModel.Http" + or + name = "System.ServiceModel.NetTcp" + or + name = "System.Private.ServiceModel" + ) and + affected = "4.1.0" and + fixed = "4.1.1" + or ( + name = "System.ServiceModel.Duplex" + or + name = "System.ServiceModel.Security" + ) and + affected = "4.0.1" and + fixed = "4.0.2" + } +} diff --git a/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll new file mode 100644 index 000000000000..2c8063e1b668 --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll @@ -0,0 +1,94 @@ +import csharp + +/** + * A package reference in an XML file, for example in a + * `.csproj` file, a `.props` file, or a `packages.config` file. + */ +class Package extends XMLElement { + string name; + Version version; + + Package() { + (this.getName() = "PackageManagement" or this.getName() = "PackageReference") and + name = this.getAttributeValue("Include") and + version = this.getAttributeValue("Version") + or + this.getName() = "package" and + name = this.getAttributeValue("id") and + version = this.getAttributeValue("version") + } + + /** Gets the name of the package, for example `System.IO.Pipelines`. */ + string getPackageName() { + result = name + } + + /** Gets the version of the package, for example `4.5.1`. */ + Version getVersion() { + result = version + } + + override string toString() { + result = name + " " + version + } +} + +/** + * A vulnerability, where the name of the vulnerability is this string. + * One of `matchesRange` or `matchesVersion` must be overridden in order to + * specify which packages are vulnerable. + */ +abstract class Vulnerability extends string { + bindingset[this] + Vulnerability() { any() } + + /** + * Holds if a package with name `name` is vulnerable from version `affected` + * until version `fixed`. + */ + predicate matchesRange(string name, Version affected, Version fixed) { none() } + + /** + * Holds if a package with name `name` is vulnerable in version `affected`, and + * is fixed by version `fixed`. + */ + predicate matchesVersion(string name, Version affected, Version fixed) { none() } + + /** Gets the URL describing the vulnerability. */ + abstract string getUrl(); + + /** + * Holds if a package with name `name` and version `version` + * has this vulnerability. The fixed version is given by `fixed`. + */ + bindingset[name, version] + predicate isVulnerable(string name, Version version, Version fixed) { + exists(Version affected, string n | + name.toLowerCase() = n.toLowerCase() | + matchesRange(n, affected, fixed) and + version.compareTo(fixed) < 0 and + version.compareTo(affected) >= 0 + or + matchesVersion(n, affected, fixed) and + version.compareTo(affected) = 0 + ) + } +} + +/** + * A package with a vulnerability. + */ +class VulnerablePackage extends Package { + Vulnerability vuln; + Version fixed; + + VulnerablePackage() { + vuln.isVulnerable(this.getPackageName(), this.getVersion(), fixed) + } + + /** Gets the vulnerability of this package. */ + Vulnerability getVulnerability() { result = vuln } + + /** Gets the version of this package where the vulnerability is fixed. */ + Version getFixedVersion() { result = fixed } +} diff --git a/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.qhelp b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.qhelp new file mode 100644 index 000000000000..112642c7958d --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.qhelp @@ -0,0 +1,43 @@ + + + + +

+Using a package with a known vulnerability is a security risk that could leave the +software vulnerable to attack. +

+

+This query reads the packages imported by the project build files and +.config files, and checks them against a list of packages with known +vulnerabilities. +

+
+ + +

+Upgrade the package to the recommended version using, for example, the NuGet package manager, +or by editing the project files directly. +

+
+ + +

+The following example shows a C# project file referencing package System.Net.Http +version 4.3.1, which is vulnerable to CVE-2018-8292. +

+ +

+The project file can be fixed by changing the version of the package to 4.3.4. +

+ +
+ + +
  • +OWASP: A9-Using Components with Known Vulnerabilities. +
  • +
    + +
    diff --git a/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql new file mode 100644 index 000000000000..956317935076 --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql @@ -0,0 +1,19 @@ +/** + * @name Using a package with a known vulnerability + * @description Using a package with a known vulnerability is a security risk. + * Upgrade the package to a version that does not contain the vulnerability. + * @kind problem + * @problem.severity error + * @precision high + * @id cs/use-of-vulnerable-package + * @tags security + * external/cwe/cwe-937 + */ + +import csharp +import Vulnerabilities + +from Vulnerability vuln, VulnerablePackage package +where vuln = package.getVulnerability() +select package, "Package '" + package + "' has vulnerability $@, and should be upgraded to version " + package.getFixedVersion() + ".", + vuln.getUrl(), vuln.toString() diff --git a/csharp/ql/src/Security Features/CWE-937/VulnerablePackageBAD.csproj b/csharp/ql/src/Security Features/CWE-937/VulnerablePackageBAD.csproj new file mode 100644 index 000000000000..b13494984ecb --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/VulnerablePackageBAD.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + Semmle.Autobuild + Semmle.Autobuild + Exe + + + + + + + + diff --git a/csharp/ql/src/Security Features/CWE-937/VulnerablePackageGOOD.csproj b/csharp/ql/src/Security Features/CWE-937/VulnerablePackageGOOD.csproj new file mode 100644 index 000000000000..98275b86a6fc --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-937/VulnerablePackageGOOD.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + Semmle.Autobuild + Semmle.Autobuild + Exe + + + + + + + + diff --git a/csharp/ql/test/query-tests/Security Features/CWE-937/Program.cs b/csharp/ql/test/query-tests/Security Features/CWE-937/Program.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.expected b/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.expected new file mode 100644 index 000000000000..bd39de4e295a --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.expected @@ -0,0 +1,6 @@ +| csproj.config:10:5:10:77 | System.Text.Encodings.Web 4.3.0 | Package 'System.Text.Encodings.Web 4.3.0' has vulnerability $@, and should be upgraded to version 4.3.1. | https://github.com/dotnet/corefx/issues/19535 | Microsoft Security Advisory 4021279 | +| csproj.config:11:5:11:75 | system.text.encodings.web 4.3 | Package 'system.text.encodings.web 4.3' has vulnerability $@, and should be upgraded to version 4.3.1. | https://github.com/dotnet/corefx/issues/19535 | Microsoft Security Advisory 4021279 | +| csproj.config:12:5:12:67 | System.Net.Http 4.1.1 | Package 'System.Net.Http 4.1.1' has vulnerability $@, and should be upgraded to version 4.1.2. | https://github.com/dotnet/corefx/issues/19535 | Microsoft Security Advisory 4021279 | +| csproj.config:13:5:13:67 | System.Net.Http 4.1.2 | Package 'System.Net.Http 4.1.2' has vulnerability $@, and should be upgraded to version 4.3.4. | https://github.com/dotnet/announcements/issues/88 | CVE-2018-8292 | +| packages.config:8:3:8:79 | System.IO.Pipelines 4.5.0 | Package 'System.IO.Pipelines 4.5.0' has vulnerability $@, and should be upgraded to version 4.5.1. | https://github.com/aspnet/Announcements/issues/316 | CVE-2018-8409 | +| packages.config:9:3:9:81 | System.IO.Pipelines 4.5.0.0 | Package 'System.IO.Pipelines 4.5.0.0' has vulnerability $@, and should be upgraded to version 4.5.1. | https://github.com/aspnet/Announcements/issues/316 | CVE-2018-8409 | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.qlref b/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.qlref new file mode 100644 index 000000000000..fb8a73b25f95 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-937/VulnerablePackage.qlref @@ -0,0 +1 @@ +Security Features/CWE-937/VulnerablePackage.ql \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-937/csproj.config b/csharp/ql/test/query-tests/Security Features/CWE-937/csproj.config new file mode 100644 index 000000000000..721d21559407 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-937/csproj.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/csharp/ql/test/query-tests/Security Features/CWE-937/packages.config b/csharp/ql/test/query-tests/Security Features/CWE-937/packages.config new file mode 100644 index 000000000000..06e5ea78fd00 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-937/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + +