AndreyAkinshin / knockout-mvc

Power of Knockout.js for ASP.NET MVC
http://knockoutmvc.com
203 stars 125 forks source link

HTML injection in KnockoutContext.Apply(Model) and Initialize(Model) #59

Open mayorovp opened 6 years ago

mayorovp commented 6 years ago

Example form to reproduce:

@model WebApplication.Models.DefaultModel
@{
    var ko = new KnockoutContext<WebApplication.Models.DefaultModel>(ViewContext);
}

<form>
    @ko.Html.TextBox(m => m.Foo)
    @ko.Html.Span(m => m.Foo)
    <button type="submit">Send</button>
</form>

@ko.Apply(Model)

model:

public class DefaultModel
{
    public string Foo { get; set; }
}

action:

[ValidateInput(false)] // turn off XSS protection in ASP.NET
public ActionResult Index(Models.DefaultModel model)
{
    Response.AddHeader("X-XSS-Protection", "0"); // turn off XSS protection in browser

    return View(model ?? new Models.DefaultModel());
}

Steps to reproduce:

  1. Type </script><script>alert('XSS');</script><script> into textbox
  2. press Enter

Vulnerable line: https://github.com/AndreyAkinshin/knockout-mvc/blob/959da9986fdff0553dcb0f4731a1d13047ca2f7b/PerpetuumSoft.Knockout/KnockoutContext.cs#L61

Possible solution:

sb.AppendLine(string.Format("var {0}Js = {1};", ViewModelName, json.Replace("<", "\\u003c")));

Workaround:

@{ 
    var script = ko.Apply(Model).ToString();
    var p1 = script.IndexOf('>');
    var p2 = script.LastIndexOf('<');
    WriteLiteral(script.Substring(0, p1) + script.Substring(p1, p2 - p1).Replace("<", "\\u003c") + script.Substring(p2));
}