Add local file writes as external location sinks

This commit is contained in:
Joe Farebrother
2023-03-24 14:09:06 +00:00
parent be6af4b3f9
commit 92198e1af0

View File

@@ -6,7 +6,9 @@ import csharp
private import Remote
private import semmle.code.csharp.commons.Loggers
private import semmle.code.csharp.frameworks.system.Web
private import semmle.code.csharp.frameworks.system.IO
private import semmle.code.csharp.dataflow.ExternalFlow
private import semmle.code.csharp.dataflow.DataFlow
/**
* An external location sink.
@@ -63,3 +65,66 @@ class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink {
)
}
}
private predicate isFileWriteCall(Expr stream, Expr data) {
exists(MethodCall mc, Method m | mc.getTarget() = m.getAnOverrider*() |
mc.getTarget().hasQualifiedName("System.IO", "Stream", ["Write", "WriteAsync"]) and
stream = mc.getQualifier() and
data = mc.getArgument(0)
or
mc.getTarget()
.hasQualifiedName("System.IO", "TextWriter",
["Write", "WriteAsync", "WriteLine", "WriteLineAsync"]) and
stream = mc.getQualifier() and
data = mc.getArgument(0)
or
mc.getTarget().hasQualifiedName("System.Xml.Linq", "XDocument", ["Save", "SaveAsync"]) and
data = mc.getQualifier() and
stream = mc.getArgument(0)
)
}
private module LocalFileOutputStreamConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(MethodCall mc | mc = src.asExpr() |
mc.getTarget().hasQualifiedName("System.IO", "File", ["Open", "Create", "OpenWrite"])
or
mc.getTarget()
.hasQualifiedName("System.IO", "FileInfo",
["AppendText", "Create", "CreateText", "Open", "OpenText", "OpenWrite"])
)
or
exists(ObjectCreation oc | oc = src.asExpr() |
oc.getObjectType() instanceof SystemIOStreamWriterClass and
oc.getArgument(0).getType() instanceof StringType
)
}
predicate isSink(DataFlow::Node sink) { isFileWriteCall(sink.asExpr(), _) }
predicate isBarrier(DataFlow::Node node) {
node.asExpr()
.(ObjectCreation)
.getObjectType()
.hasQualifiedName("System.Security.Cryptography", "CryptoStream")
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ObjectCreation oc |
node2.asExpr() = oc and
node1.asExpr() = oc.getArgument(0) and
oc.getObjectType() instanceof SystemIOStreamWriterClass
)
}
}
private module LocalFileOutputStreamFlow = DataFlow::Make<LocalFileOutputStreamConfig>;
class LocalFileOutputSink extends ExternalLocationSink {
LocalFileOutputSink() {
exists(DataFlow::Node streamSink |
LocalFileOutputStreamFlow::hasFlow(_, streamSink) and
isFileWriteCall(streamSink.asExpr(), this.asExpr())
)
}
}