mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Implement xss flow step for absolute filepath case
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import csharp
|
||||
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 {
|
||||
abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2);
|
||||
}
|
||||
|
||||
/** A call to the `View` method */
|
||||
private class ViewCall extends MethodCall {
|
||||
ViewCall() { this.getTarget().hasQualifiedName("Microsoft.AspNetCore.Mvc", "Controller", "View") }
|
||||
|
||||
/** Gets the `name` argument to this call, if any. */
|
||||
string getNameArgument() {
|
||||
exists(StringLiteral lit, int i | i in [0 .. 1] |
|
||||
this.getTarget().getParameter(i).getType() instanceof StringType and
|
||||
DataFlow::localExprFlow(lit, this.getArgument(i)) and
|
||||
result = lit.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `model` argument to this call, if any. */
|
||||
Expr getModelArgument() {
|
||||
exists(int i | i in [0 .. 1] |
|
||||
this.getTarget().getParameter(i).getType() instanceof ObjectType and
|
||||
result = this.getArgument(i)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the MVC action method that this call is made from, if any. */
|
||||
Method getActionMethod() {
|
||||
result = this.getEnclosingCallable() and
|
||||
result = this.getController().getAnActionMethod()
|
||||
}
|
||||
|
||||
/** Gets the MVC controller that this call is made from, if any. */
|
||||
MicrosoftAspNetCoreMvcController getController() {
|
||||
result = this.getEnclosingCallable().getDeclaringType()
|
||||
}
|
||||
|
||||
/** Gets the name of the MVC controller that this call is made from, if any. */
|
||||
string getControllerName() { result + "Controller" = this.getController().getName() }
|
||||
}
|
||||
|
||||
/** A compiler-generated Razor page. */
|
||||
private class RazorPage extends Class {
|
||||
AssemblyAttribute attr;
|
||||
|
||||
RazorPage() {
|
||||
attr.getFile() = this.getFile() and
|
||||
attr.getType()
|
||||
.hasQualifiedName("Microsoft.AspNetCore.Razor.Hosting", "RazorCompiledItemAttribute")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filepath of the source file that this class was generated from,
|
||||
* relative to the application root.
|
||||
*/
|
||||
string getSourceFilepath() { result = attr.getArgument(2).(StringLiteral).getValue() }
|
||||
}
|
||||
|
||||
private class ViewCallFlowStep extends XssAdditionalFlowStep {
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(ViewCall vc, RazorPage rp, PropertyAccess modelProp |
|
||||
viewCallRefersToPage(vc, rp) and
|
||||
node1.asExpr() = vc.getModelArgument() and
|
||||
node2.asExpr() = modelProp and
|
||||
modelProp.getTarget().hasName("Model") and
|
||||
modelProp.getEnclosingCallable().getDeclaringType() = rp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate viewCallRefersToPage(ViewCall vc, RazorPage rp) {
|
||||
viewCallRefersToPageAbsolute(vc, rp)
|
||||
}
|
||||
|
||||
private predicate viewCallRefersToPageAbsolute(ViewCall vc, RazorPage rp) {
|
||||
["/", "~/", ""] + vc.getNameArgument() = rp.getSourceFilepath()
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import csharp
|
||||
private import XSSSinks
|
||||
private import XSSFlowSteps
|
||||
private import semmle.code.csharp.security.Sanitizers
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
private import semmle.code.csharp.dataflow.DataFlow2
|
||||
@@ -166,6 +167,13 @@ module XssTrackingConfig implements DataFlow::ConfigSig {
|
||||
*/
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
/**
|
||||
* Holds if there is an additional dataflow step from `node1` to `node2`.
|
||||
*/
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(XssAdditionalFlowStep x).isAdditionalFlowStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
|
||||
Reference in New Issue
Block a user