[csharp] need help with taint propagation #19911
-
Hi, I don't understand why my taint is not propagating. I have 3 test cases that look similar, but it only works for one. Here is my C# code: protected FullyInstrumentedType(SerializationInfo info, StreamingContext context)
{
Console.WriteLine("Deserialization constructor");
Data = info.GetString("Data");
//1
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(this.Data)))
{
binaryFormatter.Deserialize(memoryStream);
}
//2
byte[] a = Convert.FromBase64String(this.Data);
MemoryStream stream = null;
stream = new MemoryStream(a);
(new BinaryFormatter()).Deserialize(stream);
//3
byte[] b = Encoding.UTF8.GetBytes(this.Data);
MemoryStream ms = null;
ms = new MemoryStream(b);
(new BinaryFormatter()).Deserialize(ms); In the first scenario, the taint halts at the /**
* @name Forward Partial Dataflow
* @description Forward Partial Dataflow
* @kind path-problem
* @precision low
* @problem.severity error
* @id githubsecuritylab/forward-partial-dataflow
* @tags template
*/
import csharp
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.serialization.Serialization
import PartialFlow::PartialPathGraph
import libs.Source
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node mysrc) {
mysrc.asParameter().getCallable() instanceof SerializationConstructor and
( mysrc.asParameter().getCallable().hasName("ClaimsPrincipal") or
mysrc.asParameter().getCallable().hasName("FullyInstrumentedType")
)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(SerializationInfoGetTaintStep s).step(node1, node2)
}
predicate isSink(DataFlow::Node sink) { none() }
}
/**
* We want to propagate output of SerializationInfo:
*
* Data = info.GetString("Data");
*/
class SerializationInfoGetTaintStep extends GadgetAdditionalTaintStep {
override predicate step(DataFlow::Node fromNode, DataFlow::Node toNode) {
exists(MethodCall mc, Method m |
mc.getTarget() = m and
m.getName().matches("Get%") and
m.getDeclaringType().hasFullyQualifiedName("System.Runtime.Serialization", "SerializationInfo") and
// Taint flows from the qualifier (info) to the call result
fromNode.asExpr() = mc.getQualifier() and
toNode.asExpr() = mc
)
}
}
private module MyFlow = TaintTracking::Global<MyConfig>; // or DataFlow::Global<..>
int explorationLimit() { result = 10 }
private module PartialFlow = MyFlow::FlowExplorationFwd<explorationLimit/0>;
from PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink
where PartialFlow::partialFlow(source, sink, _)
select sink.getNode(), source, sink, "This node receives taint from $@.", source.getNode(),
"this source" Based on this it should propagate the taint. What am I missing here ? Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 10 replies
-
Using the same query on a different Codeql database yield the same problem on another method: And again there is a summary step for this method here. So the problem might be somewhere else, I don't understand |
Beta Was this translation helpful? Give feedback.
-
I think that in my first example the difference is in the way the return value is tainted. For |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for reporting this.
It looks like the model for I will look into this. |
Beta Was this translation helpful? Give feedback.
-
@Hug0Vincent : Will see if I can fix at least some of the modelling and get back to you. |
Beta Was this translation helpful? Give feedback.
-
Related PR #19940 |
Beta Was this translation helpful? Give feedback.
Thank you very much for reporting this.
I suspect at least for some of the cases there are some issues with the Models as Data modelling of the library methods.
With the current modelling we have
It looks like the model for
MemoryStream.MemoryStream(byte[])
is incorrect (it should beArgument[0].Element -> Argument[this]
- this is also the case for the other overloads of the constructor). Also the model forEncoding.GetBytes
looks incorrect as taint is propagated from the argument to the return value…