├── PHPAnalysis-parser ├── src │ ├── parsed.xml │ ├── config.yml │ ├── test.php │ ├── Main.php │ ├── commands │ │ ├── GreetCommand.php │ │ ├── ScanCommand.php │ │ └── CountCommand.php │ └── YamlConfigLoader.php └── composer.json ├── PHPAnalysis ├── PHPAnalysis │ ├── FunctionSpecs │ │ ├── JSONSpecifications │ │ │ ├── Sources.json │ │ │ ├── CondSanitizers.json │ │ │ └── XSSSinks.json │ │ ├── WPSpecifications │ │ │ └── wpSQLSanitizers.json │ │ └── StoredSQLProviders │ │ │ └── databaseProviders.json │ ├── Utils │ │ ├── IMergeable.cs │ │ ├── IDeepCloneable.cs │ │ ├── Extensions │ │ │ ├── EnumerableExtensions.cs │ │ │ ├── ScopeEnumExtensions.cs │ │ │ ├── EventExtensions.cs │ │ │ ├── VariableStorageExtensions.cs │ │ │ ├── IImmutableExtentions.cs │ │ │ └── CollectionExtensions.cs │ │ ├── Exceptions │ │ │ └── ConfigurationParseException.cs │ │ ├── QueueUtils.cs │ │ ├── XmlHelpers │ │ │ ├── GlobalNode.cs │ │ │ ├── Case.cs │ │ │ ├── ExprVarNode.cs │ │ │ ├── AstNode.cs │ │ │ ├── For.cs │ │ │ ├── Conditional.cs │ │ │ ├── AstNodeInfo.cs │ │ │ ├── BreakContinue.cs │ │ │ └── ScalarNode.cs │ │ ├── Preconditions.cs │ │ └── ImmutableDictionaryComparer.cs │ ├── Analysis │ │ ├── CFG │ │ │ ├── Taint │ │ │ │ ├── IConstructRepository.cs │ │ │ │ ├── IBlockAnalyzer.cs │ │ │ │ ├── SQLITaint.cs │ │ │ │ ├── MixedTaint.cs │ │ │ │ ├── XSSTaint.cs │ │ │ │ ├── IBlockAnalyzerComponent.cs │ │ │ │ ├── AnalysisStacks.cs │ │ │ │ ├── TaintHandlerTaintSet.cs │ │ │ │ ├── ExpressionInfo.cs │ │ │ │ ├── StringAnalysis.cs │ │ │ │ └── ISinkAnalyzer.cs │ │ │ ├── Traversal │ │ │ │ ├── IWorklist.cs │ │ │ │ ├── BackwardTraversal.cs │ │ │ │ ├── ForwardTraversal.cs │ │ │ │ └── ITraversalTechnique.cs │ │ │ ├── ICFGAnalysis.cs │ │ │ ├── FunctionAndMethodAnalyzerFactory.cs │ │ │ ├── FunctionSummary.cs │ │ │ ├── QueueWorklist.cs │ │ │ ├── VariableInfoComposer.cs │ │ │ ├── PrioritizedCompositeAnalysis.cs │ │ │ ├── CFGASTNodeVisitor.cs │ │ │ └── CFGPruner.cs │ │ ├── ITaintProvider.cs │ │ ├── IVulnerabilityReporter.cs │ │ ├── IAnalysisStartingListener.cs │ │ ├── IVulnerabilityStorage.cs │ │ ├── CompositeVulneribilityReporter.cs │ │ ├── PHPDefinitions │ │ │ └── Source.cs │ │ └── AST │ │ │ ├── MetricVisitor.cs │ │ │ └── IncludeResolver.cs │ ├── Data │ │ ├── AnalysisScope.cs │ │ ├── VariableScope.cs │ │ ├── CFG │ │ │ ├── AbstractScope.cs │ │ │ ├── LoopScope.cs │ │ │ ├── SwitchScope.cs │ │ │ ├── EdgeTag.cs │ │ │ ├── IfScope.cs │ │ │ ├── CFGBlock.cs │ │ │ └── ScopeHandler.cs │ │ ├── VariableTaint.cs │ │ ├── PHP │ │ │ ├── ClosureUse.cs │ │ │ ├── Property.cs │ │ │ ├── Interface.cs │ │ │ ├── Class.cs │ │ │ ├── Closure.cs │ │ │ ├── FunctionCall.cs │ │ │ └── Parameter.cs │ │ ├── Project.cs │ │ ├── StackSet.cs │ │ ├── File.cs │ │ ├── QueueSet.cs │ │ └── VariableTreeDimension.cs │ ├── IO │ │ └── Cmd │ │ │ ├── ProgressIndicator.cs │ │ │ ├── BatsFlyingAnimation.cs │ │ │ ├── ProgressIndicatorFactory.cs │ │ │ ├── ExecutiveDeskToyAnimation.cs │ │ │ ├── AnimationIndicator.cs │ │ │ ├── BarIndicator.cs │ │ │ └── BikeGuyRidingAnimation.cs │ ├── App.config │ ├── CodeFile.cs │ ├── Parsing │ │ ├── AstTraversing │ │ │ ├── IXmlVisitor.cs │ │ │ ├── IXmlTraverser.cs │ │ │ ├── XmlTraverseEventArgs.cs │ │ │ └── ASTPrinter.cs │ │ ├── ParseResult.cs │ │ ├── ProjectParser.cs │ │ ├── XmlHelper.cs │ │ └── FileParser.cs │ ├── packages.config │ ├── config.yml │ ├── Configuration │ │ ├── ComponentConfiguration.cs │ │ ├── GraphConfiguration.cs │ │ ├── FuncSpecConfiguration.cs │ │ ├── PHPConfiguration.cs │ │ └── Config.cs │ ├── config-template.yml │ ├── Components │ │ ├── ComponentContainer.cs │ │ └── ComponentImporter.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Arguments.cs │ └── Provider │ │ └── Keys.cs ├── PHPAnalysis.PluginInterface │ ├── Class1.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── PHPAnalysis.PluginInterface.csproj ├── PHPAnalysis.Tests │ ├── TestSettings.cs │ ├── packages.config │ ├── app.config │ ├── TestUtils │ │ ├── TypeExtensions.cs │ │ ├── PHPParseUtils.cs │ │ ├── TempFileManager.cs │ │ └── GraphAssertions.cs │ ├── ConfigDependentTests.cs │ ├── Data │ │ └── AstConstantsTests.cs │ ├── Analysis │ │ ├── CFG │ │ │ ├── ExpressionInfoTests.cs │ │ │ └── CFGTraverserTests.cs │ │ ├── AST │ │ │ └── IncludeResolvertTests.cs │ │ └── ReachDefTests.cs │ ├── Parsing │ │ ├── CFGCreator_SkipElements_Tests.cs │ │ ├── CFGCreator_Case_Tests.cs │ │ ├── CFGCreator_If_Tests.cs │ │ └── CFGCreator_ClassTests.cs │ ├── Utils │ │ └── XmlHelpers │ │ │ └── ScalarNodeTests.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── PHPAnalysis.sln.DotSettings ├── WordPress.Plugin │ ├── GotoCounter.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── WpTaintProvider.cs │ └── WordPress.Plugin.csproj ├── FileWriter.Plugin │ ├── Properties │ │ └── AssemblyInfo.cs │ └── FileWriter.Plugin.csproj └── PHPAnalysis.sln ├── LICENSE ├── .gitattributes └── README.md /PHPAnalysis-parser/src/parsed.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/config.yml: -------------------------------------------------------------------------------- 1 | # 2 | php_extensions: [.php, .php3, .php4, .php5, .inc] 3 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/FunctionSpecs/JSONSpecifications/Sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "SourceFuncs":[ 3 | ] 4 | } -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/test.php: -------------------------------------------------------------------------------- 1 | 4 | { 5 | T Merge(T other); 6 | } 7 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/IConstructRepository.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Analysis.CFG 2 | { 3 | public interface IConstructRepository 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/AnalysisScope.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Data 2 | { 3 | public enum AnalysisScope 4 | { 5 | File = 0, 6 | Function = 1 7 | } 8 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/ProgressIndicator.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.IO.Cmd 2 | { 3 | internal abstract class ProgressIndicator 4 | { 5 | public abstract void Step(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/ITaintProvider.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Data; 2 | 3 | namespace PHPAnalysis.Analysis 4 | { 5 | public interface ITaintProvider 6 | { 7 | ImmutableVariableStorage GetTaint(); 8 | } 9 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/IDeepCloneable.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Utils 2 | { 3 | public interface IDeepCloneable 4 | { 5 | T DeepClone(); 6 | } 7 | 8 | public interface IShallowCloneable 9 | { 10 | T ShallowClone(); 11 | } 12 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/VariableScope.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Data 2 | { 3 | public enum VariableScope 4 | { 5 | Unknown = 0, 6 | SuperGlobal = 1, 7 | File = 2, 8 | Function = 3, 9 | Class = 4, 10 | Instance = 5 11 | } 12 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.PluginInterface/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PHPAnalysis.PluginInterface 8 | { 9 | public class Class1 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/IBlockAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using PHPAnalysis.Data; 3 | 4 | namespace PHPAnalysis.Analysis.CFG.Taint 5 | { 6 | public interface IBlockAnalyzer 7 | { 8 | ImmutableVariableStorage Analyze(XmlNode node, ImmutableVariableStorage knownTaint); 9 | } 10 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/CodeFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PHPAnalysis 8 | { 9 | public sealed class CodeFile 10 | { 11 | public string Filename { get; set; } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/AbstractScope.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Data.CFG 2 | { 3 | abstract class AbstractScope 4 | { 5 | public CFGBlock EntryBlock { get; set; } 6 | public CFGBlock EndBlock { get; set; } 7 | 8 | protected AbstractScope() 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/SQLITaint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.Analysis.CFG 4 | { 5 | [Flags] 6 | public enum SQLITaint 7 | { 8 | None = 0, 9 | SQL_SQ = 1, 10 | SQL_DQ = 2, 11 | SQL_NoQ = 4, 12 | SQL_ALL = SQL_SQ | SQL_DQ | SQL_NoQ 13 | } 14 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/MixedTaint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis 4 | { 5 | [Flags] 6 | public enum MixedStatus 7 | { 8 | XSSSQL_UNSAFE = 0, 9 | XSS_SAFE_ONLY = 1, 10 | SQL_SAFE_ONLY = 2, 11 | XSSSQL_SAFE = XSS_SAFE_ONLY | SQL_SAFE_ONLY 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/TestSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PHPAnalysis.Tests 8 | { 9 | public static class TestSettings 10 | { 11 | public const string ConfigFile = "config.yml"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/XSSTaint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.Analysis.CFG 4 | { 5 | [Flags] 6 | public enum XSSTaint 7 | { 8 | None = 0, 9 | XSS_JS = 1, 10 | XSS_HTML = 2, 11 | XSS_SQ = 4, 12 | XSS_AllQ = 8, 13 | XSS_ALL = XSS_JS | XSS_HTML | XSS_SQ | XSS_AllQ 14 | } 15 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Traversal/IWorklist.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PHPAnalysis.Analysis.CFG.Traversal 4 | { 5 | public interface IWorklist 6 | { 7 | bool Any(); 8 | 9 | void Add(T elem); 10 | 11 | T GetNext(); 12 | 13 | bool Contains(T elem, IEqualityComparer comparer = null); 14 | } 15 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Extensions/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace PHPAnalysis.Utils 5 | { 6 | public static class EnumerableExtensions 7 | { 8 | public static bool IsEmpty(this IEnumerable collection) 9 | { 10 | return !collection.Any(); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Extensions/ScopeEnumExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Data 2 | { 3 | public static class ScopeEnumExtensions 4 | { 5 | public static VariableScope ToVariableScope(this AnalysisScope analysisScope) 6 | { 7 | return analysisScope == AnalysisScope.File ? VariableScope.File : VariableScope.Function; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/ICFGAnalysis.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Data.CFG; 2 | using QuickGraph; 3 | 4 | namespace PHPAnalysis.Analysis.CFG 5 | { 6 | public interface ICFGAnalysis 7 | { 8 | void Initialize(CFGBlock cfgBlock); 9 | bool Analyze(TaggedEdge edge); 10 | 11 | bool Analyze2(CFGBlock block, IBidirectionalGraph> graph); 12 | } 13 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/AstTraversing/IXmlVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Parsing.AstTraversing 2 | { 3 | public interface IXmlVisitor 4 | { 5 | void TraverseStart(object sender, XmlStartTraverseEventArgs e); 6 | void EnteringNode(object sender, XmlTraverseEventArgs e); 7 | void LeavingNode(object sender, XmlTraverseEventArgs e); 8 | void TraverseEnd(object sender, XmlEndTraverseEventArgs e); 9 | } 10 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/IVulnerabilityReporter.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Analysis.PHPDefinitions; 2 | 3 | namespace PHPAnalysis.Analysis 4 | { 5 | public interface IVulnerabilityReporter 6 | { 7 | void ReportVulnerability(IVulnerabilityInfo vulnerabilityInfo); 8 | void ReportStoredVulnerability(IVulnerabilityInfo[] vulnerabilityPathInfos); 9 | void RegisterFunctionsHandler(FunctionsHandler functionsHandler); 10 | } 11 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Exceptions/ConfigurationParseException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.Utils.Exceptions 4 | { 5 | public sealed class ConfigurationParseException : Exception 6 | { 7 | public ConfigurationParseException() { } 8 | public ConfigurationParseException(string message) : base(message) { } 9 | 10 | public ConfigurationParseException(string message, Exception inner) : base(message, inner) { } 11 | } 12 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PHPAnalysis-parser/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MAV/PHPAnalyzer", 3 | "description": "description_text", 4 | "minimum-stability": "dev", 5 | "license": "proprietary", 6 | "authors": [ 7 | { 8 | "name": "MAV", 9 | "email": "mvej10@student.aau.dk" 10 | } 11 | ], 12 | "require": { 13 | "symfony/console": "~3.0@dev", 14 | "symfony/finder": "~3.0@dev", 15 | "nikic/php-parser": "~1.1@dev", 16 | "symfony/config": "~3.0@dev" 17 | }, 18 | "autoload": { 19 | "classmap": ["src/"] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/VariableTaint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using PHPAnalysis.Analysis.CFG; 8 | using PHPAnalysis.Utils; 9 | 10 | namespace PHPAnalysis.Data 11 | { 12 | public abstract class VariableTaint : IMergeable 13 | { 14 | public abstract VariableTaint NoTaint { get; } 15 | 16 | public abstract VariableTaint Merge(VariableTaint other); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/QueueUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PHPAnalysis.Utils 4 | { 5 | public static class QueueUtils 6 | { 7 | public static void EnqueueAll(this Queue queue, IEnumerable newElements) 8 | { 9 | Preconditions.NotNull(queue, "queue"); 10 | Preconditions.NotNull(newElements, "newElements"); 11 | 12 | foreach (var element in newElements) 13 | { 14 | queue.Enqueue(element); 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/AstTraversing/IXmlTraverser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml; 3 | 4 | namespace PHPAnalysis.Parsing.AstTraversing 5 | { 6 | public interface IXmlTraverser 7 | { 8 | event EventHandler OnTraverseStart; 9 | event EventHandler OnEnteringNode; 10 | event EventHandler OnLeavingNode; 11 | event EventHandler OnTraverseEnd; 12 | 13 | void AddVisitor(IXmlVisitor visitor); 14 | 15 | void Traverse(XmlNode node); 16 | } 17 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/TestUtils/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace PHPAnalysis.Tests.Data 7 | { 8 | internal static class TypeExtensions 9 | { 10 | public static IEnumerable GetConstants(this Type type) 11 | { 12 | const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy; 13 | return type.GetFields(bindingFlags) 14 | .Where(info => info.IsLiteral && !info.IsInitOnly); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/LoopScope.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Utils; 2 | 3 | namespace PHPAnalysis.Data.CFG 4 | { 5 | internal sealed class LoopScope : AbstractScope 6 | { 7 | public CFGBlock LoopConditionBlock { get; set; } 8 | public CFGBlock LoopBodyStartBlock { get; set; } 9 | public CFGBlock LoopUpdateBlock { get; set; } 10 | public CFGBlock ContinueDestination { get; set; } 11 | 12 | public LoopScope(CFGBlock entryBlock) 13 | { 14 | Preconditions.NotNull(entryBlock, "entryBlock"); 15 | 16 | this.EntryBlock = entryBlock; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/ConfigDependentTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using PHPAnalysis.Analysis.PHPDefinitions; 3 | using PHPAnalysis.Configuration; 4 | 5 | namespace PHPAnalysis.Tests.Analysis 6 | { 7 | public abstract class ConfigDependentTests 8 | { 9 | protected Config Config; 10 | 11 | [OneTimeSetUp] 12 | public void FixtureSetUp() 13 | { 14 | Config = Config.ReadConfiguration(TestSettings.ConfigFile); 15 | } 16 | 17 | [OneTimeTearDown] 18 | public void FixtureTearDown() 19 | { 20 | Config = null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/ClosureUse.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using PHPAnalysis.Utils; 3 | 4 | namespace PHPAnalysis.Data.PHP 5 | { 6 | public sealed class ClosureUse 7 | { 8 | public XmlNode AstNode { get; private set; } 9 | public string Name { get; set; } 10 | 11 | public bool ByReference { get; set; } 12 | 13 | public ClosureUse(XmlNode node) 14 | { 15 | Preconditions.NotNull(node, "node"); 16 | 17 | this.AstNode = node; 18 | } 19 | 20 | public override string ToString() 21 | { 22 | return string.Format("{0}{1}", ByReference ? "&" : "", Name); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Extensions/EventExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.Utils 4 | { 5 | internal static class EventExtensions 6 | { 7 | public static void RaiseEvent(this EventHandler myEvent, object sender, T e) 8 | where T : EventArgs 9 | { 10 | if (myEvent != null) 11 | { 12 | myEvent(sender, e); 13 | } 14 | } 15 | 16 | public static void RaiseEvent(this EventHandler myEvent, object sender, EventArgs e) 17 | { 18 | if (myEvent != null) 19 | { 20 | myEvent(sender, e); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/ParseResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | 8 | namespace PHPAnalysis.Parsing 9 | { 10 | public sealed class ParseResult 11 | { 12 | private readonly Dictionary _parsedFiles = new Dictionary(); 13 | public IDictionary ParsedFiles { get { return this._parsedFiles; } } 14 | 15 | private readonly List _filesFailedToParse = new List(); 16 | public IList FilesThatFailedToParse { get { return this._filesFailedToParse; } } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/Main.php: -------------------------------------------------------------------------------- 1 | addCommands($commands); 22 | 23 | $application->run(); -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/SwitchScope.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml; 3 | 4 | namespace PHPAnalysis.Data.CFG 5 | { 6 | internal sealed class SwitchScope : AbstractScope 7 | { 8 | public CFGBlock SwitchStartNode 9 | { 10 | get { return EntryBlock; } 11 | private set { EntryBlock = value; } 12 | } 13 | 14 | public CFGBlock CurrentCondition { get; set; } 15 | public CFGBlock DefaultBlock { get; set; } 16 | public CFGBlock DefaultTrueBlock { get; set; } 17 | 18 | public SwitchScope(CFGBlock switchConditionNode, CFGBlock endNode) 19 | { 20 | EntryBlock = switchConditionNode; 21 | EndBlock = endNode; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/IBlockAnalyzerComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Xml; 5 | using PHPAnalysis.Data; 6 | 7 | namespace PHPAnalysis.Analysis.CFG.Taint 8 | { 9 | public interface IBlockAnalyzerComponent 10 | { 11 | Func FunctionMethodAnalyzerFactory { get; set; } 12 | 13 | ExpressionInfo Analyze(XmlNode node, ExpressionInfo exprInfo, IVariableStorage currentStorage, IVulnerabilityStorage vulnStorage); 14 | 15 | ExpressionInfo AnalyzeFunctionCall(XmlNode node, ExpressionInfo exprInfo, IVariableStorage varStorage, IVulnerabilityStorage vulnStorage, IDictionary argumentInfos, AnalysisStacks analysisStacks); 16 | } 17 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | PHP 4 | SQL 5 | XML -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/Project.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using PHPAnalysis.Data.PHP; 3 | using YamlDotNet.Serialization.ObjectFactories; 4 | 5 | namespace PHPAnalysis.Data 6 | { 7 | public sealed class Project 8 | { 9 | public List Files { get; private set; } 10 | 11 | public List Classes { get; private set; } 12 | 13 | public List Functions { get; private set; } 14 | 15 | public List Interfaces { get; private set; } 16 | 17 | public KeyValuePair Constants { get; private set; } 18 | 19 | public Project() 20 | { 21 | Files = new List(); 22 | Classes = new List(); 23 | Functions = new List(); 24 | Interfaces = new List(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/Property.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | 3 | namespace PHPAnalysis.Data.PHP 4 | { 5 | public sealed class Property 6 | { 7 | public XmlNode AstNode { get; private set; } 8 | 9 | public int StartLine { get; set; } 10 | 11 | public int EndLine { get; set; } 12 | 13 | public AstConstants.VisibilityModifiers VisibilityModifiers { get; set; } 14 | 15 | public string Name { get; set;} 16 | 17 | public bool HasDefault { get; set; } 18 | 19 | public Property(XmlNode astNode) 20 | { 21 | AstNode = astNode; 22 | } 23 | 24 | public override string ToString() 25 | { 26 | return string.Format("{0} {1} {2};", 27 | VisibilityModifiers, 28 | Name, 29 | HasDefault ? " = " : ""); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Traversal/BackwardTraversal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using PHPAnalysis.Data.CFG; 4 | using QuickGraph; 5 | 6 | namespace PHPAnalysis.Analysis.CFG 7 | { 8 | public sealed class BackwardTraversal : ITraversalTechnique 9 | { 10 | public IEnumerable GetStartBlocks(IBidirectionalGraph> graph) 11 | { 12 | return graph.Vertices.Where(v => v.IsLeaf); 13 | } 14 | 15 | public IEnumerable> NextEdges(IBidirectionalGraph> graph, CFGBlock block) 16 | { 17 | return graph.InEdges(block); 18 | } 19 | 20 | public CFGBlock EdgeTarget(Edge edge) 21 | { 22 | return edge.Source; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/EdgeTag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using PHPAnalysis.Utils; 7 | 8 | namespace PHPAnalysis.Data.CFG 9 | { 10 | public enum EdgeType 11 | { 12 | Normal = 0, 13 | True, 14 | False 15 | } 16 | 17 | public class EdgeTag : IDeepCloneable 18 | { 19 | public EdgeType EdgeType { get; set;} 20 | public string EdgeData { get; set; } 21 | 22 | public EdgeTag(EdgeType type) 23 | { 24 | EdgeType = type; 25 | } 26 | 27 | public EdgeTag DeepClone() 28 | { 29 | return new EdgeTag(EdgeType) { 30 | EdgeData = this.EdgeData 31 | }; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/IfScope.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.Data.CFG 2 | { 3 | internal sealed class IfScope : AbstractScope 4 | { 5 | public CFGBlock IfConditionNode 6 | { 7 | get { return EntryBlock; } 8 | private set { EntryBlock = value; } 9 | } 10 | public CFGBlock TrueNode { get; set; } 11 | public CFGBlock FalseNode { get; set; } 12 | public CFGBlock ElseifBlock { get; set; } 13 | 14 | public IfScope(CFGBlock ifConditionNode, CFGBlock trueNode = null) 15 | { 16 | EntryBlock = ifConditionNode; 17 | this.TrueNode = trueNode; 18 | } 19 | 20 | public bool IsFalseNodeSet() 21 | { 22 | return FalseNode != null; 23 | } 24 | 25 | public bool IsTrueNodeSet() 26 | { 27 | return TrueNode != null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/Interface.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Data.PHP 6 | { 7 | public sealed class Interface 8 | { 9 | public XmlNode AstNode { get; set; } 10 | 11 | public IList Methods { get; private set; } 12 | 13 | public string Name { get; set; } 14 | 15 | public int StartLine { get; set; } 16 | 17 | public int EndLine { get; set; } 18 | 19 | public Interface(XmlNode node) 20 | { 21 | Preconditions.NotNull(node, "node"); 22 | 23 | this.AstNode = node; 24 | this.Methods = new List(); 25 | } 26 | 27 | public override string ToString() 28 | { 29 | return string.Format("Name: {0}, StartLine: {1}, EndLine: {2}", Name, StartLine, EndLine); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/GlobalNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml; 3 | using PHPAnalysis.Data; 4 | 5 | namespace PHPAnalysis.Utils.XmlHelpers 6 | { 7 | public static class GlobalNode 8 | { 9 | public static IEnumerable GetVariables(XmlNode node) 10 | { 11 | Preconditions.NotNull(node, "node"); 12 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Stmt_Global, 13 | "Node has to be a global statement. It was: " + node.Name, "node"); 14 | 15 | var variables = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Vars) 16 | .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array) 17 | .GetSubnodes(AstConstants.Node + ":" + AstConstants.Nodes.Expr_Variable); 18 | return variables; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/FunctionAndMethodAnalyzerFactory.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Analysis.AST; 2 | using PHPAnalysis.Analysis.CFG.Taint; 3 | using PHPAnalysis.Data; 4 | using PHPAnalysis.Analysis.PHPDefinitions; 5 | 6 | namespace PHPAnalysis.Analysis.CFG 7 | { 8 | public sealed class FunctionAndMethodAnalyzerFactory 9 | { 10 | public bool UseSummaries { get; set; } 11 | 12 | public FunctionAndMethodAnalyzer Create(ImmutableVariableStorage variableStorage, IIncludeResolver incResolver, 13 | AnalysisStacks stacks, CustomFunctionHandler customFuncHandler, 14 | IVulnerabilityStorage vulnerabilityStorage, FunctionsHandler fh) 15 | { 16 | return new FunctionAndMethodAnalyzer(variableStorage, incResolver, stacks, customFuncHandler, vulnerabilityStorage, fh) 17 | { 18 | UseSummaries = this.UseSummaries 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Traversal/ForwardTraversal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using PHPAnalysis.Data; 4 | using PHPAnalysis.Data.CFG; 5 | using PHPAnalysis.Utils; 6 | using QuickGraph; 7 | using QuickGraph.Algorithms; 8 | 9 | namespace PHPAnalysis.Analysis.CFG 10 | { 11 | public sealed class ForwardTraversal : ITraversalTechnique 12 | { 13 | public IEnumerable GetStartBlocks(IBidirectionalGraph> graph) 14 | { 15 | return graph.Roots().Where(r => r.IsRoot); 16 | } 17 | 18 | public IEnumerable> NextEdges(IBidirectionalGraph> graph, CFGBlock block) 19 | { 20 | return graph.OutEdges(block); 21 | } 22 | 23 | public CFGBlock EdgeTarget(Edge edge) 24 | { 25 | return edge.Target; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/commands/GreetCommand.php: -------------------------------------------------------------------------------- 1 | setName('greet') 15 | ->setDescription('Greetings') 16 | ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?'); 17 | } 18 | 19 | protected function execute(InputInterface $input, OutputInterface $output) { 20 | $name = $input->getArgument('name'); 21 | 22 | $text = 'Hello'; 23 | if ($name) { 24 | $text = $text . ' ' . $name; 25 | } 26 | 27 | $output->writeln($text); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/BatsFlyingAnimation.cs: -------------------------------------------------------------------------------- 1 | namespace PHPAnalysis.IO.Cmd 2 | { 3 | internal class BatsFlyingAnimation : AnimationIndicator 4 | { 5 | protected override string[] Steps 6 | { 7 | get 8 | { 9 | return new[] { 10 | @" /^v^\ 11 | /^v^\ /^v^\ 12 | /^v^\ 13 | 14 | /^v^\ ", 15 | @" \^v^/ 16 | \^v^/ \^v^/ 17 | \^v^/ 18 | 19 | \^v^/ " 20 | }; 21 | 22 | } 23 | } 24 | 25 | protected override string FinalStep 26 | { 27 | get { return Steps[1]; } 28 | } 29 | 30 | public BatsFlyingAnimation(int max = 100) : base(max) 31 | { 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/FunctionSummary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using PHPAnalysis.Analysis.CFG.Taint; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Analysis.CFG 6 | { 7 | public sealed class FunctionSummary 8 | { 9 | public string FunctionName { get; private set; } 10 | public ICollection ArgInfos { get; private set; } 11 | 12 | public ExpressionInfo ReturnValue { get; set; } 13 | 14 | public FunctionSummary(string functionName) 15 | { 16 | Preconditions.NotNull(functionName, "functionName"); 17 | 18 | this.FunctionName = functionName; 19 | this.ArgInfos = new List(); 20 | //this.GlobalElements = new Dictionary(); 21 | //this.SuperglobalElements = new Dictionary(); 22 | //this.ClassElements = new Dictionary(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Data/AstConstantsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using NUnit.Framework; 8 | using PHPAnalysis.Data; 9 | 10 | namespace PHPAnalysis.Tests.Data 11 | { 12 | [TestFixture] 13 | public class AstConstantsTests 14 | { 15 | [TestCase(typeof(AstConstants.Attributes))] 16 | [TestCase(typeof(AstConstants.Subnodes))] 17 | [TestCase(typeof(AstConstants.Scalars))] 18 | [TestCase(typeof(AstConstants.Nodes))] 19 | public static void AttributeConstantsHaveSameNameAsValue_CaseIgnored(Type type) 20 | { 21 | IEnumerable constants = type.GetConstants(); 22 | 23 | foreach (var fieldInfo in constants) 24 | { 25 | Assert.That(fieldInfo.Name, Is.EqualTo(fieldInfo.GetValue(null)).IgnoreCase); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/Case.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using System.Xml.Linq; 8 | using PHPAnalysis.Data; 9 | 10 | namespace PHPAnalysis.Utils.XmlHelpers 11 | { 12 | public sealed class Case 13 | { 14 | public static bool IsDefaultCase(XmlNode node) 15 | { 16 | Preconditions.NotNull(node, "node"); 17 | Preconditions.IsTrue(node.LocalName == AstConstants.Nodes.Stmt_Case, 18 | "Expected a case node, but received a " + node.Name); 19 | 20 | XDocument xNode = XDocument.Parse(node.OuterXml); 21 | XNamespace nsa = AstConstants.Namespaces.SubNode; 22 | 23 | var defaultLine = xNode.Descendants(nsa + AstConstants.Subnodes.Cond) 24 | .First().Value; 25 | 26 | return defaultLine == ""; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PHPAnalysis/WordPress.Plugin/GotoCounter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.Composition; 2 | using PHPAnalysis.Data; 3 | using PHPAnalysis.Parsing.AstTraversing; 4 | 5 | namespace WordPress.Plugin 6 | { 7 | [Export(typeof(IXmlVisitor))] 8 | public sealed class GotoCounter : IXmlVisitor 9 | { 10 | private int _gotos = 0; 11 | public void TraverseStart(object sender, XmlStartTraverseEventArgs e) 12 | { 13 | } 14 | 15 | public void EnteringNode(object sender, XmlTraverseEventArgs e) 16 | { 17 | if (e.Node.LocalName == AstConstants.Nodes.Stmt_Goto) 18 | { 19 | _gotos++; 20 | } 21 | } 22 | 23 | public void LeavingNode(object sender, XmlTraverseEventArgs e) 24 | { 25 | } 26 | 27 | public void TraverseEnd(object sender, XmlEndTraverseEventArgs e) 28 | { 29 | //System.IO.File.AppendAllText("john.txt", "GOTOs: " + _gotos); 30 | 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/YamlConfigLoader.php: -------------------------------------------------------------------------------- 1 | s.Key, s => s.Value.AssignmentClone()), 16 | immutableStorage.Globals.ToDictionary(s => s.Key, s => s.Value.AssignmentClone()), 17 | immutableStorage.Locals.ToDictionary(s => s.Key, s => s.Value.AssignmentClone()), 18 | immutableStorage.ClassVariables.ToDictionary(s => s.Key, s => s.Value.AssignmentClone()), 19 | immutableStorage.LocalAccessibleGlobals.ToDictionary(s => s.Key, s => s.Value.AssignmentClone())); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Analysis/CFG/ExpressionInfoTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | using PHPAnalysis.Analysis.CFG; 4 | using PHPAnalysis.Analysis.CFG.Taint; 5 | 6 | namespace PHPAnalysis.Tests.Analysis.CFG 7 | { 8 | [TestFixture] 9 | class ExpressionInfoTests 10 | { 11 | [Test] 12 | public void ExpressionInfo_Merge() 13 | { 14 | var sqliTaint = new SQLITaintSet(SQLITaint.SQL_ALL); 15 | var xsstaint = new XSSTaintSet(XSSTaint.XSS_ALL); 16 | var ts1 = new TaintSets(sqliTaint, xsstaint); 17 | var exprInfo1 = new ExpressionInfo { ExpressionTaint = ts1 }; 18 | var exprInfo2 = new ExpressionInfo(); 19 | 20 | var exprInfo = exprInfo2.Merge(exprInfo1); 21 | 22 | Assert.AreEqual(sqliTaint, exprInfo.ExpressionTaint.SqliTaint.Single(), "SQL Taint was not the expected"); 23 | Assert.AreEqual(xsstaint, exprInfo.ExpressionTaint.XssTaint.Single(), "XSS Taint was not the expected"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/config.yml: -------------------------------------------------------------------------------- 1 | php-settings: 2 | # Path to PHP executable 3 | PHPPath : C:/PHP/php.exe 4 | 5 | # PHP file extensions 6 | PHPExts : 7 | - .php 8 | - .php3 9 | - .php4 10 | - .php5 11 | - .phtml 12 | - .inc 13 | 14 | # Path to PHP parse project (Main.php file) 15 | PHPParsePath : 16 | 17 | graph-settings: 18 | # Path to the graphviz dot convert tool 19 | GraphvizPath : C:\Graphviz-2.38\dot.exe 20 | 21 | # Arguments to the graphviz 22 | GraphvizArguments : -Tpng -O 23 | 24 | component-settings: 25 | # Indicates whether external components should be used 26 | IncludeComponents : True 27 | 28 | # Path to external components. 29 | ComponentFolder : .\Components\ 30 | 31 | func-spec-settings: 32 | # Path array to function specifications 33 | PHPSpecs: 34 | - ???\JsonSpecifications 35 | - ???\StoredSqlProviders 36 | 37 | # Path to extensions specification, can be excluded if not needed 38 | ExtensionSpecs: 39 | - ???\WPSpecifications -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/AnalysisStacks.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using PHPAnalysis.Data; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Analysis.CFG.Taint 6 | { 7 | public sealed class AnalysisStacks 8 | { 9 | /// 10 | /// This stack should always contain the file currently being analyzed. 11 | /// 12 | public Stack IncludeStack { get; private set; } 13 | public Stack CallStack { get; private set; } 14 | 15 | private AnalysisStacks() 16 | { 17 | IncludeStack = new Stack(); 18 | CallStack = new Stack(); 19 | } 20 | 21 | public AnalysisStacks(File initialFile) : this() 22 | { 23 | Preconditions.NotNull(initialFile, "initialFile"); 24 | 25 | IncludeStack.Push(initialFile); 26 | } 27 | 28 | public AnalysisStacks(Stack initialIncludeStack) : this() 29 | { 30 | IncludeStack = initialIncludeStack; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/ProgressIndicatorFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.IO.Cmd 4 | { 5 | internal static class ProgressIndicatorFactory 6 | { 7 | public static ProgressIndicator CreateProgressIndicator(int maxValue) 8 | { 9 | Random rand = new Random(); 10 | int r = rand.Next(); 11 | ProgressIndicator progrssIndicator; 12 | 13 | switch (r % 4) 14 | { 15 | case 0: 16 | progrssIndicator = new BatsFlyingAnimation(maxValue); 17 | break; 18 | case 1: 19 | progrssIndicator = new BikeGuyRidingAnimation(maxValue); 20 | break; 21 | case 2: 22 | progrssIndicator = new ExecutiveDeskToyAnimation(maxValue); 23 | break; 24 | default: 25 | progrssIndicator = new BarIndicator(maxValue); 26 | break; 27 | } 28 | return progrssIndicator; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/QueueWorklist.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using PHPAnalysis.Analysis.CFG.Traversal; 4 | using PHPAnalysis.Data; 5 | using PHPAnalysis.Data.CFG; 6 | 7 | namespace PHPAnalysis.Analysis.CFG 8 | { 9 | public sealed class QueueWorklist : IWorklist 10 | { 11 | private readonly QueueSet queue = new QueueSet(); 12 | private readonly StackSet queue1 = new StackSet(); 13 | 14 | public bool Any() 15 | { 16 | return queue.Any(); 17 | } 18 | 19 | public void Add(CFGBlock elem) 20 | { 21 | queue.Enqueue(elem); 22 | } 23 | 24 | public CFGBlock GetNext() 25 | { 26 | return queue.Dequeue(); 27 | } 28 | 29 | public bool Contains(CFGBlock elem, IEqualityComparer comparer = null) 30 | { 31 | comparer = comparer ?? EqualityComparer.Default; 32 | return queue.Contains(elem, comparer); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/VariableInfoComposer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using PHPAnalysis.Data; 8 | using PHPAnalysis.Data.CFG; 9 | using PHPAnalysis.Utils.XmlHelpers; 10 | 11 | namespace PHPAnalysis.Analysis.CFG 12 | { 13 | public static class VariableInfoComposer 14 | { 15 | public static readonly Dictionary VarInfoStorage = new Dictionary(); 16 | 17 | public static ValueInfo AnalyzeBlock(ValueInfo block) 18 | { 19 | if (block.Block.AstEntryNode == null) 20 | return null; 21 | 22 | if (VarInfoStorage.ContainsKey(block.Block)) 23 | { 24 | return VarInfoStorage[block.Block]; 25 | } 26 | 27 | // type, value, arraytree 28 | var astNode = block.Block.AstEntryNode; 29 | 30 | VarInfoStorage.Add(block.Block, block); 31 | return block; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/AstTraversing/XmlTraverseEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml; 3 | 4 | namespace PHPAnalysis.Parsing.AstTraversing 5 | { 6 | /// 7 | /// Event args used when visiting an individual node in the Xml tree. 8 | /// 9 | public class XmlTraverseEventArgs : EventArgs 10 | { 11 | public XmlNode Node { get; private set; } 12 | public XmlTraverseEventArgs(XmlNode node) 13 | { 14 | this.Node = node; 15 | } 16 | } 17 | 18 | /// 19 | /// Event args used right before the Xml traversal starts. 20 | /// 21 | public class XmlStartTraverseEventArgs : EventArgs 22 | { 23 | new public static readonly XmlStartTraverseEventArgs Empty = new XmlStartTraverseEventArgs(); 24 | } 25 | 26 | /// 27 | /// Event args used after the Xml traversal is finished. 28 | /// 29 | public class XmlEndTraverseEventArgs : EventArgs 30 | { 31 | new public static readonly XmlEndTraverseEventArgs Empty = new XmlEndTraverseEventArgs(); 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Preconditions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace PHPAnalysis.Utils 5 | { 6 | internal static class Preconditions 7 | { 8 | [DebuggerHidden] 9 | public static T NotNull(T parameter, string parameterName) where T : class 10 | { 11 | if (parameter == null) 12 | { 13 | throw new ArgumentNullException(parameterName); 14 | } 15 | return parameter; 16 | } 17 | 18 | [DebuggerHidden] 19 | public static void IsTrue(bool condition, string message = "", string parameterName = "") 20 | { 21 | if ( !condition ) 22 | { 23 | throw new ArgumentException(message, parameterName); 24 | } 25 | } 26 | 27 | [DebuggerHidden] 28 | public static void IsFalse(bool condition, string message = "", string parameterName = "") 29 | { 30 | if (condition) 31 | { 32 | throw new ArgumentException(message, parameterName); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Chikila 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/TestUtils/PHPParseUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using PHPAnalysis.Parsing; 3 | using PHPAnalysis.Parsing.AstTraversing; 4 | 5 | namespace PHPAnalysis.Tests.TestUtils 6 | { 7 | public static class PHPParseUtils 8 | { 9 | public static XmlNode ParsePHPCode(string phpCode, string phpParser) 10 | { 11 | var fileParser = new FileParser(phpParser); 12 | 13 | using (var fileManager = new TempFileManager()) 14 | { 15 | string file = fileManager.WriteContent(phpCode); 16 | var xml = fileParser.ParsePHPFile(file); 17 | return xml; 18 | } 19 | } 20 | 21 | 22 | public static T ParseAndIterate(string phpCode, string phpParser) where T : IXmlVisitor, new() 23 | { 24 | XmlNode ast = ParsePHPCode(phpCode, phpParser); 25 | var traverser = new XmlTraverser(); 26 | var visitor = new T(); 27 | traverser.AddVisitor(visitor); 28 | traverser.Traverse(ast.FirstChild.NextSibling); 29 | return visitor; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Traversal/ITraversalTechnique.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using PHPAnalysis.Data.CFG; 3 | using QuickGraph; 4 | 5 | namespace PHPAnalysis.Analysis.CFG 6 | { 7 | public interface ITraversalTechnique 8 | { 9 | /// 10 | /// Returns the blocks to be used as initial blocks in the traversal. 11 | /// In a normal forward analysis, this should return the root block. 12 | /// 13 | IEnumerable GetStartBlocks(IBidirectionalGraph> graph); 14 | /// 15 | /// Return the next edges to consider in the analysis. 16 | /// 17 | IEnumerable> NextEdges(IBidirectionalGraph> graph, CFGBlock block); 18 | /// 19 | /// Returns the block of interest when looking at a specific edge. 20 | /// E.g. in a forward analysis this would be the edge target. In a backwards analysis it would be the edge source. 21 | /// 22 | CFGBlock EdgeTarget(Edge edge); 23 | } 24 | } -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/commands/ScanCommand.php: -------------------------------------------------------------------------------- 1 | setName('scan') 16 | ->setDescription('Start PHP vulnerability scanning') 17 | ->addArgument('target', InputArgument::REQUIRED, 'Target file/directory of scan.'); 18 | } 19 | 20 | protected function execute(InputInterface $input, OutputInterface $output) { 21 | $target = $input->getArgument('target'); 22 | 23 | if (is_dir($target)) { 24 | $output->writeln("Starting directory scan of " . $target); 25 | } else if (is_file($target)) { 26 | $output->writeln("Starting file scan of " . $target); 27 | } else { 28 | $output->writeln("Target does not seem to be a valid file or directory.."); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/CFGBlock.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Remoting; 3 | using System.Xml; 4 | 5 | namespace PHPAnalysis.Data.CFG 6 | { 7 | public sealed class CFGBlock 8 | { 9 | public bool IsRoot { get; set; } 10 | public bool IsLeaf { get; set; } 11 | public XmlNode AstEntryNode { get; set; } 12 | public bool IsSpecialBlock { get; private set; } 13 | /// 14 | /// Specify whether this node breaks out of the existing scope before the execution 15 | /// reaches the end of the block. E.g. by reaching a break or continue statement. 16 | /// 17 | public bool BreaksOutOfScope { get; set; } 18 | 19 | public CFGBlock(bool isSpecial = false) 20 | { 21 | this.IsSpecialBlock = isSpecial; 22 | } 23 | 24 | public bool CanBeOverridden 25 | { 26 | get { return !IsSpecialBlock && AstEntryNode == null; } 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return AstEntryNode == null ? base.ToString() : AstEntryNode.LocalName; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/IAnalysisStartingListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PHPAnalysis.Components; 3 | using PHPAnalysis.Configuration; 4 | 5 | namespace PHPAnalysis.Analysis 6 | { 7 | public interface IAnalysisStartingListener 8 | { 9 | void AnalysisStarting(object o, AnalysisStartingEventArgs e); 10 | } 11 | 12 | public interface IAnalysisEndedListener 13 | { 14 | void AnalysisEnding(object o, AnalysisEndedEventArgs e); 15 | } 16 | 17 | public sealed class AnalysisEndedEventArgs : EventArgs 18 | { 19 | public TimeSpan TimeElapsed { get; private set; } 20 | 21 | public AnalysisEndedEventArgs(TimeSpan timeElapsed) 22 | { 23 | this.TimeElapsed = timeElapsed; 24 | } 25 | } 26 | 27 | public sealed class AnalysisStartingEventArgs : EventArgs 28 | { 29 | public Config Configuration { get; private set; } 30 | public Arguments Arguments { get; private set; } 31 | 32 | public AnalysisStartingEventArgs(Config config, Arguments arguments) 33 | { 34 | this.Configuration = config; 35 | this.Arguments = arguments; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/TestUtils/TempFileManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace PHPAnalysis.Tests 5 | { 6 | public sealed class TempFileManager : IDisposable 7 | { 8 | private readonly string _folder = Path.GetTempPath(); 9 | private readonly string _file = Path.GetTempFileName(); 10 | 11 | private string FilePath => Path.Combine(_folder, _file); 12 | 13 | private bool _createdFolder = false; 14 | 15 | public string WriteContent(string content) 16 | { 17 | if (!Directory.Exists(_folder)) 18 | { 19 | Directory.CreateDirectory(_folder); 20 | _createdFolder = true; 21 | } 22 | 23 | File.WriteAllText(FilePath, content); 24 | return FilePath; 25 | } 26 | 27 | public void Dispose() 28 | { 29 | if (!File.Exists(FilePath)) { return; } 30 | 31 | if (_createdFolder) 32 | { 33 | Directory.Delete(_folder, true); 34 | } 35 | else 36 | { 37 | File.Delete(FilePath); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/TestUtils/GraphAssertions.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using PHPAnalysis.Data; 3 | using QuickGraph; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using PHPAnalysis.Data.CFG; 10 | 11 | namespace PHPAnalysis.Tests.TestUtils 12 | { 13 | public static class GraphAssertions 14 | { 15 | public static void AssertOutEdges(this BidirectionalGraph> graph, CFGBlock block, int expectedOutEdges, string message = "") 16 | { 17 | IEnumerable> edges; 18 | graph.TryGetOutEdges(block, out edges); 19 | 20 | Assert.AreEqual(expectedOutEdges, edges.Count(), message); 21 | } 22 | public static void AssertInEdges(this BidirectionalGraph> graph, CFGBlock block, int expectedInEdges, string message = "") 23 | { 24 | IEnumerable> edges; 25 | graph.TryGetInEdges(block, out edges); 26 | 27 | Assert.AreEqual(expectedInEdges, edges.Count(), message); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/ExprVarNode.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using PHPAnalysis.Data; 3 | 4 | namespace PHPAnalysis.Utils.XmlHelpers 5 | { 6 | public static class ExprVarNode 7 | { 8 | /// 9 | /// Tries to get the variables name. This will only work if the variable name is static. 10 | /// $var : will be 'var' 11 | /// $$var : will fail. 12 | /// 13 | public static bool TryGetVariableName(XmlNode node, out string varName) 14 | { 15 | Preconditions.NotNull(node, "node"); 16 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Expr_Variable, 17 | "Node has to be an Expression Variable. It was: " + node.Name, "node"); 18 | 19 | var nameNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name); 20 | 21 | if (nameNode.TryGetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.String, out nameNode)) 22 | { 23 | varName = nameNode.InnerText; 24 | return true; 25 | } 26 | varName = null; 27 | return false; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Configuration/ComponentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using PHPAnalysis.Annotations; 7 | using PHPAnalysis.Utils; 8 | 9 | namespace PHPAnalysis.Configuration 10 | { 11 | public sealed class ComponentConfiguration 12 | { 13 | public string ComponentPath { get; private set; } 14 | public bool IncludeComponents { get; private set; } 15 | 16 | public ComponentConfiguration(string componentPath, bool includeComponents) 17 | { 18 | Preconditions.NotNull(componentPath, "componentPath"); 19 | 20 | this.ComponentPath = componentPath; 21 | this.IncludeComponents = includeComponents; 22 | } 23 | 24 | public override string ToString() 25 | { 26 | var sb = new StringBuilder(); 27 | sb.AppendLine("Path: " + this.ComponentPath); 28 | return sb.ToString(); 29 | } 30 | } 31 | 32 | [UsedImplicitly] 33 | internal sealed class ComponentConfigurationMutable 34 | { 35 | public string ComponentFolder { get; set; } 36 | public bool IncludeComponents { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/AstNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using System.Xml.Linq; 8 | using PHPAnalysis.Data; 9 | 10 | namespace PHPAnalysis.Utils.XmlHelpers 11 | { 12 | public static class AstNode 13 | { 14 | public static int GetStartLine(XmlNode node) 15 | { 16 | Preconditions.NotNull(node, "node"); 17 | Preconditions.IsTrue(node.Prefix == AstConstants.Node, "Expected node but received a " + node.Name); 18 | 19 | return GetLine(node, AstConstants.Attributes.StartLine); 20 | } 21 | 22 | public static int GetEndLine(XmlNode node) 23 | { 24 | Preconditions.NotNull(node, "node"); 25 | Preconditions.IsTrue(node.Prefix == AstConstants.Node, "Expected node but received a " + node.Name); 26 | 27 | return GetLine(node, AstConstants.Attributes.EndLine); 28 | } 29 | 30 | private static int GetLine(XmlNode node, string lineType) 31 | { 32 | var line = node.GetSubNode(AstConstants.Attribute + ":" + lineType); 33 | return Convert.ToInt32(line.InnerText); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/Class.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Data.PHP 6 | { 7 | public sealed class Class 8 | { 9 | public XmlNode AstNode { get; set; } 10 | public string Name { get; set; } 11 | public string File { get; set; } 12 | 13 | public IList Properties { get; private set; } 14 | public IList Methods { get; private set; } 15 | 16 | public int StartLine { get; set; } 17 | public int EndLine { get; set; } 18 | 19 | public AstConstants.VisibilityModifiers VisibilityModifiers { get; set; } 20 | 21 | public bool IsFinal 22 | { 23 | get { return (VisibilityModifiers & AstConstants.VisibilityModifiers.Final) != 0; } 24 | } 25 | 26 | public Class(XmlNode node) 27 | { 28 | Preconditions.NotNull(node, "node"); 29 | 30 | this.AstNode = node; 31 | this.Methods = new List(); 32 | this.Properties = new List(); 33 | } 34 | 35 | public override string ToString() 36 | { 37 | return string.Format("Name: {0}, StartLine: {1}, EndLine: {2}", Name, StartLine, EndLine); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/config-template.yml: -------------------------------------------------------------------------------- 1 | php-settings: 2 | # Path to PHP executable 3 | PHPPath : C:/PHP/php.exe 4 | 5 | # PHP file extensions 6 | PHPExts : 7 | - .php 8 | - .php3 9 | - .php4 10 | - .php5 11 | - .phtml 12 | - .inc 13 | 14 | # Path to PHP parse project (Main.php file) 15 | PHPParsePath : D:\Dokumenter\Skolesager\10.-Semester\GIT\PHPAnalysis\PHPAnalysis-parser\src\Main.php 16 | 17 | graph-settings: 18 | # Path to the graphviz dot convert tool 19 | GraphvizPath : C:\Program Files (x86)\Graphviz-2.38\dot.exe 20 | 21 | # Arguments to the graphviz 22 | GraphvizArguments : -Tpng -O 23 | 24 | component-settings: 25 | # Indicates whether external components should be used 26 | IncludeComponents : True 27 | 28 | # Path to external components. 29 | ComponentFolder : .\Components\ 30 | 31 | func-spec-settings: 32 | #Path array to function specifications 33 | PHPSpecs: 34 | - "C:/mmk-php-vuln-scanner/PHPAnalysis/PHPAnalysis/FunctionSpecs/JSONSpecifications" 35 | - "C:/mmk-php-vuln-scanner/PHPAnalysis/PHPAnalysis/FunctionSpecs/StoredSQLProviders" 36 | 37 | #Path to extensions specification, can be excluded if not needed 38 | ExtensionSpecs: 39 | - "C:/mmk-php-vuln-scanner/PHPAnalysis/PHPAnalysis/FunctionSpecs/WPSpecifications" -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Parsing/CFGCreator_SkipElements_Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | using PHPAnalysis.Analysis; 4 | using PHPAnalysis.Data.CFG; 5 | using PHPAnalysis.Parsing; 6 | using PHPAnalysis.Tests.TestUtils; 7 | using PHPAnalysis.Utils; 8 | 9 | namespace PHPAnalysis.Tests.Analysis 10 | { 11 | [TestFixture] 12 | public class CFGCreator_SkipElements_Tests : ConfigDependentTests 13 | { 14 | [TestCase(@"(php, Config.PHPSettings.PHPParserPath); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Components/ComponentContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using PHPAnalysis.Analysis; 3 | using PHPAnalysis.Analysis.CFG.Taint; 4 | using PHPAnalysis.Parsing.AstTraversing; 5 | 6 | namespace PHPAnalysis.Components 7 | { 8 | internal sealed class ComponentContainer 9 | { 10 | public ICollection AstVisitors { get; private set; } 11 | 12 | public ICollection BlockAnalyzers { get; private set; } 13 | 14 | public ICollection VulnerabilityReporters { get; private set; } 15 | 16 | public ICollection TaintProviders { get; private set; } 17 | 18 | public ICollection AnalysisStartingListeners { get; private set; } 19 | 20 | public ICollection AnalysisEndedListeners { get; private set; } 21 | 22 | public ComponentContainer() 23 | { 24 | this.AstVisitors = new List(); 25 | this.BlockAnalyzers = new List(); 26 | this.VulnerabilityReporters = new List(); 27 | this.TaintProviders = new List(); 28 | this.AnalysisStartingListeners = new List(); 29 | this.AnalysisEndedListeners = new List(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Configuration/GraphConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PHPAnalysis.Utils; 3 | using System.Text; 4 | using PHPAnalysis.Annotations; 5 | 6 | namespace PHPAnalysis 7 | { 8 | public sealed class GraphConfiguration 9 | { 10 | public string GraphvizPath { get; private set; } 11 | public string GraphvizArguments { get; private set; } 12 | 13 | public GraphConfiguration(string graphvizPath, string graphvizArguments) 14 | { 15 | Preconditions.NotNull(graphvizPath, "graphvizPath"); 16 | Preconditions.NotNull(graphvizArguments, "graphvizArguments"); 17 | 18 | this.GraphvizPath = graphvizPath; 19 | this.GraphvizArguments = graphvizArguments; 20 | } 21 | 22 | public override string ToString() 23 | { 24 | var stringBuilder = new StringBuilder(); 25 | stringBuilder.AppendLine("[Graph configuration:"); 26 | stringBuilder.AppendLine(" Graphviz path: " + GraphvizPath); 27 | stringBuilder.AppendLine(" Graphviz arguments: " + GraphvizArguments); 28 | stringBuilder.Append("]"); 29 | return stringBuilder.ToString(); 30 | } 31 | } 32 | 33 | [UsedImplicitly] 34 | internal sealed class GraphConfigurationMutable 35 | { 36 | public string GraphvizPath { get; set; } 37 | public string GraphvizArguments { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/ImmutableDictionaryComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | 6 | namespace PHPAnalysis.Utils 7 | { 8 | public sealed class ImmutableDictionaryComparer : IEqualityComparer> 9 | { 10 | private readonly IEqualityComparer valueComparer; 11 | public ImmutableDictionaryComparer(IEqualityComparer valueComparer = null) 12 | { 13 | this.valueComparer = valueComparer ?? EqualityComparer.Default; 14 | } 15 | public bool Equals(IImmutableDictionary first, IImmutableDictionary second) 16 | { 17 | if (first.Count != second.Count) { return false; } 18 | if (first.Keys.Except(second.Keys).Any()) { return false; } 19 | if (second.Keys.Except(first.Keys).Any()) { return false; } 20 | 21 | foreach (var pair in first) 22 | { 23 | if (!valueComparer.Equals(pair.Value, second[pair.Key])) 24 | { 25 | return false; 26 | } 27 | } 28 | return true; 29 | } 30 | 31 | public int GetHashCode(IImmutableDictionary obj) 32 | { 33 | // Required by interface 34 | throw new NotImplementedException(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Extensions/IImmutableExtentions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using System.Linq; 4 | 5 | namespace PHPAnalysis.Utils 6 | { 7 | public static class IImmutableExtentions 8 | { 9 | public static IImmutableSet AddRange(this IImmutableSet collection, IEnumerable toAdd) 10 | { 11 | Preconditions.NotNull(toAdd, "toAdd"); 12 | 13 | return toAdd.Aggregate(collection, (current, element) => current.Add(element)); 14 | } 15 | 16 | public static System.Collections.Immutable.IImmutableDictionary Merge(this System.Collections.Immutable.IImmutableDictionary first, System.Collections.Immutable.IImmutableDictionary second) 17 | where T2 : IMergeable 18 | { 19 | var newDict = first.ToDictionary(x => x.Key, x => x.Value); 20 | foreach (var other in second) 21 | { 22 | T2 set; 23 | if (newDict.TryGetValue(other.Key, out set)) 24 | { 25 | set = set.Merge(other.Value); 26 | newDict[other.Key] = set; 27 | } 28 | else 29 | { 30 | newDict.Add(other.Key, other.Value); 31 | } 32 | } 33 | return ImmutableDictionary.Empty.AddRange(newDict); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/For.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using PHPAnalysis.Data; 8 | using QuickGraph.Algorithms.ShortestPath; 9 | 10 | namespace PHPAnalysis.Utils.XmlHelpers 11 | { 12 | internal static class ForLoop 13 | { 14 | public static XmlNode GetInitNode(XmlNode node) 15 | { 16 | const string initNodeName = AstConstants.Subnode + ":" + AstConstants.Subnodes.Init; 17 | return GetSubNode(node, initNodeName); 18 | } 19 | 20 | public static XmlNode GetConditionNode(XmlNode node) 21 | { 22 | const string conditionNodeName = AstConstants.Subnode + ":" + AstConstants.Subnodes.Cond; 23 | return GetSubNode(node, conditionNodeName); 24 | } 25 | 26 | public static XmlNode GetLoopNode(XmlNode node) 27 | { 28 | const string initNodeName = AstConstants.Subnode + ":" + AstConstants.Subnodes.Loop; 29 | return GetSubNode(node, initNodeName); 30 | } 31 | 32 | private static XmlNode GetSubNode(XmlNode node, string nodeName) 33 | { 34 | Preconditions.NotNull(node, "node"); 35 | Preconditions.IsTrue(node.LocalName == AstConstants.Nodes.Stmt_For, "Expected for-node but got " + node.Name); 36 | 37 | return node.GetSubNode(nodeName); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/AstTraversing/ASTPrinter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Xml; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Parsing.AstTraversing 6 | { 7 | public sealed class ASTPrinter : IXmlVisitor 8 | { 9 | private readonly TextWriter writer; 10 | 11 | private int indentation; 12 | 13 | public ASTPrinter(TextWriter output) 14 | { 15 | Preconditions.NotNull(output, "output"); 16 | 17 | this.writer = output; 18 | } 19 | 20 | 21 | public void TraverseStart(object sender, XmlStartTraverseEventArgs e) 22 | { 23 | } 24 | 25 | public void EnteringNode(object sender, XmlTraverseEventArgs e) 26 | { 27 | var node = e.Node; 28 | var toPrint = string.Format("{0}{1}:{2}:{3} - {4}", new string(' ', indentation), node.NodeType, node.Prefix, node.LocalName, node.Value); 29 | writer.WriteLine(toPrint); 30 | indentation++; 31 | } 32 | 33 | public void LeavingNode(object sender, XmlTraverseEventArgs e) 34 | { 35 | var node = e.Node; 36 | indentation--; 37 | var toPrint = string.Format("{0}{1}:{2}:{3} - {4}", new string(' ', indentation), node.NodeType, node.Prefix, node.LocalName, node.Value); 38 | writer.WriteLine(toPrint); 39 | } 40 | 41 | public void TraverseEnd(object sender, XmlEndTraverseEventArgs e) 42 | { 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/Closure.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | using System.Xml; 4 | using PHPAnalysis.Utils; 5 | 6 | namespace PHPAnalysis.Data.PHP 7 | { 8 | public sealed class Closure 9 | { 10 | public XmlNode AstNode { get; private set; } 11 | public int StartLine { get; set; } 12 | public int EndLine { get; set; } 13 | public string File { get; set; } 14 | public Parameter[] Parameters { get; set; } 15 | public ClosureUse[] UseParameters { get; set; } 16 | 17 | public Closure(XmlNode node) 18 | { 19 | Preconditions.NotNull(node, "node"); 20 | 21 | this.AstNode = node; 22 | Parameters = new Parameter[0]; 23 | UseParameters = new ClosureUse[0]; 24 | } 25 | 26 | public override string ToString() 27 | { 28 | var builder = new StringBuilder("function"); 29 | builder.Append("(") 30 | .Append(string.Join(", ", Parameters)) 31 | .Append(") "); 32 | if (UseParameters.Any()) 33 | { 34 | builder.Append("use (") 35 | .Append(string.Join(", ", UseParameters)) 36 | .Append(") "); 37 | } 38 | 39 | builder.Append(StartLine) 40 | .Append(" ") 41 | .Append(EndLine); 42 | 43 | return builder.ToString(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Utils/XmlHelpers/ScalarNodeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | using System.Xml.XPath; 9 | using NUnit.Framework; 10 | using PHPAnalysis.Data; 11 | using PHPAnalysis.Utils.XmlHelpers; 12 | 13 | namespace PHPAnalysis.Tests.Utils.XmlHelpers 14 | { 15 | [TestFixture] 16 | public class ScalarNodeTests 17 | { 18 | [TestCase(1.1),TestCase(123.1)] 19 | public void DValueResolving(double valueToTest) 20 | { 21 | var node = CreateDValueNodeWithValue(valueToTest); 22 | 23 | double result = ScalarNode.GetDValue(node); 24 | 25 | Assert.AreEqual(valueToTest, result); 26 | } 27 | 28 | private static XmlNode CreateDValueNodeWithValue(double value) 29 | { 30 | var doc = new XmlDocument(); 31 | var node = doc.CreateNode(XmlNodeType.Element, AstConstants.Node, AstConstants.Nodes.Scalar_DNumber, ""); 32 | var valueNode = doc.CreateNode(XmlNodeType.Element, AstConstants.Subnode, AstConstants.Subnodes.Value, ""); 33 | var floatNode = doc.CreateNode(XmlNodeType.Element, AstConstants.Scalar, AstConstants.Scalars.Float, ""); 34 | floatNode.InnerText = value.ToString(CultureInfo.InvariantCulture); 35 | valueNode.AppendChild(floatNode); 36 | node.AppendChild(valueNode); 37 | return node; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PHPAnalysis.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PHPAnalysis.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("56b730c1-f414-4401-9017-64921d754d52")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PHPAnalysis")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PHPAnalysis")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("20ea6434-7f3b-4d4a-85a2-a9dd3187803c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PHPAnalysis/WordPress.Plugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WordPress.Plugin")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("WordPress.Plugin")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ac2b0212-99fa-42d4-8902-37042cb99acb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PHPAnalysis/FileWriter.Plugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FileWriter.Plugin")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("FileWriter.Plugin")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("74954e6e-666a-4ad9-88dc-be07948d02bf")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/Conditional.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using System.Xml.Linq; 8 | using PHPAnalysis.Data; 9 | 10 | namespace PHPAnalysis.Utils.XmlHelpers 11 | { 12 | public static class Conditional 13 | { 14 | private static readonly string[] NodesWithCondSubNode = 15 | { 16 | AstConstants.Nodes.Stmt_Case, 17 | AstConstants.Nodes.Stmt_Do, 18 | AstConstants.Nodes.Stmt_ElseIf, 19 | AstConstants.Nodes.Stmt_For, 20 | AstConstants.Nodes.Stmt_If, 21 | AstConstants.Nodes.Stmt_Switch, 22 | AstConstants.Nodes.Stmt_While, 23 | }; 24 | 25 | public static bool HasConditionNode(XmlNode node) 26 | { 27 | return NodesWithCondSubNode.Contains(node.LocalName); 28 | } 29 | 30 | public static XmlNode GetCondNode(XmlNode node) 31 | { 32 | Preconditions.NotNull(node, "node"); 33 | Preconditions.IsTrue(NodesWithCondSubNode.Contains(node.LocalName), 34 | "Expected node representing conditional statement. Received a " + node.Name); 35 | 36 | return node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Cond); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/AstNodeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using PHPAnalysis.Data; 8 | 9 | namespace PHPAnalysis.Utils.XmlHelpers 10 | { 11 | public static class AstNodeInfo 12 | { 13 | public static XmlNode GetVarNameXmlNode(XmlNode node) 14 | { 15 | Preconditions.NotNull(node, "node"); 16 | var varNode = node; 17 | 18 | while (varNode.HasChildNodes) 19 | { 20 | XmlNode tempNode; 21 | if (varNode.TryGetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var, out tempNode)) 22 | { 23 | varNode = tempNode; 24 | if (tempNode.TryGetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Expr_Variable, out tempNode)) 25 | { 26 | if (tempNode.TryGetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name, out tempNode)) 27 | { 28 | return tempNode; 29 | } 30 | } 31 | } 32 | varNode = varNode.FirstChild; 33 | } 34 | 35 | throw new ArgumentException("Unknown XmlNode structure - Unable to find variable name - Implementation needed"); 36 | } 37 | 38 | public static XmlNode GetValueFromXmlNode(XmlNode node) 39 | { 40 | 41 | 42 | return null; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.PluginInterface/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PHPAnalysis.PluginInterface")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PHPAnalysis.PluginInterface")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5b1ed30b-0f69-4750-a6a0-24409f5afd0a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Analysis/CFG/CFGTraverserTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Moq; 7 | using NUnit.Framework; 8 | using PHPAnalysis.Analysis.CFG; 9 | using PHPAnalysis.Analysis.CFG.Traversal; 10 | using PHPAnalysis.Parsing; 11 | using PHPAnalysis.Tests.TestUtils; 12 | using PHPAnalysis.Utils; 13 | 14 | namespace PHPAnalysis.Tests.Analysis.CFG 15 | { 16 | [TestFixture] 17 | public class CFGTraverserTests 18 | { 19 | [Test] 20 | public void CFGTraverser_ShouldTraverseAllBlocksAtLeastOnce() 21 | { 22 | var analysisMock = new Mock(); 23 | analysisMock.Setup(a => a.Analyze(null)).Returns(false); 24 | 25 | var traverser = new CFGTraverser(new ForwardTraversal(), analysisMock.Object, new QueueWorklist()); 26 | } 27 | } 28 | 29 | [TestFixture] 30 | public sealed class ReversePostOrderTests : ConfigDependentTests 31 | { 32 | [Test] 33 | public void ReversePostOrderAlgorithm1() 34 | { 35 | string phpCode = @"(phpCode, Config.PHPSettings.PHPParserPath).Graph; 47 | new CFGPruner().Prune(cfg); 48 | 49 | //cfg.VisualizeGraph("cfg", Config.GraphSettings); 50 | 51 | var postOrder = new ReversePostOrderAlgorithm(cfg).CalculateReversePostOrder(); 52 | 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Configuration/FuncSpecConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using PHPAnalysis.Annotations; 8 | using PHPAnalysis.Utils; 9 | using YamlDotNet.Serialization; 10 | 11 | namespace PHPAnalysis.Configuration 12 | { 13 | public sealed class FuncSpecConfiguration 14 | { 15 | public IList PHPSpecs { get; private set; } 16 | public IList ExtensionSpecs { get; private set; } 17 | 18 | public FuncSpecConfiguration(IList phpSpecs, IList extensionSpecs) 19 | { 20 | Preconditions.NotNull(phpSpecs, "phpSpecs"); 21 | this.PHPSpecs = phpSpecs; 22 | 23 | this.ExtensionSpecs = extensionSpecs ?? new List(); 24 | } 25 | 26 | public override string ToString() 27 | { 28 | var sb = new StringBuilder(); 29 | sb.AppendLine("PHP specs paths: "); 30 | foreach (var path in PHPSpecs) 31 | { 32 | sb.AppendLine("-" + "".PadLeft(2) + path); 33 | } 34 | sb.AppendLine("Extension paths:"); 35 | foreach (var path in ExtensionSpecs) 36 | { 37 | sb.AppendLine("-" + "".PadLeft(2) + path); 38 | } 39 | return sb.ToString(); 40 | } 41 | } 42 | 43 | [UsedImplicitly] 44 | internal sealed class FuncSpecConfigurationMutable 45 | { 46 | public List PHPSpecs { get; set; } 47 | public List ExtensionSpecs { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/TaintHandlerTaintSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using PHPAnalysis.Data; 4 | using PHPAnalysis.Utils; 5 | 6 | namespace PHPAnalysis.Analysis.CFG 7 | { 8 | public sealed class TaintHandlerTaintSet : IMergeable 9 | { 10 | public IImmutableDictionary Taint { get; private set; } 11 | 12 | public TaintHandlerTaintSet(Dictionary variableTaints) 13 | { 14 | Preconditions.NotNull(variableTaints, "variableTaints"); 15 | 16 | Taint = ImmutableDictionary.Empty; 17 | Taint = Taint.AddRange(variableTaints); 18 | } 19 | public TaintHandlerTaintSet(IImmutableDictionary variableTaint) 20 | { 21 | Preconditions.NotNull(variableTaint, "variableTaint"); 22 | Taint = variableTaint; 23 | } 24 | 25 | public void AddTaintedVar(Variable var, VariableTaint varTaint) 26 | { 27 | Taint = Taint.SetItem(var, varTaint); 28 | } 29 | 30 | public TaintHandlerTaintSet Merge(TaintHandlerTaintSet other) 31 | { 32 | var taintDict = new Dictionary(); 33 | foreach (KeyValuePair variableTaint in Taint) 34 | { 35 | var mergedTaint = variableTaint.Value.Merge(other.Taint[variableTaint.Key]); 36 | taintDict.Add(variableTaint.Key, mergedTaint); 37 | } 38 | 39 | return new TaintHandlerTaintSet(taintDict); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Configuration/PHPConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using System.Text; 5 | using PHPAnalysis.Annotations; 6 | using PHPAnalysis.Utils; 7 | 8 | namespace PHPAnalysis.Configuration 9 | { 10 | public sealed class PHPConfiguration 11 | { 12 | public string PHPPath { get; private set; } 13 | public string PHPParserPath { get; private set; } 14 | public IList PHPFileExtensions { get; private set; } 15 | 16 | public PHPConfiguration(string phpPath, string phpParserPath, IList phpExtensions) 17 | { 18 | Preconditions.NotNull(phpPath, "phpPath"); 19 | Preconditions.NotNull(phpParserPath, "phpParserPath"); 20 | Preconditions.NotNull(phpExtensions, "phpExtensions"); 21 | 22 | this.PHPParserPath = phpParserPath; 23 | this.PHPPath = phpPath; 24 | this.PHPFileExtensions = phpExtensions; 25 | } 26 | 27 | public override string ToString() 28 | { 29 | var stringBuilder = new StringBuilder(); 30 | stringBuilder.AppendLine("PHP Path: " + PHPPath); 31 | stringBuilder.AppendLine("PHP Parser: " + PHPParserPath); 32 | stringBuilder.AppendLine("File extensions: " + string.Join(", ", PHPFileExtensions.ToArray())); 33 | return stringBuilder.ToString(); 34 | } 35 | } 36 | 37 | [UsedImplicitly] 38 | internal sealed class PHPConfigurationMutable 39 | { 40 | public string PHPPath { get; set; } 41 | public List PHPExts { get; set; } 42 | public string PHPParsePath { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/ExecutiveDeskToyAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.IO.Cmd 4 | { 5 | internal class ExecutiveDeskToyAnimation : AnimationIndicator 6 | { 7 | protected override string[] Steps 8 | { 9 | get 10 | { 11 | return new[] { 12 | @"╔════╤╤╤╤════╗" + Environment.NewLine + 13 | @"║ │││ \ ║" + Environment.NewLine + 14 | @"║ │││ O ║" + Environment.NewLine + 15 | @"║ OOO ║", 16 | @"╔════╤╤╤╤════╗" + Environment.NewLine + 17 | @"║ ││││ ║" + Environment.NewLine + 18 | @"║ ││││ ║" + Environment.NewLine + 19 | @"║ OOOO ║", 20 | @"╔════╤╤╤╤════╗" + Environment.NewLine + 21 | @"║ / │││ ║" + Environment.NewLine + 22 | @"║ O │││ ║" + Environment.NewLine + 23 | @"║ OOO ║", 24 | @"╔════╤╤╤╤════╗" + Environment.NewLine + 25 | @"║ ││││ ║" + Environment.NewLine + 26 | @"║ ││││ ║" + Environment.NewLine + 27 | @"║ OOOO ║" 28 | }; 29 | } 30 | } 31 | 32 | protected override string FinalStep 33 | { 34 | get { return Steps[1]; } 35 | } 36 | 37 | public ExecutiveDeskToyAnimation(int max = 100) : base(max) 38 | { 39 | 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/ExpressionInfo.cs: -------------------------------------------------------------------------------- 1 | using PHPAnalysis.Data; 2 | using PHPAnalysis.Utils; 3 | 4 | namespace PHPAnalysis.Analysis.CFG.Taint 5 | { 6 | /// 7 | /// Represents the information being propagated up through the AST when analyzing a CFG block 8 | /// in the taint analysis. 9 | /// 10 | public sealed class ExpressionInfo : IMergeable 11 | { 12 | public TaintSets ExpressionTaint { get; set; } 13 | public StoredVulnInfo ExpressionStoredTaint { get; set; } 14 | public ValueInfo ValueInfo { get; set; } 15 | 16 | public ExpressionInfo() 17 | { 18 | this.ExpressionTaint = new TaintSets().ClearTaint(); 19 | this.ExpressionStoredTaint = new StoredVulnInfo(); 20 | this.ValueInfo = new ValueInfo(); 21 | } 22 | 23 | public ExpressionInfo Merge(ExpressionInfo other) 24 | { 25 | return new ExpressionInfo() 26 | { 27 | ExpressionTaint = this.ExpressionTaint.Merge(other.ExpressionTaint), 28 | ExpressionStoredTaint = this.ExpressionStoredTaint.Merge(other.ExpressionStoredTaint), 29 | ValueInfo = this.ValueInfo.Merge(other.ValueInfo) 30 | }; 31 | } 32 | 33 | public ExpressionInfo AssignmentClone() 34 | { 35 | return new ExpressionInfo() { 36 | ExpressionTaint = this.ExpressionTaint.DeepClone(), 37 | ExpressionStoredTaint = this.ExpressionStoredTaint, // TODO: CLONE! 38 | ValueInfo = this.ValueInfo.AssignmentClone() 39 | }; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /PHPAnalysis-parser/src/commands/CountCommand.php: -------------------------------------------------------------------------------- 1 | setName('count') 18 | ->setDescription('Compute code file statistics (Require CLOC)') 19 | ->addArgument('target', InputArgument::REQUIRED, 'Target directory of scan.') 20 | ->addOption('ext', 'e', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Count files with specified extensions.', null) 21 | //->addOption('subdirs', 'sub', InputOption::VALUE_OPTIONAL, "Include subdirectories when counting.", true); 22 | ; 23 | } 24 | 25 | protected function execute(InputInterface $input, OutputInterface $output) { 26 | $target = $input->getArgument('target'); 27 | 28 | if ( !is_dir($target) ) { 29 | $output->writeln("Error: Target does not seem to be a valid directory.."); 30 | return; 31 | } 32 | 33 | $output->writeln("Starting directory scan of " . $target); 34 | system("cloc " . $target); 35 | 36 | //$output->writeln(iterator_count($this->GetFiles($target))); 37 | //$output->writeln(""); 38 | 39 | //foreach ($this->GetFiles($target) as $file) { 40 | // $output->writeln($file); 41 | //} 42 | } 43 | 44 | private function GetFiles($dir) { 45 | $finder = new Finder(); 46 | return $finder->files()->in($dir); 47 | } 48 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/PrioritizedCompositeAnalysis.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using PHPAnalysis.Data.CFG; 4 | using PHPAnalysis.Utils; 5 | using QuickGraph; 6 | 7 | namespace PHPAnalysis.Analysis.CFG 8 | { 9 | public sealed class PrioritizedCompositeAnalysis : ICFGAnalysis 10 | { 11 | private readonly SortedList _analyses; 12 | 13 | public PrioritizedCompositeAnalysis() 14 | { 15 | this._analyses = new SortedList(); 16 | } 17 | 18 | public void AddAnalysis(ICFGAnalysis analysis, uint priority) 19 | { 20 | Preconditions.NotNull(analysis, "analysis"); 21 | string message = "Two analyses cannot have the same priority (" + priority + ")."; 22 | Preconditions.IsFalse(_analyses.ContainsKey(priority), message, "priority"); 23 | 24 | _analyses.Add(priority, analysis); 25 | } 26 | 27 | public void Initialize(CFGBlock cfgBlock) 28 | { 29 | foreach (var cfgAnalysis in _analyses) 30 | { 31 | cfgAnalysis.Value.Initialize(cfgBlock); 32 | } 33 | } 34 | 35 | public bool Analyze(TaggedEdge edge) 36 | { 37 | var didAnyChange = false; 38 | foreach (var cfgAnalysis in _analyses) 39 | { 40 | if (cfgAnalysis.Value.Analyze(edge)) 41 | { 42 | didAnyChange = true; 43 | } 44 | } 45 | return didAnyChange; 46 | } 47 | 48 | public bool Analyze2(CFGBlock block, IBidirectionalGraph> graph) 49 | { 50 | throw new NotImplementedException(); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/StackSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using PHPAnalysis.Utils; 6 | 7 | namespace PHPAnalysis.Data 8 | { 9 | public sealed class StackSet : ICollection, IReadOnlyCollection 10 | { 11 | private readonly Stack _stack; 12 | private readonly HashSet _set; 13 | 14 | public StackSet() 15 | { 16 | this._stack = new Stack(); 17 | this._set = new HashSet(); 18 | } 19 | 20 | public void Enqueue(T item) 21 | { 22 | if (!_set.Contains(item)) 23 | { 24 | _stack.Push(item); 25 | _set.Add(item); 26 | } 27 | } 28 | 29 | public T Dequeue() 30 | { 31 | if (_stack.IsEmpty()) 32 | { 33 | throw new InvalidOperationException("Stack is empty"); 34 | } 35 | 36 | _set.Remove(_stack.Peek()); 37 | return _stack.Pop(); 38 | } 39 | 40 | public IEnumerator GetEnumerator() 41 | { 42 | return _stack.GetEnumerator(); 43 | } 44 | 45 | IEnumerator IEnumerable.GetEnumerator() 46 | { 47 | return GetEnumerator(); 48 | } 49 | 50 | public void CopyTo(Array array, int index) 51 | { 52 | ((ICollection) _stack).CopyTo(array, index); 53 | } 54 | 55 | public int Count 56 | { 57 | get { return _stack.Count; } 58 | } 59 | 60 | object ICollection.SyncRoot 61 | { 62 | get { return ((ICollection) _stack).SyncRoot; } 63 | } 64 | 65 | bool ICollection.IsSynchronized 66 | { 67 | get { return ((ICollection) _stack).IsSynchronized; } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/BreakContinue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Runtime.CompilerServices; 4 | using System.Xml; 5 | using System.Xml.Linq; 6 | using PHPAnalysis.Data; 7 | 8 | namespace PHPAnalysis.Utils.XmlHelpers 9 | { 10 | internal static class BreakContinue 11 | { 12 | public static readonly int DefaultScopeNumber = 1; 13 | 14 | /// 15 | /// Tries to get the number associated with the break/continue statement. 16 | /// e.g. Continue 3; or Break 10; 17 | /// 18 | public static bool TryGetScopeNumber(XmlNode node, out int scopeNumber) 19 | { 20 | Preconditions.NotNull(node, "node"); 21 | Preconditions.IsTrue(node.LocalName == AstConstants.Nodes.Stmt_Break || 22 | node.LocalName == AstConstants.Nodes.Stmt_Continue, 23 | "Expected a break/continue node, but received a " + node.Name); 24 | 25 | 26 | const int minimumValue = 1; 27 | scopeNumber = minimumValue; 28 | 29 | XDocument xNode = XDocument.Parse(node.OuterXml); 30 | XNamespace nsa = AstConstants.Namespaces.SubNode; 31 | 32 | var numDescendants = xNode.Descendants(nsa + AstConstants.Subnodes.Num) 33 | .SingleOrDefault(); 34 | 35 | if (numDescendants == null) 36 | { 37 | return false; 38 | } 39 | var number = numDescendants.Descendants(nsa + AstConstants.Subnodes.Value) 40 | .Select(n => Convert.ToInt32(n.Value)) 41 | .SingleOrDefault(); 42 | 43 | if (number < minimumValue) 44 | { 45 | return false; 46 | } 47 | 48 | scopeNumber = number; 49 | return true; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/StringAnalysis.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | 9 | namespace PHPAnalysis.Analysis.CFG.Taint 10 | { 11 | public static class StringAnalysis 12 | { 13 | /// 14 | /// Checks whether the given string statement is an SQL insertion statement 15 | /// Examples: INSERT INTO, UPDATE 16 | /// 17 | public static bool IsSQLInsertionStmt(string statement) 18 | { 19 | return statement.ToUpper().StartsWith("INSERT INTO") || statement.ToUpper().StartsWith("UPDATE"); 20 | } 21 | 22 | /// 23 | /// Checks whether the given string statement is an SQL retrieve statement 24 | /// Examples: SELECT 25 | /// 26 | public static bool IsSQLRetrieveStmt(string statement) 27 | { 28 | return statement.ToUpper().StartsWith("SELECT"); 29 | } 30 | 31 | public static string RetrieveSQLTableName(string statement) 32 | { 33 | var result = ""; 34 | if (statement.ToUpper().StartsWith("INSERT INTO")) 35 | { 36 | var rex = new Regex(@"(?i)(?<=\bINSERT INTO\s)[\p{L}_-]+"); 37 | result = rex.Match(statement).Value.ToLower(); 38 | } 39 | else if (statement.ToUpper().StartsWith("UPDATE")) 40 | { 41 | var rex = new Regex(@"(?i)(?<=\bUPDATE\s)[\p{L}_-]+"); 42 | result = rex.Match(statement).Value.ToLower(); 43 | } 44 | else if (statement.ToUpper().StartsWith("SELECT")) 45 | { 46 | var rex = new Regex(@"(?i)(?<=\bFROM\s)[\p{L}_-]+"); 47 | result = rex.Match(statement).Value.ToLower(); 48 | } 49 | 50 | return result; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/IVulnerabilityStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using PHPAnalysis.Analysis.CFG; 8 | using PHPAnalysis.Analysis.CFG.Taint; 9 | using PHPAnalysis.Annotations; 10 | using PHPAnalysis.Data; 11 | using PHPAnalysis.Utils; 12 | 13 | namespace PHPAnalysis.Analysis 14 | { 15 | public interface IVulnerabilityStorage 16 | { 17 | IEnumerable Vulnerabilities { get; } 18 | 19 | void AddVulnerability(IVulnerabilityInfo vulnerabilityInfo); 20 | void AddPossibleStoredVulnerability(IStoredVulnerabilityInfo vulnerabilityInfo); 21 | } 22 | 23 | public interface IVulnerabilityInfo 24 | { 25 | string Message { get; } 26 | ImmutableStack IncludeStack { get; } 27 | 28 | ImmutableStack CallStack { get; } 29 | } 30 | 31 | public interface IStoredVulnerabilityInfo : IVulnerabilityInfo 32 | { 33 | StoredVulnInfo PossibleStoredVuln { get; set; } 34 | VulnType VulnerabilityType { get; set; } 35 | } 36 | public class VulnerabilityInfo : IVulnerabilityInfo 37 | { 38 | public string Message { get; set; } 39 | public ImmutableStack IncludeStack { get; set; } 40 | 41 | public ImmutableStack CallStack { get; set; } 42 | } 43 | public class StoredVulnerabilityInfo : IStoredVulnerabilityInfo 44 | { 45 | public string Message { get; set; } 46 | public ImmutableStack IncludeStack { get; set; } 47 | public ImmutableStack CallStack { get; set; } 48 | 49 | public StoredVulnInfo PossibleStoredVuln { get; set; } 50 | public VulnType VulnerabilityType { get; set; } 51 | } 52 | 53 | [Flags] 54 | public enum VulnType 55 | { 56 | Unknown = 0, 57 | XSS = 1, 58 | SQL = 2, 59 | BOTH = 3, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CompositeVulneribilityReporter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using PHPAnalysis.Analysis.PHPDefinitions; 4 | using PHPAnalysis.Utils; 5 | 6 | namespace PHPAnalysis.Analysis 7 | { 8 | internal sealed class CompositeVulneribilityReporter : IVulnerabilityReporter 9 | { 10 | private readonly ICollection _reporters = new List(); 11 | public uint NumberOfReportedVulnerabilities { get; private set; } 12 | 13 | public CompositeVulneribilityReporter(params IVulnerabilityReporter[] reporters) 14 | { 15 | Preconditions.NotNull(reporters, "reporters"); 16 | _reporters.AddRange(reporters); 17 | } 18 | 19 | public CompositeVulneribilityReporter(IEnumerable reporters) 20 | { 21 | Preconditions.NotNull(reporters, "reporters"); 22 | _reporters.AddRange(reporters); 23 | } 24 | 25 | public void ReportVulnerability(IVulnerabilityInfo vulnerabilityInfo) 26 | { 27 | foreach (var vulnerabilityReporter in _reporters) 28 | { 29 | vulnerabilityReporter.ReportVulnerability(vulnerabilityInfo); 30 | } 31 | 32 | NumberOfReportedVulnerabilities++; 33 | } 34 | 35 | public void ReportStoredVulnerability(IVulnerabilityInfo[] vulnerabilityPathInfos) 36 | { 37 | foreach (var vulnerabilityReporter in _reporters) 38 | { 39 | vulnerabilityReporter.ReportStoredVulnerability(vulnerabilityPathInfos); 40 | } 41 | 42 | NumberOfReportedVulnerabilities++; 43 | } 44 | 45 | public void RegisterFunctionsHandler(FunctionsHandler functionsHandler) 46 | { 47 | foreach (var vulnerabilityReporter in _reporters) 48 | { 49 | vulnerabilityReporter.RegisterFunctionsHandler(functionsHandler); 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/FunctionSpecs/WPSpecifications/wpSQLSanitizers.json: -------------------------------------------------------------------------------- 1 | { 2 | "SQLSanitizersFuncs":[ 3 | { 4 | "name":"esc_sql", 5 | "formats":[ "esc_sql(string)" ], 6 | "totalParameters": 1, 7 | "parameters": [ 8 | { "number":1, "name":"sql", "type":"string", "isReturnValue":true } 9 | ], 10 | "returnType":"string", 11 | "defaultStatus": "None" 12 | }, 13 | { 14 | "name":"wpdb->prepare", 15 | "formats":[ "wpdb->prepare(string, array)" ], 16 | "totalParameters": 2, 17 | "parameters": [ 18 | { "number":1, "name":"query", "type":"string", "isReturnValue":true }, 19 | { "number":2, "name":"value_parameter", "type":"array", "IsVariadic": true, "isReturnValue":false } 20 | ], 21 | "returnType":"string", 22 | "defaultStatus": "SQL_ALL" 23 | }, 24 | { 25 | "name":"checked", 26 | "formats": [ "checked(string, bool, bool)" ], 27 | "totalParameters":3, 28 | "parameters": [ 29 | { "number":1, "name":"string", "type":"string" }, 30 | { "number":2, "name":"string", "type":"bool", "isoptional":true }, 31 | { "number":3, "name":"string", "type":"bool", "isoptional":true } 32 | ], 33 | "returnType":"string", 34 | "defaultStatus":"None" 35 | }, 36 | { 37 | "name":"selected", 38 | "formats": [ "checked(string, bool, bool)" ], 39 | "totalParameters":3, 40 | "parameters": [ 41 | { "number":1, "name":"string", "type":"string" }, 42 | { "number":2, "name":"string", "type":"bool", "isoptional":true }, 43 | { "number":3, "name":"string", "type":"bool", "isoptional":true } 44 | ], 45 | "returnType":"string", 46 | "defaultStatus":"None" 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/FunctionCall.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Xml; 4 | using System.Collections.Generic; 5 | using PHPAnalysis.Analysis.CFG.Taint; 6 | using PHPAnalysis.Data; 7 | 8 | namespace PHPAnalysis 9 | { 10 | public class FunctionCall 11 | { 12 | public string Name { get; set; } 13 | public XmlNode ASTNode { get; set; } 14 | public int StartLine { get; set; } 15 | public int EndLine { get; set; } 16 | public IDictionary Arguments { get; set; } 17 | 18 | public FunctionCall(string name, XmlNode astNode, int start, int end) 19 | { 20 | this.Name = name; 21 | this.ASTNode = astNode; 22 | this.StartLine = start; 23 | this.EndLine = end; 24 | } 25 | 26 | public override string ToString() 27 | { 28 | return string.Format("{0} {1} {2}", Name, StartLine, EndLine); 29 | } 30 | } 31 | 32 | public class MethodCall : FunctionCall 33 | { 34 | public IList ClassNames { get; set; } 35 | public Variable Var { get; set; } 36 | 37 | public MethodCall(string methodName, IList className, XmlNode astNode, int start, int end, Variable variable = null) 38 | : base(methodName, astNode, start, end) 39 | { 40 | this.ClassNames = className; 41 | this.Var = variable; 42 | } 43 | 44 | public string CreateFullMethodName(string className) 45 | { 46 | // HACK - this.Name should NOT already have class name in it! 47 | // It sometimes has because of the way we handle methodnames when extracting/putting into functionhandler. 48 | if (this.Name.Contains("->")) 49 | { 50 | return this.Name; 51 | } 52 | return className + "->" + this.Name; 53 | } 54 | 55 | public override string ToString() 56 | { 57 | return string.Format("[{0}] ->{1}", string.Join(",", ClassNames), base.ToString()); 58 | } 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/AnimationIndicator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace PHPAnalysis.IO.Cmd 5 | { 6 | internal abstract class AnimationIndicator : ProgressIndicator 7 | { 8 | protected abstract string[] Steps { get; } 9 | protected abstract string FinalStep { get; } 10 | public int Max { get; private set; } 11 | public int Min { get; private set; } 12 | 13 | private int _progress = 0; 14 | private int counter = 0; 15 | private Timer timer; 16 | private readonly int _cursorTopStart; 17 | 18 | protected AnimationIndicator(int max = 100) 19 | { 20 | this.Min = 0; 21 | this.Max = max; 22 | if (Console.CursorLeft != 0) 23 | Console.WriteLine(); 24 | this._cursorTopStart = Console.CursorTop; 25 | } 26 | 27 | public override sealed void Step() 28 | { 29 | if (_progress >= Max) { return; } 30 | if (counter == 0) 31 | { 32 | timer = new Timer(RunAnimation, null, 0, 250); 33 | } 34 | 35 | _progress++; 36 | Stepped(_progress); 37 | if (_progress == Max) 38 | { 39 | timer.Dispose(); 40 | Console.SetCursorPosition(0, _cursorTopStart); 41 | Console.Write(FinalStep); 42 | Console.Write(" " + (int)PercentOf(_progress, Max) + "%"); 43 | Console.Write(Environment.NewLine); 44 | } 45 | } 46 | 47 | private void RunAnimation(object stateInfo) 48 | { 49 | Console.SetCursorPosition(0, _cursorTopStart); 50 | counter++; 51 | Console.Write(Steps[counter % Steps.Length]); 52 | Console.Write(" " + (int)PercentOf(_progress, Max) + "%"); 53 | } 54 | 55 | private static float PercentOf(int value, int target) 56 | { 57 | return ((value / (float)target) * 100); 58 | } 59 | 60 | protected virtual void Stepped(int progress) { } 61 | } 62 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/BarIndicator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.IO.Cmd 4 | { 5 | internal sealed class BarIndicator : ProgressIndicator 6 | { 7 | public int Max { get; private set; } 8 | public int Min { get; private set; } 9 | 10 | private readonly int _barWidth; 11 | private int _progress = 0; 12 | 13 | private int ProgressPosition { get { return _barWidth + 3; } } 14 | 15 | public BarIndicator(int max = 100) 16 | { 17 | this.Min = 0; 18 | this.Max = max; 19 | this._barWidth = 32; 20 | } 21 | 22 | public override void Step() 23 | { 24 | if (_progress >= Max) { return; } 25 | 26 | _progress++; 27 | UpdateProgress(_progress, Max); 28 | if (_progress == Max) 29 | { 30 | System.Console.Write(Environment.NewLine); 31 | } 32 | } 33 | 34 | private void UpdateProgress(int progress, int total) 35 | { 36 | DrawEmptyProgressBar(); 37 | System.Console.CursorLeft = 1; 38 | 39 | DrawBar(progress, total); 40 | 41 | DrawProcent(progress, total); 42 | } 43 | 44 | private void DrawBar(int progress, int total) 45 | { 46 | System.Console.CursorLeft = 1; 47 | 48 | float howManyToPrint = (progress / (float)total) * (_barWidth - 2); 49 | 50 | System.Console.Write(new string('#', (int)howManyToPrint)); 51 | 52 | } 53 | 54 | private void DrawEmptyProgressBar() 55 | { 56 | System.Console.CursorLeft = 0; 57 | System.Console.Write("[" + new string('-', _barWidth - 2) + "]"); 58 | } 59 | 60 | private void DrawProcent(int progress, int total) 61 | { 62 | System.Console.CursorLeft = ProgressPosition; 63 | System.Console.Write((int)PercentOf(progress, total) + "%"); 64 | } 65 | 66 | private float PercentOf(int value, int target) 67 | { 68 | return ((value / (float)target) * 100); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /PHPAnalysis/WordPress.Plugin/WpTaintProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.Composition; 3 | using System.Linq; 4 | using PHPAnalysis; 5 | using PHPAnalysis.Analysis; 6 | using PHPAnalysis.Analysis.CFG; 7 | using PHPAnalysis.Analysis.CFG.Taint; 8 | using PHPAnalysis.Data; 9 | using PHPAnalysis.Utils; 10 | 11 | namespace WordPress.Plugin 12 | { 13 | [Export(typeof (ITaintProvider))] 14 | public sealed class WpTaintProvider : ITaintProvider 15 | { 16 | public ImmutableVariableStorage GetTaint() 17 | { 18 | var defaultTaint = new DefaultTaintProvider().GetTaint(); 19 | 20 | var variableStorage = defaultTaint.ToMutable(); 21 | 22 | foreach (var superGlobal in variableStorage.SuperGlobals) 23 | { 24 | foreach (var var in superGlobal.Value.Info.Variables) 25 | { 26 | var newTaint = var.Value.Info.Taints.DeepClone(); 27 | if (newTaint.SqliTaint.Single().TaintTag > SQLITaint.SQL_NoQ) 28 | { 29 | newTaint.SqliTaint.Clear(); 30 | newTaint.SqliTaint.Add(new SQLITaintSet( SQLITaint.SQL_NoQ)); 31 | } 32 | 33 | var.Value.Info.Taints = newTaint; 34 | var.Value.Info.DefaultDimensionTaintFactory = () => 35 | new TaintSets(new SQLITaintSet(SQLITaint.SQL_NoQ), new XSSTaintSet(XSSTaint.XSS_ALL)); 36 | var.Value.Info.NestedVariableDefaultTaintFactory = var.Value.Info.DefaultDimensionTaintFactory; 37 | } 38 | } 39 | 40 | var wpdbGlobal = new Variable("wpdb", VariableScope.File); 41 | var prefixVar = new Variable("prefix", VariableScope.Instance) { Info = { Value = "Eir_" } }; 42 | wpdbGlobal.Info.Variables.Add(new VariableTreeDimension() { Key = "prefix" }, prefixVar); 43 | wpdbGlobal.Info.ClassNames.Add("wpdb"); 44 | 45 | variableStorage.GlobalVariables.Add("wpdb", wpdbGlobal); 46 | 47 | return ImmutableVariableStorage.CreateFromMutable(variableStorage); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Parsing/CFGCreator_Case_Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | using PHPAnalysis.Analysis; 4 | using PHPAnalysis.Parsing; 5 | using PHPAnalysis.Tests.TestUtils; 6 | 7 | namespace PHPAnalysis.Tests.Analysis 8 | { 9 | class CFGCreator_Case_Tests : ConfigDependentTests 10 | { 11 | [TestCase(@"(php, Config.PHPSettings.PHPParserPath); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/XmlHelpers/ScalarNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Runtime.InteropServices.ComTypes; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | using PHPAnalysis.Data; 9 | 10 | namespace PHPAnalysis.Utils.XmlHelpers 11 | { 12 | public static class ScalarNode 13 | { 14 | public static string GetStringValue(XmlNode node) 15 | { 16 | Preconditions.NotNull(node, "node"); 17 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_String, "String value retrieval only supported for " + AstConstants.Nodes.Scalar_String + " nodes. Was " + node.Name, "node"); 18 | 19 | return node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) 20 | .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.String).InnerText; 21 | } 22 | 23 | public static int GetLValue(XmlNode node) 24 | { 25 | Preconditions.NotNull(node, "node"); 26 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_LNumber, "LValue retrieval only supported for " + AstConstants.Nodes.Scalar_LNumber + " nodes. Was " + node.Name, "node"); 27 | 28 | var innerText = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) 29 | .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Int).InnerText; 30 | 31 | return int.Parse(innerText); 32 | } 33 | 34 | public static double GetDValue(XmlNode node) 35 | { 36 | Preconditions.NotNull(node, "Node"); 37 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_DNumber, "DValue retrieval only supported for " + AstConstants.Nodes.Scalar_DNumber + " nodes. Was " + node.Name, "node"); 38 | 39 | var innerText = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) 40 | .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Float).InnerText; 41 | 42 | return double.Parse(innerText, CultureInfo.InvariantCulture); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/CFGASTNodeVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml; 4 | using PHPAnalysis.Data; 5 | using PHPAnalysis.Parsing.AstTraversing; 6 | 7 | namespace PHPAnalysis.Analysis.CFG 8 | { 9 | class CFGASTNodeVisitor : IXmlVisitor 10 | { 11 | public List NodesOfInterest; 12 | public void TraverseStart(object sender, XmlStartTraverseEventArgs e) 13 | { 14 | NodesOfInterest = new List(); 15 | } 16 | 17 | public void EnteringNode(object sender, XmlTraverseEventArgs e) 18 | { 19 | var node = e.Node; 20 | switch (node.LocalName) 21 | { 22 | case AstConstants.Nodes.Expr_Assign: 23 | NodesOfInterest.Add(node); 24 | break; 25 | case AstConstants.Nodes.Expr_AssignOp_BitwiseAnd: 26 | case AstConstants.Nodes.Expr_AssignOp_BitwiseOr: 27 | case AstConstants.Nodes.Expr_AssignOp_BitwiseXor: 28 | case AstConstants.Nodes.Expr_AssignOp_Concat: 29 | case AstConstants.Nodes.Expr_AssignOp_Div: 30 | case AstConstants.Nodes.Expr_AssignOp_Minus: 31 | case AstConstants.Nodes.Expr_AssignOp_Mod: 32 | case AstConstants.Nodes.Expr_AssignOp_Mul: 33 | case AstConstants.Nodes.Expr_AssignOp_Plus: 34 | case AstConstants.Nodes.Expr_AssignOp_Pow: 35 | case AstConstants.Nodes.Expr_AssignOp_ShiftLeft: 36 | case AstConstants.Nodes.Expr_AssignOp_ShiftRight: 37 | case AstConstants.Nodes.Expr_AssignRef: 38 | break; 39 | case AstConstants.Nodes.Stmt_Echo: 40 | break; 41 | case AstConstants.Nodes.Expr_ShellExec: 42 | break; 43 | case AstConstants.Nodes.Expr_Eval: 44 | break; 45 | } 46 | } 47 | 48 | public void LeavingNode(object sender, XmlTraverseEventArgs e) 49 | { 50 | 51 | } 52 | 53 | public void TraverseEnd(object sender, XmlEndTraverseEventArgs e) 54 | { 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/ProjectParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Xml; 7 | using PHPAnalysis.Configuration; 8 | using PHPAnalysis.IO.Cmd; 9 | using PHPAnalysis.Utils; 10 | 11 | namespace PHPAnalysis.Parsing 12 | { 13 | public sealed class ProjectParser 14 | { 15 | private string ProjectPath { get; set; } 16 | private PHPConfiguration PHPSettings { get; set; } 17 | 18 | public ProjectParser(string projectPath, PHPConfiguration settings) 19 | { 20 | Preconditions.NotNull(projectPath, "projectPath"); 21 | Preconditions.NotNull(settings, "settings"); 22 | 23 | PHPSettings = settings; 24 | 25 | if (!Directory.Exists(projectPath)) 26 | { 27 | string errorMsg = "Directory does not exist. (" + projectPath + ")"; 28 | throw new DirectoryNotFoundException(errorMsg); 29 | } 30 | 31 | this.ProjectPath = projectPath; 32 | } 33 | 34 | public ParseResult ParseProjectFiles() 35 | { 36 | IEnumerable files = Directory.GetFiles(ProjectPath, "*", SearchOption.AllDirectories) 37 | .Where(file => PHPSettings.PHPFileExtensions.Contains(Path.GetExtension(file))) 38 | .Select(file => file.Replace(@"\\", @"\")); 39 | 40 | var result = new ParseResult(); 41 | 42 | var phpFileParser = new FileParser(PHPSettings.PHPParserPath); 43 | 44 | var progrssIndicator = ProgressIndicatorFactory.CreateProgressIndicator(files.Count()); 45 | 46 | foreach (var file in files) 47 | { 48 | progrssIndicator.Step(); 49 | try 50 | { 51 | XmlDocument parseResult = phpFileParser.ParsePHPFile(file); 52 | result.ParsedFiles.Add(file, parseResult); 53 | } 54 | catch (XmlException) 55 | { 56 | result.FilesThatFailedToParse.Add(file); 57 | } 58 | } 59 | return result; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/IO/Cmd/BikeGuyRidingAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis.IO.Cmd 4 | { 5 | internal class BikeGuyRidingAnimation : AnimationIndicator 6 | { 7 | private string[] UseThisStep { get; set; } 8 | private int Progrezz { get; set; } 9 | protected override string[] Steps 10 | { 11 | get { return DoBikeGuy(); } 12 | } 13 | 14 | protected override string FinalStep 15 | { 16 | get 17 | { 18 | var indentation = new string(' ', GetBikePosition()); 19 | return indentation + @" PHEW- o " + Environment.NewLine + 20 | indentation + @" _ \<,_" + Environment.NewLine + 21 | indentation + @" (*)| (*)"; 22 | } 23 | } 24 | 25 | public BikeGuyRidingAnimation(int max = 100) 26 | : base(max) 27 | { 28 | UseThisStep = new[] {@" 29 | ---------- __o 30 | -------- _ \<,_ 31 | ------- (*)/ (*)",@" 32 | ---------- __o 33 | -------- _ \<,_ 34 | ------- (*) \(*)", 35 | }; 36 | } 37 | 38 | private string[] DoBikeGuy() 39 | { 40 | var indentation = new string(' ', GetBikePosition()); 41 | UseThisStep = new[] { indentation + @" ---------- __o" + Environment.NewLine + 42 | indentation + @" -------- _ \<,_" + Environment.NewLine + 43 | indentation + @"------- (*)/ (*)", 44 | indentation + @" ---------- __o" + Environment.NewLine + 45 | indentation + @" -------- _ \<,_" + Environment.NewLine + 46 | indentation + @"------- (*) \(*)", 47 | }; 48 | 49 | return UseThisStep; 50 | } 51 | 52 | protected override void Stepped(int progress) 53 | { 54 | Progrezz = progress; 55 | } 56 | 57 | private int GetBikePosition() 58 | { 59 | int windowWidth = System.Console.WindowWidth - 25; 60 | int i = (int)((Progrezz / (float)Max) * windowWidth); 61 | return i; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Parsing/CFGCreator_If_Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NUnit.Framework; 7 | using PHPAnalysis.Analysis; 8 | using PHPAnalysis.Configuration; 9 | using PHPAnalysis.Parsing; 10 | using PHPAnalysis.Tests.TestUtils; 11 | 12 | namespace PHPAnalysis.Tests.Analysis 13 | { 14 | [TestFixture] 15 | public class CFGCreator_If_Tests : ConfigDependentTests 16 | { 17 | [Test] 18 | public void CFGCreation_StandardIf() 19 | { 20 | #region PHP Code 21 | string phpCode = @"(php, Config.PHPSettings.PHPParserPath); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/File.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.IO; 5 | using System.Xml; 6 | using PHPAnalysis.Data.CFG; 7 | using PHPAnalysis.Data.PHP; 8 | using PHPAnalysis.Utils; 9 | using QuickGraph; 10 | 11 | namespace PHPAnalysis.Data 12 | { 13 | public sealed class File 14 | { 15 | public XmlNode AstNode { get; private set; } 16 | public string FullPath { get; set; } 17 | public string Name { get { return Path.GetFileName(FullPath); } } 18 | 19 | public string Extension { get { return Path.GetExtension(FullPath); } } 20 | 21 | 22 | public IDictionary> Functions { get; set; } 23 | //public IReadOnlyDictionary Functions 24 | //{ 25 | // get { return new ReadOnlyDictionary(_functions); } 26 | //} 27 | 28 | public IDictionary> Classes { get; set; } 29 | //public IReadOnlyDictionary Classes 30 | //{ 31 | // get { return new ReadOnlyDictionary(_classes); } 32 | //} 33 | 34 | public IDictionary> Interfaces { get; set; } 35 | public Closure[] Closures { get; set; } 36 | public IBidirectionalGraph> CFG { get; set; } 37 | 38 | public File() 39 | { 40 | this.Functions = new Dictionary>(); 41 | this.Classes = new Dictionary>(); 42 | this.Interfaces = new Dictionary>(); 43 | } 44 | 45 | public File(XmlNode node) : this() 46 | { 47 | Preconditions.NotNull(node, "node"); 48 | 49 | this.AstNode = node; 50 | } 51 | 52 | public File(IDictionary> functions, IDictionary> classes) 53 | { 54 | Preconditions.NotNull(functions, "functions"); 55 | Preconditions.NotNull(classes, "classes"); 56 | 57 | this.Functions = functions; 58 | this.Classes = classes; 59 | } 60 | 61 | public override string ToString() 62 | { 63 | return this.Name; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Analysis/AST/IncludeResolvertTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml; 7 | using Moq; 8 | using NUnit.Framework; 9 | using PHPAnalysis.Analysis; 10 | using PHPAnalysis.Analysis.AST; 11 | using PHPAnalysis.Analysis.CFG; 12 | using PHPAnalysis.Analysis.CFG.Taint; 13 | using PHPAnalysis.Analysis.CFG.Traversal; 14 | using PHPAnalysis.Data; 15 | using PHPAnalysis.Parsing; 16 | using PHPAnalysis.Tests.TestUtils; 17 | using PHPAnalysis.Utils.XmlHelpers; 18 | 19 | namespace PHPAnalysis.Tests.Analysis.AST 20 | { 21 | [TestFixture] 22 | public class IncludeResolvertTests : ConfigDependentTests 23 | { 24 | [TestCase(@" new File() {FullPath = f}).ToList()); 35 | 36 | var ast = PHPParseUtils.ParsePHPCode(phpCode, Config.PHPSettings.PHPParserPath); 37 | 38 | ast.IterateAllNodes(node => 39 | { 40 | if (node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Expr_Include) 41 | { 42 | File file; 43 | if (includeResolver.TryResolveInclude(node, out file)) 44 | { 45 | Assert.IsTrue(shouldResolve); 46 | } 47 | else 48 | { 49 | Assert.IsFalse(shouldResolve); 50 | } 51 | } 52 | return true; 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/QueueSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using PHPAnalysis.Utils; 5 | 6 | namespace PHPAnalysis.Data 7 | { 8 | public sealed class QueueSet : ICollection, IReadOnlyCollection 9 | { 10 | private readonly Queue _queue; 11 | private readonly HashSet _set; 12 | 13 | public QueueSet() 14 | { 15 | this._queue = new Queue(); 16 | this._set = new HashSet(); 17 | } 18 | 19 | /// 20 | /// If item already exist it will not be inserted. 21 | /// 22 | /// 23 | public void Enqueue(T item) 24 | { 25 | if (!_set.Contains(item)) 26 | { 27 | _queue.Enqueue(item); 28 | _set.Add(item); 29 | } 30 | } 31 | 32 | public T Dequeue() 33 | { 34 | if (_queue.IsEmpty()) 35 | { 36 | throw new InvalidOperationException("Queue is empty"); 37 | } 38 | _set.Remove(_queue.Peek()); 39 | return _queue.Dequeue(); 40 | } 41 | 42 | public bool Contains(T item) 43 | { 44 | return _set.Contains(item); 45 | } 46 | 47 | public void Clear() 48 | { 49 | _set.Clear(); 50 | _queue.Clear(); 51 | } 52 | 53 | public IEnumerator GetEnumerator() 54 | { 55 | return _queue.GetEnumerator(); 56 | } 57 | 58 | IEnumerator IEnumerable.GetEnumerator() 59 | { 60 | return GetEnumerator(); 61 | } 62 | 63 | void ICollection.CopyTo(Array array, int index) 64 | { 65 | ((ICollection) _queue).CopyTo(array, index); 66 | } 67 | 68 | public void CopyTo(T[] array, int index) 69 | { 70 | _queue.CopyTo(array, index); 71 | } 72 | 73 | public int Count 74 | { 75 | get { return _queue.Count; } 76 | } 77 | 78 | object ICollection.SyncRoot 79 | { 80 | get { return ((ICollection)_queue).SyncRoot; } 81 | } 82 | 83 | bool ICollection.IsSynchronized 84 | { 85 | get { return ((ICollection)_queue).IsSynchronized; } 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/PHPDefinitions/Source.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Linq; 5 | using PHPAnalysis.Analysis.CFG; 6 | 7 | namespace PHPAnalysis 8 | { 9 | public class Source 10 | { 11 | public string Name { get; set; } 12 | public string Type { get; set; } 13 | public List Formats { get; set; } 14 | public XSSTaintSet XssTaint { get; set; } 15 | public SQLITaintSet SqliTaint { get; set; } 16 | 17 | public Source(string json) : this(JToken.Parse(json)) 18 | { 19 | //Nothing! Just enabling both string and JToken version of ctor 20 | } 21 | 22 | public Source(JToken JSON) 23 | { 24 | Name = (string)JSON.SelectToken(Keys.PHPDefinitionJSONKeys.GeneralKeys.Name); 25 | Type = (string)JSON.SelectToken(Keys.PHPDefinitionJSONKeys.GeneralKeys.Type); 26 | var xssTaintStr = (string)JSON.SelectToken(Keys.PHPDefinitionJSONKeys.GeneralKeys.XssTaint); 27 | var sqlTaintStr = (string)JSON.SelectToken(Keys.PHPDefinitionJSONKeys.GeneralKeys.SqlTaint); 28 | 29 | //Set up XSS taint from JSON, if it cannot be parsed, then use the default XSS_ALL tag 30 | XSSTaint tmpXss = XSSTaint.XSS_ALL; 31 | var success = Enum.TryParse(xssTaintStr, out tmpXss); 32 | if (success) 33 | { 34 | XssTaint = new XSSTaintSet(tmpXss); 35 | } 36 | else 37 | { 38 | XssTaint = new XSSTaintSet(XSSTaint.XSS_ALL); 39 | } 40 | 41 | //Set up SQL taint from JSON. If it cannot be parsed then use the default SQL_ALL tag. 42 | SQLITaint tmpSqli = SQLITaint.SQL_ALL; 43 | success = Enum.TryParse(sqlTaintStr, out tmpSqli); 44 | if (success) 45 | { 46 | SqliTaint = new SQLITaintSet(tmpSqli); 47 | } 48 | else 49 | { 50 | SqliTaint = new SQLITaintSet(SQLITaint.SQL_ALL); 51 | } 52 | 53 | Formats = new List(); 54 | var formats = (JArray)JSON.SelectToken(Keys.PHPDefinitionJSONKeys.GeneralKeys.Formats); 55 | foreach (string format in formats) 56 | { 57 | Formats.Add(format); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/FunctionSpecs/JSONSpecifications/CondSanitizers.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConditionSanitizerFuncs": 3 | [ 4 | { 5 | "name":"is_bool", 6 | "formats": [ "is_bool(bool)" ], 7 | "totalParameters":1, 8 | "parameters": [ 9 | { "number":1, "name":"bool", "type":"object" } 10 | ], 11 | "returnType":"bool", 12 | "defaultStatus":"XSSSQL_SAFE" 13 | }, 14 | { 15 | "name":"is_int", 16 | "formats": [ "is_int(int)" ], 17 | "aliases": [ "is_integer", "is_long" ], 18 | "totalParameters":1, 19 | "parameters": [ 20 | { "number":1, "name":"int", "type":"object" } 21 | ], 22 | "returnType":"bool", 23 | "defaultStatus":"XSSSQL_SAFE" 24 | }, 25 | { 26 | "name":"is_float", 27 | "formats": [ "is_float(float)" ], 28 | "aliases": [ "is_double", "is_real" ], 29 | "totalParameters":1, 30 | "parameters": [ 31 | { "number":1, "name":"float", "type":"object" } 32 | ], 33 | "returnType":"bool", 34 | "defaultStatus":"XSSSQL_SAFE" 35 | }, 36 | { 37 | "name":"is_numeric", 38 | "formats": [ "is_numeric(number)" ], 39 | "totalParameters":1, 40 | "parameters": [ 41 | { "number":1, "name":"number", "type":"object" } 42 | ], 43 | "returnType":"bool", 44 | "defaultStatus":"XSSSQL_SAFE" 45 | }, 46 | { 47 | "name":"is_float", 48 | "formats": [ "is_null(object)" ], 49 | "totalParameters":1, 50 | "parameters": [ 51 | { "number":1, "name":"object", "type":"object" } 52 | ], 53 | "returnType":"bool", 54 | "defaultStatus":"XSSSQL_SAFE" 55 | }, 56 | { 57 | "name":"ctype_alnum", 58 | "formats": [ "ctype_alnum(string)" ], 59 | "totalParameters":1, 60 | "parameters": [ 61 | { "number":1, "name":"text", "type":"string" } 62 | ], 63 | "returnType":"bool", 64 | "defaultStatus":"XSSSQL_SAFE" 65 | }, 66 | { 67 | "name":"ctype_digit", 68 | "formats":[ "ctype_digit(string)" ], 69 | "aliases": [ "ctype_xdigit" ], 70 | "totalParameters":1, 71 | "parameters": [ 72 | { "number":1, "name":"object", "type":"string" } 73 | ], 74 | "returnType":"bool", 75 | "defaultStatus":"XSSSQL_SAFE" 76 | }, 77 | { 78 | "name":"ctype_space", 79 | "formats": [ "ctype_space(string)" ], 80 | "totalParameters":1, 81 | "parameters": [ 82 | { "number":1, "name":"text", "type":"string" } 83 | ], 84 | "returnType":"bool", 85 | "defaultStatus":"XSSSQL_SAFE" 86 | } 87 | ] 88 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Arguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using CommandLine; 4 | using CommandLine.Text; 5 | using PHPAnalysis.Annotations; 6 | 7 | namespace PHPAnalysis 8 | { 9 | public sealed class Arguments 10 | { 11 | private const string TargetHelpText = "Directory or file to be analyzed."; 12 | private const string ScanAllSubroutinesHelpText = 13 | "If set, analysis will scan all subroutines (methods + functions), " + 14 | "no matter if they are called or not."; 15 | 16 | private const string SummaryHelpText = "If set, analysis will generate summaries of " + 17 | "subroutines and use those when seing a call to a subroutine. (Warning: This will " + 18 | "decrease analysis precision)"; 19 | 20 | private const string ConfigLocHelpText = "If set, the analysis will read the given config file " + 21 | ", instead of defaulting to the one in the running folder. Use this if you encounter " + 22 | "problems with finding the Config.yml file. Usage: Full path and filename to Config.yml file"; 23 | 24 | [Option('t', "target", Required = true, HelpText = TargetHelpText)] 25 | public string Target { get; set; } 26 | 27 | [Option('a', "all", DefaultValue = false, HelpText = ScanAllSubroutinesHelpText)] 28 | public bool ScanAllSubroutines { get; set; } 29 | 30 | [Option('s', "summaries", DefaultValue = false, HelpText = SummaryHelpText)] 31 | public bool UseFunctionSummaries { get; set; } 32 | 33 | [Option('c', "configlocation", HelpText = ConfigLocHelpText)] 34 | public string ConfigLocation { get; set; } 35 | 36 | [ParserState] 37 | public IParserState LastParserState { get; set; } 38 | 39 | [HelpOption, UsedImplicitly] 40 | public string GetUsage() 41 | { 42 | var helpText = HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current)); 43 | helpText.Heading = new HeadingInfo("Eir", "0.0.1"); 44 | helpText.Copyright = new CopyrightInfo(" ", 2015); 45 | helpText.AdditionalNewLineAfterOption = true; 46 | helpText.AddPreOptionsLine("---------------------"); 47 | helpText.AddPreOptionsLine("Usage: PhpAnalyzer -t [Directory/File] [Options]"); 48 | helpText.AddPreOptionsLine(" : PhpAnalyzer [Options] -t [Directory/File]"); 49 | return helpText; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/FunctionSpecs/JSONSpecifications/XSSSinks.json: -------------------------------------------------------------------------------- 1 | { 2 | "XssSinkFuncs":[ 3 | { 4 | "name":"print", 5 | "formats":[ "print(string)", "printf string" ], 6 | "totalParameters":1, 7 | "parameters": [ 8 | { "number":1, "type":"string", "name":"arg" }, 9 | ], 10 | "defaultOutput":true, 11 | "returnType":"int", 12 | "defaultStatus":"XSS_ALL" 13 | }, 14 | { 15 | "name":"printf", 16 | "formats":[ "printf(string, mix)" ], 17 | "totalParameters":2, 18 | "parameters": [ 19 | { "number":1, "type":"string", "name":"format" }, 20 | { "number":2, "type":"mix", "name":"...", "IsVariadic":true} 21 | ], 22 | "defaultOutput":true, 23 | "returnType":"int", 24 | "defaultStatus":"XSS_ALL" 25 | }, 26 | { 27 | "name":"vprintf", 28 | "formats":[ "vsprintf(string, mix)" ], 29 | "totalParameters":2, 30 | "parameters": [ 31 | { "number":1, "type":"string", "name":"format" }, 32 | { "number":2, "type":"mix", "name":"arg", "IsVariadic":false} 33 | ], 34 | "defaultOutput":true, 35 | "returnType":"string", 36 | "defaultStatus":"XSS_ALL" 37 | }, 38 | { 39 | "name":"print_r", 40 | "formats":[ "print_r(mix, bool)", "print_r(mix)" ], 41 | "totalParameters":2, 42 | "parameters": [ 43 | { "number":1, "type":"mix", "name":"expression" }, 44 | { "number":2, "type":"bool", "name":"return", "optional":true, "values": [ 45 | {"value":true, "outputs":false }, 46 | {"value":false, "outputs":true } 47 | ] 48 | } 49 | ], 50 | "defaultOutput":true, 51 | "returnType":"string", 52 | "defaultStatus":"XSS_ALL" 53 | }, 54 | { 55 | "name":"die", 56 | "formats":[ "die(string)", "die(int)" ], 57 | "aliases": [ "exit" ], 58 | "totalParameters":1, 59 | "parameters": [ 60 | { "number":1, "type":"mix", "name":"status" } 61 | ], 62 | "defaultOutput":true, 63 | "returnType":"void", 64 | "defaultStatus":"XSS_ALL" 65 | }, 66 | { 67 | "name":"var_export", 68 | "formats":[ "var_export(mix)" ], 69 | "totalParameters":2, 70 | "parameters": [ 71 | { "number":1, "type":"mix", "name":"expression" }, 72 | { "number":2, "type":"bool", "name":"return", "values": [ 73 | {"value":true, "outputs":false }, 74 | {"value":false, "outputs":true } 75 | ] 76 | } 77 | ], 78 | "defaultOutput":true, 79 | "returnType":"mix", 80 | "defaultStatus":"XSS_ALL" 81 | }, 82 | ] 83 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/Taint/ISinkAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using System.IO.IsolatedStorage; 2 | using System.Linq; 3 | using PHPAnalysis.Data; 4 | using PHPAnalysis.Data.CFG; 5 | using PHPAnalysis.Utils; 6 | 7 | namespace PHPAnalysis.Analysis.CFG 8 | { 9 | public interface ISinkAnalyzer 10 | { 11 | bool IsSink(CFGBlock target); 12 | void AnalyzeSink(CFGBlock target, CFGTaintInfo taintInfo); 13 | } 14 | 15 | public sealed class XSSSinkAnalyzer : ISinkAnalyzer 16 | { 17 | private readonly string[] sinks = { 18 | AstConstants.Nodes.Stmt_Echo, 19 | AstConstants.Nodes.Expr_Print, 20 | }; 21 | 22 | private readonly IVulnerabilityReporter vulnerabilityReporter; 23 | 24 | public XSSSinkAnalyzer(IVulnerabilityReporter vulnerabilityReporter) 25 | { 26 | Preconditions.NotNull(vulnerabilityReporter, "vulnerabilityReporter"); 27 | this.vulnerabilityReporter = vulnerabilityReporter; 28 | } 29 | 30 | public bool IsSink(CFGBlock target) 31 | { 32 | Preconditions.NotNull(target, "target"); 33 | 34 | if (target.AstEntryNode == null) { return false; } 35 | 36 | return this.sinks.Contains(target.AstEntryNode.LocalName); 37 | } 38 | 39 | public void AnalyzeSink(CFGBlock target, CFGTaintInfo taintInfo) 40 | { 41 | switch (target.AstEntryNode.LocalName) 42 | { 43 | case AstConstants.Nodes.Stmt_Echo: 44 | AnalyzeEcho(target, taintInfo); 45 | break; 46 | case AstConstants.Nodes.Expr_Print: 47 | break; 48 | default: 49 | break; 50 | } 51 | } 52 | 53 | private void AnalyzeEcho(CFGBlock block, CFGTaintInfo taintInfo) 54 | { 55 | //var xssTaintedVars = taintInfo.In.Where(info => info.Value.XssTaint.TaintTags.Contains(XSSTaint.XSS_ALL)) 56 | // .Select(info => info.Key); 57 | //foreach (var taintedVar in xssTaintedVars) 58 | //{ 59 | // if (block.AstEntryNode.InnerText.Contains(taintedVar)) 60 | // { 61 | // vulnerabilityReporter.ReportVulnerability(block, "XSS"); 62 | // } 63 | //} 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/VariableTreeDimension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using PHPAnalysis.Utils; 4 | 5 | namespace PHPAnalysis.Data 6 | { 7 | public sealed class VariableTreeDimension : IEquatable, IDeepCloneable 8 | { 9 | public int Index { get; set; } 10 | public string Key { get; set; } 11 | 12 | //public Variable VariableKey { get; set; } 13 | 14 | public VariableTreeDimension() 15 | { 16 | this.Index = -1; 17 | } 18 | 19 | #region Equality members 20 | public bool Equals(VariableTreeDimension other) 21 | { 22 | if (ReferenceEquals(null, other)) 23 | { 24 | return false; 25 | } 26 | if (ReferenceEquals(this, other)) 27 | { 28 | return true; 29 | } 30 | return Index == other.Index && string.Equals(Key, other.Key); 31 | } 32 | 33 | public override bool Equals(object obj) 34 | { 35 | if (ReferenceEquals(null, obj)) 36 | { 37 | return false; 38 | } 39 | if (ReferenceEquals(this, obj)) 40 | { 41 | return true; 42 | } 43 | return obj is VariableTreeDimension && Equals((VariableTreeDimension) obj); 44 | } 45 | 46 | public override int GetHashCode() 47 | { 48 | unchecked 49 | { 50 | return (Index * 397) ^ (Key != null ? Key.GetHashCode() : 0); 51 | } 52 | } 53 | 54 | public static bool operator ==(VariableTreeDimension left, VariableTreeDimension right) 55 | { 56 | return Equals(left, right); 57 | } 58 | 59 | public static bool operator !=(VariableTreeDimension left, VariableTreeDimension right) 60 | { 61 | return !Equals(left, right); 62 | } 63 | #endregion 64 | 65 | public VariableTreeDimension DeepClone() 66 | { 67 | return new VariableTreeDimension() { 68 | Index = this.Index, 69 | Key = this.Key 70 | }; 71 | } 72 | 73 | public override string ToString() 74 | { 75 | return Key ?? Index.ToString(CultureInfo.InvariantCulture); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/XmlHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Xml; 7 | 8 | namespace PHPAnalysis.Parsing 9 | { 10 | public static class XmlHelper 11 | { 12 | public static bool ContainsIllegalCharacters(string toCheck) 13 | { 14 | try 15 | { 16 | XmlConvert.VerifyXmlChars(toCheck); 17 | return true; 18 | } 19 | catch (XmlException) 20 | { 21 | return false; 22 | } 23 | } 24 | 25 | //The outline for this method has been found on stack overflow: http://stackoverflow.com/questions/8331119/escape-invalid-xml-characters-in-c-sharp 26 | /// 27 | /// Method to replace Illegal XML characters, such that we can actually parse the files and analyse them! 28 | /// 29 | /// The string that has been stripped for illegal characters 30 | /// XML string with illegal characters 31 | public static string ReplaceIllegalXmlCharacters(string inputString) 32 | { 33 | if (string.IsNullOrWhiteSpace(inputString)) 34 | { 35 | return inputString; 36 | } 37 | 38 | var inputLength = inputString.Length; 39 | var output = new StringBuilder(); 40 | for (int i = 0; i < inputLength; i++) 41 | { 42 | if (XmlConvert.IsXmlChar(inputString[i])) 43 | { 44 | output.Append(inputString[i]); 45 | } 46 | else if (i + 1 < inputLength && XmlConvert.IsXmlSurrogatePair(inputString[i + 1], inputString[i])) 47 | { 48 | output.Append(inputString[i]); 49 | i++; 50 | output.Append(inputString[i]); 51 | } 52 | else 53 | { 54 | Debug.WriteLine("Found invalid XML character! Converting to HEX value with 0x prepended! The char was: {0}", inputString[i]); 55 | var utf8EndoEncoding = new UTF8Encoding(); 56 | byte[] encoded = utf8EndoEncoding.GetBytes(inputString[i].ToString()); 57 | output.Append("0x" + BitConverter.ToString(encoded)); 58 | } 59 | } 60 | return output.ToString(); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/AST/MetricVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml; 3 | using PHPAnalysis.Data; 4 | using PHPAnalysis.Parsing.AstTraversing; 5 | 6 | namespace PHPAnalysis.Analysis.AST 7 | { 8 | public class MetricVisitor : IXmlVisitor 9 | { 10 | public int TotalNodes { get; private set; } 11 | public int EchoStatements { get; private set; } 12 | public int PotentialSQLQueries { get; private set; } 13 | public int IncludeStatements { get; private set; } 14 | public int Classes { get; private set; } 15 | public int Methods { get; private set; } 16 | public int Functions { get; private set; } 17 | public int Gotos { get; private set; } 18 | 19 | public void TraverseStart(object sender, XmlStartTraverseEventArgs e) { } 20 | 21 | public void EnteringNode(object sender, XmlTraverseEventArgs e) 22 | { 23 | XmlNode node = e.Node; 24 | TotalNodes++; 25 | switch (node.LocalName) 26 | { 27 | case "Stmt_Echo": 28 | EchoStatements++; 29 | break; 30 | case "#text": 31 | StringLiteral(node); 32 | break; 33 | case AstConstants.Nodes.Stmt_Function: 34 | Functions++; 35 | break; 36 | case AstConstants.Nodes.Stmt_ClassMethod: 37 | Methods++; 38 | break; 39 | case AstConstants.Nodes.Stmt_Class: 40 | Classes++; 41 | break; 42 | case "Expr_Include": 43 | IncludeStatements++; 44 | break; 45 | case AstConstants.Nodes.Stmt_Goto: 46 | Gotos++; 47 | break; 48 | } 49 | } 50 | 51 | public void LeavingNode(object sender, XmlTraverseEventArgs e) { } 52 | 53 | public void TraverseEnd(object sender, XmlEndTraverseEventArgs e) { } 54 | 55 | private void StringLiteral(XmlNode node) 56 | { 57 | // Poor query recognizer.. But whatevs 58 | if (node.InnerText.StartsWith("select ", StringComparison.OrdinalIgnoreCase) || 59 | node.InnerText.StartsWith("update ", StringComparison.OrdinalIgnoreCase) || 60 | node.InnerText.StartsWith("delete ", StringComparison.OrdinalIgnoreCase)) 61 | { 62 | PotentialSQLQueries++; 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.PluginInterface/PHPAnalysis.PluginInterface.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {789EEAEE-8017-4C6B-8A78-F56B7E599652} 8 | Library 9 | Properties 10 | PHPAnalysis.PluginInterface 11 | PHPAnalysis.PluginInterface 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/CFG/ScopeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using PHPAnalysis.Utils; 7 | 8 | namespace PHPAnalysis.Data.CFG 9 | { 10 | /// 11 | /// Manages the different scopes (loop, if, switch, ..) were currently in, when traversing the CFG. 12 | /// 13 | internal sealed class ScopeHandler 14 | { 15 | private readonly Stack allScopes = new Stack(); 16 | private readonly Stack ifScopes = new Stack(); 17 | /// 18 | /// Contains loopscopes. The stack can contain both actual loop (while, for, ..) and switch cases. 19 | /// Switch cases are regarded as a special loop, since both break and continue works with them. 20 | /// 21 | private readonly Stack loopScopes = new Stack(); 22 | public AbstractScope CurrentScope { get { return allScopes.Peek(); } } 23 | public bool IsInLoop 24 | { 25 | get 26 | { 27 | return loopScopes.Any(); 28 | } 29 | } 30 | 31 | public bool IsInnermostScopeALoop 32 | { 33 | get 34 | { 35 | if (loopScopes.IsEmpty()) 36 | { 37 | return false; 38 | } 39 | return allScopes.Peek() == loopScopes.Peek(); 40 | } 41 | } 42 | 43 | public void PushIfStmt(IfScope ifblock) 44 | { 45 | this.ifScopes.Push(ifblock); 46 | this.allScopes.Push(ifblock); 47 | } 48 | public IfScope PopIfStmt() 49 | { 50 | this.allScopes.Pop(); 51 | return this.ifScopes.Pop(); 52 | } 53 | public IfScope GetIfStmt() 54 | { 55 | return this.ifScopes.Peek(); 56 | } 57 | 58 | public void EnterLoop(AbstractScope loopBlock) 59 | { 60 | this.loopScopes.Push(loopBlock); 61 | this.allScopes.Push(loopBlock); 62 | } 63 | public AbstractScope LeaveLoop() 64 | { 65 | this.allScopes.Pop(); 66 | return this.loopScopes.Pop(); 67 | } 68 | public AbstractScope GetInnermostLoop() 69 | { 70 | return this.loopScopes.Peek(); 71 | } 72 | 73 | public AbstractScope GetLoopScope(int scopesToSkip) 74 | { 75 | return loopScopes.ElementAt(scopesToSkip); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Parsing/CFGCreator_ClassTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using PHPAnalysis.Tests.Analysis; 4 | using PHPAnalysis.Analysis.AST; 5 | using PHPAnalysis.Parsing; 6 | using PHPAnalysis.Data.CFG; 7 | using QuickGraph.Algorithms; 8 | using System.Linq; 9 | using PHPAnalysis.Data; 10 | using PHPAnalysis.Parsing.AstTraversing; 11 | using PHPAnalysis.Tests.TestUtils; 12 | 13 | namespace PHPAnalysis.Tests 14 | { 15 | [TestFixture] 16 | public class CFGCreator_ClassTests : ConfigDependentTests 17 | { 18 | [TestCase(@"")] 30 | [TestCase(@"")] 40 | public void CFGCreator_RootAndExitIsStmtClassMethod(string phpcode) 41 | { 42 | var extract = ParseAndExtract(phpcode); 43 | foreach (var @class in extract.Classes) 44 | { 45 | foreach (var method in @class.Methods) 46 | { 47 | var ast = method.AstNode; 48 | var traverser = new XmlTraverser(); 49 | var cfgcreator = new CFGCreator(); 50 | traverser.AddVisitor(cfgcreator); 51 | traverser.Traverse(ast); 52 | 53 | var graph = cfgcreator.Graph; 54 | 55 | //Root assertions 56 | Assert.AreEqual(AstConstants.Nodes.Stmt_ClassMethod, graph.Vertices.First().ToString()); 57 | graph.AssertInEdges(graph.Vertices.First(), 0, "Entry node - in edges"); 58 | graph.AssertOutEdges(graph.Vertices.First(), 1, "Entry node - out edges"); 59 | Assert.AreEqual(true, graph.Vertices.First().IsRoot); 60 | 61 | //Leaf assertions 62 | graph.AssertOutEdges(graph.Vertices.ElementAt(1), 0, "Exit node - out edges"); 63 | Assert.AreEqual(true, graph.Vertices.ElementAt(1).IsLeaf); 64 | } 65 | } 66 | } 67 | 68 | private ClassAndFunctionExtractor ParseAndExtract(string php) 69 | { 70 | return PHPParseUtils.ParseAndIterate(php, Config.PHPSettings.PHPParserPath); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Parsing/FileParser.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Xml; 3 | using PHPAnalysis.Annotations; 4 | using PHPAnalysis.Utils; 5 | using System.Text; 6 | using System; 7 | 8 | namespace PHPAnalysis.Parsing 9 | { 10 | public sealed class FileParser 11 | { 12 | private string _parserPath; 13 | public string ParserPath 14 | { 15 | get 16 | { 17 | return _parserPath.StartsWith("\"") ? _parserPath 18 | : "\"" + _parserPath + "\""; 19 | } 20 | set { this._parserPath = value; } 21 | } 22 | 23 | public FileParser(string parserPath) 24 | { 25 | Preconditions.NotNull(parserPath, "parserPath"); 26 | 27 | this.ParserPath = parserPath; 28 | } 29 | 30 | public XmlDocument ParsePHPFile(string pathToFile) 31 | { 32 | Preconditions.NotNull(pathToFile, "pathToFile"); 33 | 34 | var xmlDocument = new XmlDocument(); 35 | 36 | var process = CreateParseProcess(pathToFile); 37 | process.Start(); 38 | 39 | string tmp; 40 | var finalOutput = new StringBuilder (); 41 | while ((tmp = process.StandardOutput.ReadLine ()) != null) 42 | { 43 | tmp = XmlHelper.ReplaceIllegalXmlCharacters(tmp); 44 | finalOutput.AppendLine (tmp); 45 | } 46 | xmlDocument.LoadXml(finalOutput.ToString()); 47 | return xmlDocument; 48 | } 49 | 50 | private Process CreateParseProcess([NotNull] string fileToParse) 51 | { 52 | string arguments = this.ParserPath + " parse "; 53 | 54 | fileToParse = fileToParse.StartsWith("\"") ? fileToParse 55 | : "\"" + fileToParse + "\""; 56 | arguments += fileToParse; 57 | 58 | var processStartInfo = new ProcessStartInfo() { 59 | FileName = "php", 60 | Arguments = arguments, 61 | UseShellExecute = false, 62 | RedirectStandardOutput = true, 63 | CreateNoWindow = true 64 | }; 65 | var process = new Process() { 66 | StartInfo = processStartInfo 67 | }; 68 | return process; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.Tests/Analysis/ReachDefTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | using PHPAnalysis.Analysis.CFG; 5 | using PHPAnalysis.Analysis.CFG.Traversal; 6 | using PHPAnalysis.Parsing; 7 | using PHPAnalysis.Tests.TestUtils; 8 | using PHPAnalysis.Utils; 9 | using PHPAnalysis.Utils.XmlHelpers; 10 | 11 | namespace PHPAnalysis.Tests.Analysis 12 | { 13 | [TestFixture] 14 | class ReachDefTests : ConfigDependentTests 15 | { 16 | [Test, Ignore("Not implemented")] 17 | public void IfElseVarDefTest() 18 | { 19 | const string php = @"() { 4, 8 }; 36 | var outLineNumbers = new List() { 4, 8, 10 }; 37 | 38 | foreach (var block in reachDef.ReachingSetDictionary) 39 | { 40 | if (block.Key.AstEntryNode != null && block.Key.AstEntryNode.Name == "node:Expr_Assign") 41 | { 42 | if (block.Value.DefinedInVars.Any()) 43 | { 44 | int ins = AstNode.GetStartLine(block.Value.DefinedInVars.Values.First().Info.Block.AstEntryNode); 45 | inLineNumbers.RemoveAll(x => ins == x); 46 | } 47 | if (block.Value.DefinedOutVars.Any()) 48 | { 49 | int outs = AstNode.GetStartLine(block.Value.DefinedOutVars.Values.First().Info.Block.AstEntryNode); 50 | outLineNumbers.RemoveAll(x => x == outs); 51 | } 52 | } 53 | } 54 | 55 | Assert.IsTrue(inLineNumbers.IsEmpty(), "The InLineNumbers are incorrect!"); 56 | Assert.IsTrue(outLineNumbers.IsEmpty(), "The OutLineNumbers are incorrect!"); 57 | } 58 | 59 | private CFGCreator ParseAndBuildCFG(string php) 60 | { 61 | return PHPParseUtils.ParseAndIterate(php, Config.PHPSettings.PHPParserPath); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Utils/Extensions/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using PHPAnalysis.Data; 10 | using YamlDotNet.Core.Tokens; 11 | 12 | namespace PHPAnalysis.Utils 13 | { 14 | public static class CollectionExtensions 15 | { 16 | public static void AddRange(this ICollection collection, IEnumerable toAdd) 17 | { 18 | Preconditions.NotNull(toAdd, "toAdd"); 19 | if (collection.IsReadOnly) { throw new NotSupportedException(); } 20 | 21 | foreach (var element in toAdd) 22 | { 23 | collection.Add(element); 24 | } 25 | } 26 | 27 | public static void AddRange(this IDictionary collection, IEnumerable> toAdd) 28 | { 29 | Preconditions.NotNull(collection, "collection"); 30 | if (collection.IsReadOnly) 31 | { 32 | throw new NotSupportedException(); 33 | } 34 | 35 | foreach (var keyValuePair in toAdd) 36 | { 37 | collection.Add(keyValuePair); 38 | } 39 | } 40 | 41 | public static bool DictionaryEquals( 42 | this IDictionary first, IDictionary second, 43 | IEqualityComparer comparer = null) 44 | { 45 | if (ReferenceEquals(first, second)) { return true; } 46 | if (first == null || second == null) { return false; } 47 | if (first.Count != second.Count) { return false; } 48 | 49 | comparer = comparer ?? EqualityComparer.Default; 50 | 51 | foreach (var keyValuePair in first) 52 | { 53 | TValue matchingValue; 54 | if (!second.TryGetValue(keyValuePair.Key, out matchingValue) || 55 | !comparer.Equals(keyValuePair.Value, matchingValue)) 56 | { 57 | return false; 58 | } 59 | } 60 | return true; 61 | } 62 | 63 | public static ImmutableStack ToImmutableStack(this Stack mutableStack) 64 | { 65 | Preconditions.NotNull(mutableStack, "mutableStack"); 66 | 67 | var result = ImmutableStack.Empty; 68 | 69 | for (int i = mutableStack.Count - 1; i >= 0; i--) 70 | { 71 | result = result.Push(mutableStack.ElementAt(i)); 72 | } 73 | return result; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Components/ComponentImporter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using System.ComponentModel.Composition; 4 | using System.ComponentModel.Composition.Hosting; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | using System.Runtime.InteropServices; 8 | using PHPAnalysis.Analysis; 9 | using PHPAnalysis.Analysis.CFG.Taint; 10 | using PHPAnalysis.Annotations; 11 | using PHPAnalysis.Parsing.AstTraversing; 12 | using PHPAnalysis.Utils; 13 | 14 | namespace PHPAnalysis.Components 15 | { 16 | internal sealed class ComponentImporter 17 | { 18 | [ImportMany(typeof(IXmlVisitor)), UsedImplicitly] 19 | private IEnumerable AstTraversers { get; set; } 20 | 21 | [ImportMany(typeof(IVulnerabilityReporter)), UsedImplicitly] 22 | private IEnumerable VulnerabilityReporters { get; set; } 23 | 24 | [ImportMany(typeof(ITaintProvider)), UsedImplicitly] 25 | private IEnumerable TaintProviders { get; set; } 26 | 27 | [ImportMany(typeof(IBlockAnalyzerComponent)), UsedImplicitly] 28 | private IEnumerable BlockAnalyzers { get; set; } 29 | 30 | [ImportMany(typeof(IAnalysisStartingListener)), UsedImplicitly] 31 | private IEnumerable AnalysisStartingListener { get; set; } 32 | 33 | [ImportMany(typeof(IAnalysisEndedListener)), UsedImplicitly] 34 | private IEnumerable AnalysisEndedListeners { get; set; } 35 | 36 | public ComponentContainer ImportComponents(string componentPath) 37 | { 38 | var catalog = new AggregateCatalog(); 39 | 40 | catalog.Catalogs.Add(new DirectoryCatalog(componentPath)); 41 | catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); 42 | 43 | var container = new CompositionContainer(catalog); 44 | 45 | container.ComposeParts(this); 46 | 47 | return CreateComponentContainer(); 48 | } 49 | 50 | private ComponentContainer CreateComponentContainer() 51 | { 52 | var componentContainer = new ComponentContainer(); 53 | 54 | componentContainer.AstVisitors.AddRange(this.AstTraversers); 55 | componentContainer.VulnerabilityReporters.AddRange(this.VulnerabilityReporters); 56 | componentContainer.BlockAnalyzers.AddRange(this.BlockAnalyzers); 57 | componentContainer.TaintProviders.AddRange(this.TaintProviders); 58 | componentContainer.AnalysisStartingListeners.AddRange(this.AnalysisStartingListener); 59 | componentContainer.AnalysisEndedListeners.AddRange(this.AnalysisEndedListeners); 60 | 61 | return componentContainer; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PHPAnalysis", "PHPAnalysis\PHPAnalysis.csproj", "{04511BB1-4881-44F2-B07D-FD88CEDE53CB}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PHPAnalysis.Tests", "PHPAnalysis.Tests\PHPAnalysis.Tests.csproj", "{19467754-4DA7-4531-BB51-8CC024A0CCB3}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WordPress.Plugin", "WordPress.Plugin\WordPress.Plugin.csproj", "{B27C2212-E33B-4BEF-9FB7-62113A3682C6}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5B98AE9F-4B39-426F-B5D5-DF549FDE4327}" 13 | ProjectSection(SolutionItems) = preProject 14 | Performance1.psess = Performance1.psess 15 | EndProjectSection 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileWriter.Plugin", "FileWriter.Plugin\FileWriter.Plugin.csproj", "{6EBE6355-A353-4614-A507-EB251282541B}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {04511BB1-4881-44F2-B07D-FD88CEDE53CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {04511BB1-4881-44F2-B07D-FD88CEDE53CB}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {04511BB1-4881-44F2-B07D-FD88CEDE53CB}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {04511BB1-4881-44F2-B07D-FD88CEDE53CB}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {19467754-4DA7-4531-BB51-8CC024A0CCB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {19467754-4DA7-4531-BB51-8CC024A0CCB3}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {19467754-4DA7-4531-BB51-8CC024A0CCB3}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {19467754-4DA7-4531-BB51-8CC024A0CCB3}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {B27C2212-E33B-4BEF-9FB7-62113A3682C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {B27C2212-E33B-4BEF-9FB7-62113A3682C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {B27C2212-E33B-4BEF-9FB7-62113A3682C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {B27C2212-E33B-4BEF-9FB7-62113A3682C6}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {6EBE6355-A353-4614-A507-EB251282541B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {6EBE6355-A353-4614-A507-EB251282541B}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {6EBE6355-A353-4614-A507-EB251282541B}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {6EBE6355-A353-4614-A507-EB251282541B}.Release|Any CPU.Build.0 = Release|Any CPU 41 | EndGlobalSection 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | EndGlobal 46 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/AST/IncludeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.Remoting.Contexts; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using System.Xml; 10 | using PHPAnalysis.Data; 11 | using PHPAnalysis.Utils; 12 | using PHPAnalysis.Utils.XmlHelpers; 13 | using File = PHPAnalysis.Data.File; 14 | 15 | namespace PHPAnalysis.Analysis.AST 16 | { 17 | public interface IIncludeResolver 18 | { 19 | bool TryResolveInclude(XmlNode node, out File path); 20 | } 21 | 22 | public sealed class IncludeResolver : IIncludeResolver 23 | { 24 | // TODO - Currently we're just looking at the filename and see if we can resolve it. 25 | // We should at least try to use the path if it is present. 26 | private readonly List _projectFiles; 27 | public IncludeResolver(ICollection projectFiles) 28 | { 29 | Preconditions.NotNull(projectFiles, "projectFiles"); 30 | _projectFiles = new List(projectFiles); 31 | } 32 | 33 | /// 34 | /// Matching last string in include expression against all files and select the first match. 35 | /// This is incredibly basic and not necessarily correct. The path is ignored and there could be multiple files 36 | /// with the same name. 37 | /// 38 | public bool TryResolveInclude(XmlNode node, out File path) 39 | { 40 | Preconditions.NotNull(node, "node"); 41 | Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Expr_Include, "Given node was not an include node. It was " + node.Name, "node"); 42 | 43 | string includeString = ""; 44 | 45 | node.IterateAllNodes(xmlNode => 46 | { 47 | if (xmlNode.LocalName != AstConstants.Nodes.Scalar_String) 48 | return false; 49 | includeString = xmlNode.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value).InnerText; 50 | return true; 51 | }); 52 | 53 | string fileName = Path.GetFileName(includeString); 54 | 55 | return TryGetFile(fileName, out path); 56 | } 57 | 58 | private bool TryGetFile(string fileName, out File file) 59 | { 60 | var matchingFiles = _projectFiles.Where(projectFile => projectFile.Name == fileName).ToList(); 61 | 62 | if (!matchingFiles.Any() || matchingFiles.Count > 1) 63 | { 64 | file = null; 65 | return false; 66 | } 67 | file = matchingFiles.Single(); 68 | return true; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Provider/Keys.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PHPAnalysis 4 | { 5 | public static class Keys 6 | { 7 | public static class PHPDefinitionJSONKeys 8 | { 9 | public static class FunctionSpecificationArrays 10 | { 11 | public const string Sources = "SourceFuncs"; 12 | public const string XssSanitizer = "XSSSanitizersFuncs"; 13 | public const string SqlSanitizer = "SQLSanitizersFuncs"; 14 | public const string XssSinks = "XssSinkFuncs"; 15 | public const string SqlSinks = "SqlSinksFuncs"; 16 | public const string CondSinks = "ConditionSanitizerFuncs"; 17 | public const string StoredVulnProviders = "StoredVulnerabilityProviders"; 18 | } 19 | 20 | public static class GeneralKeys 21 | { 22 | public const string Name = "name"; 23 | public const string Type = "type"; 24 | public const string Formats = "formats"; 25 | public const string Aliases = "aliases"; 26 | public const string ParameterCount = "totalParameters"; 27 | public const string Parameters = "parameters"; 28 | public const string DefaultStatusCode = "defaultStatus"; 29 | public const string OutputsPerDefault = "defaultOutput"; 30 | public const string ReturnType = "returnType"; 31 | public const string XssTaint = "XSSTaint"; 32 | public const string SqlTaint = "SQLTaint"; 33 | public const string Classnames = "classnames"; 34 | } 35 | 36 | public static class ParameterJSONKeys 37 | { 38 | public const string ParameterNumber = "number"; 39 | public const string ParameterType = "type"; 40 | public const string ParameterName = "name"; 41 | public const string ParameterIsOptional = "optional"; 42 | public const string ParameterValues = "values"; 43 | public const string ParameterCanCreateHole = "can_be_vulnerable"; 44 | public const string ParameterIsVariadic = "IsVariadic"; 45 | public const string ParameterIsReturnValue = "isReturnValue"; 46 | } 47 | 48 | public static class ValuesJSONKeys 49 | { 50 | public const string Value = "value"; 51 | public const string IsOutputing = "outputs"; 52 | public const string StatusCode = "outputStatus"; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eir 2 | PHP vulnerability scanner written in C#. Why C#? Because! That's why! 3 | 4 | ### Requirements 5 | * .NET 4.5 or Mono 3.12.0-1 6 | * PHP >= 5.3 7 | * Good intentions 8 | 9 | ### Getting it running 10 | 1. Download project 11 | 2. Install [Composer](https://getcomposer.org/) (for the PHP parser) 12 | 2.1. From the PHPAnalysis-parser folder run composer update in terminal 13 | 2.2. Make sure all dependencies are correctly installed. 14 | 3. Fix the config.yml 15 | 4. Run the application 16 | 17 | #### Getting it running on Ubuntu 16.04 18 | 19 | 1. Install PHP 20 | `sudo apt install php7.0-cli` 21 | 2. Make sure you have the XML library 22 | `sudo apt install php-xml` 23 | 3. Install Composer 24 | `sudo apt install composer` 25 | 4. [Install Mono](http://www.mono-project.com/download/#download-lin) 26 | `sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF` 27 | `echo "deb http://download.mono-project.com/repo/ubuntu xenial main" | sudo tee /etc/apt/sources.list.d/mono-official.list` 28 | `sudo apt-get update` 29 | `sudo apt-get install mono-devel` 30 | 5. Install NuGet 31 | `sudo apt install nuget` 32 | 6. Install PHPAnalysis-parser dependencies with Composer 33 | `composer install` 34 | `composer update` 35 | 6. Restore NuGet packages for PHPAnalysis solution 36 | `nuget restore` 37 | 7. Build solution 38 | `msbuild ./PHPAnalysis.sln` 39 | 8. Update the _config.yml_ file with correct settings 40 | - Remember to reference the _FileWriter_ and/or the _WordPress_ dll files if needed 41 | 9. Run the analysis 42 | `mono PHPAnalysis.exe --all --target ./myPhpFile.php` 43 | 44 | 45 | ### Errors 46 | 47 | A list of possible errors you might experience while setting up/using this application and possible ways to mitigate them. 48 | 49 | ----------------------- 50 | #### "Parser error: Syntax error, unexpected EOF on line xx" 51 | (PHP project/parser throws this error) 52 | 53 | Make sure that there is no syntactical errors in your PHP code. This scanner does not handle syntax errors very well. 54 | If the syntax is correct, try updating to the newest version of PHP. 55 | 56 | ----------------------- 57 | #### CONFIGURATION ERROR 58 | Make sure the configuration file (`config.yml`) is present and has the correct format. It should look like the `config-template.yml` file. 59 | Standard rules for Yaml files apply. 60 | 61 | Common error: 62 | Using tabs instead of spaces. Indentation should be done using spaces. 63 | 64 | ----------------------- 65 | ### External dependencies 66 | 67 | - [CommandLineParser](https://commandline.codeplex.com/) 1.9.71 68 | - [Newtonsoft.Json](https://www.newtonsoft.com/json) 10.0.0 69 | - [PHP-Parser](https://github.com/nikic/PHP-Parser) 1.1.0 70 | - [QuickGraph](https://quickgraph.codeplex.com/) 3.6.61119.7 71 | - [Microsoft.Bcl.Immutable](https://www.nuget.org/packages/Microsoft.Bcl.Immutable) 1.0.34 72 | - [YamlDotNet](https://github.com/aaubry/YamlDotNet) 4.2.2 73 | 74 | 75 | - [Moq](https://github.com/Moq/moq4) 4.7.127 76 | - [NUnit](http://www.nunit.org/) 3.8.1 77 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Data/PHP/Parameter.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using PHPAnalysis.Utils; 3 | 4 | namespace PHPAnalysis.Data.PHP 5 | { 6 | public class Parameter 7 | { 8 | public XmlNode AstNode { get; private set; } 9 | public string Name { get; set; } 10 | public bool ByReference { get; set; } 11 | public bool IsVariadic { get; set; } 12 | public bool IsOptional { get; set; } 13 | public bool IsReturn { get; set; } 14 | public string DefaultValue { get; set;} 15 | /// 16 | /// This property indicates whether this parameter can create a security issue through the input. 17 | /// An example is the mysqli_query($dblink, $query). The dblink cannot create an issue, however the $query can. 18 | /// 19 | /// true if this instance can create a security issue; otherwise false. 20 | public bool IsSensitive { get; set; } 21 | 22 | //public string DefaultValue 23 | //{ 24 | // get 25 | // { 26 | // var defaultNodeName = AstConstants.SubNode + ":" + AstConstants.Subnodes.Default; 27 | // var val = AstNode.GetSubNode(defaultNodeName); 28 | // return val.Value; 29 | // } 30 | //} 31 | 32 | public Parameter(bool optional = false, bool vulnerable = true, 33 | bool isVariadic = false, bool byRef = false, string defaultValue = "", bool isReturn = false) 34 | { 35 | this.ByReference = byRef; 36 | this.IsVariadic = isVariadic; 37 | this.IsOptional = optional; 38 | this.IsSensitive = vulnerable; 39 | this.AstNode = null; 40 | this.DefaultValue = defaultValue; 41 | this.IsReturn = isReturn; 42 | } 43 | 44 | public Parameter(string name, bool optional = false, bool vulnerable = true, bool variadic = false, 45 | bool byRef = false, string defaultValue = "", bool isReturn = false) : this(optional, vulnerable, variadic, byRef, defaultValue, isReturn) 46 | { 47 | this.Name = name; 48 | } 49 | 50 | public Parameter(string name, XmlNode node, bool optional = false, bool vulnerable = true, bool variadic = false, 51 | bool byRef = false, string defaultValue = "", bool isReturn = false) : this(name, optional, vulnerable, variadic, byRef, defaultValue, isReturn) 52 | { 53 | Preconditions.NotNull(node, "node"); 54 | this.AstNode = node; 55 | } 56 | 57 | public Parameter(XmlNode node) 58 | { 59 | //TODO: Could extract stuff from the param, and set the properties from the ast node 60 | //-||-: or the getters could be implemented to check if the property is null or empty and if it is, then it should extract and return 61 | Preconditions.NotNull(node, "node"); 62 | this.AstNode = node; 63 | } 64 | 65 | public override string ToString() 66 | { 67 | return string.Format("{0}{1}{2}{3}", 68 | ByReference ? "&" : "", 69 | IsVariadic ? "..." : "", 70 | Name, 71 | IsOptional ? " = ": ""); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Configuration/Config.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Text; 4 | using PHPAnalysis.Annotations; 5 | using PHPAnalysis.Utils; 6 | using PHPAnalysis.Utils.Exceptions; 7 | using YamlDotNet.Core; 8 | using YamlDotNet.Serialization; 9 | 10 | namespace PHPAnalysis.Configuration 11 | { 12 | public sealed class Config 13 | { 14 | public PHPConfiguration PHPSettings { get; private set; } 15 | public GraphConfiguration GraphSettings { get; private set; } 16 | public ComponentConfiguration ComponentSettings { get; private set; } 17 | public FuncSpecConfiguration FuncSpecSettings { get; private set; } 18 | 19 | private Config(ConfigurationMutable config) 20 | { 21 | Preconditions.NotNull(config, "config"); 22 | 23 | PHPSettings = new PHPConfiguration(config.PHPConfiguration.PHPPath, config.PHPConfiguration.PHPParsePath, config.PHPConfiguration.PHPExts); 24 | GraphSettings = new GraphConfiguration(config.GraphConfiguration.GraphvizPath, config.GraphConfiguration.GraphvizArguments); 25 | ComponentSettings = new ComponentConfiguration(config.ComponentSettings.ComponentFolder, config.ComponentSettings.IncludeComponents); 26 | FuncSpecSettings = new FuncSpecConfiguration(config.FuncSpecSettings.PHPSpecs, config.FuncSpecSettings.ExtensionSpecs); 27 | } 28 | 29 | public static Config ReadConfiguration(string configPath) 30 | { 31 | Preconditions.NotNull(configPath, "configPath"); 32 | var configInput = new StringReader(File.ReadAllText(configPath)); 33 | var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build(); 34 | 35 | try 36 | { 37 | var config = deserializer.Deserialize(configInput); 38 | return new Config(config); 39 | } 40 | catch (SyntaxErrorException e) 41 | { 42 | throw new ConfigurationParseException("Could not parse config file: " + configPath, e); 43 | } 44 | } 45 | 46 | public override string ToString() 47 | { 48 | var sb = new StringBuilder(); 49 | sb.AppendLine("PHP Settings: "); 50 | sb.AppendLine(PHPSettings.ToString()); 51 | sb.AppendLine("Graph Settings: "); 52 | sb.AppendLine(GraphSettings.ToString()); 53 | sb.AppendLine("Component Settings:"); 54 | sb.AppendLine(ComponentSettings.ToString()); 55 | return sb.ToString(); 56 | } 57 | 58 | [UsedImplicitly] 59 | internal sealed class ConfigurationMutable 60 | { 61 | [YamlMember(Alias = "php-settings")] 62 | public PHPConfigurationMutable PHPConfiguration { get; set; } 63 | 64 | [YamlMember(Alias = "graph-settings")] 65 | public GraphConfigurationMutable GraphConfiguration { get; set; } 66 | 67 | [YamlMember(Alias = "component-settings")] 68 | public ComponentConfigurationMutable ComponentSettings { get; set; } 69 | 70 | [YamlMember(Alias = "func-spec-settings")] 71 | public FuncSpecConfigurationMutable FuncSpecSettings { get; set; } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/FunctionSpecs/StoredSQLProviders/databaseProviders.json: -------------------------------------------------------------------------------- 1 | { 2 | "StoredVulnerabilityProviders": 3 | [ 4 | { 5 | "name":"mysqli_result->fetch_array", 6 | "formats":[ "mysqli_result->fetch_array(int)", "mysqli_result->fetch_array()" ], 7 | "totalParameters":1, 8 | "parameters": [ 9 | { "number":1, "name":"resulttype", "type":"int", "optional":true } 10 | ], 11 | "returnType":"mix" 12 | }, 13 | { 14 | "name":"mysqli_result->fetch_assoc", 15 | "formats": [ "mysqli_result->fetch_assoc()" ], 16 | "totalParameters":0, 17 | "parameters": [], 18 | "returnType":"array" 19 | }, 20 | { 21 | "name":"SQLiteResult->fetch", 22 | "formats": [ "SQLiteResult->fetch(int, bool)", "SQLiteResult->fetch(int)" ], 23 | "aliases": [ "SQLiteUnbuffered->fetch" ], 24 | "totalParameters":2, 25 | "parameters": [ 26 | { "number":1, "name":"result_type", "type":"int", "optional":true }, 27 | { "number":2, "name":"decode_binary", "type":"bool", "optional":true } 28 | ], 29 | "returnType":"array" 30 | }, 31 | { 32 | "name":"SQLiteResult->fetchObject", 33 | "formats": [ "SQLiteResult->fetchObject(string, array, bool)", "SQLiteResult->fetchObject(string, array)", "SQLiteResult->fetchObject(string)" ], 34 | "aliases": [ "SQLiteUnbuffered->fetchObject" ], 35 | "totalParameters":3, 36 | "parameters":[ 37 | { "number":1, "name":"class_name", "type":"string" }, 38 | { "number":2, "name":"ctor_params", "type":"array", "optional":true }, 39 | { "number":3, "name":"decode_binary", "type":"bool", "optional":true } 40 | ], 41 | "returnType":"object" 42 | }, 43 | { 44 | "name":"SQLiteResult->fetchSingle", 45 | "formats": [ "SQLiteResult->fetchSingle(bool)", "SQLiteResult->fetchSingle()" ], 46 | "aliases": [ "SQLiteUnbuffered->fetchSingle", "SQLiteResult::fetchString" ], 47 | "totalParameters":1, 48 | "parameters": [ 49 | { "number":1, "name":"decode_binary", "type":"bool", "optional":true } 50 | ], 51 | "returnType":"string" 52 | }, 53 | { 54 | "name":"mysqli_result->fetch_all", 55 | "formats": [ "mysqli_result->fetch_all(int)", "mysqli_result->fetch_all()" ], 56 | "totalParameters":1, 57 | "parameters":[ 58 | { "number":1, "name":"result_type", "type":"int", "optional":true } 59 | ], 60 | "returnType":"mix" 61 | }, 62 | { 63 | "name":"mysqli_result->fetch_field", 64 | "formats": [ "mysqli_result->fetch_field()" ], 65 | "totalParameters":0, 66 | "parameters": [], 67 | "returnType":"object" 68 | }, 69 | { 70 | "name":"mysqli_result->fetch_fields", 71 | "formats": [ "mysqli_result->fetch_fields()" ], 72 | "totalParameters":0, 73 | "parameters":[], 74 | "returnType":"array" 75 | }, 76 | { 77 | "name":"mysqli_result->fetch_object", 78 | "formats": [ "mysqli_result->fetch_object(string, array)", "mysqli_result->fetch_object(string)" ], 79 | "totalParameters":2, 80 | "parameters": [ 81 | { "number":1, "name":"class_name", "type":"string", "optional":true }, 82 | { "number":2, "name":"stdClass", "type":"array", "optional":true } 83 | ], 84 | "returnType":"object" 85 | }, 86 | { 87 | "name":"mysqli_result->fetch_row", 88 | "formats": [ "mysqli_result->fetch_row()" ], 89 | "totalParameters":0, 90 | "parameters":[], 91 | "returnType":"mix" 92 | } 93 | ] 94 | } -------------------------------------------------------------------------------- /PHPAnalysis/PHPAnalysis/Analysis/CFG/CFGPruner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using System.Xml; 5 | using PHPAnalysis.Data.CFG; 6 | using PHPAnalysis.Utils; 7 | using QuickGraph; 8 | using QuickGraph.Algorithms; 9 | 10 | namespace PHPAnalysis.Analysis.CFG 11 | { 12 | public interface ICFGPruner 13 | { 14 | void Prune(BidirectionalGraph> graph); 15 | } 16 | 17 | public sealed class CFGPruner : ICFGPruner 18 | { 19 | private BidirectionalGraph> graph; 20 | 21 | public void Prune(BidirectionalGraph> graph) 22 | { 23 | Preconditions.NotNull(graph, "graph"); 24 | this.graph = graph; 25 | 26 | RemoveUnreachableBlocks(); 27 | RemoveEmptyBlocks(); 28 | 29 | this.graph = null; 30 | } 31 | 32 | private void RemoveUnreachableBlocks() 33 | { 34 | var root = graph.Roots().Single(v => v.IsSpecialBlock); 35 | 36 | var reachableBlocks = graph.ReachableBlocks(root); 37 | var unreachableBlocks = graph.Vertices.Except(reachableBlocks).ToList(); 38 | 39 | foreach (var unreachableBlock in unreachableBlocks) 40 | { 41 | graph.RemoveVertex(unreachableBlock); 42 | } 43 | } 44 | 45 | private void RemoveEmptyBlocks() 46 | { 47 | //HACK: Not the most efficient way of solving this. 48 | //-||-: However it works. 49 | var lastTimeCount = int.MaxValue; 50 | var numberOfVertices = graph.Vertices.Count(); 51 | while (numberOfVertices != lastTimeCount) 52 | { 53 | var toRemove = new List(); 54 | 55 | foreach (var vertex in graph.Vertices) 56 | { 57 | int inEdgesCount = graph.InEdges(vertex).Count(); 58 | int outEdgesCount = graph.OutEdges(vertex).Count(); 59 | 60 | if (!(vertex.IsLeaf || vertex.IsRoot || vertex.IsSpecialBlock || vertex.AstEntryNode != null)) 61 | { 62 | if (inEdgesCount == 1 && outEdgesCount == 0) 63 | { 64 | toRemove.Add(vertex); 65 | } 66 | else if (inEdgesCount > 0 && outEdgesCount == 1) 67 | { 68 | foreach (var edge in graph.InEdges(vertex)) 69 | { 70 | var parent = edge.Source; 71 | var child = graph.OutEdge(vertex, 0).Target; 72 | 73 | graph.AddEdge(new TaggedEdge(parent, child, edge.Tag)); 74 | toRemove.Add(vertex); 75 | } 76 | } 77 | } 78 | } 79 | 80 | foreach (var vertex in toRemove) 81 | { 82 | graph.RemoveVertex(vertex); 83 | } 84 | 85 | lastTimeCount = numberOfVertices; 86 | numberOfVertices = graph.Vertices.Count(); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /PHPAnalysis/FileWriter.Plugin/FileWriter.Plugin.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6EBE6355-A353-4614-A507-EB251282541B} 8 | Library 9 | Properties 10 | FileWriter.Plugin 11 | FileWriter.Plugin 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | False 36 | ..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {04511bb1-4881-44f2-b07d-fd88cede53cb} 54 | PHPAnalysis 55 | 56 | 57 | 58 | 59 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /PHPAnalysis/WordPress.Plugin/WordPress.Plugin.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B27C2212-E33B-4BEF-9FB7-62113A3682C6} 8 | Library 9 | Properties 10 | WordPress.Plugin 11 | WordPress.Plugin 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | False 36 | ..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {04511bb1-4881-44f2-b07d-fd88cede53cb} 58 | PHPAnalysis 59 | 60 | 61 | 62 | 69 | --------------------------------------------------------------------------------