public static TConfiguration UseCodeTransformation <TConfiguration>(this TConfiguration configuration, string sourceFile, Action <ICodeTransformation> transformerAction) where TConfiguration : IConfiguration { ICodeTransformationAction transformation = new CodeTransformation(); transformerAction(transformation); configuration.AddStep(new CodeTransformationStep(sourceFile, transformation)); return(configuration); }
private void Run(CodeTransformation version, string[] args, MemoryStore memoryStore) { PhpArray get = PhpArgumentParser.Parse("get", args); PhpArray post = PhpArgumentParser.Parse("post", args); PhpArray cookies = PhpArgumentParser.Parse("cookies", args); PhpArray session = PhpArgumentParser.Parse("session", args); _evaluator.Evaluate(version, get, post, cookies, session, memoryStore); }
public void Evaluate(CodeTransformation codeTransformation, PhpArray getVariables, PhpArray postVariables, PhpArray cookieVariables, PhpArray sessionVariables, MemoryStore memoryStore) { var fullpath = Path.Combine(Directory.GetCurrentDirectory(), "main.php"); //Context.CreateConsole() is a Peachpie runtime object, representing a PHP runtime thread. using (var ctx = Context.CreateConsole(string.Empty, new string[] { })) { //declare methods to store/read channel values ctx.DeclareFunction(FunctionNames.StoreInput, new Func <int, string, string>((id, val) => { ctx.Echo($"Stored input value for channel {id}: {val}\n"); memoryStore.Store(id, val); return(val); })); ctx.DeclareFunction(FunctionNames.GetInput, new Func <int, string, string>((id, val) => { var readValue = memoryStore.Get(id, codeTransformation.SecurityLevel.Level); ctx.Echo($"Get input value for channel {id}: {readValue}\n"); return(readValue); })); ctx.DeclareFunction(FunctionNames.StoreSanitize, new Func <int, string, string>((id, val) => { ctx.Echo($"Stored sanitized value for channel {id}: {val}\n"); memoryStore.Store(id, val); return(val); })); ctx.DeclareFunction(FunctionNames.GetSanitize, new Func <int, string, string>((id, val) => { var readValue = memoryStore.Get(id, codeTransformation.SecurityLevel.Level); ctx.Echo($"Get sanitized value for channel {id}: {readValue}\n"); return(readValue); })); ctx.DeclareFunction(FunctionNames.CaptureOutput, new Action <int, string>((id, val) => { ctx.Echo($"Captured output value for channel {id}: {val}\n"); })); ctx.DeclareFunction(FunctionNames.StoreOutput, new Action <int, string>((id, val) => { ctx.Echo($"Stored output value for channel {id}: {val}\n"); memoryStore.Store(id, val); })); ctx.DeclareFunction(FunctionNames.GetOutput, new Func <int, string>((id) => { var readValue = memoryStore.Get(id, codeTransformation.SecurityLevel.Level); ctx.Echo($"Get output value for channel {id}: {readValue}\n"); return(readValue); })); ctx.Get = getVariables; ctx.Post = postVariables; ctx.Cookie = cookieVariables; ctx.Session = sessionVariables; var script = _provider.CreateScript(new Context.ScriptOptions() { Context = ctx, Location = new Location(fullpath, 0, 0), EmitDebugInformation = true, IsSubmission = false, AdditionalReferences = new string[] { typeof(Peachpie.Library.Graphics.PhpImage).Assembly.Location, typeof(Peachpie.Library.Network.CURLFunctions).Assembly.Location, typeof(Peachpie.Library.MySql.MySql).Assembly.Location, typeof(Peachpie.Library.XmlDom.XmlDom).Assembly.Location, }, }, codeTransformation.Code); //evaluate the php code script.Evaluate(ctx, ctx.Globals, null); } }
public TransformationResult Transform(string content, IPolicy policy) { var result = new TransformationResult(); var sourceUnit = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set); var nodesFactory = new BasicNodesFactory(sourceUnit); var errors = new PhpErrorSink(); sourceUnit.Parse(nodesFactory, errors); GlobalCode ast = sourceUnit.Ast; if (errors.Count != 0) { ReportErrors(errors, result, content); return(result); // AST is null or invalid } //collect channel information from source code var provider = SourceTokenProviderFactory.CreateEmptyProvider(); var collectorComposer = new PhpTokenComposer(provider); var collector = new PhpChannelCollector(policy, new TreeContext(ast), collectorComposer, provider); collector.VisitElement(ast); result.InputChannels.AddRange(collector.InputChannels); result.OutputChannels.AddRange(collector.OutputChannels); result.SanitizeChannels.AddRange(collector.SanitizeChannels); //if there are no output or input channels found in the code, it makes no sense to transform it if (result.OutputChannels.Count == 0 || result.InputChannels.Count == 0) { return(result); } var levels = collector.GetDistinctSecurityLevels().OrderByDescending(sl => sl.Level); //append a sanitize transformation if there are sanitize channels var lowestInputLevel = result.InputChannels.Min(sc => sc.Label.Level); if (result.SanitizeChannels.Any()) { var sanSourceUnit = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set); var sanNodesFactory = new BasicNodesFactory(sourceUnit); var sanErrors = new PhpErrorSink(); sanSourceUnit.Parse(sanNodesFactory, sanErrors); GlobalCode sanAst = sanSourceUnit.Ast; if (sanErrors.Count != 0) { return(result); // AST is null or invalid } var pSanitize = new CodeTransformation(); pSanitize.Kind = TransformationKind.Sanitize; pSanitize.SecurityLevel = new SecurityLevel() { Level = lowestInputLevel - 1, Name = "PS" }; var composer = new PhpTokenComposer(provider); var rewriter = new PhpChannelRewriter(new TreeContext(sanAst), composer, provider, nodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, pSanitize.SecurityLevel); rewriter.VisitElement(sanAst); pSanitize.Code = composer.Code.ToString(); result.CodeTransformations.Add(pSanitize); } //create code version for each security level foreach (var level in levels) { var levelSourceUnit = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set); var levelNodesFactory = new BasicNodesFactory(levelSourceUnit); var levelerrors = new PhpErrorSink(); levelSourceUnit.Parse(nodesFactory, levelerrors); GlobalCode levelAst = levelSourceUnit.Ast; if (levelerrors.Count != 0) { return(result); // AST is null or invalid } var version = new CodeTransformation(); version.Kind = TransformationKind.Default; version.SecurityLevel = level; var composer = new PhpTokenComposer(provider); var rewriter = new PhpChannelRewriter(new TreeContext(levelAst), composer, provider, levelNodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, level); rewriter.VisitElement(levelAst); version.Code = composer.Code.ToString(); result.CodeTransformations.Add(version); } //create P version var poSourceUnit = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set); var poNodesFactory = new BasicNodesFactory(poSourceUnit); var poErrors = new PhpErrorSink(); poSourceUnit.Parse(poNodesFactory, poErrors); GlobalCode poAst = poSourceUnit.Ast; var po = new CodeTransformation(); po.Kind = TransformationKind.Original; var poComposer = new PhpTokenComposer(provider); po.SecurityLevel = new SecurityLevel() { Level = lowestInputLevel, Name = "P'" }; var poRewriter = new PhpChannelRewriter(new TreeContext(poAst), poComposer, provider, poNodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, po.SecurityLevel, isOriginalProgram: true); poRewriter.VisitElement(poAst); po.Code = poComposer.Code.ToString(); result.CodeTransformations.Add(po); return(result); }