Skip to content

Commit 5d12896

Browse files
Add IDOR query
1 parent a510a7b commit 5d12896

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

csharp/ql/lib/semmle/code/csharp/security/auth/InsecureDirectObjectRefrerenceQuery.qll

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,46 @@ import csharp
44
import semmle.code.csharp.dataflow.flowsources.Remote
55
import ActionMethods
66

7+
/**
8+
* Holds if `m` is a method that may require checks
9+
* against the current user to modify a particular resource.
10+
*/
11+
// We exclude admin methods as it may be expected that an admin user should be able to modify any resource.
12+
// Other queries check that there are authorization checks in place for admin methods.
713
private predicate needsChecks(ActionMethod m) { m.isEdit() and not m.isAdmin() }
814

15+
private Expr getParentExpr(Expr ex) { result = ex.getParent() }
16+
17+
/**
18+
* Holds if `m` has a parameter or access a remote flow source
19+
* that may indicate that it's used as the ID for some resource
20+
*/
921
private predicate hasIdParameter(ActionMethod m) {
1022
exists(RemoteFlowSource src | src.getEnclosingCallable() = m |
11-
src.asParameter().getName().toLowerCase().matches("%id")
23+
src.asParameter().getName().toLowerCase().matches(["%id", "%idx"])
1224
or
1325
exists(StringLiteral idStr |
14-
idStr.getValue().toLowerCase().matches("%id") and
15-
idStr.getParent*() = src.asExpr()
26+
idStr.getValue().toLowerCase().matches(["%id", "%idx"]) and
27+
getParentExpr*(src.asExpr()) = getParentExpr*(idStr)
1628
)
1729
)
1830
}
1931

32+
/** Holds if `m` at some point in its call graph may make some kind of check against the current user. */
2033
private predicate checksUser(ActionMethod m) {
21-
exists(Callable c | c.getName().toLowerCase().matches("%user%") | m.calls*(c))
34+
exists(Property p | p.getName().toLowerCase().matches(["%user%", "%session%"]) |
35+
m.calls*(p.getGetter())
36+
)
2237
}
2338

39+
/**
40+
* Holds if `m` is a method that modifies a particular resource based on
41+
* and ID provided by user input, but does not check anything based on the current user
42+
* to determine if they should modify this resource.
43+
*/
2444
predicate hasInsecureDirectObjectReference(ActionMethod m) {
2545
needsChecks(m) and
2646
hasIdParameter(m) and
27-
not checksUser(m)
47+
not checksUser(m) and
48+
exists(m.getBody())
2849
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name Insecure Direct Object Reference
3+
* @description Using user input to control which object is modified without
4+
* proper authorization checks allows an attacker to modify arbitrary objects.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @precision medium
8+
* @id cs/insecure-direct0object-reference
9+
* @tags security
10+
* external/cwe/639
11+
*/
12+
13+
import csharp
14+
import semmle.code.csharp.security.auth.InsecureDirectObjectRefrerenceQuery
15+
16+
from ActionMethod m
17+
where hasInsecureDirectObjectReference(m)
18+
select m,
19+
"This method may not verify which users should be able to access resources of the provided ID."

0 commit comments

Comments
 (0)