Skip to content

Commit 5970fd9

Browse files
committed
C#: Also include property reads in possible new sink discovery. Only include public fields and properties.
1 parent 8a65efb commit 5970fd9

File tree

4 files changed

+52
-4
lines changed

4 files changed

+52
-4
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,10 @@ private class InstanceFieldOrProperty extends FieldOrProperty {
14611461
InstanceFieldOrProperty() { not this.isStatic() }
14621462
}
14631463

1464-
private class FieldOrPropertyAccess extends AssignableAccess, QualifiableExpr {
1464+
/**
1465+
* An access to a field or a property.
1466+
*/
1467+
class FieldOrPropertyAccess extends AssignableAccess, QualifiableExpr {
14651468
FieldOrPropertyAccess() { this.getTarget() instanceof FieldOrProperty }
14661469
}
14671470

csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,20 @@ predicate isRelevantSinkKind(string kind) { any() }
3838
class PropagateToSinkConfigurationSpecific extends TaintTracking::Configuration {
3939
PropagateToSinkConfigurationSpecific() { this = "parameters or fields flowing into sinks" }
4040

41+
private predicate isRelevantMemberAccess(DataFlow::Node node) {
42+
exists(MemberAccess access | access = node.asExpr() |
43+
access.hasThisQualifier() and
44+
access.getTarget().isEffectivelyPublic() and
45+
(
46+
access instanceof FieldAccess
47+
or
48+
access.getTarget().(Property).getSetter().isPublic()
49+
)
50+
)
51+
}
52+
4153
override predicate isSource(DataFlow::Node source) {
42-
(source.asExpr() instanceof FieldAccess or source instanceof DataFlow::ParameterNode) and
54+
(isRelevantMemberAccess(source) or source instanceof DataFlow::ParameterNode) and
4355
source.getEnclosingCallable().(Modifiable).isEffectivelyPublic() and
4456
isRelevantForModels(source.getEnclosingCallable())
4557
}
@@ -54,7 +66,7 @@ string asInputArgument(DataFlow::Node source) {
5466
result = "Argument[" + pos + "]"
5567
)
5668
or
57-
source.asExpr() instanceof FieldAccess and
69+
source.asExpr() instanceof FieldOrPropertyAccess and
5870
result = qualifierString()
5971
}
6072

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
| Sinks;NewSinks;false;WrapFieldResponseWriteFile;();Argument[Qualifier];html |
2+
| Sinks;NewSinks;false;WrapPropResponseWriteFile;();Argument[Qualifier];html |
23
| Sinks;NewSinks;false;WrapResponseWrite;(System.Object);Argument[0];html |
34
| Sinks;NewSinks;false;WrapResponseWriteFile;(System.String);Argument[0];html |

csharp/ql/test/utils/model-generator/Sinks.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ namespace Sinks;
55

66
public class NewSinks
77
{
8-
private string tainted;
8+
private string privateTainted;
9+
public string tainted;
10+
11+
private string PrivateTaintedProp { get; set; }
12+
public string TaintedProp { get; set; }
13+
public string PrivateSetTaintedProp { get; private set; }
914

1015
// New sink
1116
public void WrapResponseWrite(object o)
@@ -35,4 +40,31 @@ public void WrapFieldResponseWriteFile()
3540
response.WriteFile(tainted);
3641
}
3742

43+
// NOT new sink as field is private
44+
public void WrapPrivateFieldResponseWriteFile()
45+
{
46+
var response = new HttpResponse();
47+
response.WriteFile(privateTainted);
48+
}
49+
50+
// New sink
51+
public void WrapPropResponseWriteFile()
52+
{
53+
var response = new HttpResponse();
54+
response.WriteFile(TaintedProp);
55+
}
56+
57+
// NOT new sink as property is private
58+
public void WrapPrivatePropResponseWriteFile()
59+
{
60+
var response = new HttpResponse();
61+
response.WriteFile(PrivateTaintedProp);
62+
}
63+
64+
// NOT new sink as property setter is private
65+
public void WrapPropPrivateSetResponseWriteFile()
66+
{
67+
var response = new HttpResponse();
68+
response.WriteFile(PrivateSetTaintedProp);
69+
}
3870
}

0 commit comments

Comments
 (0)