mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Add relative filepath lookup
This commit is contained in:
@@ -3,7 +3,7 @@ private import codeql.util.Unit
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
|
||||
/** An additional flow step for cross-site scripting (XSS) vulnerabilities */
|
||||
abstract class XssAdditionalFlowStep extends Unit {
|
||||
class XssAdditionalFlowStep extends Unit {
|
||||
abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2);
|
||||
}
|
||||
|
||||
@@ -73,9 +73,82 @@ private class ViewCallFlowStep extends XssAdditionalFlowStep {
|
||||
}
|
||||
|
||||
private predicate viewCallRefersToPage(ViewCall vc, RazorPage rp) {
|
||||
viewCallRefersToPageAbsolute(vc, rp)
|
||||
viewCallRefersToPageAbsolute(vc, rp) or
|
||||
viewCallRefersToPageRelative(vc, rp)
|
||||
}
|
||||
|
||||
private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) {
|
||||
["/", "~/", ""] + vc.getNameArgument() = rp.getSourceFilepath()
|
||||
["/", ""] + vc.getNameArgument() = ["", "~"] + rp.getSourceFilepath()
|
||||
}
|
||||
|
||||
private predicate viewCallRefersToPageRelative(ViewCall vc, RazorPage rp) {
|
||||
rp.getSourceFilepath() =
|
||||
min(int i, RelativeViewCallFilepath fp |
|
||||
fp.hasViewCallWithIndex(vc, i) and
|
||||
exists(RazorPage rp2 | rp2.getSourceFilepath() = fp.getNormalizedPath())
|
||||
|
|
||||
fp.getNormalizedPath() order by i
|
||||
)
|
||||
}
|
||||
|
||||
private class RelativeViewCallFilepath extends NormalizableFilepath {
|
||||
ViewCall vc;
|
||||
int idx;
|
||||
|
||||
RelativeViewCallFilepath() {
|
||||
exists(string actionName |
|
||||
actionName = vc.getNameArgument() and
|
||||
not actionName.matches("%.cshtml")
|
||||
or
|
||||
not exists(vc.getNameArgument()) and
|
||||
actionName = vc.getActionMethod().getName()
|
||||
|
|
||||
idx = 0 and
|
||||
this = "/Views/" + vc.getControllerName() + "/" + actionName + ".cshtml"
|
||||
or
|
||||
idx = 1 and
|
||||
this = "/Views/Shared/" + actionName + ".cshtml"
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasViewCallWithIndex(ViewCall vc2, int idx2) { vc = vc2 and idx = idx2 }
|
||||
}
|
||||
|
||||
// TODO: this could be a shared library
|
||||
/** A filepath that should be normalized. */
|
||||
abstract private class NormalizableFilepath extends string {
|
||||
bindingset[this]
|
||||
NormalizableFilepath() { any() }
|
||||
|
||||
/** Gets the normalized filepath for this string; traversing `/../` paths. */
|
||||
string getNormalizedPath() {
|
||||
exists(string norm |
|
||||
norm = this.getNormalizedUpTo(0).regexpReplaceAll("/+$", "") and
|
||||
(if this.matches("/%") then result = "/" + norm else result = norm)
|
||||
)
|
||||
}
|
||||
|
||||
private string getComponent(int i) { result = this.splitAt("/", i) }
|
||||
|
||||
private int getNumComponents() { result = strictcount(int i | exists(this.getComponent(i))) }
|
||||
|
||||
private string getNormalizedUpTo(int i) {
|
||||
i in [0 .. this.getNumComponents()] and
|
||||
(
|
||||
i = this.getNumComponents() and
|
||||
result = ""
|
||||
or
|
||||
i < this.getNumComponents() and
|
||||
exists(string comp, string sofar |
|
||||
comp = this.getComponent(i) and sofar = this.getNormalizedUpTo(i + 1)
|
||||
|
|
||||
if comp = [".", ""]
|
||||
then result = sofar
|
||||
else
|
||||
if comp = ".." or not sofar.matches("../%")
|
||||
then result = comp + "/" + sofar
|
||||
else exists(string base | sofar = "../" + base | result = base)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user