From ba9cb5e22de3f305aaf3eb7d8fb93abd92bd69df Mon Sep 17 00:00:00 2001 From: Denis Levin Date: Thu, 16 Aug 2018 16:27:52 -0700 Subject: [PATCH 01/13] cs: Adding sources and sinks for ASPNET.Core Inintial query checkin. Note: tests require Nuget packages with ASPNET and ASPNETCore in Packages directory, and won't compile without them. The packages.config should include this: --- .../csharp/dataflow/flowsources/Remote.qll | 46 ++ .../frameworks/microsoft/AspNetCore.qll | 396 ++++++++++++++++++ .../frameworks/microsoft/Primitives.qll | 32 ++ .../csharp/frameworks/system/web/WebPages.qll | 37 ++ .../csharp/security/dataflow/UrlRedirect.qll | 62 +++ .../code/csharp/security/dataflow/XSS.qll | 71 ++++ .../CWE-079/XSSFlowAspNet/XSS.cs | 50 +++ .../CWE-079/XSSFlowAspNet/XSS.expected | 3 + .../CWE-079/XSSFlowAspNet/XSS.qlref | 1 + .../CWE-079/XSSFlowAspNetCore/XSS.cs | 79 ++++ .../CWE-079/XSSFlowAspNetCore/XSS.expected | 7 + .../CWE-079/XSSFlowAspNetCore/XSS.qlref | 1 + .../UrlRedirect.ASPNETCore/UrlRedirect.cs | 65 +++ .../UrlRedirect.expected | 10 + .../UrlRedirect.qlref | 0 .../UrlRedirect.cs | 2 +- .../UrlRedirect.expected | 0 .../UrlRedirect.qlref | 1 + 18 files changed, 862 insertions(+), 1 deletion(-) create mode 100644 csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll create mode 100644 csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll create mode 100644 csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.qlref create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected rename csharp/ql/test/query-tests/Security Features/CWE-601/{ => UrlRedirect.ASPNETCore}/UrlRedirect.qlref (100%) rename csharp/ql/test/query-tests/Security Features/CWE-601/{ => UrlRedirect.ASPNetClassic}/UrlRedirect.cs (95%) rename csharp/ql/test/query-tests/Security Features/CWE-601/{ => UrlRedirect.ASPNetClassic}/UrlRedirect.expected (100%) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index 920bcac81bc3..7e0481c6fd4e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -11,6 +11,9 @@ private import semmle.code.csharp.frameworks.system.web.Services private import semmle.code.csharp.frameworks.system.web.ui.WebControls private import semmle.code.csharp.frameworks.WCF private import semmle.code.csharp.frameworks.microsoft.Owin +private import microsoft.code.csharp.frameworks.microsoft.Primitives +private import microsoft.code.csharp.frameworks.microsoft.AspNetCore + /** A data flow source of remote user input. */ abstract class RemoteFlowSource extends DataFlow::Node { @@ -187,3 +190,46 @@ class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { override string getSourceType() { result = "ASP.NET MVC action method parameter" } } + +/** A data flow source of remote user input (ASP.NET Core). */ +abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } + + +/** A data flow source of remote user input (ASP.NET query collection). */ +class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { + AspNetCoreQueryRemoteFlowSource() { + exists(ValueOrRefType t, Call c, Access ac | + t instanceof MicrosoftAspNetCoreHttpHttpRequest or + t instanceof MicrosoftAspNetCoreHttpQueryCollection or + t instanceof MicrosoftAspNetCoreHttpQueryString | + this.getExpr() = c and + c.getTarget().getDeclaringType() = t + or + this.asExpr() = ac and + ac.getTarget().getDeclaringType() = t + or + c.getTarget().getDeclaringType().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and + c.getTarget().getName() = "TryGetValue" and + this.asExpr() = c.getArgumentForName("value") + ) + } + + override + string getSourceType() { result = "ASP.NET Core query string" } +} + +/** + * A parameter to an Mvc controller action method, viewed as a source of remote user input. + */ +class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { + AspNetCoreActionMethodParameter() { + exists(Parameter p | + p = this.getParameter() and + p.fromSource() | + p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() + ) + } + + override + string getSourceType() { result = "ASP.NET Core MVC action method parameter" } +} diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll new file mode 100644 index 000000000000..3699727dd0c1 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll @@ -0,0 +1,396 @@ +/** + * Provides classes for working with Microsoft.AspNetCore.Mvc + */ + +import csharp +import semmle.code.csharp.frameworks.Microsoft + +class MicrosoftAspNetCoreNamespace extends Namespace { + MicrosoftAspNetCoreNamespace() { + getParentNamespace() instanceof MicrosoftNamespace and + hasName("AspNetCore") + } +} + +/** + * The `Microsoft.AspNetCore.Mvc` namespace. + */ +class MicrosoftAspNetCoreMvcNamespace extends Namespace { + MicrosoftAspNetCoreMvcNamespace() { + getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and + hasName("Mvc") + } +} + +/** + * The 'Microsoft.AspNetCore.Mvc.ViewFeatures' namespace + */ +class MicrosoftAspNetCoreMvcViewFeatures extends Namespace { + MicrosoftAspNetCoreMvcViewFeatures() { + getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + hasName("ViewFeatures") + } +} + +/** + * An attribute whose type is in the `Microsoft.AspNetCore.Mvc` namespace. + */ +class MicrosoftAspNetCoreMvcAttribute extends Attribute { + MicrosoftAspNetCoreMvcAttribute() { + getType().getNamespace() = any(MicrosoftAspNetCoreMvcNamespace mvc) + } +} + +/** + * An HttpPost attribute in `Microsoft.AspNetCore.Mvc` namespace + */ +class MicrosoftAspNetCoreMvcHttpPostAttribute extends MicrosoftAspNetCoreMvcAttribute { + MicrosoftAspNetCoreMvcHttpPostAttribute() { + getType().hasName("HttpPostAttribute") + } +} + +/** + * An HttpPut attribute in `Microsoft.AspNetCore.Mvc` namespace + */ +class MicrosoftAspNetCoreMvcHttpPutAttribute extends MicrosoftAspNetCoreMvcAttribute { + MicrosoftAspNetCoreMvcHttpPutAttribute() { + getType().hasName("HttpPutAttribute") + } +} + +/** + * An HttpDelete attribute in `Microsoft.AspNetCore.Mvc` namespace + */ +class MicrosoftAspNetCoreMvcHttpDeleteAttribute extends MicrosoftAspNetCoreMvcAttribute { + MicrosoftAspNetCoreMvcHttpDeleteAttribute() { + getType().hasName("HttpDeleteAttribute") + } +} + +/** + * An attribute whose type is `Microsoft.AspNetCore.Mvc.NonAction`. + */ +class MicrosoftAspNetCoreMvcNonActionAttribute extends MicrosoftAspNetCoreMvcAttribute { + MicrosoftAspNetCoreMvcNonActionAttribute() { + getType().hasName("NonActionAttribute") + } +} + +/** + * The `Microsoft.AspNetCore.Antiforgery` namespace. + */ +class MicrosoftAspNetCoreAntiforgeryNamespace extends Namespace { + MicrosoftAspNetCoreAntiforgeryNamespace() { + getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and + hasName("Antiforgery") + } +} + +/** + * The `Microsoft.AspNetCore.Mvc.Filters` namespace. + */ +class MicrosoftAspNetCoreMvcFilters extends Namespace { + MicrosoftAspNetCoreMvcFilters() { + getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + hasName("Filters") + } +} + +/** + * The `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadataInterface` interface. + */ +class MicrosoftAspNetCoreMvcIFilterMetadataInterface extends Interface { + MicrosoftAspNetCoreMvcIFilterMetadataInterface() { + getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + hasName("IFilterMetadata") + } +} + + /** + * The `Microsoft.AspNetCore.IAuthorizationFilter` interface. + */ +class MicrosoftAspNetCoreIAuthorizationFilterInterface extends Interface { + MicrosoftAspNetCoreIAuthorizationFilterInterface() { + getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + hasName("IAsyncAuthorizationFilter") + } + + Method getOnAuthorizationMethod() { + result = getAMethod("OnAuthorizationAsync") + } +} + +/** + * The `Microsoft.AspNetCore.IAntiforgery` interface. + */ +class MicrosoftAspNetCoreIAntiForgeryInterface extends Interface { + MicrosoftAspNetCoreIAntiForgeryInterface() { + getNamespace() = any(MicrosoftAspNetCoreAntiforgeryNamespace h) and + hasName("IAntiforgery") + } + + /** + * Gets the `ValidateRequestAsync` method. + */ + Method getValidateMethod() { + result = getAMethod("ValidateRequestAsync") + } +} + +/** + * The `Microsoft.AspNetCore.DefaultAntiForgery` class, or another user-supplied class that implements IAntiForgery + */ +class AntiForgeryClass extends Class { + AntiForgeryClass () { + getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface + } + + /** + * Gets the `ValidateRequestAsync` method. + */ + Method getValidateMethod() { + result = getAMethod("ValidateRequestAsync") + } +} + +/** + * Authorization filter class defined by AspNetCore or the user + */ +class AuthorizationFilterClass extends Class { + AuthorizationFilterClass() { + getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface + } + + /** Gets the `OnAuthorization` method provided by this filter. */ + Method getOnAuthorizationMethod() { + result = getAMethod("OnAuthorizationAsync") + } +} + +/** + * An attribute whose type has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]Attribute`. + */ +class ValidateAntiForgeryAttribute extends Attribute { + ValidateAntiForgeryAttribute() { + getType().getName().matches("%Validate%Anti_orgery%Attribute") + } +} + +/** + * An class that has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]` and implements IFilterMetadata interface + * This class can be added to a collection of global MvcOptions.Filters collection + */ +class ValidateAntiforgeryTokenAuthorizationFilter extends Class { + ValidateAntiforgeryTokenAuthorizationFilter() { + getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and + getName().matches("%Validate%Anti_orgery%") + } +} + +/** + * The `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` class + */ +class MicrosoftAspNetCoreMvcFilterCollection extends Class { + MicrosoftAspNetCoreMvcFilterCollection() { + getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + hasName("FilterCollection") + } + + Method getAddMethod() { + result = getAMethod("Add") or + result = getABaseType().getAMethod("Add") + } +} + +/** + * The `Microsoft.AspNetCore.Mvc.MvcOptions` class . + */ +class MicrosoftAspNetCoreMvcOptions extends Class { + MicrosoftAspNetCoreMvcOptions() { + getNamespace() = any(MicrosoftAspNetCoreMvcNamespace mvc) and + hasName("MvcOptions") + } + + Property getFilterCollectionProperty() { + result = getProperty("Filters") + } +} + +/** + * The base class for controllers in MVC, i.e. `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase` class. + */ + +class MicrosoftAspNetCoreMvcControllerBaseClass extends Class { + MicrosoftAspNetCoreMvcControllerBaseClass() { + getNamespace() = any(MicrosoftAspNetCoreMvcNamespace h) and + (hasName("Controller") or hasName("ControllerBase")) + } +} + +/** + * An subtype of `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase`. + */ +class MicrosoftAspNetCoreMvcController extends Class { + MicrosoftAspNetCoreMvcController() { + getABaseType*() instanceof MicrosoftAspNetCoreMvcControllerBaseClass + } + + /** Gets an action method for this controller. */ + Method getAnActionMethod() { + result = getAMethod() and + result.isPublic() and + not result.isStatic() and + not result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcNonActionAttribute + } + + /** + * Gets an "action" method handling POST, PUT and DELETE request, which may be called by the MVC framework in response to a user + * request. + */ + Method getAnActionModifyingMethod() { + result = getAnActionMethod() and + (result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute or + result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute or + result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute) + } + + /** Gets a `Redirect..` method. */ + Method getARedirectMethod() { + result = this.getAMethod() and + result.getName().matches("Redirect%") + } +} + +/* + * Returns a string corresponding to an HTTP method used in the action method + */ +string httpMethodType(Method m) { + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute and result = "POST" or + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute and result = "PUT" or + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute and result = "DELETE" + } + +/** + * The `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper` class. + */ +class MicrosoftAspNetCoreMvcHtmlHelperClass extends Class { + MicrosoftAspNetCoreMvcHtmlHelperClass() { + getNamespace() = any(MicrosoftAspNetCoreMvcViewFeatures mvc) and + hasName("HtmlHelper") + } + + /** Gets the `Raw` method. */ + Method getRawMethod() { + result = getAMethod("Raw") + } +} + +/** + * Class deriving from Microsoft.AspNetCore.Mvc.Razor.RazorPageBase, implements Razor page in ASPNET Core + */ +class MicrosoftAspNetCoreMvcRazorPageBase extends Class { + MicrosoftAspNetCoreMvcRazorPageBase () { + this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPageBase") + } + + Method getWriteLiteralMethod() { + result = getAMethod("WriteLiteral") + } +} + +/** + * Class deriving from Microsoft.AspNetCore.Http.HttpRequest, implements HttpRequest in ASPNET Core + */ +class MicrosoftAspNetCoreHttpHttpRequest extends Class { + MicrosoftAspNetCoreHttpHttpRequest() { + this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpRequest") + } +} + +/** + * Class deriving from Microsoft.AspNetCore.Http.HttpResponse, implements HttpResponse in ASPNET Core + */ +class MicrosoftAspNetCoreHttpHttpResponse extends Class { + MicrosoftAspNetCoreHttpHttpResponse() { + this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpResponse") + } + + Method getRedirectMethod() { + result = this.getAMethod("Redirect") + } + + Property getHeadersProperty() { + result = this.getProperty("Headers") + } +} + +/** + * Class is a wrapper around the collection of cookies in the response + */ +class MicrosoftAspNetCoreHttpResponseCookies extends Interface{ + MicrosoftAspNetCoreHttpResponseCookies() { + this.hasQualifiedName("Microsoft.AspNetCore.Http.IResponseCookies") + } + + Method getAppendMethod() { + result = this.getAMethod("Append") + } +} + +/** + * Class Microsoft.AspNetCore.Http.QueryString, holds query string in ASP.NET Core + */ +class MicrosoftAspNetCoreHttpQueryString extends Struct { + MicrosoftAspNetCoreHttpQueryString() { + this.hasQualifiedName("Microsoft.AspNetCore.Http", "QueryString") + } +} + +/** + * Class implementing IQueryCollection, holds parsed query string in ASP.NET Core + */ +class MicrosoftAspNetCoreHttpQueryCollection extends RefType { + MicrosoftAspNetCoreHttpQueryCollection() { + this.getABaseInterface().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") + } +} + +/** + * Helper class for setting headers + */ +class MicrosoftAspNetCoreHttpResponseHeaders extends RefType { + MicrosoftAspNetCoreHttpResponseHeaders() { + this.hasQualifiedName("Microsoft.AspNetCore.Http.Headers","ResponseHeaders") + } + + Property getLocationProperty() { + result = this.getProperty("Location") + } +} + +class MicrosoftAspNetCoreHttpHeaderDictionaryExtensions extends RefType { + MicrosoftAspNetCoreHttpHeaderDictionaryExtensions () { + this.hasQualifiedName("Microsoft.AspNetCore.Http","HeaderDictionaryExtensions") + } + + Method getAppendMethod() { + result = this.getAMethod("Append") + } + + Method getAppendCommaSeparatedValuesMethod() { + result = this.getAMethod("AppendCommaSeparatedValues") + } + + Method getSetCommaSeparatedValuesMethod() { + result = this.getAMethod("SetCommaSeparatedValues") + } +} +/** + * Class Microsoft.AspNetCore.Html.HtmlString, suppose to wrap HTML-encoded string in ASP.NET Core + * Untrusted and unsanitized data should never flow there. + */ +class MicrosoftAspNetCoreHttpHtmlString extends Class { + MicrosoftAspNetCoreHttpHtmlString() { + this.hasQualifiedName("Microsoft.AspNetCore.Html", "HtmlString") + }} diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll new file mode 100644 index 000000000000..603672c08d0c --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll @@ -0,0 +1,32 @@ +/** + * Provides definitions for working with classes in Microsoft.Extensions.Primitives namespace + */ +import csharp + +module ExtensionPrimitives { +private import semmle.code.csharp.dataflow.LibraryTypeDataFlow + +/** + * StringValues class used in many .Net Core libraries. Requreres special LibraryTypeDataFlow flow. + */ + class StringValues extends Struct { + StringValues() { + this.hasQualifiedName("Microsoft.Extensions.Primitives", "StringValues") + } + } + + /** + * Custom flow through StringValues.StringValues library class + */ + class StringValuesFlow extends LibraryTypeDataFlow, StringValues { + override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + c = any(Callable ca | this = ca.getDeclaringType()) + and + (source = any(CallableFlowSourceArg a) or + source = any(CallableFlowSourceQualifier q)) + and + sink = any(CallableFlowSinkReturn r) + and preservesValue = false + } + } +} \ No newline at end of file diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll new file mode 100644 index 000000000000..8fcfe741bd58 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll @@ -0,0 +1,37 @@ +/** Definitions related to the namespace `System.Web.WebPages`, ASP.NET */ +import csharp + +private import semmle.code.csharp.frameworks.system.Web + +/** The `System.Web.WebPages` namespace. */ +class SystemWebWebPagesNamespace extends Namespace { + SystemWebWebPagesNamespace() { + getParentNamespace() instanceof SystemWebNamespace and + hasName("WebPages") + } +} + +/** The `System.Web.WebPages.WebPageExecutingBase` class. */ +class SystemWebWebPagesWebPageExecutingBaseClass extends Class { + SystemWebWebPagesWebPageExecutingBaseClass() { + getNamespace() instanceof SystemWebWebPagesNamespace and + hasName("WebPageExecutingBase") + } +} + +/** + * This class describes any class that derives from System.Web.WebPages.WebPageExecutingBase + */ +class WebPageClass extends Class { + WebPageClass () { + this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass + } + + Method getWriteLiteralMethod() { + result = getAMethod("WriteLiteral") + } + + Method getWriteLiteralToMethod() { + result = getAMethod("WriteLiteralTo") + } +} \ No newline at end of file diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll index 5ef7a9d7b628..3183b975eaa3 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll @@ -9,6 +9,7 @@ module UrlRedirect { import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Mvc import semmle.code.csharp.security.Sanitizers + import semmle.code.csharp.frameworks.microsoft.AspNetCore /** * A data flow source for unvalidated URL redirect vulnerabilities. @@ -149,4 +150,65 @@ module UrlRedirect { private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { } private class GuidSanitizer extends Sanitizer, GuidSanitizedExpr { } + + /** + * A URL argument to a call to `HttpResponse.Redirect()` or `Controller.Redirect()`, that is a + * sink for URL redirects. + */ + class AspNetCoreRedirectSink extends Sink { + AspNetCoreRedirectSink() { + exists(MethodCall mc | + mc.getTarget() = any(MicrosoftAspNetCoreHttpHttpResponse response).getRedirectMethod() or + mc.getTarget() = any(MicrosoftAspNetCoreMvcController response).getARedirectMethod() + | + // Response.Redirect uses 'location' parameter + this.getExpr() = mc.getArgumentForName("location") or + // Redirect uses the parameter name 'url' + this.getExpr() = mc.getArgumentForName("url") or + // Controller.RedirectToAction* + this.getExpr() = mc.getArgumentForName("actionName") or + // Controller.RedirectToRoute* + this.getExpr() = mc.getArgumentForName("routeName") or + // Controller.RedirectToPage* + this.getExpr() = mc.getArgumentForName("pageName") + ) + } + } + + /** + * Anything that is setting "location" header in the response headers. + */ + class AspNetCoreLocationHeaderSink extends Sink { + AspNetCoreLocationHeaderSink () { + // ResponseHeaders.Location = + exists(Assignment propAssign, PropertyAccess pa | + pa.getTarget() = any(MicrosoftAspNetCoreHttpResponseHeaders headers).getLocationProperty() and + pa = propAssign.getLValue() and + this.asExpr() = propAssign.getRValue()) + or // HttpResponse.Headers.Append("location", ) + exists(MethodCall mc, MicrosoftAspNetCoreHttpHeaderDictionaryExtensions ext | + mc.getTarget() = ext.getAppendMethod() or + mc.getTarget() = ext.getAppendCommaSeparatedValuesMethod() or + mc.getTarget() = ext.getSetCommaSeparatedValuesMethod() | + mc.getArgumentForName("key").getValue().toLowerCase() = "location" and + this.getExpr() = mc.getArgument(2)) + or // HttpResponse.Headers.Add("location", ) + exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, PropertyAccess c, MethodCall add | + c.getTarget() = resp.getHeadersProperty() and + add.getTarget() = cl.getAMethod("Add") and + c = add.getQualifier() and + add.getArgument(0).getValue().toLowerCase() = "location" and + this.getExpr() = add.getArgument(1)) + or // HttpResponse.Headers["location"] = + exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, IndexerAccess ci, Call cs, PropertyAccess pa | + pa.getTarget() = resp.getHeadersProperty() and + ci.getTarget() = cl.getAnIndexer() and + pa = ci.getQualifier() and + cs.getTarget() = cl.getAnIndexer().getSetter() and + cs.getArgument(0).getValue().toLowerCase() = "location" and + this.asExpr() = cs.getArgument(1)) + } + } } + + diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index 36261409bacc..97f886c8baf0 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -9,11 +9,13 @@ module XSS { import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Mvc + import semmle.code.csharp.frameworks.system.web.WebPages import semmle.code.csharp.frameworks.system.web.UI import semmle.code.csharp.frameworks.system.web.ui.WebControls import semmle.code.csharp.frameworks.system.windows.Forms import semmle.code.csharp.security.Sanitizers import semmle.code.asp.AspNet + import semmle.code.csharp.frameworks.microsoft.AspNetCore /** * Holds if there is tainted flow from `source` to `sink` that may lead to a @@ -514,6 +516,75 @@ module XSS { this.getExpr() = any(ObjectCreation oc | oc.getTarget().getDeclaringType().hasQualifiedName("System.Net.Http", "StringContent")).getArgumentForName("content") } } + + /** + * An expression that is used as an argument to `Page.WriteLiteral`, typically in + * a `.cshtml` file. + */ + class WebPageWriteLiteralSink extends Sink, HtmlSink { + WebPageWriteLiteralSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() + } + + override string explanation() { + result = "System.Web.WebPages.WebPage.WriteLiteral() method" + } + } + + /** + * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in + * a `.cshtml` file. + */ + class WebPageWriteLiteralToSink extends Sink, HtmlSink { + WebPageWriteLiteralToSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() + } + + override string explanation() { + result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" + } + } + + abstract class AspNetCoreSink extends Sink, HtmlSink { } + + /** + * An expression that is used as an argument to `HtmlHelper.Raw`, typically in + * a `.cshtml` file. + */ + class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink { + MicrosoftAspNetCoreMvcHtmlHelperRawSink() { + this.getExpr() = any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + } + + override string explanation() { + result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method" + } + } + + /** + * An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in + * a `.cshtml` file. + */ + class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink { + MicrosoftAspNetRazorPageWriteLiteralSink() { + this.getExpr() = any(MicrosoftAspNetCoreMvcRazorPageBase h).getWriteLiteralMethod().getACall().getAnArgument() + } + + override string explanation() { + result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method" + } + } + + /** + * HtmlString that may be rendered as is need to have sanitized value + */ + class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink { + MicrosoftAspNetHtmlStringSink() { + exists (ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | + c.getTarget() = s.getAConstructor() and + this.asExpr() = c.getAnArgument()) + } + } } private Type getMemberType(Member m) { diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs new file mode 100644 index 000000000000..887106fbcba9 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs @@ -0,0 +1,50 @@ +// semmle-extractor-options: /r:System.Web.dll /r:${testdir}/../../../../../packages/Microsoft.AspNet.WebPages.3.2.3/lib/net45/System.Web.WebPages.dll /r:${testdir}/../../../../../packages/Microsoft.AspNet.Mvc.5.2.3/lib/net45/System.Web.Mvc.dll +namespace ASP +{ + using System; + using System.IO; + using System.Net; + using System.Web; + using System.Web.UI; + using System.Web.WebPages; + + public class _Page_Views_Home_Contact_cshtml : System.Web.Mvc.WebViewPage + { + public _Page_Views_Home_Contact_cshtml() + { + } + + public override void Execute() + { + Layout = "~/_SiteLayout.cshtml"; + Page.Title = "Contact"; + var sayHi = Request.QueryString["sayHi"]; + if (sayHi.IsEmpty()) + { + WriteLiteral(""); // GOOD: hard-coded, not user input + } + else + { + WriteLiteral(sayHi); // BAD: user input flows to HTML unencoded + WriteLiteral(HttpUtility.HtmlEncode(sayHi)); // Good: user input is encoded before it flows to HTML + } + + if (sayHi.IsEmpty()) + { + WriteLiteralTo(Output, ""); // GOOD: hard-coded, not user input + } + else + { + WriteLiteralTo(Output, sayHi); // BAD: user input flows to HTML unencoded + WriteLiteralTo(Output, Html.Encode(sayHi)); // Good: user input is encoded before it flows to HTML + } + + BeginContext("~/Views/Home/Contact.cshtml", 288, 32, false); + + Write(Html.Raw("")); // GOOD: hard-coded, not user input + Write(Html.Raw(Request.QueryString["sayHi"])); // BAD: user input flows to HTML unencoded + Write(Html.Raw(HttpContext.Current.Server.HtmlEncode(Request.QueryString["sayHi"]))); // Good: user input is encoded before it flows to HTML + EndContext("~/Views/Home/Contact.cshtml", 288, 32, false); + } + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected new file mode 100644 index 000000000000..ab165784bffa --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected @@ -0,0 +1,3 @@ +| XSS.cs:28:30:28:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSS.cs:21:25:21:43 | access to property QueryString | User-provided value | +| XSS.cs:38:40:38:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSS.cs:21:25:21:43 | access to property QueryString | User-provided value | +| XSS.cs:45:28:45:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:45:28:45:46 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.qlref new file mode 100644 index 000000000000..faad1d6403c1 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/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/XSSFlowAspNetCore/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs new file mode 100644 index 000000000000..39230b1ca868 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs @@ -0,0 +1,79 @@ +// semmle-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Core.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Antiforgery.1.1.2/lib/net451/Microsoft.AspNetCore.Antiforgery.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.ViewFeatures.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.ViewFeatures.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Abstractions.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Abstractions.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Html.Abstractions.1.1.2/lib/netstandard1.0/Microsoft.AspNetCore.Html.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Http.Features.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Html; +using Microsoft.Extensions.Primitives; + +namespace Testing.Controllers +{ + public class HomeViewModel + { + public string Message { get; set; } + + public HtmlString Description { get; set; } + } + + public class TestController : Controller + { + public IActionResult Index() + { + // BAD: flow of content type to + var v = new ViewResult(); + v.ViewData["BadData"] = new HtmlString(Request.Query["Bad data"]); + + StringValues vOut; + Request.Query.TryGetValue("Foo", out vOut); + + // BAD: via Enumerable + v.ViewData["FooFirst"] = new HtmlString(vOut.First()); + + // BAD: via toArray + v.ViewData["FooArray0"] = new HtmlString(vOut.ToArray()[0]); + + // BAD: via implicit conversion operator + v.ViewData["FooImplicit"] = new HtmlString(vOut); + + return v; + } + + [HttpPost("Test")] + [ValidateAntiForgeryToken] + public IActionResult Submit([FromQuery] string foo) + { + var view = new ViewResult(); + //BAD: flow of submitted value to view in HtmlString. + view.ViewData["FOO"] = new HtmlString(foo); + return view; + } + + + public IActionResult IndexToModel() + { + //BAD: flow of submitted value to view in HtmlString. + HtmlString v = new HtmlString(Request.QueryString.Value); + return View(new HomeViewModel() { Message = "Message from Index", Description = v }); + } + + public IActionResult About() + { + //BAD: flow of submitted value to view in HtmlString. + HtmlString v = new HtmlString(Request.Query["Foo"].ToString()); + + //BAD: flow of submitted value to view in HtmlString. + HtmlString v1 = new HtmlString(Request.Query["Foo"][0]); + + return View(new HomeViewModel() { Message = "Message from About", Description = v }); + } + + public IActionResult Contact() + { + //BAD: flow of user content type to view in HtmlString. + HtmlString v = new HtmlString(Request.ContentType); + + //BAD: flow of headers to view in HtmlString. + HtmlString v1 = new HtmlString(value: Request.Headers["Foo"]); + + return View(new HomeViewModel() { Message = "Message from Contact", Description = v }); + } + } +} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected new file mode 100644 index 000000000000..3614a08046b2 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected @@ -0,0 +1,7 @@ +| XSS.cs:22:52:22:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:22:52:22:64 | access to property Query | User-provided value | +| XSS.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:41:56:41:58 | foo | User-provided value | +| XSS.cs:53:43:53:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:53:43:53:67 | access to property Value | User-provided value | +| XSS.cs:60:43:60:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:60:43:60:55 | access to property Query | User-provided value | +| XSS.cs:63:44:63:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:63:44:63:56 | access to property Query | User-provided value | +| XSS.cs:71:43:71:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:71:43:71:61 | access to property ContentType | User-provided value | +| XSS.cs:74:51:74:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:74:51:74:65 | access to property Headers | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref new file mode 100644 index 000000000000..faad1d6403c1 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/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-601/UrlRedirect.ASPNETCore/UrlRedirect.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs new file mode 100644 index 000000000000..f593ad66f9d1 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs @@ -0,0 +1,65 @@ +// semmle-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.Core.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Extensions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Features.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll + +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Headers; +using Microsoft.AspNetCore.Mvc; + +namespace Testing.Controllers +{ + public class SomeController : ControllerBase + { + private static string SomeValue = "HeaderValue"; + + [HttpPost] + public void Post([FromBody] string value) + { + // BAD: straight up controller redirect + Redirect(value); + + // BAD: Setting response headers collection, location = redirect + Response.Headers["location"] = value; + + // GOOD: Setting response header to a constant value + Response.Headers["location"] = SomeValue; + + // BAD: Setting response headers collection, location = redirect via add method + Response.Headers.Add("location", value); + + // GOOD: Setting response header to a constant value + Response.Headers.Add("location", "foo"); + + // BAD: redirect via location + Response.Headers.SetCommaSeparatedValues("location", value); + + // BAD = redirect via setting location value from tainted source + Response.Headers.Append("location", value); + + // BAD: redirect via setting location header from comma-separated values + Response.Headers.AppendCommaSeparatedValues("location", value); + + // BAD: tainted redirect to Action + RedirectToActionPermanent("Error" + value); + } + + // PUT: api/Some/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + + RedirectToPage(value); + + var headers = new ResponseHeaders(Response.Headers); + + // BAD: redirect via header helper class + headers.Location = new Uri(value); + + // BAD: response redirect + Response.Redirect(value); + + // GOOD: whitelisted redirect + if(Url.IsLocalUrl(value)) + Redirect(value); + } + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected new file mode 100644 index 000000000000..819fc89c6c61 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected @@ -0,0 +1,10 @@ +| TestController.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:36:49:36:53 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:39:69:39:73 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:42:39:42:53 | ... + ... | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:50:28:50:32 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | +| UrlRedirect.cs:55:32:55:45 | object creation of type Uri | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | +| UrlRedirect.cs:58:31:58:35 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.qlref b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.qlref similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.qlref rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.qlref diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.cs similarity index 95% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.cs rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.cs index 4ced49db6a83..8378e6743d90 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.cs @@ -1,4 +1,4 @@ -// semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll +// semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll using System; using System.Web; diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.expected rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref new file mode 100644 index 000000000000..2e061145f9ca --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref @@ -0,0 +1 @@ +Security Features/CWE-601/UrlRedirect.ql From 8b8d2f9bef82ee092baf367de57464d8555cdb99 Mon Sep 17 00:00:00 2001 From: calum Date: Thu, 20 Sep 2018 17:17:05 +0100 Subject: [PATCH 02/13] C#: Add auto-generated stubs. --- .../csharp/dataflow/flowsources/Remote.qll | 4 +- .../CWE-079/XSSFlowAspNet/XSS.cs | 6 +- .../CWE-079/XSSFlowAspNet/stubs.cs | 153 ++++++++++++++++++ 3 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index 7e0481c6fd4e..2564238ad5dc 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -11,8 +11,8 @@ private import semmle.code.csharp.frameworks.system.web.Services private import semmle.code.csharp.frameworks.system.web.ui.WebControls private import semmle.code.csharp.frameworks.WCF private import semmle.code.csharp.frameworks.microsoft.Owin -private import microsoft.code.csharp.frameworks.microsoft.Primitives -private import microsoft.code.csharp.frameworks.microsoft.AspNetCore +private import semmle.code.csharp.frameworks.microsoft.Primitives +private import semmle.code.csharp.frameworks.microsoft.AspNetCore /** A data flow source of remote user input. */ diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs index 887106fbcba9..c29d07b84d1d 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs @@ -1,11 +1,11 @@ -// semmle-extractor-options: /r:System.Web.dll /r:${testdir}/../../../../../packages/Microsoft.AspNet.WebPages.3.2.3/lib/net45/System.Web.WebPages.dll /r:${testdir}/../../../../../packages/Microsoft.AspNet.Mvc.5.2.3/lib/net45/System.Web.Mvc.dll +// semmle-extractor-options: /r:System.Dynamic.Runtime.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Expressions.dll namespace ASP { using System; using System.IO; using System.Net; using System.Web; - using System.Web.UI; + // using System.Web.UI; using System.Web.WebPages; public class _Page_Views_Home_Contact_cshtml : System.Web.Mvc.WebViewPage @@ -48,3 +48,5 @@ public override void Execute() } } } + +// source-extractor-options: /r:${testdir}/../../../../../packages/Microsoft.AspNet.WebPages.3.2.3/lib/net45/System.Web.WebPages.dll /r:${testdir}/../../../../../packages/Microsoft.AspNet.Mvc.5.2.3/lib/net45/System.Web.Mvc.dll /r:System.Dynamic.Runtime.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Expressions.dll /r:System.Web.dll /r:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Web.dll /r:System.Collections.Specialized.dll \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs new file mode 100644 index 000000000000..677c5bf3ddf9 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs @@ -0,0 +1,153 @@ +namespace System +{ +namespace Collections +{ +namespace Specialized +{ +// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection +{ + bool System.Collections.ICollection.IsSynchronized { get => throw null; } + object System.Collections.ICollection.SyncRoot { get => throw null; } + public virtual System.Collections.IEnumerator GetEnumerator() => throw null; + public virtual int Count { get => throw null; } + public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public virtual void OnDeserialization(object sender) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; +} + +// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase +{ + public string this[string name] { get => throw null; set => throw null; } +} + +} +} +namespace IO +{ +// Generated from `System.IO.TextWriter` in `System.Runtime.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class TextWriter : System.MarshalByRefObject, System.IDisposable +{ + public void Dispose() => throw null; +} + +} +namespace Web +{ +// Generated from `System.Web.HttpContext` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpContext : System.Web.IPrincipalContainer +{ + public System.Web.HttpServerUtility Server { get => throw null; } + public static System.Web.HttpContext Current { get => throw null; set => throw null; } +} + +// Generated from `System.Web.HttpRequestBase` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class HttpRequestBase +{ + public virtual System.Collections.Specialized.NameValueCollection QueryString { get => throw null; } +} + +// Generated from `System.Web.HttpServerUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpServerUtility +{ + public string HtmlEncode(string s) => throw null; +} + +// Generated from `System.Web.HttpUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpUtility +{ + public static string HtmlEncode(string s) => throw null; +} + +// Generated from `System.Web.IHtmlString` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public interface IHtmlString +{ +} + +// Generated from `System.Web.IPrincipalContainer` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +interface IPrincipalContainer +{ +} + +namespace Mvc +{ +// Generated from `System.Web.Mvc.HtmlHelper<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public class HtmlHelper : System.Web.Mvc.HtmlHelper +{ +} + +// Generated from `System.Web.Mvc.HtmlHelper` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public class HtmlHelper +{ + public System.Web.IHtmlString Raw(string value) => throw null; + public string Encode(string value) => throw null; +} + +// Generated from `System.Web.Mvc.IViewDataContainer` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public interface IViewDataContainer +{ +} + +// Generated from `System.Web.Mvc.IViewStartPageChild` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +interface IViewStartPageChild +{ +} + +// Generated from `System.Web.Mvc.WebViewPage<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebViewPage : System.Web.Mvc.WebViewPage +{ + public System.Web.Mvc.HtmlHelper Html { get => throw null; set => throw null; } +} + +// Generated from `System.Web.Mvc.WebViewPage` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebViewPage : System.Web.WebPages.WebPageBase, System.Web.Mvc.IViewStartPageChild, System.Web.Mvc.IViewDataContainer +{ +} + +} +namespace WebPages +{ +// Generated from `System.Web.WebPages.ITemplateFile` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public interface ITemplateFile +{ +} + +// Generated from `System.Web.WebPages.StringExtensions` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +static public class StringExtensions +{ + public static bool IsEmpty(this string value) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageBase : System.Web.WebPages.WebPageRenderingBase +{ + public System.IO.TextWriter Output { get => throw null; } + public override dynamic Page { get => throw null; } + public override string Layout { get => throw null; set => throw null; } + public override void Write(object value) => throw null; + public override void WriteLiteral(object value) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageExecutingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageExecutingBase +{ + protected void BeginContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; + protected void EndContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; + public abstract void Execute(); + public abstract void Write(object value); + public abstract void WriteLiteral(object value); + public static void WriteLiteralTo(System.IO.TextWriter writer, object content) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageRenderingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageRenderingBase : System.Web.WebPages.WebPageExecutingBase, System.Web.WebPages.ITemplateFile +{ + public abstract dynamic Page { get; } + public abstract string Layout { get; set; } + public virtual System.Web.HttpRequestBase Request { get => throw null; } +} + +} +} +} From 4655acadb29cf53dc7223703d2359f7b4d3e13ca Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 21 Sep 2018 10:07:47 +0100 Subject: [PATCH 03/13] C#: Stubs for XSSFlowASPNetCore test. --- .../CWE-079/XSSFlowAspNetCore/XSS.cs | 6 +- .../CWE-079/XSSFlowAspNetCore/stubs.cs | 236 ++++++++++++++++++ 2 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs index 39230b1ca868..8e21bc9deac8 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs @@ -1,4 +1,4 @@ -// semmle-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Core.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Antiforgery.1.1.2/lib/net451/Microsoft.AspNetCore.Antiforgery.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.ViewFeatures.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.ViewFeatures.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Abstractions.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Abstractions.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Html.Abstractions.1.1.2/lib/netstandard1.0/Microsoft.AspNetCore.Html.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Http.Features.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll + using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Html; @@ -76,4 +76,6 @@ public IActionResult Contact() return View(new HomeViewModel() { Message = "Message from Contact", Description = v }); } } -} \ No newline at end of file +} + +// initial-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Core.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Antiforgery.1.1.2/lib/net451/Microsoft.AspNetCore.Antiforgery.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.ViewFeatures.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.ViewFeatures.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Mvc.Abstractions.1.1.3/lib/net451/Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Abstractions.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Html.Abstractions.1.1.2/lib/netstandard1.0/Microsoft.AspNetCore.Html.Abstractions.dll /r:${testdir}/../../../../../packages/Microsoft.AspNetCore.Http.Features.1.1.2\lib\net451\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll /r:System.Linq.dll /r:System.Linq.Expressions.dll /r:System.Linq.Queryable.dll \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs new file mode 100644 index 000000000000..5e6feae68600 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs @@ -0,0 +1,236 @@ +namespace Microsoft +{ + namespace AspNetCore + { + namespace Html + { + // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent + { + public HtmlString(string value) => throw null; + public override string ToString() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHtmlContent + { + } + + } + namespace Http + { + // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpRequest + { + public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } + public abstract Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } + public abstract Microsoft.AspNetCore.Http.QueryString QueryString { get; set; } + public abstract string ContentType { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IQueryCollection : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; } + bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); + } + + // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct QueryString : System.IEquatable + { + public bool Equals(Microsoft.AspNetCore.Http.QueryString other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public string Value { get => throw null; } + } + + } + namespace Mvc + { + // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ControllerBase + { + public Microsoft.AspNetCore.Http.HttpRequest Request { get => throw null; } + } + + // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, System.IDisposable, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IActionFilter + { + public virtual Microsoft.AspNetCore.Mvc.ViewResult View(object model) => throw null; + public void Dispose() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata + { + public FromQueryAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute + { + public HttpPostAttribute() => throw null; + public HttpPostAttribute(string template) => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory + { + public ValidateAntiForgeryTokenAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult + { + public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } + public ViewResult() => throw null; + } + + namespace Filters + { + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + } + namespace ModelBinding + { + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IBindingSourceMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IModelNameProvider + { + } + + } + namespace Routing + { + // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IRouteTemplateProvider + { + } + + } + namespace ViewFeatures + { + // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewDataDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public System.Collections.Generic.ICollection Values { get => throw null; } + public System.Collections.Generic.ICollection Keys { get => throw null; } + public bool Contains(System.Collections.Generic.KeyValuePair item) => throw null; + public bool ContainsKey(string key) => throw null; + public bool IsReadOnly { get => throw null; } + public bool Remove(System.Collections.Generic.KeyValuePair item) => throw null; + public bool Remove(string key) => throw null; + public bool TryGetValue(string key, out object value) => throw null; + public int Count { get => throw null; } + public object this[string index] { get => throw null; set => throw null; } + public void Add(System.Collections.Generic.KeyValuePair item) => throw null; + public void Add(string key, object value) => throw null; + public void Clear() => throw null; + public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; + } + + } + } + } + namespace Extensions + { + namespace Primitives + { + // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, + System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection + { + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.Contains(string item) => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(string item) => throw null; + int System.Collections.Generic.IList.IndexOf(string item) => throw null; + public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; + public bool Equals(string other) => throw null; + public bool Equals(string[] other) => throw null; + public int Count { get => throw null; } + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public static implicit operator string(Microsoft.Extensions.Primitives.StringValues values) => throw null; + public string this[int index] { get => throw null; set => throw null; } + public string[] ToArray() => throw null; + void System.Collections.Generic.ICollection.Add(string item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; + void System.Collections.Generic.IList.Insert(int index, string item) => throw null; + void System.Collections.Generic.IList.RemoveAt(int index) => throw null; + } + + } + } +} +namespace System +{ + namespace Linq + { + // Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + static public class Enumerable + { + public static TSource First(this System.Collections.Generic.IEnumerable source) => throw null; + } + + } +} From d6e6ae66b86b13639b43f30cbb060717958763e5 Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 21 Sep 2018 10:52:10 +0100 Subject: [PATCH 04/13] C#: qltest stubs for UrlRedirect.ASPNETCore --- .../UrlRedirect.ASPNETCore/UrlRedirect.cs | 4 +- .../UrlRedirect.expected | 2 +- .../CWE-601/UrlRedirect.ASPNETCore/stubs.cs | 182 ++++++++++++++++++ 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs index f593ad66f9d1..ee530f5f0a43 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs @@ -1,4 +1,4 @@ -// semmle-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.Core.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Extensions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Mvc.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../packages\Microsoft.AspNetCore.Http.Features.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +// semmle-extractor-options: /r:System.Private.Uri.dll using System; using Microsoft.AspNetCore.Http; @@ -63,3 +63,5 @@ public void Put(int id, [FromBody] string value) } } } + +// original-extractor-options: /r:netstandard.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Mvc.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Mvc.Core.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Extensions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Mvc.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll /r:${testdir}/../../../../../packages\Microsoft.AspNetCore.Http.Features.2.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll /r:${testdir}/../../../../../packages\Microsoft.Extensions.Primitives.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll /r:System.Private.Uri.dll diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected index 819fc89c6c61..ab5ebeba1a4e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected @@ -1,4 +1,4 @@ -| TestController.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | +| UrlRedirect.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | | UrlRedirect.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | | UrlRedirect.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | | UrlRedirect.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs new file mode 100644 index 000000000000..1dff89716e01 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs @@ -0,0 +1,182 @@ +namespace Microsoft +{ +namespace AspNetCore +{ +namespace Http +{ +// Generated from `Microsoft.AspNetCore.Http.HeaderDictionaryExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +static public class HeaderDictionaryExtensions +{ + public static void Append(this Microsoft.AspNetCore.Http.IHeaderDictionary headers, string key, Microsoft.Extensions.Primitives.StringValues value) => throw null; + public static void AppendCommaSeparatedValues(this Microsoft.AspNetCore.Http.IHeaderDictionary headers, string key, params string[] values) => throw null; + public static void SetCommaSeparatedValues(this Microsoft.AspNetCore.Http.IHeaderDictionary headers, string key, params string[] values) => throw null; +} + +// Generated from `Microsoft.AspNetCore.Http.HttpResponse` in `Microsoft.AspNetCore.Http.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +abstract public class HttpResponse +{ + public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } + public virtual void Redirect(string location) => throw null; +} + +// Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> +{ + Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } +} + +namespace Headers +{ +// Generated from `Microsoft.AspNetCore.Http.Headers.ResponseHeaders` in `Microsoft.AspNetCore.Http.Extensions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class ResponseHeaders +{ + public ResponseHeaders(Microsoft.AspNetCore.Http.IHeaderDictionary headers) => throw null; + public System.Uri Location { get => throw null; set => throw null; } +} + +} +} +namespace Mvc +{ +// Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +abstract public class ControllerBase +{ + public Microsoft.AspNetCore.Http.HttpResponse Response { get => throw null; } + public Microsoft.AspNetCore.Mvc.IUrlHelper Url { get => throw null; set => throw null; } + public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(string url) => throw null; + public virtual Microsoft.AspNetCore.Mvc.RedirectToActionResult RedirectToActionPermanent(string actionName) => throw null; + public virtual Microsoft.AspNetCore.Mvc.RedirectToPageResult RedirectToPage(string pageName) => throw null; +} + +// Generated from `Microsoft.AspNetCore.Mvc.FromBodyAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class FromBodyAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata +{ + public FromBodyAttribute() => throw null; +} + +// Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute +{ + public HttpPostAttribute() => throw null; + public HttpPostAttribute(string template) => throw null; +} + +// Generated from `Microsoft.AspNetCore.Mvc.HttpPutAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class HttpPutAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute +{ + public HttpPutAttribute() => throw null; + public HttpPutAttribute(string template) => throw null; +} + +// Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IActionResult +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.IUrlHelper` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IUrlHelper +{ + bool IsLocalUrl(string url); +} + +// Generated from `Microsoft.AspNetCore.Mvc.RedirectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class RedirectResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult, Microsoft.AspNetCore.Mvc.IActionResult +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.RedirectToActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class RedirectToActionResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult, Microsoft.AspNetCore.Mvc.IActionResult +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.RedirectToPageResult` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public class RedirectToPageResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult, Microsoft.AspNetCore.Mvc.IActionResult +{ +} + +namespace ModelBinding +{ +// Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IBindingSourceMetadata +{ +} + +} +namespace Routing +{ +// Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IActionHttpMethodProvider +{ +} + +// Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IRouteTemplateProvider +{ +} + +} +namespace ViewFeatures +{ +// Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult` in `Microsoft.AspNetCore.Mvc.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public interface IKeepTempDataResult : Microsoft.AspNetCore.Mvc.IActionResult +{ +} + +} +} +} +namespace Extensions +{ +namespace Primitives +{ +// Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` +public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection +{ + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.Contains(string item) => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(string item) => throw null; + int System.Collections.Generic.IList.IndexOf(string item) => throw null; + public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; + public bool Equals(string other) => throw null; + public bool Equals(string[] other) => throw null; + public int Count { get => throw null; } + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public static implicit operator Microsoft.Extensions.Primitives.StringValues(string value) => throw null; + void System.Collections.Generic.ICollection.Add(string item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; + void System.Collections.Generic.IList.Insert(int index, string item) => throw null; + void System.Collections.Generic.IList.RemoveAt(int index) => throw null; + public string this[int i] { get => throw null; set => throw null; } +} + +} +} +} +namespace System +{ +// Generated from `System.Uri` in `System.Private.Uri, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class Uri : System.Runtime.Serialization.ISerializable +{ + public Uri(string uriString) => throw null; + public override bool Equals(object comparand) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; +} + +} From 697e66e312ae6283a8c4c633d7ebaf646d4ade23 Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 21 Sep 2018 11:15:57 +0100 Subject: [PATCH 05/13] C#: Move test into subdirectory. --- .../CWE-079/{ => StoredXSS}/AspInline.expected | 0 .../Security Features/CWE-079/{ => StoredXSS}/AspInline.ql | 0 .../Security Features/CWE-079/{ => StoredXSS}/StoredXSS.cs | 2 +- .../CWE-079/{ => StoredXSS}/StoredXSS.expected | 0 .../Security Features/CWE-079/{ => StoredXSS}/StoredXSS.qlref | 0 .../Security Features/CWE-079/{ => StoredXSS}/XSS.cs | 0 .../Security Features/CWE-079/{ => StoredXSS}/XSS.expected | 0 .../Security Features/CWE-079/{ => StoredXSS}/XSS.qlref | 0 .../Security Features/CWE-079/{ => StoredXSS}/script.aspx | 0 9 files changed, 1 insertion(+), 1 deletion(-) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/AspInline.expected (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/AspInline.ql (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/StoredXSS.cs (68%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/StoredXSS.expected (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/StoredXSS.qlref (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/XSS.cs (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/XSS.expected (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/XSS.qlref (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{ => StoredXSS}/script.aspx (100%) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/AspInline.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/AspInline.expected similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/AspInline.expected rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/AspInline.expected diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/AspInline.ql b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/AspInline.ql similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/AspInline.ql rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/AspInline.ql diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.cs similarity index 68% rename from csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.cs rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.cs index 7e4e97f40bf0..24c4eb73912d 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.cs @@ -1,4 +1,4 @@ -// semmle-extractor-options: /r:${testdir}/../../../resources/assemblies/System.Data.dll /r:${testdir}/../../../resources/assemblies/System.Web.dll /r:${testdir}/../../../resources/assemblies/System.Web.Mvc.dll /r:System.ComponentModel.Primitives.dll /r:System.Collections.Specialized.dll /r:${testdir}/../../../resources/assemblies/System.Net.Http.dll +// semmle-extractor-options: /r:${testdir}/../../../../resources/assemblies/System.Data.dll /r:${testdir}/../../../../resources/assemblies/System.Web.dll /r:${testdir}/../../../../resources/assemblies/System.Web.Mvc.dll /r:System.ComponentModel.Primitives.dll /r:System.Collections.Specialized.dll /r:${testdir}/../../../../resources/assemblies/System.Net.Http.dll using System; using System.Data.SqlClient; diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.expected rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.expected diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.qlref similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS.qlref rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/StoredXSS.qlref diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSS.cs rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.expected similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSS.expected rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.expected diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.qlref similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSS.qlref rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/XSS.qlref diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/script.aspx b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/script.aspx similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/script.aspx rename to csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/script.aspx From 2090d69c3fc2a5d39bac2fc182e2d6fa5114ac1d Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 21 Sep 2018 11:25:21 +0100 Subject: [PATCH 06/13] C#: Tidy up tests. --- .../CWE-079/XSSFlowAspNet/stubs.cs | 306 ++++++------ .../CWE-079/XSSFlowAspNetCore/stubs.cs | 472 +++++++++--------- 2 files changed, 389 insertions(+), 389 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs index 677c5bf3ddf9..d58af2a69087 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs @@ -1,153 +1,153 @@ -namespace System -{ -namespace Collections -{ -namespace Specialized -{ -// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -abstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection -{ - bool System.Collections.ICollection.IsSynchronized { get => throw null; } - object System.Collections.ICollection.SyncRoot { get => throw null; } - public virtual System.Collections.IEnumerator GetEnumerator() => throw null; - public virtual int Count { get => throw null; } - public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; - public virtual void OnDeserialization(object sender) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; -} - -// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -public class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase -{ - public string this[string name] { get => throw null; set => throw null; } -} - -} -} -namespace IO -{ -// Generated from `System.IO.TextWriter` in `System.Runtime.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -abstract public class TextWriter : System.MarshalByRefObject, System.IDisposable -{ - public void Dispose() => throw null; -} - -} -namespace Web -{ -// Generated from `System.Web.HttpContext` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -public class HttpContext : System.Web.IPrincipalContainer -{ - public System.Web.HttpServerUtility Server { get => throw null; } - public static System.Web.HttpContext Current { get => throw null; set => throw null; } -} - -// Generated from `System.Web.HttpRequestBase` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -abstract public class HttpRequestBase -{ - public virtual System.Collections.Specialized.NameValueCollection QueryString { get => throw null; } -} - -// Generated from `System.Web.HttpServerUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -public class HttpServerUtility -{ - public string HtmlEncode(string s) => throw null; -} - -// Generated from `System.Web.HttpUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -public class HttpUtility -{ - public static string HtmlEncode(string s) => throw null; -} - -// Generated from `System.Web.IHtmlString` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -public interface IHtmlString -{ -} - -// Generated from `System.Web.IPrincipalContainer` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` -interface IPrincipalContainer -{ -} - -namespace Mvc -{ -// Generated from `System.Web.Mvc.HtmlHelper<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -public class HtmlHelper : System.Web.Mvc.HtmlHelper -{ -} - -// Generated from `System.Web.Mvc.HtmlHelper` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -public class HtmlHelper -{ - public System.Web.IHtmlString Raw(string value) => throw null; - public string Encode(string value) => throw null; -} - -// Generated from `System.Web.Mvc.IViewDataContainer` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -public interface IViewDataContainer -{ -} - -// Generated from `System.Web.Mvc.IViewStartPageChild` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -interface IViewStartPageChild -{ -} - -// Generated from `System.Web.Mvc.WebViewPage<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -abstract public class WebViewPage : System.Web.Mvc.WebViewPage -{ - public System.Web.Mvc.HtmlHelper Html { get => throw null; set => throw null; } -} - -// Generated from `System.Web.Mvc.WebViewPage` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -abstract public class WebViewPage : System.Web.WebPages.WebPageBase, System.Web.Mvc.IViewStartPageChild, System.Web.Mvc.IViewDataContainer -{ -} - -} -namespace WebPages -{ -// Generated from `System.Web.WebPages.ITemplateFile` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -public interface ITemplateFile -{ -} - -// Generated from `System.Web.WebPages.StringExtensions` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -static public class StringExtensions -{ - public static bool IsEmpty(this string value) => throw null; -} - -// Generated from `System.Web.WebPages.WebPageBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -abstract public class WebPageBase : System.Web.WebPages.WebPageRenderingBase -{ - public System.IO.TextWriter Output { get => throw null; } - public override dynamic Page { get => throw null; } - public override string Layout { get => throw null; set => throw null; } - public override void Write(object value) => throw null; - public override void WriteLiteral(object value) => throw null; -} - -// Generated from `System.Web.WebPages.WebPageExecutingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -abstract public class WebPageExecutingBase -{ - protected void BeginContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; - protected void EndContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; - public abstract void Execute(); - public abstract void Write(object value); - public abstract void WriteLiteral(object value); - public static void WriteLiteralTo(System.IO.TextWriter writer, object content) => throw null; -} - -// Generated from `System.Web.WebPages.WebPageRenderingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` -abstract public class WebPageRenderingBase : System.Web.WebPages.WebPageExecutingBase, System.Web.WebPages.ITemplateFile -{ - public abstract dynamic Page { get; } - public abstract string Layout { get; set; } - public virtual System.Web.HttpRequestBase Request { get => throw null; } -} - -} -} -} +namespace System +{ +namespace Collections +{ +namespace Specialized +{ +// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection +{ + bool System.Collections.ICollection.IsSynchronized { get => throw null; } + object System.Collections.ICollection.SyncRoot { get => throw null; } + public virtual System.Collections.IEnumerator GetEnumerator() => throw null; + public virtual int Count { get => throw null; } + public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public virtual void OnDeserialization(object sender) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; +} + +// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase +{ + public string this[string name] { get => throw null; set => throw null; } +} + +} +} +namespace IO +{ +// Generated from `System.IO.TextWriter` in `System.Runtime.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class TextWriter : System.MarshalByRefObject, System.IDisposable +{ + public void Dispose() => throw null; +} + +} +namespace Web +{ +// Generated from `System.Web.HttpContext` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpContext : System.Web.IPrincipalContainer +{ + public System.Web.HttpServerUtility Server { get => throw null; } + public static System.Web.HttpContext Current { get => throw null; set => throw null; } +} + +// Generated from `System.Web.HttpRequestBase` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +abstract public class HttpRequestBase +{ + public virtual System.Collections.Specialized.NameValueCollection QueryString { get => throw null; } +} + +// Generated from `System.Web.HttpServerUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpServerUtility +{ + public string HtmlEncode(string s) => throw null; +} + +// Generated from `System.Web.HttpUtility` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public class HttpUtility +{ + public static string HtmlEncode(string s) => throw null; +} + +// Generated from `System.Web.IHtmlString` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +public interface IHtmlString +{ +} + +// Generated from `System.Web.IPrincipalContainer` in `System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` +interface IPrincipalContainer +{ +} + +namespace Mvc +{ +// Generated from `System.Web.Mvc.HtmlHelper<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public class HtmlHelper : System.Web.Mvc.HtmlHelper +{ +} + +// Generated from `System.Web.Mvc.HtmlHelper` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public class HtmlHelper +{ + public System.Web.IHtmlString Raw(string value) => throw null; + public string Encode(string value) => throw null; +} + +// Generated from `System.Web.Mvc.IViewDataContainer` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public interface IViewDataContainer +{ +} + +// Generated from `System.Web.Mvc.IViewStartPageChild` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +interface IViewStartPageChild +{ +} + +// Generated from `System.Web.Mvc.WebViewPage<>` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebViewPage : System.Web.Mvc.WebViewPage +{ + public System.Web.Mvc.HtmlHelper Html { get => throw null; set => throw null; } +} + +// Generated from `System.Web.Mvc.WebViewPage` in `System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebViewPage : System.Web.WebPages.WebPageBase, System.Web.Mvc.IViewStartPageChild, System.Web.Mvc.IViewDataContainer +{ +} + +} +namespace WebPages +{ +// Generated from `System.Web.WebPages.ITemplateFile` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +public interface ITemplateFile +{ +} + +// Generated from `System.Web.WebPages.StringExtensions` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +static public class StringExtensions +{ + public static bool IsEmpty(this string value) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageBase : System.Web.WebPages.WebPageRenderingBase +{ + public System.IO.TextWriter Output { get => throw null; } + public override dynamic Page { get => throw null; } + public override string Layout { get => throw null; set => throw null; } + public override void Write(object value) => throw null; + public override void WriteLiteral(object value) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageExecutingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageExecutingBase +{ + protected void BeginContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; + protected void EndContext(string virtualPath, int startPosition, int length, bool isLiteral) => throw null; + public abstract void Execute(); + public abstract void Write(object value); + public abstract void WriteLiteral(object value); + public static void WriteLiteralTo(System.IO.TextWriter writer, object content) => throw null; +} + +// Generated from `System.Web.WebPages.WebPageRenderingBase` in `System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` +abstract public class WebPageRenderingBase : System.Web.WebPages.WebPageExecutingBase, System.Web.WebPages.ITemplateFile +{ + public abstract dynamic Page { get; } + public abstract string Layout { get; set; } + public virtual System.Web.HttpRequestBase Request { get => throw null; } +} + +} +} +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs index 5e6feae68600..910ef14f5be6 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs @@ -1,236 +1,236 @@ -namespace Microsoft -{ - namespace AspNetCore - { - namespace Html - { - // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent - { - public HtmlString(string value) => throw null; - public override string ToString() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IHtmlContent - { - } - - } - namespace Http - { - // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class HttpRequest - { - public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } - public abstract Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } - public abstract Microsoft.AspNetCore.Http.QueryString QueryString { get; set; } - public abstract string ContentType { get; set; } - } - - // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> - { - Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } - } - - // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IQueryCollection : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable> - { - Microsoft.Extensions.Primitives.StringValues this[string key] { get; } - bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); - } - - // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public struct QueryString : System.IEquatable - { - public bool Equals(Microsoft.AspNetCore.Http.QueryString other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public override string ToString() => throw null; - public string Value { get => throw null; } - } - - } - namespace Mvc - { - // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class ControllerBase - { - public Microsoft.AspNetCore.Http.HttpRequest Request { get => throw null; } - } - - // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, System.IDisposable, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IActionFilter - { - public virtual Microsoft.AspNetCore.Mvc.ViewResult View(object model) => throw null; - public void Dispose() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata - { - public FromQueryAttribute() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute - { - public HttpPostAttribute() => throw null; - public HttpPostAttribute(string template) => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionResult - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory - { - public ValidateAntiForgeryTokenAttribute() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult - { - public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } - public ViewResult() => throw null; - } - - namespace Filters - { - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - } - namespace ModelBinding - { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IBindingSourceMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IModelNameProvider - { - } - - } - namespace Routing - { - // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionHttpMethodProvider - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IRouteTemplateProvider - { - } - - } - namespace ViewFeatures - { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ViewDataDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> - { - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public System.Collections.Generic.ICollection Values { get => throw null; } - public System.Collections.Generic.ICollection Keys { get => throw null; } - public bool Contains(System.Collections.Generic.KeyValuePair item) => throw null; - public bool ContainsKey(string key) => throw null; - public bool IsReadOnly { get => throw null; } - public bool Remove(System.Collections.Generic.KeyValuePair item) => throw null; - public bool Remove(string key) => throw null; - public bool TryGetValue(string key, out object value) => throw null; - public int Count { get => throw null; } - public object this[string index] { get => throw null; set => throw null; } - public void Add(System.Collections.Generic.KeyValuePair item) => throw null; - public void Add(string key, object value) => throw null; - public void Clear() => throw null; - public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; - } - - } - } - } - namespace Extensions - { - namespace Primitives - { - // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, - System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection - { - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - bool System.Collections.Generic.ICollection.Contains(string item) => throw null; - bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } - bool System.Collections.Generic.ICollection.Remove(string item) => throw null; - int System.Collections.Generic.IList.IndexOf(string item) => throw null; - public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; - public bool Equals(string other) => throw null; - public bool Equals(string[] other) => throw null; - public int Count { get => throw null; } - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public override string ToString() => throw null; - public static implicit operator string(Microsoft.Extensions.Primitives.StringValues values) => throw null; - public string this[int index] { get => throw null; set => throw null; } - public string[] ToArray() => throw null; - void System.Collections.Generic.ICollection.Add(string item) => throw null; - void System.Collections.Generic.ICollection.Clear() => throw null; - void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; - void System.Collections.Generic.IList.Insert(int index, string item) => throw null; - void System.Collections.Generic.IList.RemoveAt(int index) => throw null; - } - - } - } -} -namespace System -{ - namespace Linq - { - // Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - static public class Enumerable - { - public static TSource First(this System.Collections.Generic.IEnumerable source) => throw null; - } - - } -} +namespace Microsoft +{ + namespace AspNetCore + { + namespace Html + { + // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent + { + public HtmlString(string value) => throw null; + public override string ToString() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHtmlContent + { + } + + } + namespace Http + { + // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpRequest + { + public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } + public abstract Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } + public abstract Microsoft.AspNetCore.Http.QueryString QueryString { get; set; } + public abstract string ContentType { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IQueryCollection : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; } + bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); + } + + // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct QueryString : System.IEquatable + { + public bool Equals(Microsoft.AspNetCore.Http.QueryString other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public string Value { get => throw null; } + } + + } + namespace Mvc + { + // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ControllerBase + { + public Microsoft.AspNetCore.Http.HttpRequest Request { get => throw null; } + } + + // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, System.IDisposable, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IActionFilter + { + public virtual Microsoft.AspNetCore.Mvc.ViewResult View(object model) => throw null; + public void Dispose() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata + { + public FromQueryAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute + { + public HttpPostAttribute() => throw null; + public HttpPostAttribute(string template) => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory + { + public ValidateAntiForgeryTokenAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult + { + public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } + public ViewResult() => throw null; + } + + namespace Filters + { + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + } + namespace ModelBinding + { + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IBindingSourceMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IModelNameProvider + { + } + + } + namespace Routing + { + // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IRouteTemplateProvider + { + } + + } + namespace ViewFeatures + { + // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewDataDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public System.Collections.Generic.ICollection Values { get => throw null; } + public System.Collections.Generic.ICollection Keys { get => throw null; } + public bool Contains(System.Collections.Generic.KeyValuePair item) => throw null; + public bool ContainsKey(string key) => throw null; + public bool IsReadOnly { get => throw null; } + public bool Remove(System.Collections.Generic.KeyValuePair item) => throw null; + public bool Remove(string key) => throw null; + public bool TryGetValue(string key, out object value) => throw null; + public int Count { get => throw null; } + public object this[string index] { get => throw null; set => throw null; } + public void Add(System.Collections.Generic.KeyValuePair item) => throw null; + public void Add(string key, object value) => throw null; + public void Clear() => throw null; + public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; + } + + } + } + } + namespace Extensions + { + namespace Primitives + { + // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, + System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection + { + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.Contains(string item) => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(string item) => throw null; + int System.Collections.Generic.IList.IndexOf(string item) => throw null; + public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; + public bool Equals(string other) => throw null; + public bool Equals(string[] other) => throw null; + public int Count { get => throw null; } + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public static implicit operator string(Microsoft.Extensions.Primitives.StringValues values) => throw null; + public string this[int index] { get => throw null; set => throw null; } + public string[] ToArray() => throw null; + void System.Collections.Generic.ICollection.Add(string item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; + void System.Collections.Generic.IList.Insert(int index, string item) => throw null; + void System.Collections.Generic.IList.RemoveAt(int index) => throw null; + } + + } + } +} +namespace System +{ + namespace Linq + { + // Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + static public class Enumerable + { + public static TSource First(this System.Collections.Generic.IEnumerable source) => throw null; + } + + } +} From 62fb6939244da76998822b5697c9ca1af302d52a Mon Sep 17 00:00:00 2001 From: calum Date: Wed, 24 Oct 2018 13:07:32 +0100 Subject: [PATCH 07/13] C#: Tidy up code and fix performance of remote flow sources. --- .../csharp/dataflow/flowsources/Remote.qll | 40 ++- .../frameworks/microsoft/AspNetCore.qll | 245 ++++++++---------- .../CWE-079/XSSFlowAspNetCore/XSS.cs | 9 +- .../CWE-079/XSSFlowAspNetCore/XSS.expected | 10 +- 4 files changed, 129 insertions(+), 175 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index 2564238ad5dc..7e8f02e6cc12 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -143,9 +143,7 @@ class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode string getSourceType() { result = "Microsoft Owin request or query string" } } -/** - * A data flow source of remote user input (`Microsoft Owin IOwinRequest`). - */ +/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { MicrosoftOwinRequestRemoteFlowSource() { exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | @@ -174,15 +172,14 @@ class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::E string getSourceType() { result = "Microsoft Owin request" } } -/** - * A parameter to an Mvc controller action method, viewed as a source of remote user input. - */ +/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { ActionMethodParameter() { exists(Parameter p | p = this.getParameter() and p.fromSource() | - p = any(Controller c).getAnActionMethod().getAParameter() or + p = any(Controller c).getAnActionMethod().getAParameter() + or p = any(ApiController c).getAnActionMethod().getAParameter() ) } @@ -198,19 +195,22 @@ abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } /** A data flow source of remote user input (ASP.NET query collection). */ class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { AspNetCoreQueryRemoteFlowSource() { - exists(ValueOrRefType t, Call c, Access ac | - t instanceof MicrosoftAspNetCoreHttpHttpRequest or - t instanceof MicrosoftAspNetCoreHttpQueryCollection or - t instanceof MicrosoftAspNetCoreHttpQueryString | - this.getExpr() = c and - c.getTarget().getDeclaringType() = t + exists(ValueOrRefType t | + t instanceof MicrosoftAspNetCoreHttpHttpRequest + or + t instanceof MicrosoftAspNetCoreHttpQueryCollection or - this.asExpr() = ac and - ac.getTarget().getDeclaringType() = t + t instanceof MicrosoftAspNetCoreHttpQueryString + | + this.getExpr().(Call).getTarget().getDeclaringType() = t or - c.getTarget().getDeclaringType().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and - c.getTarget().getName() = "TryGetValue" and - this.asExpr() = c.getArgumentForName("value") + this.asExpr().(Access).getTarget().getDeclaringType() = t + ) + or + exists(Call c | + c.getTarget().getDeclaringType().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and + c.getTarget().getName() = "TryGetValue" and + this.asExpr() = c.getArgumentForName("value") ) } @@ -218,9 +218,7 @@ class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFl string getSourceType() { result = "ASP.NET Core query string" } } -/** - * A parameter to an Mvc controller action method, viewed as a source of remote user input. - */ +/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { AspNetCoreActionMethodParameter() { exists(Parameter p | diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll index 3699727dd0c1..7cccd6f74e96 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll @@ -1,6 +1,4 @@ -/** - * Provides classes for working with Microsoft.AspNetCore.Mvc - */ +/** Provides classes for working with `Microsoft.AspNetCore.Mvc`. */ import csharp import semmle.code.csharp.frameworks.Microsoft @@ -8,169 +6,136 @@ import semmle.code.csharp.frameworks.Microsoft class MicrosoftAspNetCoreNamespace extends Namespace { MicrosoftAspNetCoreNamespace() { getParentNamespace() instanceof MicrosoftNamespace and - hasName("AspNetCore") + hasName("AspNetCore") } } -/** - * The `Microsoft.AspNetCore.Mvc` namespace. - */ +/** The `Microsoft.AspNetCore.Mvc` namespace. */ class MicrosoftAspNetCoreMvcNamespace extends Namespace { MicrosoftAspNetCoreMvcNamespace() { getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and - hasName("Mvc") + hasName("Mvc") } } -/** - * The 'Microsoft.AspNetCore.Mvc.ViewFeatures' namespace - */ +/** The 'Microsoft.AspNetCore.Mvc.ViewFeatures' namespace. */ class MicrosoftAspNetCoreMvcViewFeatures extends Namespace { - MicrosoftAspNetCoreMvcViewFeatures() { - getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("ViewFeatures") - } + MicrosoftAspNetCoreMvcViewFeatures() { + getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + hasName("ViewFeatures") + } } -/** - * An attribute whose type is in the `Microsoft.AspNetCore.Mvc` namespace. - */ +/** An attribute whose type is in the `Microsoft.AspNetCore.Mvc` namespace. */ class MicrosoftAspNetCoreMvcAttribute extends Attribute { MicrosoftAspNetCoreMvcAttribute() { getType().getNamespace() = any(MicrosoftAspNetCoreMvcNamespace mvc) } } -/** - * An HttpPost attribute in `Microsoft.AspNetCore.Mvc` namespace - */ +/** A `Microsoft.AspNetCore.Mvc.HttpPost` attribute. */ class MicrosoftAspNetCoreMvcHttpPostAttribute extends MicrosoftAspNetCoreMvcAttribute { MicrosoftAspNetCoreMvcHttpPostAttribute() { getType().hasName("HttpPostAttribute") } } -/** - * An HttpPut attribute in `Microsoft.AspNetCore.Mvc` namespace - */ +/** A `Microsoft.AspNetCore.Mvc.HttpPut`. */ class MicrosoftAspNetCoreMvcHttpPutAttribute extends MicrosoftAspNetCoreMvcAttribute { MicrosoftAspNetCoreMvcHttpPutAttribute() { getType().hasName("HttpPutAttribute") } } -/** - * An HttpDelete attribute in `Microsoft.AspNetCore.Mvc` namespace - */ +/** A `Microsoft.AspNetCore.Mvc.HttpDelete` attribute. */ class MicrosoftAspNetCoreMvcHttpDeleteAttribute extends MicrosoftAspNetCoreMvcAttribute { MicrosoftAspNetCoreMvcHttpDeleteAttribute() { getType().hasName("HttpDeleteAttribute") } } -/** - * An attribute whose type is `Microsoft.AspNetCore.Mvc.NonAction`. - */ +/** A `Microsoft.AspNetCore.Mvc.NonAction` attribute. */ class MicrosoftAspNetCoreMvcNonActionAttribute extends MicrosoftAspNetCoreMvcAttribute { MicrosoftAspNetCoreMvcNonActionAttribute() { getType().hasName("NonActionAttribute") } } -/** - * The `Microsoft.AspNetCore.Antiforgery` namespace. - */ +/** The `Microsoft.AspNetCore.Antiforgery` namespace. */ class MicrosoftAspNetCoreAntiforgeryNamespace extends Namespace { MicrosoftAspNetCoreAntiforgeryNamespace() { getParentNamespace() instanceof MicrosoftAspNetCoreNamespace and - hasName("Antiforgery") + hasName("Antiforgery") } } -/** - * The `Microsoft.AspNetCore.Mvc.Filters` namespace. - */ +/** The `Microsoft.AspNetCore.Mvc.Filters` namespace. */ class MicrosoftAspNetCoreMvcFilters extends Namespace { MicrosoftAspNetCoreMvcFilters() { getParentNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and - hasName("Filters") + hasName("Filters") } } -/** - * The `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadataInterface` interface. - */ +/** The `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadataInterface` interface. */ class MicrosoftAspNetCoreMvcIFilterMetadataInterface extends Interface { MicrosoftAspNetCoreMvcIFilterMetadataInterface() { - getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and hasName("IFilterMetadata") } } - /** - * The `Microsoft.AspNetCore.IAuthorizationFilter` interface. - */ + /** The `Microsoft.AspNetCore.IAuthorizationFilter` interface. */ class MicrosoftAspNetCoreIAuthorizationFilterInterface extends Interface { MicrosoftAspNetCoreIAuthorizationFilterInterface() { - getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and hasName("IAsyncAuthorizationFilter") } - + + /** Gets the `OnAuthorizationAsync` method. */ Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } } -/** - * The `Microsoft.AspNetCore.IAntiforgery` interface. - */ +/** The `Microsoft.AspNetCore.IAntiforgery` interface. */ class MicrosoftAspNetCoreIAntiForgeryInterface extends Interface { MicrosoftAspNetCoreIAntiForgeryInterface() { - getNamespace() = any(MicrosoftAspNetCoreAntiforgeryNamespace h) and + getNamespace() instanceof MicrosoftAspNetCoreAntiforgeryNamespace and hasName("IAntiforgery") } - /** - * Gets the `ValidateRequestAsync` method. - */ + /** Gets the `ValidateRequestAsync` method. */ Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } } -/** - * The `Microsoft.AspNetCore.DefaultAntiForgery` class, or another user-supplied class that implements IAntiForgery - */ +/** The `Microsoft.AspNetCore.DefaultAntiForgery` class, or another user-supplied class that implements `IAntiForgery`. */ class AntiForgeryClass extends Class { AntiForgeryClass () { getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface } - /** - * Gets the `ValidateRequestAsync` method. - */ + /** Gets the `ValidateRequestAsync` method. */ Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } } -/** - * Authorization filter class defined by AspNetCore or the user - */ +/** Authorization filter class defined by AspNetCore or the user. */ class AuthorizationFilterClass extends Class { - AuthorizationFilterClass() { - getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface - } - - /** Gets the `OnAuthorization` method provided by this filter. */ + AuthorizationFilterClass() { + getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface + } + + /** Gets the `OnAuthorization` method provided by this filter. */ Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } } -/** - * An attribute whose type has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]Attribute`. - */ +/** An attribute whose type has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]Attribute`. */ class ValidateAntiForgeryAttribute extends Attribute { ValidateAntiForgeryAttribute() { getType().getName().matches("%Validate%Anti_orgery%Attribute") @@ -178,59 +143,55 @@ class ValidateAntiForgeryAttribute extends Attribute { } /** - * An class that has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]` and implements IFilterMetadata interface - * This class can be added to a collection of global MvcOptions.Filters collection + * A class that has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]` and implements `IFilterMetadata` interface + * This class can be added to a collection of global `MvcOptions.Filters` collection. */ class ValidateAntiforgeryTokenAuthorizationFilter extends Class { ValidateAntiforgeryTokenAuthorizationFilter() { - getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and + getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and getName().matches("%Validate%Anti_orgery%") } } -/** - * The `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` class - */ +/** The `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` class. */ class MicrosoftAspNetCoreMvcFilterCollection extends Class { MicrosoftAspNetCoreMvcFilterCollection() { - getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and hasName("FilterCollection") } - + + /** Gets an `Add` method. */ Method getAddMethod() { - result = getAMethod("Add") or - result = getABaseType().getAMethod("Add") + result = getAMethod("Add") or + result = getABaseType().getAMethod("Add") } } -/** - * The `Microsoft.AspNetCore.Mvc.MvcOptions` class . - */ +/** The `Microsoft.AspNetCore.Mvc.MvcOptions` class. */ class MicrosoftAspNetCoreMvcOptions extends Class { MicrosoftAspNetCoreMvcOptions() { - getNamespace() = any(MicrosoftAspNetCoreMvcNamespace mvc) and + getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and hasName("MvcOptions") } - Property getFilterCollectionProperty() { - result = getProperty("Filters") - } + /** Gets the `Filters` property. */ + Property getFilterCollectionProperty() { + result = getProperty("Filters") + } } -/** - * The base class for controllers in MVC, i.e. `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase` class. - */ - +/** The base class for controllers in MVC, i.e. `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase` class. */ class MicrosoftAspNetCoreMvcControllerBaseClass extends Class { - MicrosoftAspNetCoreMvcControllerBaseClass() { - getNamespace() = any(MicrosoftAspNetCoreMvcNamespace h) and - (hasName("Controller") or hasName("ControllerBase")) - } + MicrosoftAspNetCoreMvcControllerBaseClass() { + getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and ( + hasName("Controller") + or + hasName("ControllerBase") + ) + } } -/** - * An subtype of `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase`. - */ +/** A subtype of `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase`. */ class MicrosoftAspNetCoreMvcController extends Class { MicrosoftAspNetCoreMvcController() { getABaseType*() instanceof MicrosoftAspNetCoreMvcControllerBaseClass @@ -249,31 +210,30 @@ class MicrosoftAspNetCoreMvcController extends Class { * request. */ Method getAnActionModifyingMethod() { - result = getAnActionMethod() and - (result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute or - result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute or - result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute) + result = getAnActionMethod() and ( + result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute + or + result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute + or + result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute + ) } - /** Gets a `Redirect..` method. */ + /** Gets a `Redirect*` method. */ Method getARedirectMethod() { result = this.getAMethod() and result.getName().matches("Redirect%") } } -/* - * Returns a string corresponding to an HTTP method used in the action method - */ +/** Gets a string corresponding to the HTTP method used in the action method. */ string httpMethodType(Method m) { - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute and result = "POST" or - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute and result = "PUT" or - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute and result = "DELETE" - } + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute and result = "POST" or + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute and result = "PUT" or + m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute and result = "DELETE" +} -/** - * The `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper` class. - */ +/** The `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper` class. */ class MicrosoftAspNetCoreMvcHtmlHelperClass extends Class { MicrosoftAspNetCoreMvcHtmlHelperClass() { getNamespace() = any(MicrosoftAspNetCoreMvcViewFeatures mvc) and @@ -286,111 +246,108 @@ class MicrosoftAspNetCoreMvcHtmlHelperClass extends Class { } } -/** - * Class deriving from Microsoft.AspNetCore.Mvc.Razor.RazorPageBase, implements Razor page in ASPNET Core - */ +/** Class deriving from `Microsoft.AspNetCore.Mvc.Razor.RazorPageBase`, implements Razor page in ASPNET Core. */ class MicrosoftAspNetCoreMvcRazorPageBase extends Class { MicrosoftAspNetCoreMvcRazorPageBase () { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPageBase") } - + + /** Gets the `WriteLiteral` method. */ Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") } } -/** - * Class deriving from Microsoft.AspNetCore.Http.HttpRequest, implements HttpRequest in ASPNET Core - */ +/** Class deriving from `Microsoft.AspNetCore.Http.HttpRequest`, implements `HttpRequest` in ASP.NET Core. */ class MicrosoftAspNetCoreHttpHttpRequest extends Class { MicrosoftAspNetCoreHttpHttpRequest() { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpRequest") } } -/** - * Class deriving from Microsoft.AspNetCore.Http.HttpResponse, implements HttpResponse in ASPNET Core - */ +/** Class deriving from `Microsoft.AspNetCore.Http.HttpResponse`, implements `HttpResponse` in ASP.NET Core. */ class MicrosoftAspNetCoreHttpHttpResponse extends Class { MicrosoftAspNetCoreHttpHttpResponse() { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpResponse") } - + + /** Gets the `Redirect` method. */ Method getRedirectMethod() { result = this.getAMethod("Redirect") } - + + /** Gets the `Headers` property. */ Property getHeadersProperty() { result = this.getProperty("Headers") } } -/** - * Class is a wrapper around the collection of cookies in the response - */ +/** Class is a wrapper around the collection of cookies in the response. */ class MicrosoftAspNetCoreHttpResponseCookies extends Interface{ MicrosoftAspNetCoreHttpResponseCookies() { this.hasQualifiedName("Microsoft.AspNetCore.Http.IResponseCookies") } - + + /** Gets the `Append` method. */ Method getAppendMethod() { result = this.getAMethod("Append") } } -/** - * Class Microsoft.AspNetCore.Http.QueryString, holds query string in ASP.NET Core - */ +/** Class `Microsoft.AspNetCore.Http.QueryString`, holds query string in ASP.NET Core. */ class MicrosoftAspNetCoreHttpQueryString extends Struct { MicrosoftAspNetCoreHttpQueryString() { this.hasQualifiedName("Microsoft.AspNetCore.Http", "QueryString") } } -/** - * Class implementing IQueryCollection, holds parsed query string in ASP.NET Core - */ +/** Class implementing `IQueryCollection`, holds parsed query string in ASP.NET Core. */ class MicrosoftAspNetCoreHttpQueryCollection extends RefType { MicrosoftAspNetCoreHttpQueryCollection() { this.getABaseInterface().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") } } -/** - * Helper class for setting headers - */ +/** Helper class for setting headers. */ class MicrosoftAspNetCoreHttpResponseHeaders extends RefType { MicrosoftAspNetCoreHttpResponseHeaders() { - this.hasQualifiedName("Microsoft.AspNetCore.Http.Headers","ResponseHeaders") + this.hasQualifiedName("Microsoft.AspNetCore.Http.Headers", "ResponseHeaders") } - + + /** Gets the `Location` property. */ Property getLocationProperty() { result = this.getProperty("Location") } } +/** The `Microsoft.AspNetCore.Http.HeaderDictionaryExtensions` class. */ class MicrosoftAspNetCoreHttpHeaderDictionaryExtensions extends RefType { MicrosoftAspNetCoreHttpHeaderDictionaryExtensions () { - this.hasQualifiedName("Microsoft.AspNetCore.Http","HeaderDictionaryExtensions") + this.hasQualifiedName("Microsoft.AspNetCore.Http", "HeaderDictionaryExtensions") } + /** Gets the `Append` extension method. */ Method getAppendMethod() { result = this.getAMethod("Append") } + /** Gets the `AppendCommaSeparatedValues` extension method. */ Method getAppendCommaSeparatedValuesMethod() { result = this.getAMethod("AppendCommaSeparatedValues") } + /** Gets the `SetCommaSeparatedValues` extension method. */ Method getSetCommaSeparatedValuesMethod() { result = this.getAMethod("SetCommaSeparatedValues") } } + /** - * Class Microsoft.AspNetCore.Html.HtmlString, suppose to wrap HTML-encoded string in ASP.NET Core + * The `Microsoft.AspNetCore.Html.HtmlString` class, supposed to wrap HTML-encoded string in ASP.NET Core * Untrusted and unsanitized data should never flow there. */ class MicrosoftAspNetCoreHttpHtmlString extends Class { MicrosoftAspNetCoreHttpHtmlString() { this.hasQualifiedName("Microsoft.AspNetCore.Html", "HtmlString") - }} + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs index 8e21bc9deac8..829065bcb28b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs @@ -17,20 +17,20 @@ public class TestController : Controller { public IActionResult Index() { - // BAD: flow of content type to + // BAD: flow of content type to. var v = new ViewResult(); v.ViewData["BadData"] = new HtmlString(Request.Query["Bad data"]); StringValues vOut; Request.Query.TryGetValue("Foo", out vOut); - // BAD: via Enumerable + // BAD: via Enumerable. v.ViewData["FooFirst"] = new HtmlString(vOut.First()); - // BAD: via toArray + // BAD: via toArray. v.ViewData["FooArray0"] = new HtmlString(vOut.ToArray()[0]); - // BAD: via implicit conversion operator + // BAD: via implicit conversion operator. v.ViewData["FooImplicit"] = new HtmlString(vOut); return v; @@ -46,7 +46,6 @@ public IActionResult Submit([FromQuery] string foo) return view; } - public IActionResult IndexToModel() { //BAD: flow of submitted value to view in HtmlString. diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected index 3614a08046b2..9850eb457dcb 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected @@ -1,7 +1,7 @@ | XSS.cs:22:52:22:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:22:52:22:64 | access to property Query | User-provided value | | XSS.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:41:56:41:58 | foo | User-provided value | -| XSS.cs:53:43:53:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:53:43:53:67 | access to property Value | User-provided value | -| XSS.cs:60:43:60:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:60:43:60:55 | access to property Query | User-provided value | -| XSS.cs:63:44:63:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:63:44:63:56 | access to property Query | User-provided value | -| XSS.cs:71:43:71:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:71:43:71:61 | access to property ContentType | User-provided value | -| XSS.cs:74:51:74:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:74:51:74:65 | access to property Headers | User-provided value | +| XSS.cs:52:43:52:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:52:43:52:67 | access to property Value | User-provided value | +| XSS.cs:59:43:59:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:59:43:59:55 | access to property Query | User-provided value | +| XSS.cs:62:44:62:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:62:44:62:56 | access to property Query | User-provided value | +| XSS.cs:70:43:70:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:70:43:70:61 | access to property ContentType | User-provided value | +| XSS.cs:73:51:73:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:73:51:73:65 | access to property Headers | User-provided value | From aff47c9f381800529ef6e03c909cec2e2897a7e0 Mon Sep 17 00:00:00 2001 From: calum Date: Wed, 24 Oct 2018 13:19:49 +0100 Subject: [PATCH 08/13] C#: Tidy up whitespace. --- .../csharp/frameworks/system/web/WebPages.qll | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll index 8fcfe741bd58..04e61696706e 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll @@ -19,19 +19,19 @@ class SystemWebWebPagesWebPageExecutingBaseClass extends Class { } } -/** - * This class describes any class that derives from System.Web.WebPages.WebPageExecutingBase - */ +/** A class that derives from `System.Web.WebPages.WebPageExecutingBase`. */ class WebPageClass extends Class { - WebPageClass () { - this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass - } - - Method getWriteLiteralMethod() { + WebPageClass () { + this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass + } + + /** Gets the `WriteLiteral` method. */ + Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") - } - - Method getWriteLiteralToMethod() { + } + + /** Gets the `WriteLiteralTo` method. */ + Method getWriteLiteralToMethod() { result = getAMethod("WriteLiteralTo") - } -} \ No newline at end of file + } +} From 13f0a401f38ae99d9bfc7e15024e8b20535108df Mon Sep 17 00:00:00 2001 From: calum Date: Thu, 25 Oct 2018 14:07:01 +0100 Subject: [PATCH 09/13] C#: Update analysis change notes. --- change-notes/1.19/analysis-csharp.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/change-notes/1.19/analysis-csharp.md b/change-notes/1.19/analysis-csharp.md index 674a5fcd3814..d1b2b33974b7 100644 --- a/change-notes/1.19/analysis-csharp.md +++ b/change-notes/1.19/analysis-csharp.md @@ -3,9 +3,9 @@ ## General improvements * Control flow graph improvements: - * The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead. +* The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead. * Code that is only reachable from a constant failing assertion, such as `Debug.Assert(false)`, is considered to be unreachable. - + ## New queries | **Query** | **Tags** | **Purpose** | @@ -16,6 +16,7 @@ | Inconsistent lock sequence (`cs/inconsistent-lock-sequence`) | More results | This query now finds inconsistent lock sequences globally across calls. | | Local scope variable shadows member (`cs/local-shadows-member`) | Fewer results | Results have been removed where a constructor parameter shadows a member, because the parameter is probably used to initialize the member. | +| Cross-site scripting (`cs/web/xss`) | More results | This query now finds cross-site scripting vulnerabilities in ASP.NET Core applications. | | *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* | From ae96b347e263915db39c542ac38e80ceb6800e38 Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 2 Nov 2018 13:56:01 +0000 Subject: [PATCH 10/13] C#: Address review comments. --- .../csharp/dataflow/LibraryTypeDataFlow.qll | 25 +++ .../csharp/dataflow/flowsources/Remote.qll | 87 +++++----- .../frameworks/microsoft/AspNetCore.qll | 150 ++++++------------ .../frameworks/microsoft/Primitives.qll | 32 ---- .../csharp/security/dataflow/UrlRedirect.qll | 20 +-- .../code/csharp/security/dataflow/XSS.qll | 2 +- .../CWE-079/XSSFlowAspNet/XSS.cs | 1 - .../CWE-079/XSSFlowAspNet/XSS.expected | 6 +- 8 files changed, 122 insertions(+), 201 deletions(-) delete mode 100644 csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index a104477baff1..d5debe55cfea 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -1746,3 +1746,28 @@ class SystemNetWebUtilityFlow extends LibraryTypeDataFlow, SystemNetWebUtility { preservesValue = false } } + +/** + * The `StringValues` class used in many .NET Core libraries. Requires special `LibraryTypeDataFlow` flow. + */ +class StringValues extends Struct { + StringValues() { this.hasQualifiedName("Microsoft.Extensions.Primitives", "StringValues") } +} + +/** + * Custom flow through StringValues.StringValues library class + */ +class StringValuesFlow extends LibraryTypeDataFlow, StringValues { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { + c = any(Callable ca | this = ca.getDeclaringType()) and + ( + source = any(CallableFlowSourceArg a) or + source = any(CallableFlowSourceQualifier q) + ) and + sink = any(CallableFlowSinkReturn r) and + preservesValue = false + } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index 7e8f02e6cc12..92e505242c2f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -11,10 +11,8 @@ private import semmle.code.csharp.frameworks.system.web.Services private import semmle.code.csharp.frameworks.system.web.ui.WebControls private import semmle.code.csharp.frameworks.WCF private import semmle.code.csharp.frameworks.microsoft.Owin -private import semmle.code.csharp.frameworks.microsoft.Primitives private import semmle.code.csharp.frameworks.microsoft.AspNetCore - /** A data flow source of remote user input. */ abstract class RemoteFlowSource extends DataFlow::Node { /** Gets a string that describes the type of this remote flow source. */ @@ -31,9 +29,8 @@ class AspNetQueryStringMember extends Member { t instanceof SystemWebHttpRequestClass or t instanceof SystemNetHttpListenerRequestClass or t instanceof SystemWebHttpRequestBaseClass - | - this = t.getProperty(getHttpRequestFlowPropertyNames()) - or + | + this = t.getProperty(getHttpRequestFlowPropertyNames()) or this.(Field).getType() = t or this.(Property).getType() = t or this.(Callable).getReturnType() = t @@ -64,7 +61,7 @@ class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow t instanceof SystemWebHttpRequestClass or t instanceof SystemNetHttpListenerRequestClass or t instanceof SystemWebHttpRequestBaseClass - | + | // A request object can be indexed, so taint the object as well this.getExpr().getType() = t ) @@ -72,39 +69,35 @@ class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow this.getExpr() = any(AspNetQueryStringMember m).getAnAccess() } - override - string getSourceType() { result = "ASP.NET query string" } + override string getSourceType() { result = "ASP.NET query string" } } /** A data flow source of remote user input (ASP.NET unvalidated request data). */ -class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { +class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, + DataFlow::ExprNode { AspNetUnvalidatedQueryStringRemoteFlowSource() { this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or - this.getExpr() = any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall() + this.getExpr() = any(SystemWebUnvalidatedRequestValuesBase c) + .getAProperty() + .getGetter() + .getACall() } - override - string getSourceType() { result = "ASP.NET unvalidated request data" } + override string getSourceType() { result = "ASP.NET unvalidated request data" } } /** A data flow source of remote user input (ASP.NET user input). */ class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetUserInputRemoteFlowSource() { - getType() instanceof SystemWebUIWebControlsTextBoxClass - } + AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } - override - string getSourceType() { result = "ASP.NET user input" } + override string getSourceType() { result = "ASP.NET user input" } } /** A data flow source of remote user input (WCF based web service). */ class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { - WcfRemoteFlowSource() { - exists(OperationMethod om | om.getAParameter() = this.getParameter()) - } + WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) } - override - string getSourceType() { result = "web service input" } + override string getSourceType() { result = "web service input" } } /** A data flow source of remote user input (ASP.NET web service). */ @@ -116,8 +109,7 @@ class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::Paramete ) } - override - string getSourceType() { result = "ASP.NET web service input" } + override string getSourceType() { result = "ASP.NET web service input" } } /** A data flow source of remote user input (ASP.NET request message). */ @@ -126,8 +118,7 @@ class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, Data getType() instanceof SystemWebHttpRequestMessageClass } - override - string getSourceType() { result = "ASP.NET request message" } + override string getSourceType() { result = "ASP.NET request message" } } /** @@ -139,15 +130,15 @@ class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall() } - override - string getSourceType() { result = "Microsoft Owin request or query string" } + override string getSourceType() { result = "Microsoft Owin request or query string" } } /** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { MicrosoftOwinRequestRemoteFlowSource() { exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | - this.getExpr() = p.getGetter().getACall() | + this.getExpr() = p.getGetter().getACall() + | p = owinRequest.getAcceptProperty() or p = owinRequest.getBodyProperty() or p = owinRequest.getCacheControlProperty() or @@ -168,8 +159,7 @@ class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::E ) } - override - string getSourceType() { result = "Microsoft Owin request" } + override string getSourceType() { result = "Microsoft Owin request" } } /** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ @@ -177,45 +167,42 @@ class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { ActionMethodParameter() { exists(Parameter p | p = this.getParameter() and - p.fromSource() | - p = any(Controller c).getAnActionMethod().getAParameter() - or + p.fromSource() + | + p = any(Controller c).getAnActionMethod().getAParameter() or p = any(ApiController c).getAnActionMethod().getAParameter() ) } - override - string getSourceType() { result = "ASP.NET MVC action method parameter" } + override string getSourceType() { result = "ASP.NET MVC action method parameter" } } /** A data flow source of remote user input (ASP.NET Core). */ abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } - /** A data flow source of remote user input (ASP.NET query collection). */ class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { AspNetCoreQueryRemoteFlowSource() { exists(ValueOrRefType t | - t instanceof MicrosoftAspNetCoreHttpHttpRequest - or - t instanceof MicrosoftAspNetCoreHttpQueryCollection - or + t instanceof MicrosoftAspNetCoreHttpHttpRequest or + t instanceof MicrosoftAspNetCoreHttpQueryCollection or t instanceof MicrosoftAspNetCoreHttpQueryString - | - this.getExpr().(Call).getTarget().getDeclaringType() = t - or + | + this.getExpr().(Call).getTarget().getDeclaringType() = t or this.asExpr().(Access).getTarget().getDeclaringType() = t ) or exists(Call c | - c.getTarget().getDeclaringType().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and + c + .getTarget() + .getDeclaringType() + .hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and c.getTarget().getName() = "TryGetValue" and this.asExpr() = c.getArgumentForName("value") ) } - override - string getSourceType() { result = "ASP.NET Core query string" } + override string getSourceType() { result = "ASP.NET Core query string" } } /** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ @@ -223,11 +210,11 @@ class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::Parame AspNetCoreActionMethodParameter() { exists(Parameter p | p = this.getParameter() and - p.fromSource() | + p.fromSource() + | p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() ) } - override - string getSourceType() { result = "ASP.NET Core MVC action method parameter" } + override string getSourceType() { result = "ASP.NET Core MVC action method parameter" } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll index 7cccd6f74e96..cdcc9c2a37c8 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll @@ -3,6 +3,7 @@ import csharp import semmle.code.csharp.frameworks.Microsoft +/** The `Microsoft.AspNetCore` namespace. */ class MicrosoftAspNetCoreNamespace extends Namespace { MicrosoftAspNetCoreNamespace() { getParentNamespace() instanceof MicrosoftNamespace and @@ -29,36 +30,28 @@ class MicrosoftAspNetCoreMvcViewFeatures extends Namespace { /** An attribute whose type is in the `Microsoft.AspNetCore.Mvc` namespace. */ class MicrosoftAspNetCoreMvcAttribute extends Attribute { MicrosoftAspNetCoreMvcAttribute() { - getType().getNamespace() = any(MicrosoftAspNetCoreMvcNamespace mvc) + getType().getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace } } /** A `Microsoft.AspNetCore.Mvc.HttpPost` attribute. */ class MicrosoftAspNetCoreMvcHttpPostAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpPostAttribute() { - getType().hasName("HttpPostAttribute") - } + MicrosoftAspNetCoreMvcHttpPostAttribute() { getType().hasName("HttpPostAttribute") } } -/** A `Microsoft.AspNetCore.Mvc.HttpPut`. */ +/** A `Microsoft.AspNetCore.Mvc.HttpPut` attribute. */ class MicrosoftAspNetCoreMvcHttpPutAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpPutAttribute() { - getType().hasName("HttpPutAttribute") - } + MicrosoftAspNetCoreMvcHttpPutAttribute() { getType().hasName("HttpPutAttribute") } } /** A `Microsoft.AspNetCore.Mvc.HttpDelete` attribute. */ class MicrosoftAspNetCoreMvcHttpDeleteAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcHttpDeleteAttribute() { - getType().hasName("HttpDeleteAttribute") - } + MicrosoftAspNetCoreMvcHttpDeleteAttribute() { getType().hasName("HttpDeleteAttribute") } } /** A `Microsoft.AspNetCore.Mvc.NonAction` attribute. */ class MicrosoftAspNetCoreMvcNonActionAttribute extends MicrosoftAspNetCoreMvcAttribute { - MicrosoftAspNetCoreMvcNonActionAttribute() { - getType().hasName("NonActionAttribute") - } + MicrosoftAspNetCoreMvcNonActionAttribute() { getType().hasName("NonActionAttribute") } } /** The `Microsoft.AspNetCore.Antiforgery` namespace. */ @@ -85,7 +78,7 @@ class MicrosoftAspNetCoreMvcIFilterMetadataInterface extends Interface { } } - /** The `Microsoft.AspNetCore.IAuthorizationFilter` interface. */ +/** The `Microsoft.AspNetCore.IAuthorizationFilter` interface. */ class MicrosoftAspNetCoreIAuthorizationFilterInterface extends Interface { MicrosoftAspNetCoreIAuthorizationFilterInterface() { getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and @@ -93,9 +86,7 @@ class MicrosoftAspNetCoreIAuthorizationFilterInterface extends Interface { } /** Gets the `OnAuthorizationAsync` method. */ - Method getOnAuthorizationMethod() { - result = getAMethod("OnAuthorizationAsync") - } + Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } } /** The `Microsoft.AspNetCore.IAntiforgery` interface. */ @@ -106,40 +97,30 @@ class MicrosoftAspNetCoreIAntiForgeryInterface extends Interface { } /** Gets the `ValidateRequestAsync` method. */ - Method getValidateMethod() { - result = getAMethod("ValidateRequestAsync") - } + Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } } /** The `Microsoft.AspNetCore.DefaultAntiForgery` class, or another user-supplied class that implements `IAntiForgery`. */ class AntiForgeryClass extends Class { - AntiForgeryClass () { - getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface - } + AntiForgeryClass() { getABaseInterface*() instanceof MicrosoftAspNetCoreIAntiForgeryInterface } /** Gets the `ValidateRequestAsync` method. */ - Method getValidateMethod() { - result = getAMethod("ValidateRequestAsync") - } + Method getValidateMethod() { result = getAMethod("ValidateRequestAsync") } } -/** Authorization filter class defined by AspNetCore or the user. */ +/** An authorization filter class defined by AspNetCore or the user. */ class AuthorizationFilterClass extends Class { AuthorizationFilterClass() { getABaseInterface*() instanceof MicrosoftAspNetCoreIAuthorizationFilterInterface } /** Gets the `OnAuthorization` method provided by this filter. */ - Method getOnAuthorizationMethod() { - result = getAMethod("OnAuthorizationAsync") - } + Method getOnAuthorizationMethod() { result = getAMethod("OnAuthorizationAsync") } } /** An attribute whose type has a name like `[Auto...]Validate[...]Anti[Ff]orgery[...Token]Attribute`. */ class ValidateAntiForgeryAttribute extends Attribute { - ValidateAntiForgeryAttribute() { - getType().getName().matches("%Validate%Anti_orgery%Attribute") - } + ValidateAntiForgeryAttribute() { getType().getName().matches("%Validate%Anti_orgery%Attribute") } } /** @@ -148,7 +129,7 @@ class ValidateAntiForgeryAttribute extends Attribute { */ class ValidateAntiforgeryTokenAuthorizationFilter extends Class { ValidateAntiforgeryTokenAuthorizationFilter() { - getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and + getABaseInterface*() instanceof MicrosoftAspNetCoreMvcIFilterMetadataInterface and getName().matches("%Validate%Anti_orgery%") } } @@ -156,7 +137,7 @@ class ValidateAntiforgeryTokenAuthorizationFilter extends Class { /** The `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` class. */ class MicrosoftAspNetCoreMvcFilterCollection extends Class { MicrosoftAspNetCoreMvcFilterCollection() { - getNamespace() = any(MicrosoftAspNetCoreMvcFilters h) and + getNamespace() instanceof MicrosoftAspNetCoreMvcFilters and hasName("FilterCollection") } @@ -170,22 +151,20 @@ class MicrosoftAspNetCoreMvcFilterCollection extends Class { /** The `Microsoft.AspNetCore.Mvc.MvcOptions` class. */ class MicrosoftAspNetCoreMvcOptions extends Class { MicrosoftAspNetCoreMvcOptions() { - getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and hasName("MvcOptions") } /** Gets the `Filters` property. */ - Property getFilterCollectionProperty() { - result = getProperty("Filters") - } + Property getFilterCollectionProperty() { result = getProperty("Filters") } } /** The base class for controllers in MVC, i.e. `Microsoft.AspNetCore.Mvc.Controller` or `Microsoft.AspNetCore.Mvc.ControllerBase` class. */ class MicrosoftAspNetCoreMvcControllerBaseClass extends Class { MicrosoftAspNetCoreMvcControllerBaseClass() { - getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and ( - hasName("Controller") - or + getNamespace() instanceof MicrosoftAspNetCoreMvcNamespace and + ( + hasName("Controller") or hasName("ControllerBase") ) } @@ -199,137 +178,102 @@ class MicrosoftAspNetCoreMvcController extends Class { /** Gets an action method for this controller. */ Method getAnActionMethod() { - result = getAMethod() and - result.isPublic() and - not result.isStatic() and - not result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcNonActionAttribute + result = getAMethod() and + result.isPublic() and + not result.isStatic() and + not result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcNonActionAttribute } - /** - * Gets an "action" method handling POST, PUT and DELETE request, which may be called by the MVC framework in response to a user - * request. - */ - Method getAnActionModifyingMethod() { - result = getAnActionMethod() and ( - result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute - or - result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute - or - result.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute - ) - } - /** Gets a `Redirect*` method. */ Method getARedirectMethod() { result = this.getAMethod() and result.getName().matches("Redirect%") } } - -/** Gets a string corresponding to the HTTP method used in the action method. */ -string httpMethodType(Method m) { - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPostAttribute and result = "POST" or - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpPutAttribute and result = "PUT" or - m.getAnAttribute() instanceof MicrosoftAspNetCoreMvcHttpDeleteAttribute and result = "DELETE" -} /** The `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper` class. */ class MicrosoftAspNetCoreMvcHtmlHelperClass extends Class { MicrosoftAspNetCoreMvcHtmlHelperClass() { - getNamespace() = any(MicrosoftAspNetCoreMvcViewFeatures mvc) and + getNamespace() instanceof MicrosoftAspNetCoreMvcViewFeatures and hasName("HtmlHelper") } /** Gets the `Raw` method. */ - Method getRawMethod() { - result = getAMethod("Raw") - } + Method getRawMethod() { result = getAMethod("Raw") } } -/** Class deriving from `Microsoft.AspNetCore.Mvc.Razor.RazorPageBase`, implements Razor page in ASPNET Core. */ +/** A class deriving from `Microsoft.AspNetCore.Mvc.Razor.RazorPageBase`, implements Razor page in ASPNET Core. */ class MicrosoftAspNetCoreMvcRazorPageBase extends Class { - MicrosoftAspNetCoreMvcRazorPageBase () { + MicrosoftAspNetCoreMvcRazorPageBase() { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Mvc.Razor", "RazorPageBase") } /** Gets the `WriteLiteral` method. */ - Method getWriteLiteralMethod() { - result = getAMethod("WriteLiteral") - } + Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") } } -/** Class deriving from `Microsoft.AspNetCore.Http.HttpRequest`, implements `HttpRequest` in ASP.NET Core. */ +/** A class deriving from `Microsoft.AspNetCore.Http.HttpRequest`, implements `HttpRequest` in ASP.NET Core. */ class MicrosoftAspNetCoreHttpHttpRequest extends Class { MicrosoftAspNetCoreHttpHttpRequest() { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpRequest") } } -/** Class deriving from `Microsoft.AspNetCore.Http.HttpResponse`, implements `HttpResponse` in ASP.NET Core. */ +/** A class deriving from `Microsoft.AspNetCore.Http.HttpResponse`, implements `HttpResponse` in ASP.NET Core. */ class MicrosoftAspNetCoreHttpHttpResponse extends Class { MicrosoftAspNetCoreHttpHttpResponse() { this.getABaseType*().hasQualifiedName("Microsoft.AspNetCore.Http", "HttpResponse") } /** Gets the `Redirect` method. */ - Method getRedirectMethod() { - result = this.getAMethod("Redirect") - } + Method getRedirectMethod() { result = this.getAMethod("Redirect") } /** Gets the `Headers` property. */ - Property getHeadersProperty() { - result = this.getProperty("Headers") - } + Property getHeadersProperty() { result = this.getProperty("Headers") } } -/** Class is a wrapper around the collection of cookies in the response. */ -class MicrosoftAspNetCoreHttpResponseCookies extends Interface{ +/** An interface that is a wrapper around the collection of cookies in the response. */ +class MicrosoftAspNetCoreHttpResponseCookies extends Interface { MicrosoftAspNetCoreHttpResponseCookies() { this.hasQualifiedName("Microsoft.AspNetCore.Http.IResponseCookies") } /** Gets the `Append` method. */ - Method getAppendMethod() { - result = this.getAMethod("Append") - } + Method getAppendMethod() { result = this.getAMethod("Append") } } -/** Class `Microsoft.AspNetCore.Http.QueryString`, holds query string in ASP.NET Core. */ +/** The class `Microsoft.AspNetCore.Http.QueryString`, holds query string in ASP.NET Core. */ class MicrosoftAspNetCoreHttpQueryString extends Struct { MicrosoftAspNetCoreHttpQueryString() { this.hasQualifiedName("Microsoft.AspNetCore.Http", "QueryString") } } - -/** Class implementing `IQueryCollection`, holds parsed query string in ASP.NET Core. */ + +/** A class or interface implementing `IQueryCollection`, holds parsed query string in ASP.NET Core. */ class MicrosoftAspNetCoreHttpQueryCollection extends RefType { MicrosoftAspNetCoreHttpQueryCollection() { this.getABaseInterface().hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") } } -/** Helper class for setting headers. */ +/** The helper class `ResponseHeaders` for setting headers. */ class MicrosoftAspNetCoreHttpResponseHeaders extends RefType { MicrosoftAspNetCoreHttpResponseHeaders() { this.hasQualifiedName("Microsoft.AspNetCore.Http.Headers", "ResponseHeaders") } /** Gets the `Location` property. */ - Property getLocationProperty() { - result = this.getProperty("Location") - } + Property getLocationProperty() { result = this.getProperty("Location") } } /** The `Microsoft.AspNetCore.Http.HeaderDictionaryExtensions` class. */ class MicrosoftAspNetCoreHttpHeaderDictionaryExtensions extends RefType { - MicrosoftAspNetCoreHttpHeaderDictionaryExtensions () { + MicrosoftAspNetCoreHttpHeaderDictionaryExtensions() { this.hasQualifiedName("Microsoft.AspNetCore.Http", "HeaderDictionaryExtensions") } /** Gets the `Append` extension method. */ - Method getAppendMethod() { - result = this.getAMethod("Append") - } + Method getAppendMethod() { result = this.getAMethod("Append") } /** Gets the `AppendCommaSeparatedValues` extension method. */ Method getAppendCommaSeparatedValuesMethod() { @@ -337,9 +281,7 @@ class MicrosoftAspNetCoreHttpHeaderDictionaryExtensions extends RefType { } /** Gets the `SetCommaSeparatedValues` extension method. */ - Method getSetCommaSeparatedValuesMethod() { - result = this.getAMethod("SetCommaSeparatedValues") - } + Method getSetCommaSeparatedValuesMethod() { result = this.getAMethod("SetCommaSeparatedValues") } } /** diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll deleted file mode 100644 index 603672c08d0c..000000000000 --- a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Primitives.qll +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Provides definitions for working with classes in Microsoft.Extensions.Primitives namespace - */ -import csharp - -module ExtensionPrimitives { -private import semmle.code.csharp.dataflow.LibraryTypeDataFlow - -/** - * StringValues class used in many .Net Core libraries. Requreres special LibraryTypeDataFlow flow. - */ - class StringValues extends Struct { - StringValues() { - this.hasQualifiedName("Microsoft.Extensions.Primitives", "StringValues") - } - } - - /** - * Custom flow through StringValues.StringValues library class - */ - class StringValuesFlow extends LibraryTypeDataFlow, StringValues { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { - c = any(Callable ca | this = ca.getDeclaringType()) - and - (source = any(CallableFlowSourceArg a) or - source = any(CallableFlowSourceQualifier q)) - and - sink = any(CallableFlowSinkReturn r) - and preservesValue = false - } - } -} \ No newline at end of file diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll index 3183b975eaa3..bb8cae46e267 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll @@ -181,10 +181,10 @@ module UrlRedirect { class AspNetCoreLocationHeaderSink extends Sink { AspNetCoreLocationHeaderSink () { // ResponseHeaders.Location = - exists(Assignment propAssign, PropertyAccess pa | - pa.getTarget() = any(MicrosoftAspNetCoreHttpResponseHeaders headers).getLocationProperty() and - pa = propAssign.getLValue() and - this.asExpr() = propAssign.getRValue()) + exists(AssignableDefinition def | + def.getTarget() = any(MicrosoftAspNetCoreHttpResponseHeaders headers).getLocationProperty() | + this.asExpr() = def.getSource() + ) or // HttpResponse.Headers.Append("location", ) exists(MethodCall mc, MicrosoftAspNetCoreHttpHeaderDictionaryExtensions ext | mc.getTarget() = ext.getAppendMethod() or @@ -193,17 +193,17 @@ module UrlRedirect { mc.getArgumentForName("key").getValue().toLowerCase() = "location" and this.getExpr() = mc.getArgument(2)) or // HttpResponse.Headers.Add("location", ) - exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, PropertyAccess c, MethodCall add | - c.getTarget() = resp.getHeadersProperty() and + exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, PropertyAccess qualifier, MethodCall add | + qualifier.getTarget() = resp.getHeadersProperty() and add.getTarget() = cl.getAMethod("Add") and - c = add.getQualifier() and + qualifier = add.getQualifier() and add.getArgument(0).getValue().toLowerCase() = "location" and this.getExpr() = add.getArgument(1)) or // HttpResponse.Headers["location"] = - exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, IndexerAccess ci, Call cs, PropertyAccess pa | - pa.getTarget() = resp.getHeadersProperty() and + exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, IndexerAccess ci, Call cs, PropertyAccess qualifier | + qualifier.getTarget() = resp.getHeadersProperty() and ci.getTarget() = cl.getAnIndexer() and - pa = ci.getQualifier() and + qualifier = ci.getQualifier() and cs.getTarget() = cl.getAnIndexer().getSetter() and cs.getArgument(0).getValue().toLowerCase() = "location" and this.asExpr() = cs.getArgument(1)) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index 97f886c8baf0..de16c91a7488 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -6,6 +6,7 @@ import csharp module XSS { import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.frameworks.microsoft.AspNetCore import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Mvc @@ -15,7 +16,6 @@ module XSS { import semmle.code.csharp.frameworks.system.windows.Forms import semmle.code.csharp.security.Sanitizers import semmle.code.asp.AspNet - import semmle.code.csharp.frameworks.microsoft.AspNetCore /** * Holds if there is tainted flow from `source` to `sink` that may lead to a diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs index c29d07b84d1d..247b681e8272 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs @@ -5,7 +5,6 @@ namespace ASP using System.IO; using System.Net; using System.Web; - // using System.Web.UI; using System.Web.WebPages; public class _Page_Views_Home_Contact_cshtml : System.Web.Mvc.WebViewPage diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected index ab165784bffa..4af94aa22d23 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected @@ -1,3 +1,3 @@ -| XSS.cs:28:30:28:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSS.cs:21:25:21:43 | access to property QueryString | User-provided value | -| XSS.cs:38:40:38:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSS.cs:21:25:21:43 | access to property QueryString | User-provided value | -| XSS.cs:45:28:45:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:45:28:45:46 | access to property QueryString | User-provided value | +| XSS.cs:27:30:27:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSS.cs:20:25:20:43 | access to property QueryString | User-provided value | +| XSS.cs:37:40:37:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSS.cs:20:25:20:43 | access to property QueryString | User-provided value | +| XSS.cs:44:28:44:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:44:28:44:46 | access to property QueryString | User-provided value | From 7fa442d12769777e8f7fa2e655272c7b0a1337f2 Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 2 Nov 2018 14:22:04 +0000 Subject: [PATCH 11/13] C#: Merge tests. --- .../CWE-079/XSS/XSS.expected | 10 + .../CWE-079/{XSSFlowAspNet => XSS}/XSS.qlref | 0 .../XSS.cs => XSS/XSSAspNet.cs} | 0 .../XSS.cs => XSS/XSSAspNetCore.cs} | 0 .../CWE-079/{XSSFlowAspNet => XSS}/stubs.cs | 0 .../CWE-079/XSSFlowAspNet/XSS.expected | 3 - .../CWE-079/XSSFlowAspNetCore/XSS.expected | 7 - .../CWE-079/XSSFlowAspNetCore/XSS.qlref | 1 - .../CWE-079/XSSFlowAspNetCore/stubs.cs | 236 ------------------ .../UrlRedirect.expected | 10 - .../UrlRedirect.expected | 4 - .../UrlRedirect.qlref | 1 - .../UrlRedirect.cs | 0 .../CWE-601/UrlRedirect/UrlRedirect.expected | 14 ++ .../UrlRedirect.qlref | 0 .../UrlRedirectCore.cs} | 0 .../stubs.cs | 0 17 files changed, 24 insertions(+), 262 deletions(-) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected rename csharp/ql/test/query-tests/Security Features/CWE-079/{XSSFlowAspNet => XSS}/XSS.qlref (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{XSSFlowAspNet/XSS.cs => XSS/XSSAspNet.cs} (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{XSSFlowAspNetCore/XSS.cs => XSS/XSSAspNetCore.cs} (100%) rename csharp/ql/test/query-tests/Security Features/CWE-079/{XSSFlowAspNet => XSS}/stubs.cs (100%) delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref rename csharp/ql/test/query-tests/Security Features/CWE-601/{UrlRedirect.ASPNetClassic => UrlRedirect}/UrlRedirect.cs (100%) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected rename csharp/ql/test/query-tests/Security Features/CWE-601/{UrlRedirect.ASPNETCore => UrlRedirect}/UrlRedirect.qlref (100%) rename csharp/ql/test/query-tests/Security Features/CWE-601/{UrlRedirect.ASPNETCore/UrlRedirect.cs => UrlRedirect/UrlRedirectCore.cs} (100%) rename csharp/ql/test/query-tests/Security Features/CWE-601/{UrlRedirect.ASPNETCore => UrlRedirect}/stubs.cs (100%) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected new file mode 100644 index 000000000000..80e181ca5045 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected @@ -0,0 +1,10 @@ +| XSSAspNet.cs:27:30:27:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSSAspNet.cs:20:25:20:43 | access to property QueryString | User-provided value | +| XSSAspNet.cs:37:40:37:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSSAspNet.cs:20:25:20:43 | access to property QueryString | User-provided value | +| XSSAspNet.cs:44:28:44:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNet.cs:44:28:44:46 | access to property QueryString | User-provided value | +| XSSAspNetCore.cs:22:52:22:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:22:52:22:64 | access to property Query | User-provided value | +| XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:41:56:41:58 | foo | User-provided value | +| XSSAspNetCore.cs:52:43:52:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:52:43:52:67 | access to property Value | User-provided value | +| XSSAspNetCore.cs:59:43:59:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:59:43:59:55 | access to property Query | User-provided value | +| XSSAspNetCore.cs:62:44:62:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:62:44:62:56 | access to property Query | User-provided value | +| XSSAspNetCore.cs:70:43:70:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:70:43:70:61 | access to property ContentType | User-provided value | +| XSSAspNetCore.cs:73:51:73:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:73:51:73:65 | access to property Headers | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.qlref similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.qlref rename to csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.qlref diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNet.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.cs rename to csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNet.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.cs rename to csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/stubs.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/stubs.cs rename to csharp/ql/test/query-tests/Security Features/CWE-079/XSS/stubs.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected deleted file mode 100644 index 4af94aa22d23..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNet/XSS.expected +++ /dev/null @@ -1,3 +0,0 @@ -| XSS.cs:27:30:27:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSS.cs:20:25:20:43 | access to property QueryString | User-provided value | -| XSS.cs:37:40:37:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSS.cs:20:25:20:43 | access to property QueryString | User-provided value | -| XSS.cs:44:28:44:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:44:28:44:46 | access to property QueryString | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected deleted file mode 100644 index 9850eb457dcb..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.expected +++ /dev/null @@ -1,7 +0,0 @@ -| XSS.cs:22:52:22:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:22:52:22:64 | access to property Query | User-provided value | -| XSS.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:41:56:41:58 | foo | User-provided value | -| XSS.cs:52:43:52:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:52:43:52:67 | access to property Value | User-provided value | -| XSS.cs:59:43:59:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:59:43:59:55 | access to property Query | User-provided value | -| XSS.cs:62:44:62:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:62:44:62:56 | access to property Query | User-provided value | -| XSS.cs:70:43:70:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:70:43:70:61 | access to property ContentType | User-provided value | -| XSS.cs:73:51:73:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:73:51:73:65 | access to property Headers | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref deleted file mode 100644 index faad1d6403c1..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/XSS.qlref +++ /dev/null @@ -1 +0,0 @@ -Security Features/CWE-079/XSS.ql \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs deleted file mode 100644 index 910ef14f5be6..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSSFlowAspNetCore/stubs.cs +++ /dev/null @@ -1,236 +0,0 @@ -namespace Microsoft -{ - namespace AspNetCore - { - namespace Html - { - // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent - { - public HtmlString(string value) => throw null; - public override string ToString() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IHtmlContent - { - } - - } - namespace Http - { - // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class HttpRequest - { - public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } - public abstract Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } - public abstract Microsoft.AspNetCore.Http.QueryString QueryString { get; set; } - public abstract string ContentType { get; set; } - } - - // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> - { - Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } - } - - // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IQueryCollection : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable> - { - Microsoft.Extensions.Primitives.StringValues this[string key] { get; } - bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); - } - - // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public struct QueryString : System.IEquatable - { - public bool Equals(Microsoft.AspNetCore.Http.QueryString other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public override string ToString() => throw null; - public string Value { get => throw null; } - } - - } - namespace Mvc - { - // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class ControllerBase - { - public Microsoft.AspNetCore.Http.HttpRequest Request { get => throw null; } - } - - // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, System.IDisposable, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IActionFilter - { - public virtual Microsoft.AspNetCore.Mvc.ViewResult View(object model) => throw null; - public void Dispose() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata - { - public FromQueryAttribute() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute - { - public HttpPostAttribute() => throw null; - public HttpPostAttribute(string template) => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionResult - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory - { - public ValidateAntiForgeryTokenAttribute() => throw null; - } - - // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult - { - public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } - public ViewResult() => throw null; - } - - namespace Filters - { - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IFilterMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata - { - } - - } - namespace ModelBinding - { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IBindingSourceMetadata - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IModelNameProvider - { - } - - } - namespace Routing - { - // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IActionHttpMethodProvider - { - } - - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public interface IRouteTemplateProvider - { - } - - } - namespace ViewFeatures - { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ViewDataDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> - { - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public System.Collections.Generic.ICollection Values { get => throw null; } - public System.Collections.Generic.ICollection Keys { get => throw null; } - public bool Contains(System.Collections.Generic.KeyValuePair item) => throw null; - public bool ContainsKey(string key) => throw null; - public bool IsReadOnly { get => throw null; } - public bool Remove(System.Collections.Generic.KeyValuePair item) => throw null; - public bool Remove(string key) => throw null; - public bool TryGetValue(string key, out object value) => throw null; - public int Count { get => throw null; } - public object this[string index] { get => throw null; set => throw null; } - public void Add(System.Collections.Generic.KeyValuePair item) => throw null; - public void Add(string key, object value) => throw null; - public void Clear() => throw null; - public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; - } - - } - } - } - namespace Extensions - { - namespace Primitives - { - // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, - System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection - { - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - bool System.Collections.Generic.ICollection.Contains(string item) => throw null; - bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } - bool System.Collections.Generic.ICollection.Remove(string item) => throw null; - int System.Collections.Generic.IList.IndexOf(string item) => throw null; - public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; - public bool Equals(string other) => throw null; - public bool Equals(string[] other) => throw null; - public int Count { get => throw null; } - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public override string ToString() => throw null; - public static implicit operator string(Microsoft.Extensions.Primitives.StringValues values) => throw null; - public string this[int index] { get => throw null; set => throw null; } - public string[] ToArray() => throw null; - void System.Collections.Generic.ICollection.Add(string item) => throw null; - void System.Collections.Generic.ICollection.Clear() => throw null; - void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; - void System.Collections.Generic.IList.Insert(int index, string item) => throw null; - void System.Collections.Generic.IList.RemoveAt(int index) => throw null; - } - - } - } -} -namespace System -{ - namespace Linq - { - // Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - static public class Enumerable - { - public static TSource First(this System.Collections.Generic.IEnumerable source) => throw null; - } - - } -} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected deleted file mode 100644 index ab5ebeba1a4e..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.expected +++ /dev/null @@ -1,10 +0,0 @@ -| UrlRedirect.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:36:49:36:53 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:39:69:39:73 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:42:39:42:53 | ... + ... | Untrusted URL redirection due to $@. | UrlRedirect.cs:15:44:15:48 | value | user-provided value | -| UrlRedirect.cs:50:28:50:32 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | -| UrlRedirect.cs:55:32:55:45 | object creation of type Uri | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | -| UrlRedirect.cs:58:31:58:35 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirect.cs:47:51:47:55 | value | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected deleted file mode 100644 index ed5ddab84070..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.expected +++ /dev/null @@ -1,4 +0,0 @@ -| UrlRedirect.cs:14:31:14:61 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:14:31:14:53 | access to property QueryString | user-provided value | -| UrlRedirect.cs:39:44:39:74 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:39:44:39:66 | access to property QueryString | user-provided value | -| UrlRedirect.cs:40:47:40:77 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:40:47:40:69 | access to property QueryString | user-provided value | -| UrlRedirect.cs:49:29:49:31 | access to local variable url | Untrusted URL redirection due to $@. | UrlRedirect.cs:24:22:24:44 | access to property QueryString | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref deleted file mode 100644 index 2e061145f9ca..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.qlref +++ /dev/null @@ -1 +0,0 @@ -Security Features/CWE-601/UrlRedirect.ql diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNetClassic/UrlRedirect.cs rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected new file mode 100644 index 000000000000..eec21ad90a13 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.expected @@ -0,0 +1,14 @@ +| UrlRedirect.cs:14:31:14:61 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:14:31:14:53 | access to property QueryString | user-provided value | +| UrlRedirect.cs:39:44:39:74 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:39:44:39:66 | access to property QueryString | user-provided value | +| UrlRedirect.cs:40:47:40:77 | access to indexer | Untrusted URL redirection due to $@. | UrlRedirect.cs:40:47:40:69 | access to property QueryString | user-provided value | +| UrlRedirect.cs:49:29:49:31 | access to local variable url | Untrusted URL redirection due to $@. | UrlRedirect.cs:24:22:24:44 | access to property QueryString | user-provided value | +| UrlRedirectCore.cs:18:22:18:26 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:21:44:21:48 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:27:46:27:50 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:33:66:33:70 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:36:49:36:53 | call to operator implicit conversion | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:39:69:39:73 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:42:39:42:53 | ... + ... | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:15:44:15:48 | value | user-provided value | +| UrlRedirectCore.cs:50:28:50:32 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | +| UrlRedirectCore.cs:55:32:55:45 | object creation of type Uri | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | +| UrlRedirectCore.cs:58:31:58:35 | access to parameter value | Untrusted URL redirection due to $@. | UrlRedirectCore.cs:47:51:47:55 | value | user-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.qlref b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.qlref similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.qlref rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirect.qlref diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirectCore.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/UrlRedirect.cs rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/UrlRedirectCore.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/stubs.cs similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect.ASPNETCore/stubs.cs rename to csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/stubs.cs From 29df7f5e967ece657b85825f333faf738b3ce333 Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 2 Nov 2018 14:49:37 +0000 Subject: [PATCH 12/13] C#: Mark false-negatives. --- .../Security Features/CWE-079/XSS/XSS.expected | 14 +++++++------- .../Security Features/CWE-079/XSS/XSSAspNetCore.cs | 9 ++++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected index 80e181ca5045..3f231e656004 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSS.expected @@ -1,10 +1,10 @@ | XSSAspNet.cs:27:30:27:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSSAspNet.cs:20:25:20:43 | access to property QueryString | User-provided value | | XSSAspNet.cs:37:40:37:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSSAspNet.cs:20:25:20:43 | access to property QueryString | User-provided value | | XSSAspNet.cs:44:28:44:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNet.cs:44:28:44:46 | access to property QueryString | User-provided value | -| XSSAspNetCore.cs:22:52:22:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:22:52:22:64 | access to property Query | User-provided value | -| XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:41:56:41:58 | foo | User-provided value | -| XSSAspNetCore.cs:52:43:52:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:52:43:52:67 | access to property Value | User-provided value | -| XSSAspNetCore.cs:59:43:59:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:59:43:59:55 | access to property Query | User-provided value | -| XSSAspNetCore.cs:62:44:62:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:62:44:62:56 | access to property Query | User-provided value | -| XSSAspNetCore.cs:70:43:70:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:70:43:70:61 | access to property ContentType | User-provided value | -| XSSAspNetCore.cs:73:51:73:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:73:51:73:65 | access to property Headers | User-provided value | +| XSSAspNetCore.cs:21:52:21:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:21:52:21:64 | access to property Query | User-provided value | +| XSSAspNetCore.cs:44:51:44:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:40:56:40:58 | foo | User-provided value | +| XSSAspNetCore.cs:51:43:51:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:51:43:51:67 | access to property Value | User-provided value | +| XSSAspNetCore.cs:58:43:58:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:58:43:58:55 | access to property Query | User-provided value | +| XSSAspNetCore.cs:61:44:61:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:61:44:61:56 | access to property Query | User-provided value | +| XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | User-provided value | +| XSSAspNetCore.cs:72:51:72:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:72:51:72:65 | access to property Headers | User-provided value | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs index 829065bcb28b..98cda988da87 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/XSSAspNetCore.cs @@ -1,5 +1,4 @@ - -using System.Linq; +using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Html; using Microsoft.Extensions.Primitives; @@ -24,13 +23,13 @@ public IActionResult Index() StringValues vOut; Request.Query.TryGetValue("Foo", out vOut); - // BAD: via Enumerable. + // BAD: via Enumerable. (false negative) v.ViewData["FooFirst"] = new HtmlString(vOut.First()); - // BAD: via toArray. + // BAD: via toArray. (false negative) v.ViewData["FooArray0"] = new HtmlString(vOut.ToArray()[0]); - // BAD: via implicit conversion operator. + // BAD: via implicit conversion operator. (false negative) v.ViewData["FooImplicit"] = new HtmlString(vOut); return v; From c003150ed83b6b168571f0f702dc0cbb1ef6fbef Mon Sep 17 00:00:00 2001 From: calum Date: Fri, 2 Nov 2018 14:51:07 +0000 Subject: [PATCH 13/13] C#: Add missing file. --- .../CWE-079/XSS/corestubs.cs | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-079/XSS/corestubs.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/corestubs.cs b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/corestubs.cs new file mode 100644 index 000000000000..910ef14f5be6 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/XSS/corestubs.cs @@ -0,0 +1,236 @@ +namespace Microsoft +{ + namespace AspNetCore + { + namespace Html + { + // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent + { + public HtmlString(string value) => throw null; + public override string ToString() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHtmlContent + { + } + + } + namespace Http + { + // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpRequest + { + public abstract Microsoft.AspNetCore.Http.IHeaderDictionary Headers { get; } + public abstract Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } + public abstract Microsoft.AspNetCore.Http.QueryString QueryString { get; set; } + public abstract string ContentType { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHeaderDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; set; } + } + + // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IQueryCollection : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable> + { + Microsoft.Extensions.Primitives.StringValues this[string key] { get; } + bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); + } + + // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct QueryString : System.IEquatable + { + public bool Equals(Microsoft.AspNetCore.Http.QueryString other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public string Value { get => throw null; } + } + + } + namespace Mvc + { + // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class ControllerBase + { + public Microsoft.AspNetCore.Http.HttpRequest Request { get => throw null; } + } + + // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, System.IDisposable, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IActionFilter + { + public virtual Microsoft.AspNetCore.Mvc.ViewResult View(object model) => throw null; + public void Dispose() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata + { + public FromQueryAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute + { + public HttpPostAttribute() => throw null; + public HttpPostAttribute(string template) => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionResult + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory + { + public ValidateAntiForgeryTokenAttribute() => throw null; + } + + // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult + { + public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } + public ViewResult() => throw null; + } + + namespace Filters + { + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFilterMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata + { + } + + } + namespace ModelBinding + { + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IBindingSourceMetadata + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IModelNameProvider + { + } + + } + namespace Routing + { + // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + abstract public class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IActionHttpMethodProvider + { + } + + // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IRouteTemplateProvider + { + } + + } + namespace ViewFeatures + { + // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=1.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ViewDataDictionary : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection> + { + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public System.Collections.Generic.ICollection Values { get => throw null; } + public System.Collections.Generic.ICollection Keys { get => throw null; } + public bool Contains(System.Collections.Generic.KeyValuePair item) => throw null; + public bool ContainsKey(string key) => throw null; + public bool IsReadOnly { get => throw null; } + public bool Remove(System.Collections.Generic.KeyValuePair item) => throw null; + public bool Remove(string key) => throw null; + public bool TryGetValue(string key, out object value) => throw null; + public int Count { get => throw null; } + public object this[string index] { get => throw null; set => throw null; } + public void Add(System.Collections.Generic.KeyValuePair item) => throw null; + public void Add(string key, object value) => throw null; + public void Clear() => throw null; + public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; + } + + } + } + } + namespace Extensions + { + namespace Primitives + { + // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct StringValues : System.IEquatable, System.IEquatable, System.IEquatable, System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, + System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection + { + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.Contains(string item) => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(string item) => throw null; + int System.Collections.Generic.IList.IndexOf(string item) => throw null; + public bool Equals(Microsoft.Extensions.Primitives.StringValues other) => throw null; + public bool Equals(string other) => throw null; + public bool Equals(string[] other) => throw null; + public int Count { get => throw null; } + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public override string ToString() => throw null; + public static implicit operator string(Microsoft.Extensions.Primitives.StringValues values) => throw null; + public string this[int index] { get => throw null; set => throw null; } + public string[] ToArray() => throw null; + void System.Collections.Generic.ICollection.Add(string item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + void System.Collections.Generic.ICollection.CopyTo(string[] array, int arrayIndex) => throw null; + void System.Collections.Generic.IList.Insert(int index, string item) => throw null; + void System.Collections.Generic.IList.RemoveAt(int index) => throw null; + } + + } + } +} +namespace System +{ + namespace Linq + { + // Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + static public class Enumerable + { + public static TSource First(this System.Collections.Generic.IEnumerable source) => throw null; + } + + } +}