Replacing eval() in MicrosoftAjax.js file with different code

478 Views Asked by At

The HTML/JS .aspx pages in my Asp.NET WebForm application use MicrosoftAjax.js file, But some security policies disallows the use of javascript eval() function. They claim that all instances of eval can be replaced by another (hopefully safer) function.

<script src="../../Scripts/MicrosoftAjax.js"></script>

How can we replace these eval() functions with different code so that the file can surpass the security validations ?

1

There are 1 best solutions below

3
Bravo On BEST ANSWER

If you're using MicrosoftAjax.js version 4.5.2, I can safely say the following probably won't break anything

The line numbers are a guide only - look for the specific code to replace

The first two are easy, single line replacements

Around line 531

Type.parse = function (typeName, ns) {
    var fn;
    if (ns) {
        fn = Sys.__upperCaseTypes[ns.getName().toUpperCase() + "." + typeName.toUpperCase()];
        return fn || null
    }
    if (!typeName)
        return null;
    if (!Type.__htClasses)
        Type.__htClasses = {};
    fn = Type.__htClasses[typeName];
    if (!fn) {
//replace next line
        fn = eval(typeName);
// with next line
        fn = typeName.split('.').reduce(function(r, v) { return r && r[v]; }, window);
//
        Type.__htClasses[typeName] = fn
    }
    return fn
};

Around line 662

Array.parse = function (value) {
    if (!value)
        return [];
    // replace next line
    return eval(value)
    // with next line
    return JSON.parse(value)
};

Next one just comment out the lines as shown

Around line 830

    fail: function (message) {
        this._appendConsole(message);
// comment out the next two lines
        //if (Sys.Browser.hasDebuggerStatement)
        //    eval("debugger")
    },

You can completely comment or remove the next function

Around line 2448

// comment out this whole function
//Sys.Serialization.JavaScriptSerializer.deserialize = function (data, secure) {
//    if (data.length === 0)
//        throw Error.argument("data", Sys.Res.cannotDeserializeEmptyString);
//    try {
//        var exp = data.replace(Sys.Serialization.JavaScriptSerializer._dateRegEx, "$1new Date($2)");
//        if (secure && Sys.Serialization.JavaScriptSerializer._jsonRegEx.test(exp.replace(Sys.Serialization.JavaScriptSerializer._jsonStringRegEx, "")))
//            throw null;
//        return eval("(" + exp + ")")
//    } catch (a) {
//        throw Error.argument("data", Sys.Res.cannotDeserializeInvalidJson)
//    }
//};

the get_object method needs to be replaced

Around line 3938

// replace this function
    get_object: function () {
        if (!this._resultObject)
            this._resultObject = Sys.Serialization.JavaScriptSerializer.deserialize(this.get_responseData());
        return this._resultObject
    },
// with this function
    get_object: function () {
        if (!this._resultObject) {
            this._resultObject = JSON.parse(this.get_responseData(), function wcfReviver(key, value) {
                if (typeof value !== "string") {
                    return value;
                }
                var d = value.match(/^\/Date\((-?\d+)(?:[+-]\d{4}|)\)\/$/);
                return d && d.length === 2 ? new Date(+d[1]) : value;
            });
        }
        return this._resultObject
    },

And another, simple, single line replacement

Around line 4166

    executeRequest: function (webRequest) {
        var executor = webRequest.get_executor();
        if (!executor) {
            var failed = false;
            try {
// replace next line
                var executorType = eval(this._defaultExecutorType);
// with next line
                var executorType = this._defaultExecutorType.split('.').reduce(function(r, v) { return r && r[v]; }, window);
// 
                executor = new executorType
            } catch (a) {
                failed = true
            }
            webRequest.set_executor(executor)
        }
        if (executor.get_aborted())
            return;
        var evArgs = new Sys.Net.NetworkRequestEventArgs(webRequest),
        handler = this._get_eventHandlerList().getHandler("invokingRequest");
        if (handler)
            handler(this, evArgs);
        if (!evArgs.get_cancel())
            executor.executeRequest()
    }

I can confirm that I applied these changes to a a development testing site, and it kept working. I even applied it to the production version of the site for one sparsely used section that, for some reason specifically loads MicrosoftAjax.js (in the rest of our site using, this file is loaded as part of a common header), and nothing broke there either - I then even tried changing the global common section, and the production site didn't skip a beat.

That said, no warranties implied or given, if you break something you get to keep all pieces.