@@ -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
@@ -145,7 +145,9 @@ module CryptoTransformFlow {
145145/**
146146 * A flow analysis module that tracks the flow from a `PaddingMode` member
147147 * access (e.g. `PaddingMode.PKCS7`) to a `Padding` property write on a
148- * `SymmetricAlgorithm` instance.
148+ * `SymmetricAlgorithm` instance, or from a `CipherMode` member access
149+ * (e.g. `CipherMode.CBC`) to a `Mode` property write on a `SymmetricAlgorithm`
150+ * instance.
149151 *
150152 * Example:
151153 * ```
@@ -154,13 +156,18 @@ module CryptoTransformFlow {
154156 * ...
155157 * ```
156158 */
157- module PaddingModeLiteralFlow {
158- private module PaddingModeLiteralConfig implements DataFlow:: ConfigSig {
159+ module ModeLiteralFlow {
160+ private module ModeLiteralConfig implements DataFlow:: ConfigSig {
159161 predicate isSource ( DataFlow:: Node source ) {
160162 source .asExpr ( ) = any ( PaddingMode mode ) .getAnAccess ( )
163+ or
164+ source .asExpr ( ) = any ( CipherMode mode ) .getAnAccess ( )
161165 }
162166
163- predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof PaddingPropertyWrite }
167+ predicate isSink ( DataFlow:: Node sink ) {
168+ sink .asExpr ( ) instanceof PaddingPropertyWrite or
169+ sink .asExpr ( ) instanceof CipherModePropertyWrite
170+ }
164171
165172 // TODO: Figure out why this is needed.
166173 predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
@@ -171,51 +178,96 @@ module PaddingModeLiteralFlow {
171178 }
172179 }
173180
174- private module PaddingModeLiteralFlow = DataFlow:: Global< PaddingModeLiteralConfig > ;
181+ private module ModeLiteralFlow = DataFlow:: Global< ModeLiteralConfig > ;
175182
176183 SymmetricAlgorithmUse getConsumer (
177- Expr mode , PaddingModeLiteralFlow :: PathNode source , PaddingModeLiteralFlow :: PathNode sink
184+ Expr mode , ModeLiteralFlow :: PathNode source , ModeLiteralFlow :: PathNode sink
178185 ) {
179186 source .getNode ( ) .asExpr ( ) = mode and
180187 sink .getNode ( ) .asExpr ( ) = result and
181- PaddingModeLiteralFlow :: flowPath ( source , sink )
188+ ModeLiteralFlow :: flowPath ( source , sink )
182189 }
183190}
184191
185192/**
186- * A flow analysis module that tracks the flow from a `MemoryStream` object
187- * creation to the `stream` argument passed to a `CryptoStream` constructor
188- * call.
193+ * A flow analysis module that tracks the flow from an arbitrary `Stream` object
194+ * creation to the creation of a second `Stream` object wrapping the first one.
189195 *
190- * TODO: This should probably be made generic over multiple stream types.
196+ * This is useful for tracking the flow of data from a buffer passed to a
197+ * `MemoryStream` to a `CryptoStream` wrapping the original `MemoryStream`. It
198+ * can also be used to track dataflow from a `Stream` object to a call to
199+ * `ToArray()` on the stream, or a wrapped stream.
191200 */
192- module MemoryStreamFlow {
193- private class MemoryStreamCreation extends ObjectCreation {
194- MemoryStreamCreation ( ) {
195- this .getObjectType ( ) .hasFullyQualifiedName ( "System.IO" , "MemoryStream" )
201+ module StreamFlow {
202+ private class Stream extends Class {
203+ Stream ( ) { this .getABaseType ( ) .hasFullyQualifiedName ( "System.IO" , "Stream" ) }
204+ }
205+
206+ /**
207+ * A `Stream` object creation.
208+ */
209+ private class StreamCreation extends ObjectCreation {
210+ StreamCreation ( ) { this .getObjectType ( ) instanceof Stream }
211+
212+ Expr getInputArg ( ) {
213+ result = this .getAnArgument ( ) and
214+ result .getType ( ) .hasFullyQualifiedName ( "System" , "Byte[]" )
215+ }
216+
217+ Expr getStreamArg ( ) {
218+ result = this .getAnArgument ( ) and
219+ result .getType ( ) instanceof Stream
220+ }
221+ }
222+
223+ private class StreamUse extends MethodCall {
224+ StreamUse ( ) {
225+ this .getQualifier ( ) .getType ( ) instanceof Stream and
226+ this .getTarget ( ) .hasName ( "ToArray" )
196227 }
197228
198- Expr getBufferArg ( ) { result = this . getArgument ( 0 ) }
229+ Expr getOutput ( ) { result = this }
199230 }
200231
201- // (Note that we cannot use `CreationToUseFlow` here, because the use is not a
202- // `QualifiableExpr`.)
203- private module MemoryStreamConfig implements DataFlow:: ConfigSig {
204- predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof MemoryStreamCreation }
232+ private module StreamConfig implements DataFlow:: ConfigSig {
233+ predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof StreamCreation }
205234
206235 predicate isSink ( DataFlow:: Node sink ) {
207- exists ( CryptoStreamCreation creation | sink .asExpr ( ) = creation .getStreamArg ( ) )
236+ sink .asExpr ( ) instanceof StreamCreation
237+ or
238+ exists ( StreamUse use | sink .asExpr ( ) = use .getQualifier ( ) )
239+ }
240+
241+ predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
242+ // Allow flow from one stream wrapped by a second stream.
243+ exists ( StreamCreation creation |
244+ node1 .asExpr ( ) = creation .getStreamArg ( ) and
245+ node2 .asExpr ( ) = creation
246+ )
247+ or
248+ exists ( MethodCall copy |
249+ node1 .asExpr ( ) = copy .getQualifier ( ) and
250+ node2 .asExpr ( ) = copy .getAnArgument ( ) and
251+ copy .getTarget ( ) .hasName ( "CopyTo" )
252+ )
208253 }
209254 }
210255
211- private module MemoryStreamFlow = DataFlow:: Global< MemoryStreamConfig > ;
256+ private module StreamFlow = DataFlow:: Global< StreamConfig > ;
212257
213- MemoryStreamCreation getCreationFromUse (
214- CryptoStreamCreation creation , MemoryStreamFlow:: PathNode source ,
215- MemoryStreamFlow:: PathNode sink
258+ StreamCreation getWrappedStream (
259+ StreamCreation stream , StreamFlow:: PathNode source , StreamFlow:: PathNode sink
216260 ) {
217261 source .getNode ( ) .asExpr ( ) = result and
218- sink .getNode ( ) .asExpr ( ) = creation .getStreamArg ( ) and
219- MemoryStreamFlow:: flowPath ( source , sink )
262+ sink .getNode ( ) .asExpr ( ) = stream and
263+ StreamFlow:: flowPath ( source , sink )
264+ }
265+
266+ StreamUse getStreamUse (
267+ StreamCreation stream , StreamFlow:: PathNode source , StreamFlow:: PathNode sink
268+ ) {
269+ source .getNode ( ) .asExpr ( ) = stream and
270+ sink .getNode ( ) .asExpr ( ) = result .getQualifier ( ) and
271+ StreamFlow:: flowPath ( source , sink )
220272 }
221273}
0 commit comments