using System; using System.Text; using System.Collections.Generic; using System.Linq; /// /// All (tainted) sinks are named `sink[Param|Field|Property]N`, for some N, and all /// non-sinks are named `nonSink[Param|Field|Property]N`, for some N. /// Both sinks and non-sinks are passed to the method `Check` for convenience in the /// test query. /// public class DataFlow { public void M() { // Static field, tainted Test.SinkField0 = "taint source"; Check(Test.SinkField0); // Static field, not tainted Test.NonSinkField0 = "not tainted"; Check(Test.NonSinkField0); // Static property, tainted Test.SinkProperty0 = Test.SinkField0; Check(Test.SinkProperty0); // Static property, not tainted Test.NonSinkProperty0 = Test.NonSinkField0; Check(Test.NonSinkProperty0); Test.NonSinkProperty1 = Test.SinkField0; Check(Test.NonSinkProperty1); // Flow into a callable (non-delegate), tainted In0(Test.SinkProperty0); var methodInfo = typeof(DataFlow).GetMethod("In1"); var args = new object[] { Test.SinkProperty0 }; methodInfo.Invoke(null, args); // Flow into a callable (non-delegate), not tainted NonIn0(""); // Flow into a callable (delegate, locally resolvable), tainted Action in2 = sinkParam2 => Check(sinkParam2); in2(Test.SinkProperty0); // Flow into a callable (delegate, locally resolvable), not tainted Action nonIn1 = nonSinkParam1 => Check(nonSinkParam1); nonIn1(""); // Flow into a callable (delegate, resolvable via call), tainted Apply(In3, Test.SinkProperty0); Apply(x => In4(x), Test.SinkProperty0); ApplyDelegate(new MyDelegate(In5), Test.SinkProperty0); ApplyDelegate(In6, Test.SinkProperty0); myDelegate = new MyDelegate(x => In7(x)); ApplyDelegate(myDelegate, Test.SinkProperty0); // Flow into a callable (delegate, resolvable via call), not tainted Apply(nonSinkParam0 => Check(nonSinkParam0), "not tainted"); ApplyDelegate(new MyDelegate(nonSinkParam0 => Check(nonSinkParam0)), "not tainted"); // Flow into a callable (property), tainted InProperty = Test.SinkProperty0; // Flow into a callable (property), not tainted NonInProperty = "not tainted"; // Flow through a callable that returns the argument (non-delegate), tainted var sink0 = Return(Test.SinkProperty0); Check(sink0); var sink1 = (string)typeof(DataFlow).GetMethod("Return").Invoke(null, new object[] { sink0 }); Check(sink1); string sink2; ReturnOut(sink1, out sink2); Check(sink2); var sink3 = ""; ReturnRef(sink2, ref sink3); Check(sink3); var sink13 = ((IEnumerable)new string[] { sink3 }).SelectEven(x => x); Check(sink13); var sink14 = ((IEnumerable)new string[] { sink13.First() }).Select(ReturnCheck); Check(sink14); var sink15 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => x); Check(sink15); var sink16 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => y); Check(sink16); var sink17 = sink14.Aggregate("", (acc, s) => acc + s, x => x); Check(sink17); var sink18 = ((IEnumerable)new string[] { "" }).Aggregate(sink14.First(), (acc, s) => acc + s, x => x); Check(sink18); int sink21; Int32.TryParse(sink18, out sink21); Check(sink21); bool sink22; bool.TryParse(sink18, out sink22); Check(sink22); // Flow through a callable that returns the argument (non-delegate), not tainted var nonSink0 = Return(""); Check(nonSink0); nonSink0 = (string)typeof(DataFlow).GetMethod("Return").Invoke(null, new object[] { nonSink0 }); Check(nonSink0); ReturnOut("", out nonSink0); Check(nonSink0); ReturnRef("", ref nonSink0); Check(nonSink0); var nonSink1 = ((IEnumerable)new string[] { nonSink0 }).SelectEven(x => x); Check(nonSink1); nonSink1 = ((IEnumerable)new string[] { nonSink0 }).Select(x => x); Check(nonSink1); nonSink1 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => y); Check(nonSink1); nonSink1 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => x); Check(nonSink1); nonSink0 = sink14.Aggregate("", (acc, s) => acc, x => x); Check(nonSink0); nonSink0 = sink14.Aggregate("", (acc, s) => acc + s, x => ""); Check(nonSink0); nonSink0 = nonSink1.Aggregate(sink1, (acc, s) => s, x => x); Check(nonSink0); int nonSink2; Int32.TryParse(nonSink0, out nonSink2); Check(nonSink2); bool nonSink3; bool.TryParse(nonSink0, out nonSink3); Check(nonSink3); // Flow through a callable that returns the argument (delegate, locally resolvable), tainted Func @return = x => ApplyFunc(Return, x); var sink4 = @return(sink3); Check(sink4); // Flow through a callable that returns the argument (delegate, locally resolvable), not tainted nonSink0 = @return(nonSink0); Check(nonSink0); // Flow through a callable that returns the argument (delegate, resolvable via call), tainted var sink5 = ApplyFunc(Return, sink4); Check(sink5); // Flow through a callable that (doesn't) return(s) the argument (delegate, resolvable via call), not tainted nonSink0 = ApplyFunc(Return, ""); Check(nonSink0); nonSink0 = ApplyFunc(_ => "", sink5); Check(nonSink0); // Flow out of a callable (non-delegate), tainted var sink6 = Out(); Check(sink6); string sink7; OutOut(out sink7); Check(sink7); var sink8 = ""; OutRef(ref sink8); Check(sink8); var sink12 = OutYield(); Check(sink12); var sink23 = TaintedParam(nonSink0); // even though the argument is not tainted, the parameter is considered tainted Check(sink23); // Flow out of a callable (non-delegate), not tainted nonSink0 = NonOut(); Check(nonSink0); NonOutOut(out nonSink0); Check(nonSink0); NonOutRef(ref nonSink0); Check(nonSink0); nonSink0 = NonOutYield().First(); Check(nonSink0); nonSink0 = NonTaintedParam(nonSink0); Check(nonSink0); // Flow out of a callable (delegate), tainted Func @out = () => "taint source"; var sink9 = @out(); Check(sink9); // Flow out of a callable (delegate), not tainted Func nonOut = () => ""; nonSink0 = nonOut(); Check(nonSink0); // Flow out of a callable (method access), tainted var sink10 = new Lazy(Out).Value; Check(sink10); // Flow out of a callable (method access), not tainted nonSink0 = new Lazy(NonOut).Value; Check(nonSink0); // Flow out of a callable (property), tainted var sink19 = OutProperty; Check(sink19); // Flow out of a callable (property), not tainted nonSink0 = NonOutProperty; Check(nonSink0); } public void M2(IQueryable tainted, IQueryable notTainted) { // Flow into a callable via library call, tainted Func f1 = sinkParam10 => { Check(sinkParam10); return sinkParam10; }; System.Linq.Expressions.Expression> f2 = x => ReturnCheck2(x); var sink24 = tainted.Select(f1); Check(sink24); var sink25 = tainted.Select(f2); Check(sink25); var sink26 = tainted.Select(ReturnCheck3); Check(sink26); // Flow into a callable via library call, not tainted Func f3 = nonSinkParam => { Check(nonSinkParam); return nonSinkParam; }; System.Linq.Expressions.Expression> f4 = x => NonReturnCheck(x); var nonSink = notTainted.Select(f1); Check(nonSink); nonSink = notTainted.Select(f2); Check(nonSink); nonSink = notTainted.Select(f3); Check(nonSink); nonSink = notTainted.Select(f4); Check(nonSink); nonSink = notTainted.Select(ReturnCheck3); Check(nonSink); } static void Check(T x) { } static void In0(T sinkParam0) { In0(sinkParam0); Check(sinkParam0); } static void In1(T sinkParam1) { Check(sinkParam1); } static void In3(T sinkParam3) { Check(sinkParam3); } static void In4(T sinkParam4) { Check(sinkParam4); } static void In5(T sinkParam5) { Check(sinkParam5); } static void In6(T sinkParam6) { Check(sinkParam6); } static void In7(T sinkParam7) { Check(sinkParam7); } static void NonIn0(T nonSinkParam0) { Check(nonSinkParam0); } static T Return(T x) { var y = ApplyFunc(x0 => x0, x); return y == null ? default(T) : y; } static void ReturnOut(T x, out T y) { y = x; } static void ReturnRef(T x, ref T y) { y = x; } static T ReturnCheck(T sinkParam8) { Check(sinkParam8); return sinkParam8; } static T ReturnCheck2(T sinkParam9) { Check(sinkParam9); return sinkParam9; } static T ReturnCheck3(T sinkParam11) { Check(sinkParam11); return sinkParam11; } static T NonReturnCheck(T nonSinkParam) { Check(nonSinkParam); return nonSinkParam; } string Out() { return "taint source"; } void OutOut(out string x) { x = "taint source"; } void OutRef(ref string x) { x = "taint source"; } IEnumerable OutYield() { yield return ""; yield return "taint source"; yield return ""; } string NonOut() { return ""; } void NonOutOut(out string x) { x = ""; } void NonOutRef(ref string x) { x = ""; } IEnumerable NonOutYield() { yield return ""; yield return ""; } static void Apply(Action a, T x) { a(x); } static T ApplyFunc(Func f, S x) { return f(x); } public delegate void MyDelegate(string x); static MyDelegate myDelegate; static void ApplyDelegate(MyDelegate a, string x) { a(x); } static string TaintedParam(string tainted) { var sink11 = tainted; Check(sink11); return sink11; } static string NonTaintedParam(string nonTainted) { var nonSink0 = nonTainted; Check(nonSink0); return nonSink0; } class Test { public static string SinkField0; public static string SinkProperty0 { get; set; } public static string NonSinkField0; public static string NonSinkProperty0 { get; set; } public static string NonSinkProperty1 { get { return ""; } set { } } } string InProperty { get { return ""; } set { var sink20 = value; Check(sink20); } } string NonInProperty { get { return ""; } set { var nonSink0 = value; Check(nonSink0); } } string OutProperty { get { return "taint source"; } } string NonOutProperty { get { return ""; } } } static class IEnumerableExtensions { public static IEnumerable SelectEven(this IEnumerable e, Func f) { int i = 0; foreach (var x in e) { if (i++ % 2 == 0) yield return f(x); } } } // semmle-extractor-options: /r:System.Diagnostics.Process.dll /r:System.Linq.dll /r:System.Linq.Expressions.dll /r:System.Linq.Queryable.dll /r:System.ComponentModel.Primitives.dll