Check for generic base types in Missing Function Level Access Control and Insecure Direct Object Reference.

This commit is contained in:
Joe Farebrother
2023-10-13 14:22:45 +01:00
parent f6570710e7
commit 915352861d
5 changed files with 54 additions and 8 deletions

View File

@@ -51,31 +51,33 @@ private predicate callsPlus(Callable c1, Callable c2) = fastTC(calls/2)(c1, c2)
/** Holds if `m`, its containing class, or a parent class has an attribute that extends `AuthorizeAttribute` */
private predicate hasAuthorizeAttribute(ActionMethod m) {
exists(Attribute attr |
attr.getType()
.getABaseType*()
getAnUnboundBaseType*(attr.getType())
.hasQualifiedName([
"Microsoft.AspNetCore.Authorization", "System.Web.Mvc", "System.Web.Http"
], "AuthorizeAttribute")
|
attr = m.getOverridee*().getAnAttribute() or
attr = m.getDeclaringType().getABaseType*().getAnAttribute()
attr = getAnUnboundBaseType*(m.getDeclaringType()).getAnAttribute()
)
}
/** Holds if `m`, its containing class, or a parent class has an attribute that extends `AllowAnonymousAttribute` */
private predicate hasAllowAnonymousAttribute(ActionMethod m) {
exists(Attribute attr |
attr.getType()
.getABaseType*()
getAnUnboundBaseType*(attr.getType())
.hasQualifiedName([
"Microsoft.AspNetCore.Authorization", "System.Web.Mvc", "System.Web.Http"
], "AllowAnonymousAttribute")
|
attr = m.getOverridee*().getAnAttribute() or
attr = m.getDeclaringType().getABaseType*().getAnAttribute()
attr = getAnUnboundBaseType*(m.getDeclaringType()).getAnAttribute()
)
}
private ValueOrRefType getAnUnboundBaseType(ValueOrRefType t) {
result = t.getABaseType().getUnboundDeclaration()
}
/** Holds if `m` is authorized via an `Authorize` attribute */
private predicate isAuthorizedViaAttribute(ActionMethod m) {
hasAuthorizeAttribute(m) and

View File

@@ -82,11 +82,15 @@ predicate hasAuthViaXml(ActionMethod m) {
/** Holds if the given action has an attribute that indications authorization. */
predicate hasAuthViaAttribute(ActionMethod m) {
exists(Attribute attr | attr.getType().getName().toLowerCase().matches("%auth%") |
attr = m.getAnAttribute() or
attr = m.getDeclaringType().getABaseType*().getAnAttribute()
attr = m.getOverridee*().getAnAttribute() or
attr = getAnUnboundBaseType*(m.getDeclaringType()).getAnAttribute()
)
}
private ValueOrRefType getAnUnboundBaseType(ValueOrRefType t) {
result = t.getABaseType().getUnboundDeclaration()
}
/** Holds if `m` is a method that should have an auth check, but is missing it. */
predicate missingAuth(ActionMethod m) {
needsAuth(m) and

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cs/web/insecure-direct-object-reference` and `cs/web/missing-function-level-access-control` have been improved to better recognize attributes on generic classes.

View File

@@ -27,4 +27,30 @@ public class ProfileController : Controller {
return View();
}
}
[Authorize]
public class AuthBaseController : Controller {
protected void doThings() { }
}
public class SubController : AuthBaseController {
// GOOD: The Authorize attribute is used on the base class.
public ActionResult Delete4(int id) {
doThings();
return View();
}
}
[Authorize]
public class AuthBaseGenericController<T> : Controller {
protected void doThings() { }
}
public class SubGenericController : AuthBaseGenericController<string> {
// GOOD: The Authorize attribute is used on the base class.
public ActionResult Delete5(int id) {
doThings();
return View();
}
}

View File

@@ -43,4 +43,14 @@ public class CController : BaseAnonController {
// BAD - AllowAnonymous is inherited from base class and overrides Authorize
[Authorize]
public ActionResult Edit4(int id) { return View(); }
}
[Authorize]
public class BaseGenController<T> : Controller {
}
public class SubGenController : BaseGenController<string> {
// GOOD - Authorize is inherited from parent class
public ActionResult Edit5(int id) { return View(); }
}