Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject javascript into a javascript function

I've got a weird question in that I need to inject some javascript into another javascript function. I am using a framework which is locked so I can not change the existing function.

What I've got is something like this

function doSomething(){ ... }

...***

I can manipulate the ***(above) however I can not change the doSomething function... Instead I need to somehow inject a few lines of code into the end of the doSomething code.

The reason I need to do this is that the custom framework calls doSomething() and this results in an ID being returned from the server that I need to extract. This ID is only referenced inside the doSomething function so I can not catch it unless I inject code to that function (unless I've missed something).

Is there a way to do this?

like image 525
Grunt Avatar asked Jan 21 '10 11:01

Grunt


People also ask

Can you inject JavaScript?

JavaScript injection is a process by which we can insert and use our own JavaScript code in a page, either by entering the code into the address bar, or by finding an XSS vulnerability in a website. Note that the changes can only be seen by you and are not permanent.

What does it mean to inject JavaScript?

A JavaScript injection attack is a type of attack in which a threat actor injects malicious code directly into the client-side JavasScript. This allows the threat actor to manipulate the website or web application and collect sensitive data, such as personally identifiable information (PII) or payment information.

What is function () () in JavaScript?

A function in JavaScript is similar to a procedure—a set of statements that performs a task or calculates a value, but for a procedure to qualify as a function, it should take some input and return an output where there is some obvious relationship between the input and the output.


2 Answers

Alias it.

var oldDoSomething = doSomething;
doSomething = function() {
  // Do what you need to do.
  return oldDoSomething.apply(oldDoSomething, arguments);
}
like image 96
August Lilleaas Avatar answered Sep 18 '22 21:09

August Lilleaas


Altering the function by working with the source code strings can be quite simple. To do it for a specific instance, try:

eval(doSomething.toString().replace(/}\s*$/, ' return id; $&'));

Now doSomething returns the ID. I'm not normally a fan of eval, but normal aspect oriented programming techniques don't apply here, due to the requirement for accessing a local variable.

If doSomething already returns a value, try wrapping the body in a try ... finally:

eval(doSomething.toString()
    .replace(/^function *\w* *\([^)]*\) *{/, '$& try {')
    .replace(/}\s*$/, '} finally { window.someID = id; } $&')
);

To turn this into a function, we need to make the code evaluate in global scope. Originally, this answer made use of with to change the scope of the eval, but this doesn't currently work in browsers. Instead, .call is used to change the scope of eval to window.

(function () {
    var begin = /^function\s*\w*\s*\([^)]*\)\s*{/,
        end = /}\s*$/;

    function alter(func, replacer) {
        var newFunc = replacer(func.toString());
        eval.call(window, newFunc);
    }

    function insertCode(func, replacer, pattern) {
        alter(func, function (source) { 
            return source.replace(pattern, replacer);
        });
    };

    /* Note: explicit `window` to mark these as globals */
    window.before = function (func, code) {
        return insertCode(func, '$& ' + code, begin);
    };

    window.after = function (func, code) {
        return insertCode(func, code + ' $&', end);
    };

    window.around = function (func, pre, post) {
        /* Can't simply call `before` and `after`, as a partial code insertion may produce a syntax error. */
        alter(func, function(source) {
            return source
                .replace(begin, '$& ' + pre)
                .replace(end, post + ' $&');
        });
    };
})();
...
after(doSomething, 'return id;');
/* or */
around(doSomething, 'try {', '} finally { window.someID = id; }');

If you want to rewrite methods and anonymous functions bound to variables, change alter to:

...
    function alter(func, replacer) {
        var newFunc = replacer(eval('window.' + funcName).toString());
        eval.call(window, newFunc);
    }
...
function Foo() {}
Foo.prototype.bar = function () { var secret=0x09F91102; }
...
after('Foo.prototype.bar', 'return secret;');

Note the first argument to the functions are now strings. Further improvements could be made to handle methods that aren't accessible in global scope.

like image 25
outis Avatar answered Sep 20 '22 21:09

outis