/// <summary> /// Visits an extension point and sets the parameters /// </summary> /// <param name="p">point to visit</param> public override void VisitExtension(ExtensionPoint p) { _currentPoint = p; // set the arguments if (p.Graph.FunctionName == null) { return; } var declaration = p.Graph.SourceObject; var signature = getSignature(declaration); var callPoint = p.Caller as RCallPoint; if (callPoint != null) { _currentPoint = callPoint; if (signature.HasValue) { // We have names for passed arguments setNamedArguments(OutputSet, callPoint.CallSignature, signature.Value, p.Arguments); } else { // There are no names - use numbered arguments setOrderedArguments(OutputSet, p.Arguments, declaration); } } }
public override void CallDispatchMerge(ProgramPointBase beforeCall, FlowOutputSet afterCall, IEnumerable <ExtensionPoint> dispatchedExtensions) { var ends = (from callOutput in dispatchedExtensions where callOutput.Graph.End.OutSet != null select callOutput.Graph.End.OutSet as ISnapshotReadonly).ToArray(); //TODO determine correct extension type var callType = dispatchedExtensions.First().Type; switch (callType) { case ExtensionType.ParallelEval: case ExtensionType.ParallelInclude: //merging from includes behaves like usual //program points extend afterCall.Extend(ends); break; case ExtensionType.ParallelCall: //merging from calls needs special behaviour //from memory model (there are no propagation of locales e.g) afterCall.MergeWithCallLevel(beforeCall, ends); break; default: throw new NotImplementedException(); } }
/// <summary> /// Visits a jump statement point /// </summary> /// <param name="p">point to visit</param> public override void VisitJump(JumpStmtPoint p) { _currentPoint = p; switch (p.Jump.Type) { case JumpStmt.Types.Return: var returnVar = Output.GetLocalControlVariable(SnapshotBase.ReturnValue); /*var returnValue = p.Expression.Value.ReadMemory(Input); * returnVar.WriteMemory(Output, returnValue);*/ if (p.Expression != null) { var varID = getVariableIdentifier(p.Expression.Value); List <Value> possibleValues = new List <Value>(p.Expression.Value.ReadMemory(p.Expression.OutSnapshot).PossibleValues); List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(possibleValues, varID)); bool nullValue = hasPossibleNullValue(p.Expression) || hasPossibleNullValue(p.Expression); TaintInfo outputTaint = mergeTaint(values, nullValue); returnVar.WriteMemory(Output, new MemoryEntry(Output.CreateInfo(outputTaint))); } break; default: throw new NotImplementedException(); } }
/// <summary> /// Construct new instance of AnalysisWarning, without cause /// </summary> /// <param name="fullFileName">Full name of source code file</param> /// <param name="message">Warning message</param> /// <param name="element">Element, where the warning was produced</param> /// <param name="programPoint">The program point, where the warning was produced</param> public AnalysisWarning(string fullFileName, string message, LangElement element, ProgramPointBase programPoint) { Message = message; LangElement = element; ProgramPoint = programPoint; FullFileName = fullFileName; }
internal ExtensionPoint(ProgramPointBase caller, ProgramPointGraph graph, ExtensionType type) { Graph = graph; Type = type; Caller = caller; AddFlowChild(Graph.Start); }
/// <summary> /// Visits a native analyzer program point. If function is a sanitizer, the output is sanitized, /// if it is a reporting function, a warning is created. /// </summary> /// <param name="p">program point to visit</param> public override void VisitNativeAnalyzer(NativeAnalyzerPoint p) { _currentPoint = p; string functionName = p.OwningPPGraph.FunctionName; // 1. Get values of arguments of the function // TODO: code duplication: the following code, code in SimpleFunctionResolver, and NativeFunctionAnalyzer. Move the code to some API (? FlowInputSet) Input.SetMode(SnapshotMode.MemoryLevel); MemoryEntry argc = InputSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(Input); Input.SetMode(SnapshotMode.InfoLevel); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; List <MemoryEntry> arguments = new List <MemoryEntry>(); List <ValueInfo> values = new List <ValueInfo>(); bool nullValue = false; for (int i = 0; i < argumentCount; i++) { arguments.Add(OutputSet.ReadVariable(Argument(i)).ReadMemory(OutputSet.Snapshot)); List <Value> argumentValues = new List <Value>(arguments.Last().PossibleValues); if (hasPossibleNullValue(OutputSet.ReadVariable(Argument(i)))) { nullValue = true; } VariableIdentifier varID = null; Value toRemove = null; foreach (Value val in argumentValues) { if (val is InfoValue <VariableIdentifier> ) { varID = (val as InfoValue <VariableIdentifier>).Data; toRemove = val; } } if (toRemove != null) { argumentValues.Remove(toRemove); } values.Add(new ValueInfo(argumentValues, varID)); } TaintInfo outputTaint = mergeTaint(values, nullValue); // try to sanitize the taint info if (outputTaint != null) { sanitize(p, ref outputTaint); warningsReportingFunct(p, outputTaint); } // 2. Propagate arguments to the return value. // TODO: quick fix if (outputTaint.tainted || outputTaint.nullValue) { FunctionResolverBase.SetReturn(OutputSet, new MemoryEntry(Output.CreateInfo(outputTaint))); } }
/// <summary> /// Register given program point with current assitant. Registered program point /// is available in Point property. /// </summary> /// <param name="programPoint">Registered program point</param> internal void RegisterProgramPoint(ProgramPointBase programPoint) { if (Point != null) { throw new NotSupportedException("Cannot register Point twice"); } Point = programPoint; }
/// <summary> /// Append given point at end of current chain /// </summary> /// <param name="appendedPoint">Point that is appended</param> internal void AppendToChain(ProgramPointBase appendedPoint) { if (!_chainedPoints.Add(appendedPoint)) { //point is already contained in the chain return; } _postfixChainOrdering.Add(appendedPoint); }
/// <summary> /// Enqueue point to pointsToVisit if it already hasn't been visited /// </summary> /// <param name="point">Point to be visited</param> /// <param name="pointsToVisit">Storage of points that will be visited</param> /// <param name="visitedPoints">Already visited points</param> private void visitPoint(ProgramPointBase point, Queue <ProgramPointBase> pointsToVisit, HashSet <ProgramPointBase> visitedPoints) { if (!visitedPoints.Add(point)) { //point has already been visited return; } pointsToVisit.Enqueue(point); }
private static void writeProgramPointInformation(ProgramPointBase p, bool outset) { if (p == null || p.Partial == null) { return; } if (p is FunctionDeclPoint) { return; } fileOutput.Write("Point position: "); fileOutput.WriteLine("First line: " + p.Partial.Position.FirstLine + " Last line: " + p.Partial.Position.LastLine + " First offset: " + p.Partial.Position.FirstOffset + " Last offset: " + p.Partial.Position.LastOffset); if (p.OwningPPGraph.OwningScript != null) { fileOutput.WriteLine("OwningScript: " + p.OwningScriptFullName); } String callStack = p.OwningPPGraph.Context.ToString(); if (callStack != "") { fileOutput.WriteLine("Called from: "); fileOutput.WriteLine(p.OwningPPGraph.Context.ToString()); } fileOutput.WriteLine("Point information:"); fileOutput.Write("Fixpoint iterations="); fileOutput.WriteLine(p.FixpointIterationsCount); if (outset) { if (p.OutSet != null) { fileOutput.WriteLine(p.OutSet.Representation); } else { fileOutput.WriteLine("Dead code"); } } if (!outset) { if (p.InSet != null) { fileOutput.WriteLine(p.InSet.Representation); } else { fileOutput.WriteLine("Dead code"); } } }
/// <summary> /// Visits a ConditionalExPoint point and propagates the taint /// </summary> /// <param name="p">point to visit</param> public override void VisitValue(ValuePoint p) { _currentPoint = p; if (p is ConditionalExPoint) { var pEx = p as ConditionalExPoint; var possibleValues = pEx.Condition.Value.ReadMemory(Output).PossibleValues; if (pEx.TrueAssume.Assumed && pEx.FalseAssume.Assumed) { var truevarID = getVariableIdentifier(pEx.TrueOperand.Value); var falsevarID = getVariableIdentifier(pEx.FalseOperand.Value); List <Value> trueValues = new List <Value>(pEx.TrueOperand.Value.ReadMemory(pEx.TrueOperand.OutSnapshot).PossibleValues); List <Value> falseValues = new List <Value>(pEx.FalseOperand.Value.ReadMemory(pEx.FalseOperand.OutSnapshot).PossibleValues); //merge taint info from both branches List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(trueValues, truevarID)); values.Add(new ValueInfo(falseValues, falsevarID)); bool nullValue = hasPossibleNullValue(pEx.TrueOperand) || hasPossibleNullValue(pEx.FalseOperand); TaintInfo outputTaint = mergeTaint(values, nullValue); pEx.SetValueContent(new MemoryEntry(Output.CreateInfo(outputTaint))); } else if (pEx.TrueAssume.Assumed) { var truevarID = getVariableIdentifier(pEx.TrueOperand.Value); List <Value> trueValues = new List <Value>(pEx.TrueOperand.Value.ReadMemory(Output).PossibleValues); //only true value is used List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(trueValues, truevarID)); bool nullValue = hasPossibleNullValue(pEx.TrueOperand); TaintInfo outputTaint = mergeTaint(values, nullValue); pEx.SetValueContent(new MemoryEntry(Output.CreateInfo(outputTaint))); } else { var falsevarID = getVariableIdentifier(pEx.FalseOperand.Value); List <Value> falseValues = new List <Value>(pEx.FalseOperand.Value.ReadMemory(Output).PossibleValues); //only false value is used List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(falseValues, falsevarID)); bool nullValue = hasPossibleNullValue(pEx.FalseOperand); TaintInfo outputTaint = mergeTaint(values, nullValue); pEx.SetValueContent(new MemoryEntry(Output.CreateInfo(outputTaint))); } } }
/// <summary> /// Visits a concatenation expression point and propagates the taint from all operands. /// </summary> /// <param name="p">point to visit</param> public override void VisitConcat(ConcatExPoint p) { _currentPoint = p; List <ValueInfo> values = new List <ValueInfo>(); bool nullValue = false; foreach (var operand in p.Parts) { nullValue = addOperandValues(values, operand, nullValue); } TaintInfo outputTaint = mergeTaint(values, nullValue); p.SetValueContent(new MemoryEntry(Output.CreateInfo(outputTaint))); }
private static void writeAll(ProgramPointGraph graph, ref HashSet <ProgramPointGraph> processedPPGraphs, ref HashSet <ProgramPointBase> processedPPoints) { processedPPGraphs.Add(graph); ProgramPointBase lastPPoint = null; foreach (ProgramPointBase p in graph.Points) { foreach (ProgramPointBase processedPoint in processedPPoints) { if (processedPoint == p) { continue; } } processedPPoints.Add(p); if (p.Partial == null || !p.Partial.Position.IsValid) { continue; } //only first and last program point from one line is shown if (lastPPoint != null && lastPPoint.Partial.Position.FirstLine == p.Partial.Position.FirstLine) { lastPPoint = p; } else { // For efficiency reasons, information about instate of program points are now not printed if (lastPPoint != null) // show the last program point { //writeProgramPointInformation(lastPPoint, true); } //writeProgramPointInformation(p, false); writeProgramPointInformation(p, true); lastPPoint = p; } // for each program poind resolve extensions FlowExtension ext = p.Extension; foreach (ExtensionPoint extPoint in ext.Branches) { writeExtension(extPoint, ref processedPPGraphs, ref processedPPoints); } } writeProgramPointInformation(lastPPoint, true); }
/// <inheritdoc /> protected override void mergeWithCallLevel(ProgramPointBase callerPoint, ISnapshotReadonly[] callOutputs) { Extend(callerPoint.OutSnapshot); switch (CurrentMode) { case SnapshotMode.MemoryLevel: mergeWithCallLevelMemory(callOutputs); break; case SnapshotMode.InfoLevel: mergeWithCallLevelInfo(callOutputs); break; default: throw notSupportedMode(); } }
private void createWarnings(ProgramPointBase p, TaintInfo taintInfo, List <FlagType> flags, String message = null) { if (taintInfo.nullValue) { String taint = taintInfo.printNullFlows(); String nullMessage = message; if (message == "Eval shoudn't contain anything from user input") { nullMessage = "Eval shoudn't contain null"; } if (flags == null) { createWarning(p, FlagType.HTMLDirty, nullMessage, taint, true, false); } else { foreach (FlagType flag in flags) { createWarning(p, flag, nullMessage, taint, true, false); } } } if (flags == null) { if (!taintInfo.tainted) { return; } String taint = taintInfo.print(); Boolean priority = !taintInfo.priority.allFalse(); createWarning(p, FlagType.HTMLDirty, message, taint, false, priority); } else { foreach (FlagType flag in flags) { if (!(taintInfo.taint.get(flag))) { continue; } String taint = taintInfo.print(flag); createWarning(p, flag, message, taint, false, taintInfo.priority.get(flag)); } } }
/// <summary> /// Visits including point /// </summary> /// <param name="p">program point to visit</param> public override void VisitInclude(IncludingExPoint p) { _currentPoint = p; var varID = getVariableIdentifier(p.Value); List <Value> argumentValues = new List <Value>(p.IncludePath.Value.ReadMemory(Output).PossibleValues); List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(argumentValues, varID)); bool nullValue = hasPossibleNullValue(p.IncludePath); TaintInfo outputTaint = mergeTaint(values, nullValue); createWarnings(p, outputTaint, new List <FlagType>() { FlagType.FilePathDirty }); }
/// <summary> /// Visits unary expression point - if operation is print, warning might be created /// </summary> /// <param name="p"></param> public override void VisitUnary(UnaryExPoint p) { _currentPoint = p; if (p.Expression.PublicOperation == Operations.Print) { var varID = getVariableIdentifier(p.Operand.Value); List <Value> argumentValues = new List <Value>(p.Operand.Value.ReadMemory(Output).PossibleValues); List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(argumentValues, varID)); bool nullValue = hasPossibleNullValue(p.Operand); TaintInfo outputTaint = mergeTaint(values, nullValue); createWarnings(p, outputTaint, new List <FlagType>() { FlagType.HTMLDirty }); } }
public override void VisitRefAssign(RefAssignPoint p) { _currentPoint = p; var source = p.ROperand; var target = p.LOperand; if (target.LValue == null || source.Value == null) { //Variable has to be LValue return; } var sourceTaint = getTaint(source); var finalPropagation = sourceTaint; setTaint(target.LValue, finalPropagation); }
/// <summary> /// Visits a binary expression point and propagates the taint from both the operands. /// </summary> /// <param name="p">point to visit</param> public override void VisitBinary(BinaryExPoint p) { _currentPoint = p; List <ValueInfo> values = new List <ValueInfo>(); bool nullValue = false; nullValue = addOperandValues(values, p.LeftOperand, nullValue); nullValue = addOperandValues(values, p.RightOperand, nullValue); TaintInfo outputTaint = mergeTaint(values, nullValue); outputTaint.setSanitized(new List <FlagType>() { FlagType.FilePathDirty, FlagType.HTMLDirty, FlagType.SQLDirty }); p.SetValueContent(new MemoryEntry(Output.CreateInfo(outputTaint))); }
/// <summary> /// Initialize call into callInput. /// /// NOTE: /// arguments has to be initialized /// sharing program point graphs is possible /// </summary> /// <param name="callInput"></param> /// <param name="extensionGraph"></param> /// <param name="arguments"></param> public override void InitializeCall(ProgramPointBase caller, ProgramPointGraph extensionGraph, MemoryEntry[] arguments) { _environmentInitializer(OutSet); var declaration = extensionGraph.SourceObject; var signature = getSignature(declaration); var hasNamedSignature = signature.HasValue; if (hasNamedSignature) { //we have names for passed arguments setNamedArguments(OutSet, arguments, signature.Value); } else { //there are no names - use numbered arguments setOrderedArguments(OutSet, arguments); } }
/// <summary> /// Visits eval point /// </summary> /// <param name="p">program point to visit</param> public override void VisitRCall(RCallPoint p) { _currentPoint = p; OutputSet.Snapshot.SetMode(SnapshotMode.InfoLevel); if (p is EvalExPoint) { EvalExPoint pEval = p as EvalExPoint; var varID = getVariableIdentifier(pEval.EvalCode.Value); List <Value> argumentValues = new List <Value>(pEval.EvalCode.Value.ReadMemory(Output).PossibleValues); List <ValueInfo> values = new List <ValueInfo>(); values.Add(new ValueInfo(argumentValues, varID)); bool nullValue = hasPossibleNullValue(pEval.EvalCode); TaintInfo outputTaint = mergeTaint(values, nullValue); createWarnings(p, outputTaint, null, "Eval shoudn't contain anything from user input"); } /* if (p is FunctionCallPoint) * { * FunctionCallPoint pCall = p as FunctionCallPoint; * * List<ValueInfo> values = new List<ValueInfo>(); * * List<ValuePoint> args = new List<ValuePoint>(pCall.Arguments); * bool nullValue = false; * * foreach (ValuePoint arg in args) * { * var varID = getVariableIdentifier(arg.Value); * List<Value> argumentValues = new List<Value>(arg.Value.ReadMemory(Output).PossibleValues); * values.Add(new ValueInfo(argumentValues, varID)); * nullValue |= hasPossibleNullValue(arg.Value); * } * * TaintInfo outputTaint = mergeTaint(values, nullValue); * * if (outputTaint.tainted || outputTaint.nullValue) * FunctionResolverBase.SetReturn(OutputSet, new MemoryEntry(Output.CreateInfo(outputTaint))); * }*/ }
private void createWarning(ProgramPointBase p, FlagType flag, String message, String taint, Boolean nullFlow, Boolean priority) { var currentScript = p.OwningScriptFullName; AnalysisTaintWarning warning; if (message == null) { warning = new AnalysisTaintWarning(currentScript, taint, priority, p.Partial, p, flag, nullFlow); } else { warning = new AnalysisTaintWarning(currentScript, message, taint, priority, p.Partial, p, flag); } int index = analysisTaintWarnings.IndexOf(warning); if (index != -1) { analysisTaintWarnings.RemoveAt(index); } analysisTaintWarnings.Add(warning); }
/// <summary> /// Construct new instance of <see cref="AnalysisSecurityWarning"/>, message will be generated automatically /// </summary> /// <param name="fullFileName">Full name of source code file</param> /// <param name="element">Element, where the warning was produced</param> /// <param name="programPoint">The program point, where the warning was produced</param> /// <param name="cause">Flag type</param> public AnalysisSecurityWarning(string fullFileName, LangElement element, ProgramPointBase programPoint, FlagType cause, string taintedVar) : base(programPoint) { FullFileName = fullFileName; switch (cause) { case FlagType.HTMLDirty: Message = "Unsanitized value " + (taintedVar != "" ? "(" + taintedVar + ") " : "") + "goes into browser"; break; case FlagType.FilePathDirty: Message = "Unsanitized value " + (taintedVar != "" ? "(" + taintedVar + ") " : "") + "used as a filename when opening a file"; break; case FlagType.SQLDirty: Message = "Unsanitized value " + (taintedVar != "" ? "(" + taintedVar + ") " : "") + "goes into database"; break; } LangElement = element; Flag = cause; TaintedVarName = taintedVar; }
/// <summary> /// Visits echo statement /// </summary> /// <param name="p">program point to visit</param> public override void VisitEcho(EchoStmtPoint p) { _currentPoint = p; var count = p.Echo.Parameters.Count; List <ValuePoint> valpoints = new List <ValuePoint>(p.Parameters); List <ValueInfo> values = new List <ValueInfo>(); bool nullValue = false; foreach (ValuePoint val in valpoints) { var varID = getVariableIdentifier(val.Value); List <Value> argumentValues = new List <Value>(val.Value.ReadMemory(Output).PossibleValues); values.Add(new ValueInfo(argumentValues, varID)); nullValue |= hasPossibleNullValue(val); } TaintInfo outputTaint = mergeTaint(values, nullValue); createWarnings(p, outputTaint, new List <FlagType>() { FlagType.HTMLDirty }); }
/// <summary> /// Print representative info for given program point. /// </summary> /// <param name="pointCaption">Caption which specifies program point</param> /// <param name="point">Program point which info is printed</param> public void ProgramPointInfo(string pointCaption, ProgramPointBase point) { Headline("PROGRAM POINT: " + pointCaption); comment("Call context:"); line(); comment(point.OwningPPGraph.Context.ToString()); Indent(); line(); if (point.OutSet == null) { line(); Headline("Point not reached"); line(); line(); } else { foreach (var infoLine in lineSplit(point.OutSet.Representation)) { if (isCommentLine(infoLine)) { comment(infoLine); } else if (!isEmpty(infoLine)) { variableInfoLine(infoLine); } line(); } } Dedent(); }
/// <summary> /// Append given point at end of current chain /// </summary> /// <param name="appendedPoint">Point that is appended</param> internal void AppendToChain(ProgramPointBase appendedPoint) { _valueCreator.AppendToChain(appendedPoint); }
/// <summary> /// All program points that are not returne via Result method has to be registered by current method /// </summary> /// <param name="point">Registered point</param> private void RegisterPoint(ProgramPointBase point) { _valueCreator.Register(point); }
/// <summary> /// Prevent from adding edge when chaining points /// </summary> /// <param name="preventedPoint">Point which flow child wont be set</param> internal void PreventChainEdge(ProgramPointBase preventedPoint) { _valueCreator.PreventChainEdge(preventedPoint); }
/// <summary> /// Method handler called after program point is processed /// <remarks>Every program point is processed only once at on call level</remarks> /// </summary> /// <param name="point">Processed program point</param> protected abstract void onWalkPoint(ProgramPointBase point);
public override MemoryEntry InitializeCalledObject(ProgramPointBase caller, ProgramPointGraph extensionGraph, MemoryEntry calledObject) { return(calledObject); }