Sean Kenny

Web Api and AngularJS - JSON Vulnerability Protection Filter

permalink

The Issue

From the AngularJS documentation

A JSON vulnerability allows third party website to turn your JSON resource URL into JSONP request under some conditions. To counter this your server can prefix all JSON requests with following string “)]}‘,\n”. Angular will automatically strip the prefix before processing it as JSON.

Phil Haack outlines the issue here.

Can we automatically prepend ")]}',\n" in Web Api? Sure!

The code

I’m going to create a custom JsonConverter by extending the Newtonsoft one that web api uses out of the box:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class AngularArrayConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(")]}',\n");

        writer.WriteStartArray();

        var items = value as IEnumerable;
        if (items == null)
        {
            return;
        }

        foreach (var item in items)
        {
            serializer.Serialize(writer, item, item.GetType());
        }
        writer.WriteEndArray();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        // string is an IEnumerable.  This will ensure this converter is only used for arrays
        return !(objectType == typeof(string)) && typeof(IEnumerable).IsAssignableFrom(objectType);
    }

    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
}

Then just plug it in using the WebApiConfig.cs class:

1
2
3
4
5
6
7
public static void Register(HttpConfiguration config)
{
    // other config stuff here
    ...

    config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new AngularArrayConverter());
}

Now using fiddler or wireshark we can see the results:

1
2
)]}',
[{"id":1,"name":"Sean"},{"id":2,"name":"Mike"}]

AngularJS will handle this automagically as per their documentation.

HTH someone.

Comments