From 40a722362036fa082a4a1f244a89839925b15dcf Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 27 Sep 2023 15:03:15 +0100 Subject: [PATCH 01/28] Implement xss flow step for absolute filepath case --- .../csharp/security/dataflow/XSSFlowSteps.qll | 81 +++++++++++++++++++ .../csharp/security/dataflow/XSSQuery.qll | 8 ++ 2 files changed, 89 insertions(+) create mode 100644 csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll new file mode 100644 index 000000000000..5310f37b999e --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -0,0 +1,81 @@ +import csharp +private import codeql.util.Unit +private import semmle.code.csharp.frameworks.microsoft.AspNetCore + +/** An additional flow step for cross-site scripting (XSS) vulnerabilities */ +abstract class XssAdditionalFlowStep extends Unit { + abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2); +} + +/** A call to the `View` method */ +private class ViewCall extends MethodCall { + ViewCall() { this.getTarget().hasQualifiedName("Microsoft.AspNetCore.Mvc", "Controller", "View") } + + /** Gets the `name` argument to this call, if any. */ + string getNameArgument() { + exists(StringLiteral lit, int i | i in [0 .. 1] | + this.getTarget().getParameter(i).getType() instanceof StringType and + DataFlow::localExprFlow(lit, this.getArgument(i)) and + result = lit.getValue() + ) + } + + /** Gets the `model` argument to this call, if any. */ + Expr getModelArgument() { + exists(int i | i in [0 .. 1] | + this.getTarget().getParameter(i).getType() instanceof ObjectType and + result = this.getArgument(i) + ) + } + + /** Gets the MVC action method that this call is made from, if any. */ + Method getActionMethod() { + result = this.getEnclosingCallable() and + result = this.getController().getAnActionMethod() + } + + /** Gets the MVC controller that this call is made from, if any. */ + MicrosoftAspNetCoreMvcController getController() { + result = this.getEnclosingCallable().getDeclaringType() + } + + /** Gets the name of the MVC controller that this call is made from, if any. */ + string getControllerName() { result + "Controller" = this.getController().getName() } +} + +/** A compiler-generated Razor page. */ +private class RazorPage extends Class { + AssemblyAttribute attr; + + RazorPage() { + attr.getFile() = this.getFile() and + attr.getType() + .hasQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute") + } + + /** + * Gets the filepath of the source file that this class was generated from, + * relative to the application root. + */ + string getSourceFilepath() { result = attr.getArgument(2).(StringLiteral).getValue() } +} + +private class ViewCallFlowStep extends XssAdditionalFlowStep { + override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(ViewCall vc, RazorPage rp, PropertyAccess modelProp | + viewCallRefersToPage(vc, rp) and + node1.asExpr() = vc.getModelArgument() and + node2.asExpr() = modelProp and + modelProp.getTarget().hasName("Model") and + modelProp.getEnclosingCallable().getDeclaringType() = rp + ) + } +} + +private predicate viewCallRefersToPage(ViewCall vc, RazorPage rp) { + viewCallRefersToPageAbsolute(vc, rp) +} + +private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) { + ["/", "~/", ""] + vc.getNameArgument() = rp.getSourceFilepath() +} diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll index 5ad2b6bc675a..248a3af45b0a 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll @@ -5,6 +5,7 @@ import csharp private import XSSSinks +private import XSSFlowSteps private import semmle.code.csharp.security.Sanitizers private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.dataflow.DataFlow2 @@ -166,6 +167,13 @@ module XssTrackingConfig implements DataFlow::ConfigSig { */ predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + /** + * Holds if there is an additional dataflow step from `node1` to `node2`. + */ + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(XssAdditionalFlowStep x).isAdditionalFlowStep(node1, node2) + } + /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. From 12a579e0aa1d97a9141d8ad7fe66dcfc14f4846c Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Fri, 29 Sep 2023 15:16:23 +0100 Subject: [PATCH 02/28] Add relative filepath lookup --- .../csharp/security/dataflow/XSSFlowSteps.qll | 79 ++++++++++++++++++- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 5310f37b999e..a7472e944306 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -3,7 +3,7 @@ private import codeql.util.Unit private import semmle.code.csharp.frameworks.microsoft.AspNetCore /** An additional flow step for cross-site scripting (XSS) vulnerabilities */ -abstract class XssAdditionalFlowStep extends Unit { +class XssAdditionalFlowStep extends Unit { abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2); } @@ -73,9 +73,82 @@ private class ViewCallFlowStep extends XssAdditionalFlowStep { } private predicate viewCallRefersToPage(ViewCall vc, RazorPage rp) { - viewCallRefersToPageAbsolute(vc, rp) + viewCallRefersToPageAbsolute(vc, rp) or + viewCallRefersToPageRelative(vc, rp) } private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) { - ["/", "~/", ""] + vc.getNameArgument() = rp.getSourceFilepath() + ["/", ""] + vc.getNameArgument() = ["", "~"] + rp.getSourceFilepath() +} + +private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { + rp.getSourceFilepath() = + min(int i, RelativeViewCallFilepath fp | + fp.hasViewCallWithIndex(vc, i) and + exists(RazorPage rp2 | rp2.getSourceFilepath() = fp.getNormalizedPath()) + | + fp.getNormalizedPath() order by i + ) +} + +private class RelativeViewCallFilepath extends NormalizableFilepath { + ViewCall vc; + int idx; + + RelativeViewCallFilepath() { + exists(string actionName | + actionName = vc.getNameArgument() and + not actionName.matches("%.cshtml") + or + not exists(vc.getNameArgument()) and + actionName = vc.getActionMethod().getName() + | + idx = 0 and + this = "/Views/" + vc.getControllerName() + "/" + actionName + ".cshtml" + or + idx = 1 and + this = "/Views/Shared/" + actionName + ".cshtml" + ) + } + + predicate hasViewCallWithIndex(ViewCall vc2, int idx2) { vc = vc2 and idx = idx2 } +} + +// TODO: this could be a shared library +/** A filepath that should be normalized. */ +abstract private class NormalizableFilepath extends string { + bindingset[this] + NormalizableFilepath() { any() } + + /** Gets the normalized filepath for this string; traversing `/../` paths. */ + string getNormalizedPath() { + exists(string norm | + norm = this.getNormalizedUpTo(0).regexpReplaceAll("/+$", "") and + (if this.matches("/%") then result = "/" + norm else result = norm) + ) + } + + private string getComponent(int i) { result = this.splitAt("/", i) } + + private int getNumComponents() { result = strictcount(int i | exists(this.getComponent(i))) } + + private string getNormalizedUpTo(int i) { + i in [0 .. this.getNumComponents()] and + ( + i = this.getNumComponents() and + result = "" + or + i < this.getNumComponents() and + exists(string comp, string sofar | + comp = this.getComponent(i) and sofar = this.getNormalizedUpTo(i + 1) + | + if comp = [".", ""] + then result = sofar + else + if comp = ".." or not sofar.matches("../%") + then result = comp + "/" + sofar + else exists(string base | sofar = "../" + base | result = base) + ) + ) + } } From ac3f642b45b49dd8bfff72fa10794bc45af135b4 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 9 Oct 2023 15:44:57 +0100 Subject: [PATCH 03/28] Unit tests - Write script to aid generating necessary code from .cshtml files. --- .../csharp/security/dataflow/XSSFlowSteps.qll | 56 ++++++++++---- .../Controllers/TestController.cs | 16 ++++ .../XSSRazorPages/Generated/Template.g | 74 +++++++++++++++++++ .../Generated/Views_Test_Test1.cshtml.g.cs | 74 +++++++++++++++++++ .../XSSRazorPages/Views/Test/Test1.cshtml | 9 +++ .../CWE-079/XSSRazorPages/XSS.expected | 12 +++ .../CWE-079/XSSRazorPages/XSS.qlref | 1 + .../CWE-079/XSSRazorPages/gen_files.py | 46 ++++++++++++ .../CWE-079/XSSRazorPages/options | 3 + 9 files changed, 275 insertions(+), 16 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Template.g create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test1.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test1.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.qlref create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/options diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index a7472e944306..6af176f82c10 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -1,9 +1,15 @@ +/** Definitions for additional flow steps for cross-site scripting (XSS) vulnerabilities. */ + import csharp private import codeql.util.Unit private import semmle.code.csharp.frameworks.microsoft.AspNetCore -/** An additional flow step for cross-site scripting (XSS) vulnerabilities */ +/** + * A unit class for providing additional flow steps for cross-site scripting (XSS) vulnerabilities. + * Extend to provide additional flow steps. + */ class XssAdditionalFlowStep extends Unit { + /** Holds if there is an additional dataflow step from `node1` to `node2`. */ abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2); } @@ -34,6 +40,17 @@ private class ViewCall extends MethodCall { result = this.getController().getAnActionMethod() } + /** + * Gets the action name that this call refers to, if any. + * This is either the name argument, or the name of the action method calling this if there is no name argument. + */ + string getActionName() { + result = this.getNameArgument() + or + not exists(this.getNameArgument()) and + result = this.getActionMethod().getName() + } + /** Gets the MVC controller that this call is made from, if any. */ MicrosoftAspNetCoreMvcController getController() { result = this.getEnclosingCallable().getDeclaringType() @@ -91,31 +108,38 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { ) } +/** Gets the `i`th template for view discovery. */ +private string getViewSearchTemplate(int i) { + i = 0 and result = "/Views/{1}/{0}.cshtml" + or + i = 1 and result = "/Views/Shared/{0}.cshtml" +} + +/** A filepath that should be searched for a View call. */ private class RelativeViewCallFilepath extends NormalizableFilepath { - ViewCall vc; - int idx; + ViewCall vc_; + int idx_; RelativeViewCallFilepath() { - exists(string actionName | - actionName = vc.getNameArgument() and - not actionName.matches("%.cshtml") - or - not exists(vc.getNameArgument()) and - actionName = vc.getActionMethod().getName() - | - idx = 0 and - this = "/Views/" + vc.getControllerName() + "/" + actionName + ".cshtml" + exists(string template | template = getViewSearchTemplate(idx_) | + this = + template.replaceAll("{0}", vc_.getActionName()).replaceAll("{1}", vc_.getControllerName()) or - idx = 1 and - this = "/Views/Shared/" + actionName + ".cshtml" + not exists(vc_.getControllerName()) and + not template.matches("%{1}%") and + this = template.replaceAll("{0}", vc_.getActionName()) ) } - predicate hasViewCallWithIndex(ViewCall vc2, int idx2) { vc = vc2 and idx = idx2 } + /** Holds if this string is the `idx`th path that will be searched for the `vc` call. */ + predicate hasViewCallWithIndex(ViewCall vc, int idx) { vc = vc_ and idx = idx_ } } // TODO: this could be a shared library -/** A filepath that should be normalized. */ +/** + * A filepath that should be normalized. + * Extend to provide additional strings that should be normalized as filepaths. + */ abstract private class NormalizableFilepath extends string { bindingset[this] NormalizableFilepath() { any() } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs new file mode 100644 index 000000000000..c91a940aac8a --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -0,0 +1,16 @@ +namespace test; + +using System.Net; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +public class UserData +{ + public string Name { get; set; } +} + +public class TestController : Controller { + public IActionResult test1(UserData tainted) { + return View("Test1", tainted); + } +} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Template.g b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Template.g new file mode 100644 index 000000000000..1f283c9e3a01 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Template.g @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.$PATHUNDER), @"mvc.1.0.view", @"/$PATHSLASH")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/$PATHSLASH")] + public class $PATHUNDER : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "$PATHSLASH" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "$PATHSLASH" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "$PATHSLASH" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test1.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test1.cshtml.g.cs new file mode 100644 index 000000000000..2ad66b7a0323 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test1.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test_Test1), @"mvc.1.0.view", @"/Views/Test/Test1.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test/Test1.cshtml")] + public class Views_Test_Test1 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test/Test1.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test/Test1.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test/Test1.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test1.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test1.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test1.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected new file mode 100644 index 000000000000..5f5a27377125 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -0,0 +1,12 @@ +edges +| Controllers/TestController.cs:13:41:13:47 | tainted : UserData | Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | +| Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | +| Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | +nodes +| Controllers/TestController.cs:13:41:13:47 | tainted : UserData | semmle.label | tainted : UserData | +| Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | semmle.label | access to parameter tainted : UserData | +| Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +subpaths +#select +| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:47 | tainted : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:47 | tainted : UserData | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.qlref new file mode 100644 index 000000000000..faad1d6403c1 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.qlref @@ -0,0 +1 @@ +Security Features/CWE-079/XSS.ql \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py new file mode 100644 index 000000000000..01861cb50dae --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py @@ -0,0 +1,46 @@ +# A script for generating code from .cshtml files, mimicking the output of the C# compiler with an option that is not available from the codeql test runner. + +import sys +import os + +work_dir = os.path.dirname(sys.argv[0]) +gen_dir = f"{work_dir}/Generated" +with open(f"{gen_dir}/Template.g") as f: + template = f.read() + + +def process_file(path: str): + """ + Generates the file from the .cshtml file at `path`. + `path` is a relative filepath from `work_dir`. + """ + # The location of the .cshtml file is the only relevant part for these tests; its contents are assumed to be the same. + assert path.endswith(".cshtml") + path = path.lstrip("/") + path_under = path.replace("/", "_")[:-len(".cshtml")] + + gen = template.replace("$PATHSLASH", path).replace("$PATHUNDER", path_under) + + with open(f"{gen_dir}/{path_under}.cshtml.g.cs", "w") as f: + f.write(gen) + + +def process_dir(path: str): + """ + Generates all the .cshtml files in the directory `path`. + `path` is a relative filepath from `work_dir`. + """ + abs_path = f"{work_dir}/{path}" + assert os.path.isdir(abs_path) + + for sub in os.listdir(abs_path): + sub_abs = f"{abs_path}/{sub}" + sub_rel = f"{path}/{sub}" + + if sub.endswith(".cshtml") and os.path.isfile(sub_abs): + process_file(sub_rel) + elif os.path.isdir(sub_abs) and ".testproj" not in sub_abs: + process_dir(sub_rel) + + +process_dir("") diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/options b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/options new file mode 100644 index 000000000000..9864339f5c95 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/options @@ -0,0 +1,3 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj \ No newline at end of file From 4f5ecb899b5f277d09f2e462526cebdfb701e4f5 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 9 Oct 2023 18:01:10 +0100 Subject: [PATCH 04/28] Add unit tests + fix issue in stubs --- .../Controllers/TestController.cs | 70 +++++++++++++- .../Generated/Views_Other_Test13.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Other_Test5.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Other_Test6.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Other_Test8.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Other_Test9.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Shared_Test12.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Shared_Test14.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Shared_Test2.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Shared_Test3.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test1.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test10.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test11.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test12.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test14.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test2.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test2_Test3.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test_Test3.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test_Test4.cshtml.g.cs | 74 +++++++++++++++ .../Generated/Views_Test_Test7.cshtml.g.cs | 74 +++++++++++++++ .../XSSRazorPages/Views/Other/Test13.cshtml | 9 ++ .../XSSRazorPages/Views/Other/Test5.cshtml | 9 ++ .../XSSRazorPages/Views/Other/Test6.cshtml | 9 ++ .../XSSRazorPages/Views/Other/Test8.cshtml | 9 ++ .../XSSRazorPages/Views/Other/Test9.cshtml | 9 ++ .../XSSRazorPages/Views/Shared/Test12.cshtml | 9 ++ .../XSSRazorPages/Views/Shared/Test14.cshtml | 9 ++ .../XSSRazorPages/Views/Shared/Test2.cshtml | 9 ++ .../XSSRazorPages/Views/Shared/Test3.cshtml | 9 ++ .../XSSRazorPages/Views/Test/Test3.cshtml | 9 ++ .../XSSRazorPages/Views/Test/Test4.cshtml | 9 ++ .../XSSRazorPages/Views/Test/Test7.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test1.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test10.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test11.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test12.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test14.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test2.cshtml | 9 ++ .../XSSRazorPages/Views/Test2/Test3.cshtml | 9 ++ .../CWE-079/XSSRazorPages/XSS.expected | 94 ++++++++++++++++++- 40 files changed, 1734 insertions(+), 7 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test13.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test5.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test6.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test8.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test9.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test12.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test14.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test2.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test3.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test1.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test10.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test11.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test12.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test14.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test2.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test3.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test3.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test4.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test7.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test13.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test5.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test6.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test8.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test9.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test12.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test14.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test2.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test3.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test3.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test4.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test7.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test1.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test10.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test11.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test12.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test14.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test2.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test3.cshtml diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index c91a940aac8a..bbfe38ae8f2f 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -10,7 +10,73 @@ public class UserData } public class TestController : Controller { - public IActionResult test1(UserData tainted) { - return View("Test1", tainted); + public IActionResult test1(UserData tainted1) { + // Expected to find file /Views/Test/Test1.cshtml + return View("Test1", tainted1); } + + public IActionResult test2(UserData tainted2) { + // Expected to find file /Views/Shared/Test2.cshtml + return View("Test2", tainted2); + } + + public IActionResult test3(UserData tainted3) { + // Expected to find file /Views/Test/Test3.cshtml and NOT /Views/Shared/Test3.cshtml + return View("Test3", tainted3); + } + + public IActionResult test4(UserData tainted4) { + // Expected to find file /Views/Test/Test4.cshtml + return View("./Test4", tainted4); + } + + public IActionResult test5(UserData tainted5) { + // Expected to find file /Views/Other/Test5.cshtml + return View("../Other/Test5", tainted5); + } + + public IActionResult test6(UserData tainted6) { + // Expected to find file /Views/Other/Test6.cshtml + return View("../../Views/.////Shared/../Other//Test6", tainted6); + } + + public IActionResult Test7(UserData tainted7) { + // Expected to find file /Views/Test/Test7.cshtml + return View(tainted7); + } + + public IActionResult test8(UserData tainted8) { + // Expected to find file /Views/Other/Test8.cshtml + return View("/Views/Other/Test8.cshtml", tainted8); + } + + public IActionResult test9(UserData tainted9) { + // Expected to find file /Views/Test/Test9.cshtml + return View("~/Views/Other/Test9.cshtml", tainted9); + } +} + +public class Test2Controller : Controller { + public IActionResult test10(UserData tainted10) { + // Expected to find file /Views/Test2/Test10.cshtml + return View("Test10", tainted10); + } + + public IActionResult test11(UserData tainted11) { + // Expected to find file /Views/Test2/Test10.cshtml + return helper(tainted11); + } + + private IActionResult helper(UserData x) { + return View("Test11", x); + } + + public IActionResult Test12(UserData tainted12) { + // Expected to find nothing. + return helper2(tainted12); + } + + private IActionResult helper2(UserData x) { + return View(x); + } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test13.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test13.cshtml.g.cs new file mode 100644 index 000000000000..ad153243a9dc --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test13.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Other_Test13), @"mvc.1.0.view", @"/Views/Other/Test13.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Other/Test13.cshtml")] + public class Views_Other_Test13 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Other/Test13.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Other/Test13.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Other/Test13.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test5.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test5.cshtml.g.cs new file mode 100644 index 000000000000..8b6dcfa243bb --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test5.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Other_Test5), @"mvc.1.0.view", @"/Views/Other/Test5.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Other/Test5.cshtml")] + public class Views_Other_Test5 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Other/Test5.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Other/Test5.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Other/Test5.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test6.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test6.cshtml.g.cs new file mode 100644 index 000000000000..58aa308379b8 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test6.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Other_Test6), @"mvc.1.0.view", @"/Views/Other/Test6.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Other/Test6.cshtml")] + public class Views_Other_Test6 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Other/Test6.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Other/Test6.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Other/Test6.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test8.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test8.cshtml.g.cs new file mode 100644 index 000000000000..799e7a84768c --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test8.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Other_Test8), @"mvc.1.0.view", @"/Views/Other/Test8.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Other/Test8.cshtml")] + public class Views_Other_Test8 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Other/Test8.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Other/Test8.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Other/Test8.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test9.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test9.cshtml.g.cs new file mode 100644 index 000000000000..9c1199c2ee30 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Other_Test9.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Other_Test9), @"mvc.1.0.view", @"/Views/Other/Test9.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Other/Test9.cshtml")] + public class Views_Other_Test9 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Other/Test9.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Other/Test9.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Other/Test9.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test12.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test12.cshtml.g.cs new file mode 100644 index 000000000000..6292047ecec9 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test12.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test12), @"mvc.1.0.view", @"/Views/Shared/Test12.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test12.cshtml")] + public class Views_Shared_Test12 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test12.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test12.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test12.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test14.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test14.cshtml.g.cs new file mode 100644 index 000000000000..93cb009780fb --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test14.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test14), @"mvc.1.0.view", @"/Views/Shared/Test14.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test14.cshtml")] + public class Views_Shared_Test14 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test14.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test14.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test14.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test2.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test2.cshtml.g.cs new file mode 100644 index 000000000000..c20f1456c067 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test2.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test2), @"mvc.1.0.view", @"/Views/Shared/Test2.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test2.cshtml")] + public class Views_Shared_Test2 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test2.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test2.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test2.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test3.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test3.cshtml.g.cs new file mode 100644 index 000000000000..7bd08d8665b3 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test3.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test3), @"mvc.1.0.view", @"/Views/Shared/Test3.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test3.cshtml")] + public class Views_Shared_Test3 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test3.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test3.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test3.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test1.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test1.cshtml.g.cs new file mode 100644 index 000000000000..a4dec53b6324 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test1.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test1), @"mvc.1.0.view", @"/Views/Test2/Test1.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test1.cshtml")] + public class Views_Test2_Test1 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test1.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test1.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test1.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test10.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test10.cshtml.g.cs new file mode 100644 index 000000000000..33a4d27e254a --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test10.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test10), @"mvc.1.0.view", @"/Views/Test2/Test10.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test10.cshtml")] + public class Views_Test2_Test10 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test10.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test10.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test10.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test11.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test11.cshtml.g.cs new file mode 100644 index 000000000000..da0b0a9c1625 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test11.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test11), @"mvc.1.0.view", @"/Views/Test2/Test11.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test11.cshtml")] + public class Views_Test2_Test11 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test11.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test11.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test11.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test12.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test12.cshtml.g.cs new file mode 100644 index 000000000000..023daa7b03ea --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test12.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test12), @"mvc.1.0.view", @"/Views/Test2/Test12.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test12.cshtml")] + public class Views_Test2_Test12 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test12.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test12.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test12.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test14.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test14.cshtml.g.cs new file mode 100644 index 000000000000..28b0ab8ee3fd --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test14.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test14), @"mvc.1.0.view", @"/Views/Test2/Test14.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test14.cshtml")] + public class Views_Test2_Test14 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test14.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test14.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test14.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test2.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test2.cshtml.g.cs new file mode 100644 index 000000000000..53c7e6eed471 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test2.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test2), @"mvc.1.0.view", @"/Views/Test2/Test2.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test2.cshtml")] + public class Views_Test2_Test2 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test2.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test2.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test2.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test3.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test3.cshtml.g.cs new file mode 100644 index 000000000000..299f6f89a16d --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test2_Test3.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test2_Test3), @"mvc.1.0.view", @"/Views/Test2/Test3.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test2/Test3.cshtml")] + public class Views_Test2_Test3 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test2/Test3.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test2/Test3.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test2/Test3.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test3.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test3.cshtml.g.cs new file mode 100644 index 000000000000..95ef158286b2 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test3.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test_Test3), @"mvc.1.0.view", @"/Views/Test/Test3.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test/Test3.cshtml")] + public class Views_Test_Test3 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test/Test3.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test/Test3.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test/Test3.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test4.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test4.cshtml.g.cs new file mode 100644 index 000000000000..7a8cea221f71 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test4.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test_Test4), @"mvc.1.0.view", @"/Views/Test/Test4.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test/Test4.cshtml")] + public class Views_Test_Test4 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test/Test4.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test/Test4.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test/Test4.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test7.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test7.cshtml.g.cs new file mode 100644 index 000000000000..1eef0024c7ad --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test_Test7.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test_Test7), @"mvc.1.0.view", @"/Views/Test/Test7.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test/Test7.cshtml")] + public class Views_Test_Test7 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test/Test7.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test/Test7.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test/Test7.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test13.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test13.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test13.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test5.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test5.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test5.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test6.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test6.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test6.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test8.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test8.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test8.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test9.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test9.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Other/Test9.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test12.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test12.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test12.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test14.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test14.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test14.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test2.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test2.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test2.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test3.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test3.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test3.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test3.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test3.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test3.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test4.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test4.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test4.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test7.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test7.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test/Test7.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test1.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test1.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test1.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test10.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test10.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test10.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test11.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test11.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test11.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test12.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test12.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test12.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test14.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test14.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test14.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test2.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test2.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test2.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test3.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test3.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test2/Test3.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index 5f5a27377125..62453fe8d391 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -1,12 +1,96 @@ edges -| Controllers/TestController.cs:13:41:13:47 | tainted : UserData | Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | -| Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:70:43:70:43 | x : UserData | +| Controllers/TestController.cs:70:43:70:43 | x : UserData | Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | +| Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | +| Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | +| Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | +| Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | +| Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | +| Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | +| Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | +| Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | +| Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | +| Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | +| Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | nodes -| Controllers/TestController.cs:13:41:13:47 | tainted : UserData | semmle.label | tainted : UserData | -| Controllers/TestController.cs:14:30:14:36 | access to parameter tainted : UserData | semmle.label | access to parameter tainted : UserData | +| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | +| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | +| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | semmle.label | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | semmle.label | tainted3 : UserData | +| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | semmle.label | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | semmle.label | tainted4 : UserData | +| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | semmle.label | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | semmle.label | tainted5 : UserData | +| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | semmle.label | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | semmle.label | tainted6 : UserData | +| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | semmle.label | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | semmle.label | tainted7 : UserData | +| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | semmle.label | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | semmle.label | tainted8 : UserData | +| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | semmle.label | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | semmle.label | tainted9 : UserData | +| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | semmle.label | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | semmle.label | tainted10 : UserData | +| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | semmle.label | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | semmle.label | tainted11 : UserData | +| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:70:43:70:43 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select -| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:47 | tainted : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:47 | tainted : UserData | User-provided value | +| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | User-provided value | +| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | User-provided value | +| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | User-provided value | +| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | User-provided value | +| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | User-provided value | +| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | User-provided value | +| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | User-provided value | +| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | User-provided value | +| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | User-provided value | +| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | User-provided value | +| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | User-provided value | From f84b2a96afaca6888e5a179138aff47acfcb981f Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 17 Oct 2023 16:10:50 +0100 Subject: [PATCH 05/28] Add support for view locations defined in code through RazoeViewEngineOptions --- .../csharp/security/dataflow/XSSFlowSteps.qll | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 6af176f82c10..1dd86707521b 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -113,6 +113,30 @@ private string getViewSearchTemplate(int i) { i = 0 and result = "/Views/{1}/{0}.cshtml" or i = 1 and result = "/Views/Shared/{0}.cshtml" + or + i = 2 and result = getAViewSearchTemplateInCode() +} + +/** Gets an additional template used for view discovery defined in code. */ +private string getAViewSearchTemplateInCode() { + exists(StringLiteral str, MethodCall addCall | + addCall.getTarget().hasQualifiedName("System.Collections.Generic", "IList", "Add") and + DataFlow::localExprFlow(str, addCall.getArgument(0)) and + addCall.getQualifier() = getAViewLocationList() and + result = str.getValue() + ) +} + +/** Gets a list expression containing view search locations */ +private Expr getAViewLocationList() { + result + .(PropertyRead) + .getProperty() + .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", + [ + "ViewLocationFormats", "PageViewLocationFormats", "AreaViewLocationFormats", + "AreaPageViewLocationFormats" + ]) } /** A filepath that should be searched for a View call. */ From 7691cbce8765f45e1ffbbfc0b9ea72545b8dc633 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 17 Oct 2023 16:58:20 +0100 Subject: [PATCH 06/28] Add additional test cases --- .../csharp/security/dataflow/XSSFlowSteps.qll | 2 +- .../Controllers/TestController.cs | 32 +++++++- .../Views_Custom_Test3_Test15.cshtml.g.cs | 74 +++++++++++++++++++ .../Views/Custom/Test3/Test15.cshtml | 9 +++ 4 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom_Test3_Test15.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom/Test3/Test15.cshtml diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 1dd86707521b..2c7c6fb0afad 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -99,7 +99,7 @@ private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) { } private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { - rp.getSourceFilepath() = + ["", "~"] + rp.getSourceFilepath() = min(int i, RelativeViewCallFilepath fp | fp.hasViewCallWithIndex(vc, i) and exists(RazorPage rp2 | rp2.getSourceFilepath() = fp.getNormalizedPath()) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index bbfe38ae8f2f..aff0dc0ee5a4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -67,9 +67,7 @@ public IActionResult test11(UserData tainted11) { return helper(tainted11); } - private IActionResult helper(UserData x) { - return View("Test11", x); - } + private IActionResult helper(UserData x) { return View("Test11", x); } public IActionResult Test12(UserData tainted12) { // Expected to find nothing. @@ -79,4 +77,32 @@ public IActionResult Test12(UserData tainted12) { private IActionResult helper2(UserData x) { return View(x); } + + private IActionResult test13(UserData tainted13) { + // Expected to find file /Views/Other/Test13.cshtml + return Helper.helper3(this, tainted13); + } + + private IActionResult test14(UserData tainted14) { + // Expected to find file /Views/Shared/Test14.cshtml and NOT /Views/Test2/Test14.cshtml + return Helper.helper4(this, tainted14); + } + +} + +class Helper { + public static IActionResult helper3(Controller c, UserData x) { return c.View("/Views/Other/Test13.cshtml", x); } + + public static IActionResult helper4(Controller c, UserData x) { return c.View("Test14", x); } +} + +public class Test3Controller : Controller { + public void Setup(RazorViewEngineOptions o) { + o.ViewLocationFormats.Add("/Views/Custom/{1}/{0}.cshtml"); + } + + private IActionResult Test15(UserData tainted14) { + // Expected to find file /Views/Custom/Test3/Test15.cshtml + return View(x); + } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom_Test3_Test15.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom_Test3_Test15.cshtml.g.cs new file mode 100644 index 000000000000..00edb1f4b8c9 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom_Test3_Test15.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Custom_Test3_Test15), @"mvc.1.0.view", @"/Views/Custom/Test3/Test15.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Custom/Test3/Test15.cshtml")] + public class Views_Custom_Test3_Test15 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Custom/Test3/Test15.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Custom/Test3/Test15.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Custom/Test3/Test15.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom/Test3/Test15.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom/Test3/Test15.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom/Test3/Test15.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file From 7194113a6461fe8a0326c4cdc4679c70ebb178e1 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 23 Oct 2023 16:11:11 +0100 Subject: [PATCH 07/28] Add areas --- .../csharp/security/dataflow/XSSFlowSteps.qll | 47 +++++-- .../Controllers/TestController.cs | 11 +- .../CWE-079/XSSRazorPages/XSS.expected | 118 +++++++++--------- 3 files changed, 99 insertions(+), 77 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 2c7c6fb0afad..10c18705b64e 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -58,6 +58,15 @@ private class ViewCall extends MethodCall { /** Gets the name of the MVC controller that this call is made from, if any. */ string getControllerName() { result + "Controller" = this.getController().getName() } + + /** Gets the name of the Area that the controller of this call belongs to, if any. */ + string getAreaName() { + exists(Attribute attr | + attr = this.getController().getAnAttribute() and + attr.getType().hasQualifiedName("Microsoft.AspNetCore.Mvc", "AreaAttribute") and + result = attr.getArgument(0).(StringLiteral).getValue() + ) + } } /** A compiler-generated Razor page. */ @@ -110,17 +119,21 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { /** Gets the `i`th template for view discovery. */ private string getViewSearchTemplate(int i) { - i = 0 and result = "/Views/{1}/{0}.cshtml" + i = 0 and result = "/Areas/{2}/Views/{1}/{0}.cshtml" + or + i = 1 and result = "/Areas/{2}/Views/Shared/{0}.cshtml" or - i = 1 and result = "/Views/Shared/{0}.cshtml" + i = 2 and result = "/Views/{1}/{0}.cshtml" or - i = 2 and result = getAViewSearchTemplateInCode() + i = 3 and result = "/Views/Shared/{0}.cshtml" + or + i = 4 and result = getAViewSearchTemplateInCode() } /** Gets an additional template used for view discovery defined in code. */ private string getAViewSearchTemplateInCode() { exists(StringLiteral str, MethodCall addCall | - addCall.getTarget().hasQualifiedName("System.Collections.Generic", "IList", "Add") and + addCall.getTarget().hasName("Add") and DataFlow::localExprFlow(str, addCall.getArgument(0)) and addCall.getQualifier() = getAViewLocationList() and result = str.getValue() @@ -134,8 +147,8 @@ private Expr getAViewLocationList() { .getProperty() .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", [ - "ViewLocationFormats", "PageViewLocationFormats", "AreaViewLocationFormats", - "AreaPageViewLocationFormats" + "ViewLocationFormats", "AreaViewLocationFormats", + //"PageViewLocationFormats","AreaPageViewLocationFormats" ]) } @@ -145,13 +158,21 @@ private class RelativeViewCallFilepath extends NormalizableFilepath { int idx_; RelativeViewCallFilepath() { - exists(string template | template = getViewSearchTemplate(idx_) | - this = - template.replaceAll("{0}", vc_.getActionName()).replaceAll("{1}", vc_.getControllerName()) - or - not exists(vc_.getControllerName()) and - not template.matches("%{1}%") and - this = template.replaceAll("{0}", vc_.getActionName()) + exists(string template, string sub2, string sub1, string sub0 | + template = getViewSearchTemplate(idx_) + | + ( + if template.matches("%{2}%") + then sub2 = template.replaceAll("{2}", vc_.getAreaName()) + else sub2 = template + ) and + ( + if template.matches("%{1}%") + then sub1 = sub2.replaceAll("{1}", vc_.getControllerName()) + else sub1 = sub2 + ) and + sub0 = sub1.replaceAll("{0}", vc_.getActionName()) and + this = sub0 ) } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index aff0dc0ee5a4..d682c6bbf7f1 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -3,6 +3,7 @@ namespace test; using System.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.Razor; public class UserData { @@ -79,12 +80,12 @@ private IActionResult helper2(UserData x) { } private IActionResult test13(UserData tainted13) { - // Expected to find file /Views/Other/Test13.cshtml + // MISSING: Expected to find file /Views/Other/Test13.cshtml. return Helper.helper3(this, tainted13); } private IActionResult test14(UserData tainted14) { - // Expected to find file /Views/Shared/Test14.cshtml and NOT /Views/Test2/Test14.cshtml + // MISSING: Expected to find file /Views/Shared/Test14.cshtml and NOT /Views/Test2/Test14.cshtml return Helper.helper4(this, tainted14); } @@ -101,8 +102,8 @@ public void Setup(RazorViewEngineOptions o) { o.ViewLocationFormats.Add("/Views/Custom/{1}/{0}.cshtml"); } - private IActionResult Test15(UserData tainted14) { - // Expected to find file /Views/Custom/Test3/Test15.cshtml - return View(x); + private IActionResult Test15(UserData tainted15) { + // MISSING: Expected to find file /Views/Custom/Test3/Test15.cshtml + return View(tainted15); } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index 62453fe8d391..ac10d7b2adf1 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -1,28 +1,28 @@ edges -| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | -| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | -| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | -| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | -| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | -| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | -| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | -| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | -| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | -| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | -| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | -| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:70:43:70:43 | x : UserData | -| Controllers/TestController.cs:70:43:70:43 | x : UserData | Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | -| Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:71:43:71:43 | x : UserData | +| Controllers/TestController.cs:71:43:71:43 | x : UserData | Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | +| Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | @@ -35,30 +35,30 @@ edges | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | nodes -| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | -| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | -| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | -| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | semmle.label | access to parameter tainted2 : UserData | -| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | semmle.label | tainted3 : UserData | -| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | semmle.label | access to parameter tainted3 : UserData | -| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | semmle.label | tainted4 : UserData | -| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | semmle.label | access to parameter tainted4 : UserData | -| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | semmle.label | tainted5 : UserData | -| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | semmle.label | access to parameter tainted5 : UserData | -| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | semmle.label | tainted6 : UserData | -| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | semmle.label | access to parameter tainted6 : UserData | -| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | semmle.label | tainted7 : UserData | -| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | semmle.label | access to parameter tainted7 : UserData | -| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | semmle.label | tainted8 : UserData | -| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | semmle.label | access to parameter tainted8 : UserData | -| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | semmle.label | tainted9 : UserData | -| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | semmle.label | access to parameter tainted9 : UserData | -| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | semmle.label | tainted10 : UserData | -| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | semmle.label | access to parameter tainted10 : UserData | -| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | semmle.label | tainted11 : UserData | -| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | -| Controllers/TestController.cs:70:43:70:43 | x : UserData | semmle.label | x : UserData | -| Controllers/TestController.cs:71:31:71:31 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | +| Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | +| Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | semmle.label | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | semmle.label | tainted3 : UserData | +| Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | semmle.label | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | semmle.label | tainted4 : UserData | +| Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | semmle.label | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | semmle.label | tainted5 : UserData | +| Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | semmle.label | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | semmle.label | tainted6 : UserData | +| Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | semmle.label | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | semmle.label | tainted7 : UserData | +| Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | semmle.label | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | semmle.label | tainted8 : UserData | +| Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | semmle.label | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | semmle.label | tainted9 : UserData | +| Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | semmle.label | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | semmle.label | tainted10 : UserData | +| Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | semmle.label | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | semmle.label | tainted11 : UserData | +| Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:71:43:71:43 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -83,14 +83,14 @@ nodes | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select -| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | User-provided value | -| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | User-provided value | -| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | User-provided value | -| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | User-provided value | -| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | User-provided value | -| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | User-provided value | -| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | User-provided value | -| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | User-provided value | -| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | User-provided value | -| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | User-provided value | -| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | User-provided value | +| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | User-provided value | +| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | User-provided value | +| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | User-provided value | +| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | User-provided value | +| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | User-provided value | +| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | User-provided value | +| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | User-provided value | +| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | User-provided value | +| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | User-provided value | +| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | User-provided value | +| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | User-provided value | From f1b0f1a35d223af65d6953b9fb7cae4ec87e60d4 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 23 Oct 2023 21:22:03 +0100 Subject: [PATCH 08/28] Use shared filepath normalization libary --- .../csharp/security/dataflow/XSSFlowSteps.qll | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 10c18705b64e..88d8727ef0c5 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -2,6 +2,7 @@ import csharp private import codeql.util.Unit +private import codeql.util.FilePath private import semmle.code.csharp.frameworks.microsoft.AspNetCore /** @@ -179,45 +180,3 @@ private class RelativeViewCallFilepath extends NormalizableFilepath { /** Holds if this string is the `idx`th path that will be searched for the `vc` call. */ predicate hasViewCallWithIndex(ViewCall vc, int idx) { vc = vc_ and idx = idx_ } } - -// TODO: this could be a shared library -/** - * A filepath that should be normalized. - * Extend to provide additional strings that should be normalized as filepaths. - */ -abstract private class NormalizableFilepath extends string { - bindingset[this] - NormalizableFilepath() { any() } - - /** Gets the normalized filepath for this string; traversing `/../` paths. */ - string getNormalizedPath() { - exists(string norm | - norm = this.getNormalizedUpTo(0).regexpReplaceAll("/+$", "") and - (if this.matches("/%") then result = "/" + norm else result = norm) - ) - } - - private string getComponent(int i) { result = this.splitAt("/", i) } - - private int getNumComponents() { result = strictcount(int i | exists(this.getComponent(i))) } - - private string getNormalizedUpTo(int i) { - i in [0 .. this.getNumComponents()] and - ( - i = this.getNumComponents() and - result = "" - or - i < this.getNumComponents() and - exists(string comp, string sofar | - comp = this.getComponent(i) and sofar = this.getNormalizedUpTo(i + 1) - | - if comp = [".", ""] - then result = sofar - else - if comp = ".." or not sofar.matches("../%") - then result = comp + "/" + sofar - else exists(string base | sofar = "../" + base | result = base) - ) - ) - } -} From 7bd7cc5dbe79c8746d2471acda4c147e41fbfdb9 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 24 Oct 2023 15:06:50 +0100 Subject: [PATCH 09/28] Fix tests --- .../Controllers/TestController.cs | 12 +++---- .../CWE-079/XSSRazorPages/XSS.expected | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index d682c6bbf7f1..05c10ec9146e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -79,13 +79,13 @@ private IActionResult helper2(UserData x) { return View(x); } - private IActionResult test13(UserData tainted13) { - // MISSING: Expected to find file /Views/Other/Test13.cshtml. + public IActionResult test13(UserData tainted13) { + // Expected to find file /Views/Other/Test13.cshtml. return Helper.helper3(this, tainted13); } - private IActionResult test14(UserData tainted14) { - // MISSING: Expected to find file /Views/Shared/Test14.cshtml and NOT /Views/Test2/Test14.cshtml + public IActionResult test14(UserData tainted14) { + // Expected to find file /Views/Shared/Test14.cshtml and NOT /Views/Test2/Test14.cshtml return Helper.helper4(this, tainted14); } @@ -102,8 +102,8 @@ public void Setup(RazorViewEngineOptions o) { o.ViewLocationFormats.Add("/Views/Custom/{1}/{0}.cshtml"); } - private IActionResult Test15(UserData tainted15) { - // MISSING: Expected to find file /Views/Custom/Test3/Test15.cshtml + public IActionResult Test15(UserData tainted15) { + // Expected to find file /Views/Custom/Test3/Test15.cshtml return View(tainted15); } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index ac10d7b2adf1..06f4e3492930 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -23,11 +23,24 @@ edges | Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:71:43:71:43 | x : UserData | | Controllers/TestController.cs:71:43:71:43 | x : UserData | Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | | Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | +| Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | Controllers/TestController.cs:95:64:95:64 | x : UserData | +| Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | +| Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | Controllers/TestController.cs:97:64:97:64 | x : UserData | +| Controllers/TestController.cs:95:64:95:64 | x : UserData | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | +| Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:97:64:97:64 | x : UserData | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | +| Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | +| Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | +| Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | +| Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | @@ -59,6 +72,18 @@ nodes | Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | | Controllers/TestController.cs:71:43:71:43 | x : UserData | semmle.label | x : UserData | | Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | semmle.label | tainted13 : UserData | +| Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | semmle.label | access to parameter tainted13 : UserData | +| Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | semmle.label | tainted14 : UserData | +| Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | semmle.label | access to parameter tainted14 : UserData | +| Controllers/TestController.cs:95:64:95:64 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:97:64:97:64 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | +| Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | +| Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -67,8 +92,12 @@ nodes | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -83,11 +112,14 @@ nodes | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select +| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | User-provided value | | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | User-provided value | | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | User-provided value | | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | User-provided value | | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | User-provided value | +| Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | User-provided value | | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | User-provided value | +| Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | User-provided value | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | User-provided value | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | User-provided value | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | User-provided value | From f2c3d83d9e1e64c4312b30353968b5c4565b6cb3 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 24 Oct 2023 15:32:44 +0100 Subject: [PATCH 10/28] Add tests for area cases --- .../csharp/security/dataflow/XSSFlowSteps.qll | 2 +- .../Areas/TestArea/Views/Shared/Test18.cshtml | 9 +++ .../Areas/TestArea/Views/Test4/Test17.cshtml | 9 +++ .../Controllers/TestController.cs | 29 ++++++++ ...s_TestArea_Views_Shared_Test18.cshtml.g.cs | 74 +++++++++++++++++++ ...as_TestArea_Views_Test4_Test17.cshtml.g.cs | 74 +++++++++++++++++++ .../Views_Custom2_Test16.cshtml.g.cs | 74 +++++++++++++++++++ .../Generated/Views_Shared_Test19.cshtml.g.cs | 74 +++++++++++++++++++ .../Generated/Views_Test4_Test20.cshtml.g.cs | 74 +++++++++++++++++++ .../XSSRazorPages/Views/Custom2/Test16.cshtml | 9 +++ .../XSSRazorPages/Views/Shared/Test19.cshtml | 9 +++ .../XSSRazorPages/Views/Test4/Test20.cshtml | 9 +++ .../CWE-079/XSSRazorPages/XSS.expected | 50 +++++++++++-- 13 files changed, 490 insertions(+), 6 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Shared/Test18.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Test4/Test17.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Shared_Test18.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Test4_Test17.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom2_Test16.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test19.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test4_Test20.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom2/Test16.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test19.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test4/Test20.cshtml diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 88d8727ef0c5..fb3df099b771 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -112,7 +112,7 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { ["", "~"] + rp.getSourceFilepath() = min(int i, RelativeViewCallFilepath fp | fp.hasViewCallWithIndex(vc, i) and - exists(RazorPage rp2 | rp2.getSourceFilepath() = fp.getNormalizedPath()) + exists(RazorPage rp2 | ["", "~"] + rp2.getSourceFilepath() = fp.getNormalizedPath()) | fp.getNormalizedPath() order by i ) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Shared/Test18.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Shared/Test18.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Shared/Test18.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Test4/Test17.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Test4/Test17.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Areas/TestArea/Views/Test4/Test17.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index 05c10ec9146e..32978907c15b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -100,10 +100,39 @@ class Helper { public class Test3Controller : Controller { public void Setup(RazorViewEngineOptions o) { o.ViewLocationFormats.Add("/Views/Custom/{1}/{0}.cshtml"); + o.ViewLocationFormats.Add("~/Views/Custom2/{0}.cshtml"); } public IActionResult Test15(UserData tainted15) { // Expected to find file /Views/Custom/Test3/Test15.cshtml return View(tainted15); } + + public IActionResult test16(UserData tainted16) { + // Expected to find file /Views/Custom2/Test16.cshtml + return View("Test16", tainted16); + } +} + +[Area("TestArea")] +public class Test4Controller : Controller { + public IActionResult test17(UserData tainted17) { + // Expected to find file /Areas/TestArea/Views/Test4/Test17.cshtml + return View("Test17", tainted17); + } + + public IActionResult test18(UserData tainted18) { + // Expected to find file /Areas/TestArea/Views/Shared/Test17.cshtml + return View("Test18", tainted18); + } + + public IActionResult test19(UserData tainted19) { + // Expected to find file /Views/Shared/Test19.cshtml + return View("Test19", tainted19); + } + + public IActionResult test20(UserData tainted20) { + // SPURIOUS: Expected to find nothing (and NOT /Views/Test4/Test20.cshtml). + return View("Test20", tainted20); + } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Shared_Test18.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Shared_Test18.cshtml.g.cs new file mode 100644 index 000000000000..eecb00361d68 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Shared_Test18.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Areas_TestArea_Views_Shared_Test18), @"mvc.1.0.view", @"/Areas/TestArea/Views/Shared/Test18.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Areas/TestArea/Views/Shared/Test18.cshtml")] + public class Areas_TestArea_Views_Shared_Test18 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Areas/TestArea/Views/Shared/Test18.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Areas/TestArea/Views/Shared/Test18.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Areas/TestArea/Views/Shared/Test18.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Test4_Test17.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Test4_Test17.cshtml.g.cs new file mode 100644 index 000000000000..ee7ee811920f --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Areas_TestArea_Views_Test4_Test17.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Areas_TestArea_Views_Test4_Test17), @"mvc.1.0.view", @"/Areas/TestArea/Views/Test4/Test17.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Areas/TestArea/Views/Test4/Test17.cshtml")] + public class Areas_TestArea_Views_Test4_Test17 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Areas/TestArea/Views/Test4/Test17.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Areas/TestArea/Views/Test4/Test17.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Areas/TestArea/Views/Test4/Test17.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom2_Test16.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom2_Test16.cshtml.g.cs new file mode 100644 index 000000000000..c6048503384b --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Custom2_Test16.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Custom2_Test16), @"mvc.1.0.view", @"/Views/Custom2/Test16.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Custom2/Test16.cshtml")] + public class Views_Custom2_Test16 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Custom2/Test16.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Custom2/Test16.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Custom2/Test16.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test19.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test19.cshtml.g.cs new file mode 100644 index 000000000000..daacf56a1f1e --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test19.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test19), @"mvc.1.0.view", @"/Views/Shared/Test19.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test19.cshtml")] + public class Views_Shared_Test19 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test19.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test19.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test19.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test4_Test20.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test4_Test20.cshtml.g.cs new file mode 100644 index 000000000000..814a81a5b5d0 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Test4_Test20.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Test4_Test20), @"mvc.1.0.view", @"/Views/Test4/Test20.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Test4/Test20.cshtml")] + public class Views_Test4_Test20 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Test4/Test20.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Test4/Test20.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Test4/Test20.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom2/Test16.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom2/Test16.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Custom2/Test16.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test19.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test19.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test19.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test4/Test20.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test4/Test20.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Test4/Test20.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index 06f4e3492930..18680b978db9 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -1,4 +1,6 @@ edges +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | | Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | @@ -31,8 +33,19 @@ edges | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | | Controllers/TestController.cs:97:64:97:64 | x : UserData | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | -| Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | +| Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | +| Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | @@ -41,13 +54,19 @@ edges | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | +| Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | +| Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | nodes +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | | Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | @@ -80,8 +99,20 @@ nodes | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | | Controllers/TestController.cs:97:64:97:64 | x : UserData | semmle.label | x : UserData | | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | -| Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | -| Controllers/TestController.cs:107:21:107:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | +| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | semmle.label | tainted16 : UserData | +| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | semmle.label | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | semmle.label | tainted17 : UserData | +| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | semmle.label | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | semmle.label | tainted18 : UserData | +| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | semmle.label | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | semmle.label | tainted19 : UserData | +| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | semmle.label | tainted20 : UserData | +| Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | semmle.label | access to parameter tainted20 : UserData | +| Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -98,10 +129,14 @@ nodes | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -112,7 +147,10 @@ nodes | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select -| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:105:42:105:50 | tainted15 : UserData | User-provided value | +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | User-provided value | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | User-provided value | +| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | User-provided value | +| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | User-provided value | | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | User-provided value | | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | User-provided value | | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | User-provided value | @@ -120,8 +158,10 @@ subpaths | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | User-provided value | | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | User-provided value | | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | User-provided value | +| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | User-provided value | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | User-provided value | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | User-provided value | +| Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | User-provided value | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | User-provided value | | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | User-provided value | | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | User-provided value | From 826111dc08cd05b0971d0f4401ab74be67740b28 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 24 Oct 2023 16:09:58 +0100 Subject: [PATCH 11/28] Separate area view discovery list for increased precision --- .../csharp/security/dataflow/XSSFlowSteps.qll | 44 ++++++----- .../Controllers/TestController.cs | 13 +++- .../MyAreas_Test4_Test22.cshtml.g.cs | 74 +++++++++++++++++++ .../Generated/Pages_Shared_Test21.cshtml.g.cs | 74 +++++++++++++++++++ .../XSSRazorPages/MyAreas/Test4/Test22.cshtml | 9 +++ .../XSSRazorPages/Pages/Shared/Test21.cshtml | 9 +++ .../CWE-079/XSSRazorPages/XSS.expected | 66 ++++++++--------- 7 files changed, 237 insertions(+), 52 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/MyAreas_Test4_Test22.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Pages_Shared_Test21.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/MyAreas/Test4/Test22.cshtml create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Pages/Shared/Test21.cshtml diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index fb3df099b771..5dce1c2e6dd3 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -68,6 +68,9 @@ private class ViewCall extends MethodCall { result = attr.getArgument(0).(StringLiteral).getValue() ) } + + /** `result` is `true` if this cal is from a controller that is an an Area, `false` otherwise. */ + boolean hasArea() { if exists(this.getAreaName()) then result = true else result = false } } /** A compiler-generated Razor page. */ @@ -119,38 +122,43 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { } /** Gets the `i`th template for view discovery. */ -private string getViewSearchTemplate(int i) { - i = 0 and result = "/Areas/{2}/Views/{1}/{0}.cshtml" +private string getViewSearchTemplate(int i, boolean isArea) { + i = 0 and result = "/Areas/{2}/Views/{1}/{0}.cshtml" and isArea = true + or + i = 1 and result = "/Areas/{2}/Views/Shared/{0}.cshtml" and isArea = true or - i = 1 and result = "/Areas/{2}/Views/Shared/{0}.cshtml" + i = 2 and result = "/Views/{1}/{0}.cshtml" and isArea = false or - i = 2 and result = "/Views/{1}/{0}.cshtml" + i = 3 and result = "/Views/Shared/{0}.cshtml" and isArea = [true, false] or - i = 3 and result = "/Views/Shared/{0}.cshtml" + i = 4 and result = "/Pages/Shared/{0}.cshtml" and isArea = true or - i = 4 and result = getAViewSearchTemplateInCode() + i = 5 and result = getAViewSearchTemplateInCode(isArea) } /** Gets an additional template used for view discovery defined in code. */ -private string getAViewSearchTemplateInCode() { +private string getAViewSearchTemplateInCode(boolean isArea) { exists(StringLiteral str, MethodCall addCall | addCall.getTarget().hasName("Add") and DataFlow::localExprFlow(str, addCall.getArgument(0)) and - addCall.getQualifier() = getAViewLocationList() and + addCall.getQualifier() = getAViewLocationList(isArea) and result = str.getValue() ) } /** Gets a list expression containing view search locations */ -private Expr getAViewLocationList() { - result - .(PropertyRead) - .getProperty() - .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", - [ - "ViewLocationFormats", "AreaViewLocationFormats", - //"PageViewLocationFormats","AreaPageViewLocationFormats" - ]) +private Expr getAViewLocationList(boolean isArea) { + exists(string name | + result + .(PropertyRead) + .getProperty() + .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", name) + | + name = "ViewLocationFormats" and isArea = false + or + name = "AreaViewLocationFormats" and isArea = true + // PageViewLocationFormats and AreaPageViewLocationFormats are used for calls within a page rather than a controller + ) } /** A filepath that should be searched for a View call. */ @@ -160,7 +168,7 @@ private class RelativeViewCallFilepath extends NormalizableFilepath { RelativeViewCallFilepath() { exists(string template, string sub2, string sub1, string sub0 | - template = getViewSearchTemplate(idx_) + template = getViewSearchTemplate(idx_, vc_.hasArea()) | ( if template.matches("%{2}%") diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index 32978907c15b..8fab66b7ba55 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -101,6 +101,7 @@ public class Test3Controller : Controller { public void Setup(RazorViewEngineOptions o) { o.ViewLocationFormats.Add("/Views/Custom/{1}/{0}.cshtml"); o.ViewLocationFormats.Add("~/Views/Custom2/{0}.cshtml"); + o.AreaViewLocationFormats.Add("/MyAreas/{2}/{1}/{0}.cshtml"); } public IActionResult Test15(UserData tainted15) { @@ -132,7 +133,17 @@ public IActionResult test19(UserData tainted19) { } public IActionResult test20(UserData tainted20) { - // SPURIOUS: Expected to find nothing (and NOT /Views/Test4/Test20.cshtml). + // Expected to find nothing (and NOT /Views/Test4/Test20.cshtml). return View("Test20", tainted20); } + + public IActionResult test21(UserData tainted21) { + // Expected to find file /Pages/Shared/Test21.cshtml + return View("Test21", tainted21); + } + + public IActionResult test22(UserData tainted22) { + // Expected to find file /MyAreas/TestArea/Test4/Test22.cshtml + return View("Test22", tainted22); + } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/MyAreas_Test4_Test22.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/MyAreas_Test4_Test22.cshtml.g.cs new file mode 100644 index 000000000000..f8b2ecde53a4 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/MyAreas_Test4_Test22.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.MyAreas_Test4_Test22), @"mvc.1.0.view", @"/MyAreas/Test4/Test22.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/MyAreas/Test4/Test22.cshtml")] + public class MyAreas_Test4_Test22 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "MyAreas/Test4/Test22.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "MyAreas/Test4/Test22.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "MyAreas/Test4/Test22.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Pages_Shared_Test21.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Pages_Shared_Test21.cshtml.g.cs new file mode 100644 index 000000000000..483df5af705f --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Pages_Shared_Test21.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Pages_Shared_Test21), @"mvc.1.0.view", @"/Pages/Shared/Test21.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Pages/Shared/Test21.cshtml")] + public class Pages_Shared_Test21 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Pages/Shared/Test21.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Pages/Shared/Test21.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Pages/Shared/Test21.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/MyAreas/Test4/Test22.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/MyAreas/Test4/Test22.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/MyAreas/Test4/Test22.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Pages/Shared/Test21.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Pages/Shared/Test21.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Pages/Shared/Test21.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index 18680b978db9..795bc2e2f5db 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -33,18 +33,19 @@ edges | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | | Controllers/TestController.cs:97:64:97:64 | x : UserData | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | -| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | -| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | -| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | -| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | -| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | -| Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | +| Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | +| Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | @@ -57,7 +58,6 @@ edges | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | -| Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | @@ -99,18 +99,20 @@ nodes | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | | Controllers/TestController.cs:97:64:97:64 | x : UserData | semmle.label | x : UserData | | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | -| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | -| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | -| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | semmle.label | tainted16 : UserData | -| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | semmle.label | access to parameter tainted16 : UserData | -| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | semmle.label | tainted17 : UserData | -| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | semmle.label | access to parameter tainted17 : UserData | -| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | semmle.label | tainted18 : UserData | -| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | semmle.label | access to parameter tainted18 : UserData | -| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | semmle.label | tainted19 : UserData | -| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | -| Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | semmle.label | tainted20 : UserData | -| Controllers/TestController.cs:136:31:136:39 | access to parameter tainted20 : UserData | semmle.label | access to parameter tainted20 : UserData | +| Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | +| Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | semmle.label | tainted16 : UserData | +| Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | semmle.label | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | semmle.label | tainted17 : UserData | +| Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | semmle.label | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | semmle.label | tainted18 : UserData | +| Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | semmle.label | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | semmle.label | tainted19 : UserData | +| Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | semmle.label | tainted21 : UserData | +| Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | semmle.label | access to parameter tainted21 : UserData | +| Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | +| Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -135,8 +137,6 @@ nodes | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | -| Views/Test4/Test20.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | -| Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -147,10 +147,11 @@ nodes | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select -| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | User-provided value | -| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | User-provided value | -| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | User-provided value | -| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | User-provided value | +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | User-provided value | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | User-provided value | +| Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | User-provided value | +| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | User-provided value | +| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | User-provided value | | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | User-provided value | | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | User-provided value | | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | User-provided value | @@ -158,10 +159,9 @@ subpaths | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | User-provided value | | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | User-provided value | | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | User-provided value | -| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | User-provided value | +| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | User-provided value | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | User-provided value | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | User-provided value | -| Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | Views/Test4/Test20.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:134:42:134:50 | tainted20 : UserData | User-provided value | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | User-provided value | | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | User-provided value | | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | User-provided value | From 7371751801d6e68eb8cf5a16cf81322080916b95 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 24 Oct 2023 16:15:20 +0100 Subject: [PATCH 12/28] Add change note --- csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md diff --git a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md new file mode 100644 index 000000000000..04ed3b97aae1 --- /dev/null +++ b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +Additional flow steps have been added to the `cs/web/xss` query to track flow from a `View` call in an MVC controller to the corresponding Razor page. \ No newline at end of file From 0ed7b3c3adc33e6ff439eb44f556dd36bd264dc2 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 24 Oct 2023 17:26:35 +0100 Subject: [PATCH 13/28] Update qldoc --- .../lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll index 5dce1c2e6dd3..e0456f9ea32b 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll @@ -69,7 +69,7 @@ private class ViewCall extends MethodCall { ) } - /** `result` is `true` if this cal is from a controller that is an an Area, `false` otherwise. */ + /** `result` is `true` if this call is from a controller that is an Area, and `false` otherwise. */ boolean hasArea() { if exists(this.getAreaName()) then result = true else result = false } } From 047f8e485ae7e3857be995f1ddee1e3429f148a0 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 26 Oct 2023 14:05:20 +0100 Subject: [PATCH 14/28] Make the additional flow steps generally applicible to all queries --- .../dataflow/internal/TaintTrackingPrivate.qll | 5 ++++- .../dataflow/internal/TaintTrackingPublic.qll | 15 +++++++++++++++ .../XSSFlowSteps.qll => frameworks/Razor.qll} | 17 ++++------------- .../code/csharp/security/dataflow/XSSQuery.qll | 8 -------- .../change-notes/2023-10-24-xss-flow-steps.md | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-) rename csharp/ql/lib/semmle/code/csharp/{security/dataflow/XSSFlowSteps.qll => frameworks/Razor.qll} (90%) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index d7e2444c7d5c..dc923cefec1a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -9,9 +9,10 @@ private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.commons.ComparisonTest private import cil private import dotnet -// import `TaintedMember` definitions from other files to avoid potential reevaluation +// import `TaintedMember` and `AdditionalTaintStep` definitions from other files to avoid potential reevaluation private import semmle.code.csharp.frameworks.JsonNET private import semmle.code.csharp.frameworks.WCF +private import semmle.code.csharp.frameworks.Razor private import semmle.code.csharp.security.dataflow.flowsources.Remote /** @@ -160,6 +161,8 @@ private module Cached { nodeTo.(FlowSummaryNode).getSummaryNode(), false) or nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false) + or + any(AdditionalTaintStep step).step(nodeFrom, nodeTo) } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll index 1e60165d7484..9f91f517570b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll @@ -1,5 +1,6 @@ private import csharp private import TaintTrackingPrivate +private import codeql.util.Unit /** * Holds if taint propagates from `source` to `sink` in zero or more local @@ -20,4 +21,18 @@ predicate localExprTaint(Expr e1, Expr e2) { /** A member (property or field) that is tainted if its containing object is tainted. */ abstract class TaintedMember extends AssignableMember { } +/** + * A unit class for adding additional taint steps. + * + * Extend this class to add additional taint steps that should apply to all + * taint configurations. + */ +class AdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for all configurations. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); +} + predicate localTaintStep = localTaintStepImpl/2; diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll similarity index 90% rename from csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll rename to csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index e0456f9ea32b..c500de20ffc6 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSFlowSteps.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -1,19 +1,10 @@ -/** Definitions for additional flow steps for cross-site scripting (XSS) vulnerabilities. */ +/** Provides definitions and flow steps related to Razor pages. */ import csharp private import codeql.util.Unit private import codeql.util.FilePath private import semmle.code.csharp.frameworks.microsoft.AspNetCore -/** - * A unit class for providing additional flow steps for cross-site scripting (XSS) vulnerabilities. - * Extend to provide additional flow steps. - */ -class XssAdditionalFlowStep extends Unit { - /** Holds if there is an additional dataflow step from `node1` to `node2`. */ - abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2); -} - /** A call to the `View` method */ private class ViewCall extends MethodCall { ViewCall() { this.getTarget().hasQualifiedName("Microsoft.AspNetCore.Mvc", "Controller", "View") } @@ -74,7 +65,7 @@ private class ViewCall extends MethodCall { } /** A compiler-generated Razor page. */ -private class RazorPage extends Class { +class RazorPage extends Class { AssemblyAttribute attr; RazorPage() { @@ -90,8 +81,8 @@ private class RazorPage extends Class { string getSourceFilepath() { result = attr.getArgument(2).(StringLiteral).getValue() } } -private class ViewCallFlowStep extends XssAdditionalFlowStep { - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { +private class ViewCallFlowStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { exists(ViewCall vc, RazorPage rp, PropertyAccess modelProp | viewCallRefersToPage(vc, rp) and node1.asExpr() = vc.getModelArgument() and diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll index 248a3af45b0a..5ad2b6bc675a 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/XSSQuery.qll @@ -5,7 +5,6 @@ import csharp private import XSSSinks -private import XSSFlowSteps private import semmle.code.csharp.security.Sanitizers private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.dataflow.DataFlow2 @@ -167,13 +166,6 @@ module XssTrackingConfig implements DataFlow::ConfigSig { */ predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - /** - * Holds if there is an additional dataflow step from `node1` to `node2`. - */ - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - any(XssAdditionalFlowStep x).isAdditionalFlowStep(node1, node2) - } - /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. diff --git a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md index 04ed3b97aae1..1c25d743d2a5 100644 --- a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md +++ b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -Additional flow steps have been added to the `cs/web/xss` query to track flow from a `View` call in an MVC controller to the corresponding Razor page. \ No newline at end of file +Additional flow steps to track flow from a `View` call in an MVC controller to the corresponding Razor page, which may result in additional results for queries such as `cs/web/xss`. \ No newline at end of file From 2416040854ac9b8d1f2eeefa74194a297efaeec4 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Fri, 27 Oct 2023 11:44:07 +0100 Subject: [PATCH 15/28] Review suggestions - make import private and update change note --- csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll | 2 +- csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index c500de20ffc6..1567664b9bf6 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -1,6 +1,6 @@ /** Provides definitions and flow steps related to Razor pages. */ -import csharp +private import csharp private import codeql.util.Unit private import codeql.util.FilePath private import semmle.code.csharp.frameworks.microsoft.AspNetCore diff --git a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md index 1c25d743d2a5..46398e051f59 100644 --- a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md +++ b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -Additional flow steps to track flow from a `View` call in an MVC controller to the corresponding Razor page, which may result in additional results for queries such as `cs/web/xss`. \ No newline at end of file +* Modelled additional flow steps to track flow from a `View` call in an MVC controller to the corresponding Razor page, which may result in additional results for queries such as `cs/web/xss`. \ No newline at end of file From ef15980bb6d73bedff7e4346bd5f15cc02906c6d Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Fri, 27 Oct 2023 14:53:23 +0100 Subject: [PATCH 16/28] Remove unnecessary check for the name parameter as parameter 1 --- csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 1567664b9bf6..d9efaa2f0395 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -11,9 +11,9 @@ private class ViewCall extends MethodCall { /** Gets the `name` argument to this call, if any. */ string getNameArgument() { - exists(StringLiteral lit, int i | i in [0 .. 1] | - this.getTarget().getParameter(i).getType() instanceof StringType and - DataFlow::localExprFlow(lit, this.getArgument(i)) and + exists(StringLiteral lit | + this.getTarget().getParameter(0).getType() instanceof StringType and + DataFlow::localExprFlow(lit, this.getArgument(0)) and result = lit.getValue() ) } From 96bddde7c1d0570b271ff54fa1dcff937e7e280d Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 31 Oct 2023 15:52:42 +0000 Subject: [PATCH 17/28] Review suggestions - Remove unneeded import in tests, rename RazorPage to RazorPageClass --- .../semmle/code/csharp/frameworks/Razor.qll | 30 +-- .../Controllers/TestController.cs | 1 - .../CWE-079/XSSRazorPages/XSS.expected | 214 +++++++++--------- 3 files changed, 124 insertions(+), 121 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index d9efaa2f0395..13fd502548ea 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -65,10 +65,13 @@ private class ViewCall extends MethodCall { } /** A compiler-generated Razor page. */ -class RazorPage extends Class { +class RazorPageClass extends Class { AssemblyAttribute attr; - RazorPage() { + RazorPageClass() { + this.getBaseClass() + .getUnboundDeclaration() + .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage<>") and attr.getFile() = this.getFile() and attr.getType() .hasQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute") @@ -83,7 +86,7 @@ class RazorPage extends Class { private class ViewCallFlowStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node node1, DataFlow::Node node2) { - exists(ViewCall vc, RazorPage rp, PropertyAccess modelProp | + exists(ViewCall vc, RazorPageClass rp, PropertyAccess modelProp | viewCallRefersToPage(vc, rp) and node1.asExpr() = vc.getModelArgument() and node2.asExpr() = modelProp and @@ -93,23 +96,24 @@ private class ViewCallFlowStep extends TaintTracking::AdditionalTaintStep { } } -private predicate viewCallRefersToPage(ViewCall vc, RazorPage rp) { +private predicate viewCallRefersToPage(ViewCall vc, RazorPageClass rp) { viewCallRefersToPageAbsolute(vc, rp) or viewCallRefersToPageRelative(vc, rp) } -private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) { +private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPageClass rp) { ["/", ""] + vc.getNameArgument() = ["", "~"] + rp.getSourceFilepath() } -private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) { - ["", "~"] + rp.getSourceFilepath() = - min(int i, RelativeViewCallFilepath fp | - fp.hasViewCallWithIndex(vc, i) and - exists(RazorPage rp2 | ["", "~"] + rp2.getSourceFilepath() = fp.getNormalizedPath()) - | - fp.getNormalizedPath() order by i - ) +private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { + rp = min(int i, RazorPageClass rp2 | matchesViewCallWithIndex(vc, rp2, i) | rp2 order by i) +} + +private predicate matchesViewCallWithIndex(ViewCall vc, RazorPageClass rp, int i) { + exists(RelativeViewCallFilepath fp | + fp.hasViewCallWithIndex(vc, i) and + fp.getNormalizedPath() = ["", "~"] + rp.getSourceFilepath() + ) } /** Gets the `i`th template for view discovery. */ diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index 8fab66b7ba55..007a54dd67f0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -2,7 +2,6 @@ namespace test; using System.Net; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Razor; public class UserData diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index 795bc2e2f5db..fa6e276eb82d 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -1,50 +1,50 @@ edges | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | -| Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | -| Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | -| Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | -| Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | -| Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | -| Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | -| Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | -| Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | -| Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | -| Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | -| Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | -| Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:71:43:71:43 | x : UserData | -| Controllers/TestController.cs:71:43:71:43 | x : UserData | Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | -| Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | -| Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | Controllers/TestController.cs:95:64:95:64 | x : UserData | -| Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | -| Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | Controllers/TestController.cs:97:64:97:64 | x : UserData | -| Controllers/TestController.cs:95:64:95:64 | x : UserData | Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | -| Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:97:64:97:64 | x : UserData | Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | -| Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | -| Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | -| Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | -| Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | -| Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | -| Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | -| Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | -| Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | Controllers/TestController.cs:70:43:70:43 | x : UserData | +| Controllers/TestController.cs:70:43:70:43 | x : UserData | Controllers/TestController.cs:70:70:70:70 | access to parameter x : UserData | +| Controllers/TestController.cs:70:70:70:70 | access to parameter x : UserData | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:81:42:81:50 | tainted13 : UserData | Controllers/TestController.cs:83:37:83:45 | access to parameter tainted13 : UserData | +| Controllers/TestController.cs:83:37:83:45 | access to parameter tainted13 : UserData | Controllers/TestController.cs:94:64:94:64 | x : UserData | +| Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | Controllers/TestController.cs:88:37:88:45 | access to parameter tainted14 : UserData | +| Controllers/TestController.cs:88:37:88:45 | access to parameter tainted14 : UserData | Controllers/TestController.cs:96:64:96:64 | x : UserData | +| Controllers/TestController.cs:94:64:94:64 | x : UserData | Controllers/TestController.cs:94:113:94:113 | access to parameter x : UserData | +| Controllers/TestController.cs:94:113:94:113 | access to parameter x : UserData | Views/Other/Test13.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:96:64:96:64 | x : UserData | Controllers/TestController.cs:96:93:96:93 | access to parameter x : UserData | +| Controllers/TestController.cs:96:93:96:93 | access to parameter x : UserData | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | +| Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | @@ -67,50 +67,50 @@ nodes | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | -| Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | -| Controllers/TestController.cs:16:30:16:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | -| Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | -| Controllers/TestController.cs:21:30:21:37 | access to parameter tainted2 : UserData | semmle.label | access to parameter tainted2 : UserData | -| Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | semmle.label | tainted3 : UserData | -| Controllers/TestController.cs:26:30:26:37 | access to parameter tainted3 : UserData | semmle.label | access to parameter tainted3 : UserData | -| Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | semmle.label | tainted4 : UserData | -| Controllers/TestController.cs:31:32:31:39 | access to parameter tainted4 : UserData | semmle.label | access to parameter tainted4 : UserData | -| Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | semmle.label | tainted5 : UserData | -| Controllers/TestController.cs:36:39:36:46 | access to parameter tainted5 : UserData | semmle.label | access to parameter tainted5 : UserData | -| Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | semmle.label | tainted6 : UserData | -| Controllers/TestController.cs:41:64:41:71 | access to parameter tainted6 : UserData | semmle.label | access to parameter tainted6 : UserData | -| Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | semmle.label | tainted7 : UserData | -| Controllers/TestController.cs:46:21:46:28 | access to parameter tainted7 : UserData | semmle.label | access to parameter tainted7 : UserData | -| Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | semmle.label | tainted8 : UserData | -| Controllers/TestController.cs:51:50:51:57 | access to parameter tainted8 : UserData | semmle.label | access to parameter tainted8 : UserData | -| Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | semmle.label | tainted9 : UserData | -| Controllers/TestController.cs:56:51:56:58 | access to parameter tainted9 : UserData | semmle.label | access to parameter tainted9 : UserData | -| Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | semmle.label | tainted10 : UserData | -| Controllers/TestController.cs:63:31:63:39 | access to parameter tainted10 : UserData | semmle.label | access to parameter tainted10 : UserData | -| Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | semmle.label | tainted11 : UserData | -| Controllers/TestController.cs:68:23:68:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | -| Controllers/TestController.cs:71:43:71:43 | x : UserData | semmle.label | x : UserData | -| Controllers/TestController.cs:71:70:71:70 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | -| Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | semmle.label | tainted13 : UserData | -| Controllers/TestController.cs:84:37:84:45 | access to parameter tainted13 : UserData | semmle.label | access to parameter tainted13 : UserData | -| Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | semmle.label | tainted14 : UserData | -| Controllers/TestController.cs:89:37:89:45 | access to parameter tainted14 : UserData | semmle.label | access to parameter tainted14 : UserData | -| Controllers/TestController.cs:95:64:95:64 | x : UserData | semmle.label | x : UserData | -| Controllers/TestController.cs:95:113:95:113 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | -| Controllers/TestController.cs:97:64:97:64 | x : UserData | semmle.label | x : UserData | -| Controllers/TestController.cs:97:93:97:93 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | -| Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | -| Controllers/TestController.cs:109:21:109:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | -| Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | semmle.label | tainted16 : UserData | -| Controllers/TestController.cs:114:31:114:39 | access to parameter tainted16 : UserData | semmle.label | access to parameter tainted16 : UserData | -| Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | semmle.label | tainted17 : UserData | -| Controllers/TestController.cs:122:31:122:39 | access to parameter tainted17 : UserData | semmle.label | access to parameter tainted17 : UserData | -| Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | semmle.label | tainted18 : UserData | -| Controllers/TestController.cs:127:31:127:39 | access to parameter tainted18 : UserData | semmle.label | access to parameter tainted18 : UserData | -| Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | semmle.label | tainted19 : UserData | -| Controllers/TestController.cs:132:31:132:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | -| Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | semmle.label | tainted21 : UserData | -| Controllers/TestController.cs:142:31:142:39 | access to parameter tainted21 : UserData | semmle.label | access to parameter tainted21 : UserData | +| Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | semmle.label | tainted1 : UserData | +| Controllers/TestController.cs:15:30:15:37 | access to parameter tainted1 : UserData | semmle.label | access to parameter tainted1 : UserData | +| Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | semmle.label | tainted2 : UserData | +| Controllers/TestController.cs:20:30:20:37 | access to parameter tainted2 : UserData | semmle.label | access to parameter tainted2 : UserData | +| Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | semmle.label | tainted3 : UserData | +| Controllers/TestController.cs:25:30:25:37 | access to parameter tainted3 : UserData | semmle.label | access to parameter tainted3 : UserData | +| Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | semmle.label | tainted4 : UserData | +| Controllers/TestController.cs:30:32:30:39 | access to parameter tainted4 : UserData | semmle.label | access to parameter tainted4 : UserData | +| Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | semmle.label | tainted5 : UserData | +| Controllers/TestController.cs:35:39:35:46 | access to parameter tainted5 : UserData | semmle.label | access to parameter tainted5 : UserData | +| Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | semmle.label | tainted6 : UserData | +| Controllers/TestController.cs:40:64:40:71 | access to parameter tainted6 : UserData | semmle.label | access to parameter tainted6 : UserData | +| Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | semmle.label | tainted7 : UserData | +| Controllers/TestController.cs:45:21:45:28 | access to parameter tainted7 : UserData | semmle.label | access to parameter tainted7 : UserData | +| Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | semmle.label | tainted8 : UserData | +| Controllers/TestController.cs:50:50:50:57 | access to parameter tainted8 : UserData | semmle.label | access to parameter tainted8 : UserData | +| Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | semmle.label | tainted9 : UserData | +| Controllers/TestController.cs:55:51:55:58 | access to parameter tainted9 : UserData | semmle.label | access to parameter tainted9 : UserData | +| Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | semmle.label | tainted10 : UserData | +| Controllers/TestController.cs:62:31:62:39 | access to parameter tainted10 : UserData | semmle.label | access to parameter tainted10 : UserData | +| Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | semmle.label | tainted11 : UserData | +| Controllers/TestController.cs:67:23:67:31 | access to parameter tainted11 : UserData | semmle.label | access to parameter tainted11 : UserData | +| Controllers/TestController.cs:70:43:70:43 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:70:70:70:70 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:81:42:81:50 | tainted13 : UserData | semmle.label | tainted13 : UserData | +| Controllers/TestController.cs:83:37:83:45 | access to parameter tainted13 : UserData | semmle.label | access to parameter tainted13 : UserData | +| Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | semmle.label | tainted14 : UserData | +| Controllers/TestController.cs:88:37:88:45 | access to parameter tainted14 : UserData | semmle.label | access to parameter tainted14 : UserData | +| Controllers/TestController.cs:94:64:94:64 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:94:113:94:113 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:96:64:96:64 | x : UserData | semmle.label | x : UserData | +| Controllers/TestController.cs:96:93:96:93 | access to parameter x : UserData | semmle.label | access to parameter x : UserData | +| Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | semmle.label | tainted15 : UserData | +| Controllers/TestController.cs:108:21:108:29 | access to parameter tainted15 : UserData | semmle.label | access to parameter tainted15 : UserData | +| Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | semmle.label | tainted16 : UserData | +| Controllers/TestController.cs:113:31:113:39 | access to parameter tainted16 : UserData | semmle.label | access to parameter tainted16 : UserData | +| Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | semmle.label | tainted17 : UserData | +| Controllers/TestController.cs:121:31:121:39 | access to parameter tainted17 : UserData | semmle.label | access to parameter tainted17 : UserData | +| Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | semmle.label | tainted18 : UserData | +| Controllers/TestController.cs:126:31:126:39 | access to parameter tainted18 : UserData | semmle.label | access to parameter tainted18 : UserData | +| Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | semmle.label | tainted19 : UserData | +| Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | +| Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | semmle.label | tainted21 : UserData | +| Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | semmle.label | access to parameter tainted21 : UserData | | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -147,22 +147,22 @@ nodes | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | subpaths #select -| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:125:42:125:50 | tainted18 : UserData | User-provided value | -| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:120:42:120:50 | tainted17 : UserData | User-provided value | -| Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:140:42:140:50 | tainted21 : UserData | User-provided value | -| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:112:42:112:50 | tainted16 : UserData | User-provided value | -| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:107:42:107:50 | tainted15 : UserData | User-provided value | -| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:34:41:34:48 | tainted5 : UserData | User-provided value | -| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:39:41:39:48 | tainted6 : UserData | User-provided value | -| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:49:41:49:48 | tainted8 : UserData | User-provided value | -| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:54:41:54:48 | tainted9 : UserData | User-provided value | -| Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:82:42:82:50 | tainted13 : UserData | User-provided value | -| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:19:41:19:48 | tainted2 : UserData | User-provided value | -| Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:87:42:87:50 | tainted14 : UserData | User-provided value | -| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:130:42:130:50 | tainted19 : UserData | User-provided value | -| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:61:42:61:50 | tainted10 : UserData | User-provided value | -| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:66:42:66:50 | tainted11 : UserData | User-provided value | -| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:14:41:14:48 | tainted1 : UserData | User-provided value | -| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:24:41:24:48 | tainted3 : UserData | User-provided value | -| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:29:41:29:48 | tainted4 : UserData | User-provided value | -| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:44:41:44:48 | tainted7 : UserData | User-provided value | +| Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | Areas/TestArea/Views/Shared/Test18.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:124:42:124:50 | tainted18 : UserData | User-provided value | +| Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | Areas/TestArea/Views/Test4/Test17.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:119:42:119:50 | tainted17 : UserData | User-provided value | +| Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | User-provided value | +| Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:111:42:111:50 | tainted16 : UserData | User-provided value | +| Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:106:42:106:50 | tainted15 : UserData | User-provided value | +| Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | Views/Other/Test5.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:33:41:33:48 | tainted5 : UserData | User-provided value | +| Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | Views/Other/Test6.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:38:41:38:48 | tainted6 : UserData | User-provided value | +| Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | Views/Other/Test8.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:48:41:48:48 | tainted8 : UserData | User-provided value | +| Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | Views/Other/Test9.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:53:41:53:48 | tainted9 : UserData | User-provided value | +| Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:81:42:81:50 | tainted13 : UserData | Views/Other/Test13.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:81:42:81:50 | tainted13 : UserData | User-provided value | +| Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | User-provided value | +| Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | User-provided value | +| Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | User-provided value | +| Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | User-provided value | +| Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | User-provided value | +| Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | User-provided value | +| Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | Views/Test/Test3.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:23:41:23:48 | tainted3 : UserData | User-provided value | +| Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | Views/Test/Test4.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:28:41:28:48 | tainted4 : UserData | User-provided value | +| Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | Views/Test/Test7.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:43:41:43:48 | tainted7 : UserData | User-provided value | From 052166f17ed2010fb3270bf3607ff8240ad85b4b Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 1 Nov 2023 16:29:34 +0000 Subject: [PATCH 18/28] Fix issue in genfiles.py + add help text --- .../CWE-079/XSSRazorPages/gen_files.py | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py index 01861cb50dae..a01398e8201b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/gen_files.py @@ -3,11 +3,13 @@ import sys import os -work_dir = os.path.dirname(sys.argv[0]) +work_dir = os.path.abspath(os.path.dirname(sys.argv[0])) gen_dir = f"{work_dir}/Generated" with open(f"{gen_dir}/Template.g") as f: template = f.read() +verbose = False + def process_file(path: str): """ @@ -21,9 +23,13 @@ def process_file(path: str): gen = template.replace("$PATHSLASH", path).replace("$PATHUNDER", path_under) - with open(f"{gen_dir}/{path_under}.cshtml.g.cs", "w") as f: + out_path = f"{gen_dir}/{path_under}.cshtml.g.cs" + with open(out_path, "w") as f: f.write(gen) + if verbose: + print(out_path) + def process_dir(path: str): """ @@ -43,4 +49,22 @@ def process_dir(path: str): process_dir(sub_rel) -process_dir("") +def print_usage(): + print("""Usage: python3 gen_files.py [-v] [--verbose] [-h] [--help] + +Generates files from .cshtml files found in the directory tree of this script's parent folder, mimicking the C# compiler. +`.testproj` is ignored. + +-h, --help: Displays this message and exits. +-v, --verbose: Prints the name of each file generated.""") + + +if __name__ == "__main__": + if "-h" in sys.argv or "--help" in sys.argv: + print_usage() + exit() + + if "-v" in sys.argv or "--verbose" in sys.argv: + verbose = True + + process_dir("") From 9af44ed0a2577ac741759c35c421c98b9dd8e7d0 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 7 Nov 2023 10:59:50 +0000 Subject: [PATCH 19/28] Convert flow steps to value steps --- .../dataflow/internal/DataFlowPrivate.qll | 1 + .../internal/TaintTrackingPrivate.qll | 1 - .../semmle/code/csharp/frameworks/Razor.qll | 19 +++-- .../Controllers/TestController.cs | 7 ++ .../Generated/Views_Shared_Test23.cshtml.g.cs | 74 +++++++++++++++++++ .../XSSRazorPages/Views/Shared/Test23.cshtml | 9 +++ .../CWE-079/XSSRazorPages/XSS.expected | 12 +++ 7 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test23.cshtml.g.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test23.cshtml diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index fb9a0c6b13cc..37b493e001f6 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -15,6 +15,7 @@ private import semmle.code.csharp.controlflow.Guards private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.frameworks.EntityFramework private import semmle.code.csharp.frameworks.NHibernate +private import semmle.code.csharp.frameworks.Razor private import semmle.code.csharp.frameworks.system.Collections private import semmle.code.csharp.frameworks.system.threading.Tasks private import semmle.code.cil.Ssa::Ssa as CilSsa diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index dc923cefec1a..5bcf873e45d8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -12,7 +12,6 @@ private import dotnet // import `TaintedMember` and `AdditionalTaintStep` definitions from other files to avoid potential reevaluation private import semmle.code.csharp.frameworks.JsonNET private import semmle.code.csharp.frameworks.WCF -private import semmle.code.csharp.frameworks.Razor private import semmle.code.csharp.security.dataflow.flowsources.Remote /** diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 13fd502548ea..51e495459d0d 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -84,12 +84,19 @@ class RazorPageClass extends Class { string getSourceFilepath() { result = attr.getArgument(2).(StringLiteral).getValue() } } -private class ViewCallFlowStep extends TaintTracking::AdditionalTaintStep { - override predicate step(DataFlow::Node node1, DataFlow::Node node2) { - exists(ViewCall vc, RazorPageClass rp, PropertyAccess modelProp | - viewCallRefersToPage(vc, rp) and - node1.asExpr() = vc.getModelArgument() and - node2.asExpr() = modelProp and +private class ViewCallJumpNode extends DataFlow::NonLocalJumpNode { + ViewCall vc; + RazorPageClass rp; + + ViewCallJumpNode() { + viewCallRefersToPage(vc, rp) and + this.asExpr() = vc.getModelArgument() + } + + override DataFlow::Node getAJumpSuccessor(boolean preservesValue) { + preservesValue = true and + exists(PropertyAccess modelProp | + result.asExpr() = modelProp and modelProp.getTarget().hasName("Model") and modelProp.getEnclosingCallable().getDeclaringType() = rp ) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs index 007a54dd67f0..001c83b9f345 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Controllers/TestController.cs @@ -145,4 +145,11 @@ public IActionResult test22(UserData tainted22) { // Expected to find file /MyAreas/TestArea/Test4/Test22.cshtml return View("Test22", tainted22); } + + public IActionResult test23(string tainted23) { + // Expected to find file /Views/Shared/Test23.cshtml + UserData x = new UserData(); + x.Name = tainted23; + return View("Test23", x); + } } \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test23.cshtml.g.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test23.cshtml.g.cs new file mode 100644 index 000000000000..919c874680b8 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Generated/Views_Shared_Test23.cshtml.g.cs @@ -0,0 +1,74 @@ +// A test file that mimics the output of compiling a `.cshtml` file +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(test.Views.Views_Shared_Test23), @"mvc.1.0.view", @"/Views/Shared/Test23.cshtml")] +namespace test.Views +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewFeatures; +#nullable restore +using test; + +#line default +#line hidden +#nullable disable + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Shared/Test23.cshtml")] + public class Views_Shared_Test23 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + { + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#line 6 "Views/Shared/Test23.cshtml" + if (Model != null) +{ + +#line default +#line hidden +#nullable disable + WriteLiteral("

Hello \""); +#nullable restore +#line 8 "Views/Shared/Test23.cshtml" +Write(Html.Raw(Model.Name)); + +#line default +#line hidden +#nullable disable + WriteLiteral("\"

\n"); +#nullable restore +#line 9 "Views/Shared/Test23.cshtml" +} + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test23.cshtml b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test23.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/Views/Shared/Test23.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected index fa6e276eb82d..19413509bcb4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSRazorPages/XSS.expected @@ -45,6 +45,10 @@ edges | Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | | Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | | Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | +| Controllers/TestController.cs:149:40:149:48 | tainted23 : String | Controllers/TestController.cs:152:18:152:26 | access to parameter tainted23 : String | +| Controllers/TestController.cs:152:9:152:9 | [post] access to local variable x : UserData [property Name] : String | Controllers/TestController.cs:153:31:153:31 | access to local variable x : UserData [property Name] : String | +| Controllers/TestController.cs:152:18:152:26 | access to parameter tainted23 : String | Controllers/TestController.cs:152:9:152:9 | [post] access to local variable x : UserData [property Name] : String | +| Controllers/TestController.cs:153:31:153:31 | access to local variable x : UserData [property Name] : String | Views/Shared/Test23.cshtml:8:16:8:20 | access to property Model : UserData [property Name] : String | | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom2/Test16.cshtml:8:16:8:25 | access to property Name | | Views/Custom/Test3/Test15.cshtml:8:16:8:20 | access to property Model : UserData | Views/Custom/Test3/Test15.cshtml:8:16:8:25 | access to property Name | @@ -56,6 +60,7 @@ edges | Views/Shared/Test2.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | | Views/Shared/Test14.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | +| Views/Shared/Test23.cshtml:8:16:8:20 | access to property Model : UserData [property Name] : String | Views/Shared/Test23.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | | Views/Test/Test1.cshtml:8:16:8:20 | access to property Model : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | @@ -111,6 +116,10 @@ nodes | Controllers/TestController.cs:131:31:131:39 | access to parameter tainted19 : UserData | semmle.label | access to parameter tainted19 : UserData | | Controllers/TestController.cs:139:42:139:50 | tainted21 : UserData | semmle.label | tainted21 : UserData | | Controllers/TestController.cs:141:31:141:39 | access to parameter tainted21 : UserData | semmle.label | access to parameter tainted21 : UserData | +| Controllers/TestController.cs:149:40:149:48 | tainted23 : String | semmle.label | tainted23 : String | +| Controllers/TestController.cs:152:9:152:9 | [post] access to local variable x : UserData [property Name] : String | semmle.label | [post] access to local variable x : UserData [property Name] : String | +| Controllers/TestController.cs:152:18:152:26 | access to parameter tainted23 : String | semmle.label | access to parameter tainted23 : String | +| Controllers/TestController.cs:153:31:153:31 | access to local variable x : UserData [property Name] : String | semmle.label | access to local variable x : UserData [property Name] : String | | Pages/Shared/Test21.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Pages/Shared/Test21.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Custom2/Test16.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -133,6 +142,8 @@ nodes | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Shared/Test19.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | +| Views/Shared/Test23.cshtml:8:16:8:20 | access to property Model : UserData [property Name] : String | semmle.label | access to property Model : UserData [property Name] : String | +| Views/Shared/Test23.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test10.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | semmle.label | access to property Name | | Views/Test2/Test11.cshtml:8:16:8:20 | access to property Model : UserData | semmle.label | access to property Model : UserData | @@ -160,6 +171,7 @@ subpaths | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | Views/Shared/Test2.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:18:41:18:48 | tainted2 : UserData | User-provided value | | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | Views/Shared/Test14.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:86:42:86:50 | tainted14 : UserData | User-provided value | | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | Views/Shared/Test19.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:129:42:129:50 | tainted19 : UserData | User-provided value | +| Views/Shared/Test23.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:149:40:149:48 | tainted23 : String | Views/Shared/Test23.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:149:40:149:48 | tainted23 : String | User-provided value | | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | Views/Test2/Test10.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:60:42:60:50 | tainted10 : UserData | User-provided value | | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | Views/Test2/Test11.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:65:42:65:50 | tainted11 : UserData | User-provided value | | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | Views/Test/Test1.cshtml:8:16:8:25 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:41:13:48 | tainted1 : UserData | User-provided value | From 7a098dde509519a643a14b8d7a9786db64145d0a Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 7 Nov 2023 11:03:49 +0000 Subject: [PATCH 20/28] Remove AdditionalTaintStep (redundant with NonLocalJumpNode) --- .../dataflow/internal/TaintTrackingPrivate.qll | 4 +--- .../dataflow/internal/TaintTrackingPublic.qll | 14 -------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index 5bcf873e45d8..d7e2444c7d5c 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -9,7 +9,7 @@ private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.commons.ComparisonTest private import cil private import dotnet -// import `TaintedMember` and `AdditionalTaintStep` definitions from other files to avoid potential reevaluation +// import `TaintedMember` definitions from other files to avoid potential reevaluation private import semmle.code.csharp.frameworks.JsonNET private import semmle.code.csharp.frameworks.WCF private import semmle.code.csharp.security.dataflow.flowsources.Remote @@ -160,8 +160,6 @@ private module Cached { nodeTo.(FlowSummaryNode).getSummaryNode(), false) or nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false) - or - any(AdditionalTaintStep step).step(nodeFrom, nodeTo) } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll index 9f91f517570b..878e235bb837 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll @@ -21,18 +21,4 @@ predicate localExprTaint(Expr e1, Expr e2) { /** A member (property or field) that is tainted if its containing object is tainted. */ abstract class TaintedMember extends AssignableMember { } -/** - * A unit class for adding additional taint steps. - * - * Extend this class to add additional taint steps that should apply to all - * taint configurations. - */ -class AdditionalTaintStep extends Unit { - /** - * Holds if the step from `node1` to `node2` should be considered a taint - * step for all configurations. - */ - abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); -} - predicate localTaintStep = localTaintStepImpl/2; From e2e4642037352834c217f9bf6aad073d8f4352a9 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 7 Nov 2023 13:08:58 +0000 Subject: [PATCH 21/28] Remove redundant import --- .../semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll index 878e235bb837..1e60165d7484 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll @@ -1,6 +1,5 @@ private import csharp private import TaintTrackingPrivate -private import codeql.util.Unit /** * Holds if taint propagates from `source` to `sink` in zero or more local From 26c048a650f52dac4692d746b778233f9d114094 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 7 Nov 2023 16:12:01 +0000 Subject: [PATCH 22/28] Minor refactoring --- .../lib/semmle/code/csharp/frameworks/Razor.qll | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 51e495459d0d..9a921085527b 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -85,12 +85,13 @@ class RazorPageClass extends Class { } private class ViewCallJumpNode extends DataFlow::NonLocalJumpNode { - ViewCall vc; RazorPageClass rp; ViewCallJumpNode() { - viewCallRefersToPage(vc, rp) and - this.asExpr() = vc.getModelArgument() + exists(ViewCall vc | + viewCallRefersToPage(vc, rp) and + this.asExpr() = vc.getModelArgument() + ) } override DataFlow::Node getAJumpSuccessor(boolean preservesValue) { @@ -108,8 +109,11 @@ private predicate viewCallRefersToPage(ViewCall vc, RazorPageClass rp) { viewCallRefersToPageRelative(vc, rp) } +bindingset[path] +private string stripTilde(string path) { result = path.regexpReplaceAll("^~/", "/") } + private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPageClass rp) { - ["/", ""] + vc.getNameArgument() = ["", "~"] + rp.getSourceFilepath() + ["/", ""] + stripTilde(vc.getNameArgument()) = rp.getSourceFilepath() } private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { @@ -119,7 +123,7 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { private predicate matchesViewCallWithIndex(ViewCall vc, RazorPageClass rp, int i) { exists(RelativeViewCallFilepath fp | fp.hasViewCallWithIndex(vc, i) and - fp.getNormalizedPath() = ["", "~"] + rp.getSourceFilepath() + fp.getNormalizedPath() = rp.getSourceFilepath() ) } @@ -183,7 +187,7 @@ private class RelativeViewCallFilepath extends NormalizableFilepath { else sub1 = sub2 ) and sub0 = sub1.replaceAll("{0}", vc_.getActionName()) and - this = sub0 + this = stripTilde(sub0) ) } From 82fbae3e5a1820b17427c9b7c9e489486b255ce0 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 9 Nov 2023 11:47:02 +0000 Subject: [PATCH 23/28] Handle standalone extraction case in which generated files list absolute paths --- .../semmle/code/csharp/frameworks/Razor.qll | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 9a921085527b..f7989d1a0d7b 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -78,12 +78,28 @@ class RazorPageClass extends Class { } /** - * Gets the filepath of the source file that this class was generated from, - * relative to the application root. + * Gets the filepath of the source file that this class was generated from. + * + * This is an absolute path if the database was extracted in standalone mode, + * and is relative to to application root (the directory containing the .csproj file) otherwise. */ string getSourceFilepath() { result = attr.getArgument(2).(StringLiteral).getValue() } } +/** + * Gets a possible prefix to be applied to view search paths to locate a Razor page. + * This may be empty (for the case that the generated Razor page files contain paths relative to the application root), + * or the absolute path of the directory containing the .csproj file (for the case that standalone extraction is used and the generated files contain absolute paths). + */ +private string getARazorPathPrefix() { + result = "" + or + exists(File csproj | + csproj.getExtension() = "csproj" and + result = csproj.getParentContainer().getAbsolutePath() + ) +} + private class ViewCallJumpNode extends DataFlow::NonLocalJumpNode { RazorPageClass rp; @@ -113,7 +129,7 @@ bindingset[path] private string stripTilde(string path) { result = path.regexpReplaceAll("^~/", "/") } private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPageClass rp) { - ["/", ""] + stripTilde(vc.getNameArgument()) = rp.getSourceFilepath() + getARazorPathPrefix() + ["/", ""] + stripTilde(vc.getNameArgument()) = rp.getSourceFilepath() } private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { @@ -123,7 +139,7 @@ private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { private predicate matchesViewCallWithIndex(ViewCall vc, RazorPageClass rp, int i) { exists(RelativeViewCallFilepath fp | fp.hasViewCallWithIndex(vc, i) and - fp.getNormalizedPath() = rp.getSourceFilepath() + getARazorPathPrefix() + fp.getNormalizedPath() = rp.getSourceFilepath() ) } From 33186ac797088f73b5034c8a66a27ba83b899dc9 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 13 Nov 2023 18:39:36 +0000 Subject: [PATCH 24/28] Add integration tests --- .../Controllers/TestController.cs | 16 ++++++++++++++++ .../Views/Test/Test.cshtml | 9 +++++++++ .../cshtml_standalone_flowsteps/XSS.expected | 0 .../cshtml_standalone_flowsteps/XSS.qlref | 1 + .../cshtml_standalone_flowsteps/cshtml.csproj | 0 .../cshtml_standalone_flowsteps/test.py | 6 ++++++ 6 files changed, 32 insertions(+) create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Controllers/TestController.cs create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/test.py diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Controllers/TestController.cs b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Controllers/TestController.cs new file mode 100644 index 000000000000..48d4b340fbf8 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Controllers/TestController.cs @@ -0,0 +1,16 @@ +namespace test; + +using System.Net; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Razor; + +public class UserData +{ + public string Name { get; set; } +} + +public class TestController : Controller { + public IActionResult Test(UserData tainted1) { + return View("Test", tainted1); + } +} \ No newline at end of file diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml new file mode 100644 index 000000000000..74a8eab1c715 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml @@ -0,0 +1,9 @@ +@namespace test +@model UserData +@{ +} + +@if (Model != null) +{ +

Hello "@Html.Raw(Model.Name)"

+} \ No newline at end of file diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref new file mode 100644 index 000000000000..faad1d6403c1 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref @@ -0,0 +1 @@ +Security Features/CWE-079/XSS.ql \ No newline at end of file diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/test.py b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/test.py new file mode 100644 index 000000000000..5fa07537d4ae --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/test.py @@ -0,0 +1,6 @@ +import os +from create_database_utils import * + + +os.environ['CODEQL_EXTRACTOR_CSHARP_STANDALONE_EXTRACT_WEB_VIEWS'] = 'true' +run_codeql_database_create(lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"]) From aa3fd6add0e9d7baef56ba10efe686f1d6267a29 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 15 Nov 2023 17:07:47 +0000 Subject: [PATCH 25/28] Fix standalone tests --- .../Views/Test/Test.cshtml | 5 ++--- .../Views/_ViewImports.cshtml | 3 +++ .../cshtml_standalone_flowsteps/XSS.expected | 1 + .../cshtml_standalone_flowsteps/XSS.ql | 21 +++++++++++++++++++ .../cshtml_standalone_flowsteps/XSS.qlref | 1 - .../cshtml_standalone_flowsteps/cshtml.csproj | 9 ++++++++ .../semmle/code/csharp/frameworks/Razor.qll | 8 ++++--- 7 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/_ViewImports.cshtml create mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.ql delete mode 100644 csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml index 74a8eab1c715..3489539fe87c 100644 --- a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/Test/Test.cshtml @@ -1,7 +1,6 @@ -@namespace test +@page + @model UserData -@{ -} @if (Model != null) { diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/_ViewImports.cshtml b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/_ViewImports.cshtml new file mode 100644 index 000000000000..f4d0ca8def7f --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/Views/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using test + +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected index e69de29bb2d1..c5e1e6db6d6c 100644 --- a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.expected @@ -0,0 +1 @@ +| Views/Test/Test.cshtml:7:27:7:36 | access to property Name | Controllers/TestController.cs:13:40:13:47 | tainted1 : UserData | Views/Test/Test.cshtml:7:27:7:36 | access to property Name | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Controllers/TestController.cs:13:40:13:47 | tainted1 : UserData | User-provided value | diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.ql b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.ql new file mode 100644 index 000000000000..762d792b92f7 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.ql @@ -0,0 +1,21 @@ +/** + * @name Cross-site scripting + * @description Writing user input directly to a web page + * allows for a cross-site scripting vulnerability. + * @kind path-problem + * @problem.severity error + * @security-severity 6.1 + * @precision high + * @id cs/web/xss + * @tags security + * external/cwe/cwe-079 + * external/cwe/cwe-116 + */ + +import csharp +import semmle.code.csharp.security.dataflow.XSSQuery + +// import PathGraph // exclude query predicates with output dependant on the absolute filepath the tests are run in +from XssNode source, XssNode sink, string message +where xssFlow(source, sink, message) +select sink, source, sink, "$@ flows to here and " + message, source, "User-provided value" diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref deleted file mode 100644 index faad1d6403c1..000000000000 --- a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/XSS.qlref +++ /dev/null @@ -1 +0,0 @@ -Security Features/CWE-079/XSS.ql \ No newline at end of file diff --git a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj index e69de29bb2d1..e580f24c65d6 100644 --- a/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj +++ b/csharp/ql/integration-tests/all-platforms/cshtml_standalone_flowsteps/cshtml.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + \ No newline at end of file diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index f7989d1a0d7b..0259585ec1bf 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -69,9 +69,11 @@ class RazorPageClass extends Class { AssemblyAttribute attr; RazorPageClass() { - this.getBaseClass() - .getUnboundDeclaration() - .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage<>") and + exists(Class baseClass | baseClass = this.getBaseClass().getUnboundDeclaration() | + baseClass.hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage<>") + or + baseClass.hasQualifiedName("Microsoft.AspNetCore.Mvc.RazorPages", "Page") + ) and attr.getFile() = this.getFile() and attr.getType() .hasQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute") From f24c042d04249ad47ac477a4a4f227cd0b04c983 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 16 Nov 2023 10:50:22 +0000 Subject: [PATCH 26/28] Rename Razor Page class to Razor View class --- .../semmle/code/csharp/frameworks/Razor.qll | 18 +++++++++--------- .../change-notes/2023-10-24-xss-flow-steps.md | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 0259585ec1bf..155841361368 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -64,11 +64,11 @@ private class ViewCall extends MethodCall { boolean hasArea() { if exists(this.getAreaName()) then result = true else result = false } } -/** A compiler-generated Razor page. */ -class RazorPageClass extends Class { +/** A compiler-generated Razor page from a `.cshtml` file. */ +class RazorViewClass extends Class { AssemblyAttribute attr; - RazorPageClass() { + RazorViewClass() { exists(Class baseClass | baseClass = this.getBaseClass().getUnboundDeclaration() | baseClass.hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage<>") or @@ -103,7 +103,7 @@ private string getARazorPathPrefix() { } private class ViewCallJumpNode extends DataFlow::NonLocalJumpNode { - RazorPageClass rp; + RazorViewClass rp; ViewCallJumpNode() { exists(ViewCall vc | @@ -122,7 +122,7 @@ private class ViewCallJumpNode extends DataFlow::NonLocalJumpNode { } } -private predicate viewCallRefersToPage(ViewCall vc, RazorPageClass rp) { +private predicate viewCallRefersToPage(ViewCall vc, RazorViewClass rp) { viewCallRefersToPageAbsolute(vc, rp) or viewCallRefersToPageRelative(vc, rp) } @@ -130,15 +130,15 @@ private predicate viewCallRefersToPage(ViewCall vc, RazorPageClass rp) { bindingset[path] private string stripTilde(string path) { result = path.regexpReplaceAll("^~/", "/") } -private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPageClass rp) { +private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorViewClass rp) { getARazorPathPrefix() + ["/", ""] + stripTilde(vc.getNameArgument()) = rp.getSourceFilepath() } -private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPageClass rp) { - rp = min(int i, RazorPageClass rp2 | matchesViewCallWithIndex(vc, rp2, i) | rp2 order by i) +private predicate viewCallRefersToPageRelative(ViewCall vc, RazorViewClass rp) { + rp = min(int i, RazorViewClass rp2 | matchesViewCallWithIndex(vc, rp2, i) | rp2 order by i) } -private predicate matchesViewCallWithIndex(ViewCall vc, RazorPageClass rp, int i) { +private predicate matchesViewCallWithIndex(ViewCall vc, RazorViewClass rp, int i) { exists(RelativeViewCallFilepath fp | fp.hasViewCallWithIndex(vc, i) and getARazorPathPrefix() + fp.getNormalizedPath() = rp.getSourceFilepath() diff --git a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md index 46398e051f59..19001e0df003 100644 --- a/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md +++ b/csharp/ql/src/change-notes/2023-10-24-xss-flow-steps.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -* Modelled additional flow steps to track flow from a `View` call in an MVC controller to the corresponding Razor page, which may result in additional results for queries such as `cs/web/xss`. \ No newline at end of file +* Modelled additional flow steps to track flow from a `View` call in an MVC controller to the corresponding Razor View (`.cshtml`) file, which may result in additional results for queries such as `cs/web/xss`. \ No newline at end of file From e4edb19f43d33cd820f8e90471077b0afab5ec6c Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 16 Nov 2023 10:56:47 +0000 Subject: [PATCH 27/28] Update to hasFullyQualifiedName --- .../ql/lib/semmle/code/csharp/frameworks/Razor.qll | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 155841361368..5912d01e33b0 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -7,7 +7,9 @@ private import semmle.code.csharp.frameworks.microsoft.AspNetCore /** A call to the `View` method */ private class ViewCall extends MethodCall { - ViewCall() { this.getTarget().hasQualifiedName("Microsoft.AspNetCore.Mvc", "Controller", "View") } + ViewCall() { + this.getTarget().hasFullyQualifiedName("Microsoft.AspNetCore.Mvc", "Controller", "View") + } /** Gets the `name` argument to this call, if any. */ string getNameArgument() { @@ -55,7 +57,7 @@ private class ViewCall extends MethodCall { string getAreaName() { exists(Attribute attr | attr = this.getController().getAnAttribute() and - attr.getType().hasQualifiedName("Microsoft.AspNetCore.Mvc", "AreaAttribute") and + attr.getType().hasFullyQualifiedName("Microsoft.AspNetCore.Mvc", "AreaAttribute") and result = attr.getArgument(0).(StringLiteral).getValue() ) } @@ -70,13 +72,13 @@ class RazorViewClass extends Class { RazorViewClass() { exists(Class baseClass | baseClass = this.getBaseClass().getUnboundDeclaration() | - baseClass.hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage<>") + baseClass.hasFullyQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPage`1") or - baseClass.hasQualifiedName("Microsoft.AspNetCore.Mvc.RazorPages", "Page") + baseClass.hasFullyQualifiedName("Microsoft.AspNetCore.Mvc.RazorPages", "Page") ) and attr.getFile() = this.getFile() and attr.getType() - .hasQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute") + .hasFullyQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute") } /** @@ -176,7 +178,7 @@ private Expr getAViewLocationList(boolean isArea) { result .(PropertyRead) .getProperty() - .hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", name) + .hasFullyQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorViewEngineOptions", name) | name = "ViewLocationFormats" and isArea = false or From befb1ccd84aa222e516b7dd134691a9840041f77 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 16 Nov 2023 14:55:52 +0000 Subject: [PATCH 28/28] Fix integration tests for windows --- csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll index 5912d01e33b0..6bfa927e7c0e 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Razor.qll @@ -100,7 +100,8 @@ private string getARazorPathPrefix() { or exists(File csproj | csproj.getExtension() = "csproj" and - result = csproj.getParentContainer().getAbsolutePath() + // possibly prepend '/' to match Windows absolute paths starting with `C:/` with paths appearing in the Razor file in standalone mode starting with `/C:/` + result = ["/", ""] + csproj.getParentContainer().getAbsolutePath() ) }