Merge pull request #20983 from smowton/smowton/feature/csharp-csrf-aspnetcore

C# CSRF query: add support for ASP.NET Core
This commit is contained in:
Chris Smowton
2025-12-08 12:14:48 +00:00
committed by GitHub
6 changed files with 62 additions and 6 deletions

View File

@@ -15,6 +15,7 @@ import csharp
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.system.web.Helpers
import semmle.code.csharp.frameworks.system.web.Mvc
import semmle.code.csharp.frameworks.microsoft.AspNetCore as AspNetCore
private Method getAValidatingMethod() {
result = any(AntiForgeryClass a).getValidateMethod()
@@ -35,6 +36,8 @@ 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
@@ -48,16 +51,30 @@ predicate hasGlobalAntiForgeryFilter() {
)
}
from Controller c, Method postMethod
predicate isUnvalidatedPostMethod(Class c, Method m) {
c.(Controller).getAPostActionMethod() = m and
not m.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and
not c.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute
or
c.(AspNetCore::MicrosoftAspNetCoreMvcController).getAnActionMethod() = m and
m.getAnAttribute() instanceof AspNetCore::MicrosoftAspNetCoreMvcHttpPostAttribute and
not m.getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute and
not c.getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute
}
Element getAValidatedElement() {
any(ValidateAntiForgeryTokenAttribute a).getTarget() = result
or
any(AspNetCore::ValidateAntiForgeryAttribute a).getTarget() = result
}
from Class c, Method postMethod
where
postMethod = c.getAPostActionMethod() and
// The method is not protected by a validate anti forgery token attribute
not postMethod.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and
not c.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and
isUnvalidatedPostMethod(c, postMethod) and
// Verify that validate anti forgery token attributes are used somewhere within this project, to
// avoid reporting false positives on projects that use an alternative approach to mitigate CSRF
// issues.
exists(ValidateAntiForgeryTokenAttribute a, Element e | e = a.getTarget()) and
exists(getAValidatedElement()) and
// Also ignore cases where a global anti forgery filter is in use.
not hasGlobalAntiForgeryFilter()
select postMethod,

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `Missing cross-site request forgery token validation` query was extended to support ASP.NET Core.

View File

@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
// BAD: Anti forgery token has been forgotten
[HttpPost]
public ActionResult Login()
{
return View();
}
// GOOD: Anti forgery token is validated
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateDetails()
{
return View();
}
// No validation required, as this is a GET method.
public ActionResult ShowHelp()
{
return View();
}
// Should be ignored, because it is not an action method
[NonAction]
public void UtilityMethod()
{
}
}

View File

@@ -0,0 +1 @@
| MissingAntiForgeryTokenValidation.cs:7:25:7:29 | Login | Method 'Login' handles a POST request without performing CSRF token validation. |

View File

@@ -0,0 +1 @@
query: Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql

View File

@@ -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