在反序列化

时间:2015-09-21 15:11:54

标签: c# json security xss

我正在使用Newtonsoft JSON反序列化器。如何为XSS(跨站点脚本)清理JSON?在反序列化或编写某种自定义转换器/消毒剂之前清理JSON字符串?如果是这样 - 我不是百分之百确定最好的方法来解决这个问题。

下面是注入了危险脚本并需要“清理”的JSON示例。我希望在我对其进行反序列化之前管理它。但我们需要假设所有类型的XSS场景,包括BASE64编码脚本等,所以问题更复杂,简单的REGEX字符串替换。

{ "MyVar" : "hello<script>bad script code</script>world" } 

以下是我的反序列化程序(JSON - &gt; Object)的快照:

public T Deserialize<T>(string json)
{
    T obj;

    var JSON = cleanJSON(json); //OPTION 1 sanitize here

    var customConverter = new JSONSanitizer();// OPTION 2 create a custom converter

    obj = JsonConvert.DeserializeObject<T>(json, customConverter);

    return obj;
}

JSON是从第三方UI界面发布的,所以它公平,因此服务器端验证。从那里,它被序列化为各种对象,并且通常存储在DB中,以后可以直接在基于HTML的UI中检索和输出,因此必须减轻脚本注入。

2 个答案:

答案 0 :(得分:3)

好的,我将尝试来保持这个相当短的时间,因为写下整个内容需要做很多工作。但是,基本上,您需要关注需要清理的数据的上下文。根据对原始帖子的评论,听起来JSON中的某些值将被用作将呈现的HTML,并且此HTML来自不受信任的来源。

第一步是提取需要作为HTML进行清理的JSON值,并且对于每个对象,您需要通过HTML解析器运行它们并剥离不在白名单中的所有内容。别忘了你还需要一个白名单属性。

HTML Agility Pack是在C#中解析HTML的一个很好的起点。在我看来,如何做这部分是一个单独的问题 - 可能是链接问题的重复。

我认为你对base64字符串的担心似乎有点过分强调了。它不像您可以简单地将aW5zZXJ0IGg0eCBoZXJl放入HTML文档中,浏览器将呈现它。它可以通过javascript(你的白名单会阻止它)以及在某种程度上通过data:网址滥用(但这不是坏事,因为javascript将在数据页面的上下文中运行。很好,但你不会自动吞噬饼干)。如果您必须允许a标记,则部分过程需要验证URL是否为http(s)(或您想要允许的任何方案)。

理想情况下,你会避免这种不舒服的情况,而是使用类似markdown的东西 - 那么你可以简单地转义HTML字符串,但这并不总是我们可以控制的。您仍然需要进行一些URL验证。

答案 1 :(得分:2)

有趣!!谢谢你的询问。我们通常在Web表单方面使用html.urlencode。我有一个运行的企业web api,它有这样的验证。我们创建了一个自定义正则表达式来验证。请看一下这个 MSDN link

这是为解析名为KeyValue(例如)

的请求而创建的示例模型
public class KeyValue
{
    public string Key { get; set; }
}

第1步:尝试使用自定义正则表达式

var json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";

        JArray readArray = JArray.Parse(json);
        IList<KeyValue> blogPost = readArray.Select(p => new KeyValue { Key = (string)p["MyVar"] }).ToList();

        if (!Regex.IsMatch(blogPost.ToString(),
           @"^[\p{L}\p{Zs}\p{Lu}\p{Ll}\']{1,40}$"))
            Console.WriteLine("InValid");
            //           ^ means start looking at this position.
            //           \p{ ..} matches any character in the named character class specified by {..}.
            //           {L} performs a left-to-right match.
            //           {Lu} performs a match of uppercase.
            //           {Ll} performs a match of lowercase.
            //           {Zs} matches separator and space.
            //           'matches apostrophe.
            //            {1,40} specifies the number of characters: no less than 1 and no more than 40.
            //            $ means stop looking at this position.

第2步:使用HttpUtility.UrlEncode - this newtonsoft website link建议以下实施。

string json = @"[{ 'MyVar' : 'hello<script>bad script code</script>world' }]";

        JArray readArray = JArray.Parse(json);
        IList<KeyValue> blogPost = readArray.Select(p => new KeyValue {Key =HttpUtility.UrlEncode((string)p["MyVar"])}).ToList();