@@ -31,15 +31,15 @@ module CreationToUseFlow<CreationCallSig Creation, UseCallSig Use> {
3131 Use use , CreationToUseFlow:: PathNode source , CreationToUseFlow:: PathNode sink
3232 ) {
3333 source .getNode ( ) .asExpr ( ) = result and
34- sink .getNode ( ) .asExpr ( ) = use .( MethodCall ) .getQualifier ( ) and
34+ sink .getNode ( ) .asExpr ( ) = use .( QualifiableExpr ) .getQualifier ( ) and
3535 CreationToUseFlow:: flowPath ( source , sink )
3636 }
3737
3838 Use getUseFromCreation (
3939 Creation creation , CreationToUseFlow:: PathNode source , CreationToUseFlow:: PathNode sink
4040 ) {
4141 source .getNode ( ) .asExpr ( ) = creation and
42- sink .getNode ( ) .asExpr ( ) = result .( MethodCall ) .getQualifier ( ) and
42+ sink .getNode ( ) .asExpr ( ) = result .( QualifiableExpr ) .getQualifier ( ) and
4343 CreationToUseFlow:: flowPath ( source , sink )
4444 }
4545
@@ -143,7 +143,9 @@ module CryptoTransformFlow {
143143/**
144144 * A flow analysis module that tracks the flow from a `PaddingMode` member
145145 * access (e.g. `PaddingMode.PKCS7`) to a `Padding` property write on a
146- * `SymmetricAlgorithm` instance.
146+ * `SymmetricAlgorithm` instance, or from a `CipherMode` member access
147+ * (e.g. `CipherMode.CBC`) to a `Mode` property write on a `SymmetricAlgorithm`
148+ * instance.
147149 *
148150 * Example:
149151 * ```
@@ -152,13 +154,18 @@ module CryptoTransformFlow {
152154 * ...
153155 * ```
154156 */
155- module PaddingModeLiteralFlow {
156- private module PaddingModeLiteralConfig implements DataFlow:: ConfigSig {
157+ module ModeLiteralFlow {
158+ private module ModeLiteralConfig implements DataFlow:: ConfigSig {
157159 predicate isSource ( DataFlow:: Node source ) {
158160 source .asExpr ( ) = any ( PaddingMode mode ) .getAnAccess ( )
161+ or
162+ source .asExpr ( ) = any ( CipherMode mode ) .getAnAccess ( )
159163 }
160164
161- predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof PaddingPropertyWrite }
165+ predicate isSink ( DataFlow:: Node sink ) {
166+ sink .asExpr ( ) instanceof PaddingPropertyWrite or
167+ sink .asExpr ( ) instanceof CipherModePropertyWrite
168+ }
162169
163170 // TODO: Figure out why this is needed.
164171 predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
@@ -169,51 +176,96 @@ module PaddingModeLiteralFlow {
169176 }
170177 }
171178
172- private module PaddingModeLiteralFlow = DataFlow:: Global< PaddingModeLiteralConfig > ;
179+ private module ModeLiteralFlow = DataFlow:: Global< ModeLiteralConfig > ;
173180
174181 SymmetricAlgorithmUse getConsumer (
175- Expr mode , PaddingModeLiteralFlow :: PathNode source , PaddingModeLiteralFlow :: PathNode sink
182+ Expr mode , ModeLiteralFlow :: PathNode source , ModeLiteralFlow :: PathNode sink
176183 ) {
177184 source .getNode ( ) .asExpr ( ) = mode and
178185 sink .getNode ( ) .asExpr ( ) = result and
179- PaddingModeLiteralFlow :: flowPath ( source , sink )
186+ ModeLiteralFlow :: flowPath ( source , sink )
180187 }
181188}
182189
183190/**
184- * A flow analysis module that tracks the flow from a `MemoryStream` object
185- * creation to the `stream` argument passed to a `CryptoStream` constructor
186- * call.
191+ * A flow analysis module that tracks the flow from an arbitrary `Stream` object
192+ * creation to the creation of a second `Stream` object wrapping the first one.
187193 *
188- * TODO: This should probably be made generic over multiple stream types.
194+ * This is useful for tracking the flow of data from a buffer passed to a
195+ * `MemoryStream` to a `CryptoStream` wrapping the original `MemoryStream`. It
196+ * can also be used to track dataflow from a `Stream` object to a call to
197+ * `ToArray()` on the stream, or a wrapped stream.
189198 */
190- module MemoryStreamFlow {
191- private class MemoryStreamCreation extends ObjectCreation {
192- MemoryStreamCreation ( ) {
193- this .getObjectType ( ) .hasFullyQualifiedName ( "System.IO" , "MemoryStream" )
199+ module StreamFlow {
200+ private class Stream extends Class {
201+ Stream ( ) { this .getABaseType ( ) .hasFullyQualifiedName ( "System.IO" , "Stream" ) }
202+ }
203+
204+ /**
205+ * A `Stream` object creation.
206+ */
207+ private class StreamCreation extends ObjectCreation {
208+ StreamCreation ( ) { this .getObjectType ( ) instanceof Stream }
209+
210+ Expr getInputArg ( ) {
211+ result = this .getAnArgument ( ) and
212+ result .getType ( ) .hasFullyQualifiedName ( "System" , "Byte[]" )
213+ }
214+
215+ Expr getStreamArg ( ) {
216+ result = this .getAnArgument ( ) and
217+ result .getType ( ) instanceof Stream
218+ }
219+ }
220+
221+ private class StreamUse extends MethodCall {
222+ StreamUse ( ) {
223+ this .getQualifier ( ) .getType ( ) instanceof Stream and
224+ this .getTarget ( ) .hasName ( "ToArray" )
194225 }
195226
196- Expr getBufferArg ( ) { result = this . getArgument ( 0 ) }
227+ Expr getOutput ( ) { result = this }
197228 }
198229
199- // (Note that we cannot use `CreationToUseFlow` here, because the use is not a
200- // `QualifiableExpr`.)
201- private module MemoryStreamConfig implements DataFlow:: ConfigSig {
202- predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof MemoryStreamCreation }
230+ private module StreamConfig implements DataFlow:: ConfigSig {
231+ predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof StreamCreation }
203232
204233 predicate isSink ( DataFlow:: Node sink ) {
205- exists ( CryptoStreamCreation creation | sink .asExpr ( ) = creation .getStreamArg ( ) )
234+ sink .asExpr ( ) instanceof StreamCreation
235+ or
236+ exists ( StreamUse use | sink .asExpr ( ) = use .getQualifier ( ) )
237+ }
238+
239+ predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
240+ // Allow flow from one stream wrapped by a second stream.
241+ exists ( StreamCreation creation |
242+ node1 .asExpr ( ) = creation .getStreamArg ( ) and
243+ node2 .asExpr ( ) = creation
244+ )
245+ or
246+ exists ( MethodCall copy |
247+ node1 .asExpr ( ) = copy .getQualifier ( ) and
248+ node2 .asExpr ( ) = copy .getAnArgument ( ) and
249+ copy .getTarget ( ) .hasName ( "CopyTo" )
250+ )
206251 }
207252 }
208253
209- private module MemoryStreamFlow = DataFlow:: Global< MemoryStreamConfig > ;
254+ private module StreamFlow = DataFlow:: Global< StreamConfig > ;
210255
211- MemoryStreamCreation getCreationFromUse (
212- CryptoStreamCreation creation , MemoryStreamFlow:: PathNode source ,
213- MemoryStreamFlow:: PathNode sink
256+ StreamCreation getWrappedStream (
257+ StreamCreation stream , StreamFlow:: PathNode source , StreamFlow:: PathNode sink
214258 ) {
215259 source .getNode ( ) .asExpr ( ) = result and
216- sink .getNode ( ) .asExpr ( ) = creation .getStreamArg ( ) and
217- MemoryStreamFlow:: flowPath ( source , sink )
260+ sink .getNode ( ) .asExpr ( ) = stream and
261+ StreamFlow:: flowPath ( source , sink )
262+ }
263+
264+ StreamUse getStreamUse (
265+ StreamCreation stream , StreamFlow:: PathNode source , StreamFlow:: PathNode sink
266+ ) {
267+ source .getNode ( ) .asExpr ( ) = stream and
268+ sink .getNode ( ) .asExpr ( ) = result .getQualifier ( ) and
269+ StreamFlow:: flowPath ( source , sink )
218270 }
219271}
0 commit comments