Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ class ValidateAntiForgeryAttribute extends Attribute {
}
}

/**
* The `Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute` class.
*/
class AutoValidateAntiforgeryTokenAttribute extends Class {
AutoValidateAntiforgeryTokenAttribute() {
this.hasFullyQualifiedName("Microsoft.AspNetCore.Mvc", "AutoValidateAntiforgeryTokenAttribute")
}
}

/**
* 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.
Expand Down Expand Up @@ -230,11 +239,20 @@ private Assembly getAnAssemblyFor(Type type) {
result = getACompilationFor(type).getOutputAssembly()
}

private predicate isMicrosoftAspNetCoreMvcRegistration(MethodCall call) {
call.getTarget()
.hasFullyQualifiedName("Microsoft.Extensions.DependencyInjection",
["MvcServiceCollectionExtensions", "MvcCoreServiceCollectionExtensions"],
["AddControllers", "AddControllersWithViews", "AddMvc", "AddMvcCore"])
/**
* A method that is a registration of an ASP.NET Core MVC service, i.e. `AddControllers`, `AddControllersWithViews`, `AddMvc`, or `AddMvcCore`.
*/
class MicrosoftAspNetCoreMvcRegistration extends Method {
MicrosoftAspNetCoreMvcRegistration() {
this.hasFullyQualifiedName("Microsoft.Extensions.DependencyInjection",
["MvcServiceCollectionExtensions", "MvcCoreServiceCollectionExtensions"],
["AddControllers", "AddControllersWithViews", "AddMvc", "AddMvcCore"])
}
}

/** Holds if the method call is a registration of an ASP.NET Core MVC service. */
predicate isMicrosoftAspNetCoreMvcRegistration(MethodCall call) {
call.getTarget() instanceof MicrosoftAspNetCoreMvcRegistration
}

private predicate isMicrosoftAspNetCoreMvcApplication(Compilation compilation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ private Method getAStartedMethod() {

/**
* Holds if the project has a global anti forgery filter.
*
* No AspNetCore case here as the corresponding class doesn't seem to exist.
*/
predicate hasGlobalAntiForgeryFilter() {
// A global filter added
Expand All @@ -49,6 +47,18 @@ predicate hasGlobalAntiForgeryFilter() {
// The filter is added by the Application_Start() method
getAStartedMethod() = addGlobalFilter.getEnclosingCallable()
)
or
exists(MethodCall addGlobalFilter, MethodCall registrationCall |
addGlobalFilter.getTarget() =
any(AspNetCore::MicrosoftAspNetCoreMvcFilterCollection collection).getAddMethod() and
// The filter is the `AutoValidateAntiforgeryTokenAttribute` filter.
addGlobalFilter.getArgument(0).getType() instanceof
AspNetCore::AutoValidateAntiforgeryTokenAttribute and
// The filter is added in an ASP.NET Core registration call, which is provided as a lambda argument
// to the Mvc registration method.
registrationCall.getTarget() instanceof AspNetCore::MicrosoftAspNetCoreMvcRegistration and
registrationCall.getAnArgument() = addGlobalFilter.getEnclosingCallable()
)
}

private class RequireAntiforgeryTokenAttribute extends Attribute {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

public class HomeController : Controller
{
// GOOD: This is validated by the global filter.
[HttpPost]
public ActionResult Login()
{
return View();
}

// GOOD: Antiforgery token is validated explicitly.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateDetails()
{
return View();
}
}

public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Register MVC controllers and Razor views.
// The global filter automatically validates antiforgery tokens
// for unsafe HTTP methods such as POST, PUT, PATCH, and DELETE.
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
query: Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
Loading