DEV Community

WangLiwen
WangLiwen

Posted on • Updated on

JavaScript Magic Tricks: Ajax hacking

When communicating between the front-end and back-end, Ajax (Asynchronous Javascript And XML) is commonly used. In this article, a technique is demonstrated: intercepting and modifying data sent and received through Ajax.

Technical Principle

During Ajax communication, the open and send methods are used to send data, and the data return is obtained through the onreadystatechange event. To intercept bi-directional Ajax data, it is necessary to take over these methods.

Example code:

<script>
    (function(){

        //接管open、send方法
        var open = XMLHttpRequest.prototype.open;
        var send = XMLHttpRequest.prototype.send;

        //open
        XMLHttpRequest.prototype.open = function (method, url) {

            console.log("发送:",method,url);
            open.call(this, method, url);
        };

        //send
        XMLHttpRequest.prototype.send = function () {

            //接收数据
            this.onreadystatechange = function(res){
                if (this.readyState == 4 && this.status == 200) {

                    console.log("接收:",JSON.parse(res.target.response).content);

                    return true;
                }
            };

            send.apply(this, arguments);
        };
    })();
</script>
Enter fullscreen mode Exit fullscreen mode

Execute result:

Image description

In this way, it is simple to implement monitoring of sent and received data.

Modifying Data

To demonstrate modifying the upstream and downstream data, let's prepare another piece of code:

<html>
<head>
    <script src="http://www.jshaman.com/js/jquery-3.5.1.min.js"></script>
</head>
<body>
<h3>Ajax方法,调用JShaman接口混淆加密JS代码</h3>
JS代码:<br>
<textarea id="free_code_source" style="width: 550px; height:100px">
function get_copyright(){
    var domain = "jshaman.com";
    var from_year = 2017;
    var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
    return copyright;
}
console.log(get_copyright());
</textarea>
<br><br>
<input type="button" value="混淆加密" onclick="free_example()">
<br><br>
<script>
    function free_example(){
        $.ajax({
            url: "http://www.jshaman.com:800/submit_js_code/",
            dataType: "json",
            data : {
                //JS代码
                "js_code": document.getElementById("free_code_source").value,
                //VIP码,调用JSHaman免费接口,此处必须为"free"
                "vip_code": "free"
            },
            method: "POST"
        }).done(function (res) {
            //返回结果
            document.getElementById("free_code_result").value = JSON.stringify(res);
        }).fail(function(e){
            alert("发生了未知错误!");
            console.log(e)
        });
    }
</script>
混淆加密结果:<br>
<textarea id="free_code_result" style="width: 550px; height:100px">
</textarea>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

This code uses jQuery to call the JShaman API in Ajax mode for JavaScript code obfuscation. This example demonstrates how to modify the URL and returned data during the request.

URL Modification

As shown in the above code, when making the request, the URL is using the HTTP protocol.

Image description

You can modify the URL in the interception function for the open method in the initial code to change the HTTP request to an HTTPS request and replace "800" with "4430".

Image description

Note: This can also be used to modify the request method and request data depending on the actual usage, such as possible username, password, parameters, etc.

Return Data Modification

In the data reception function, the returned data can also be modified.

Image description

Pay attention to these two important lines of code:

Object.defineProperty(this, 'response', { writable: true });
Object.defineProperty(this, 'responseText', { writable: true });
Enter fullscreen mode Exit fullscreen mode

They are the key to implementing the modification of return values, and they set some field attributes that are defaulted to read-only, to writable here.

Full source code

<script>
    (function(){

        //接管open、send方法
        var open = XMLHttpRequest.prototype.open;
        var send = XMLHttpRequest.prototype.send;

        //open
        XMLHttpRequest.prototype.open = function (method, url) {

            url = "https://www.jshaman.com:4430/submit_js_code/";

            console.log("发送:",method,url);
            open.call(this, method, url);
        };

        //send
        XMLHttpRequest.prototype.send = function () {

            //接收数据
            this.onreadystatechange = function(res){
                if (this.readyState == 4 && this.status == 200) {

                    console.log("接收:",JSON.parse(res.target.response).content);

                    Object.defineProperty(this, 'response', { writable: true });
                    Object.defineProperty(this, 'responseText', { writable: true });

                    res.target.response = JSON.stringify({"status":0,"message":"恭喜,保护成功!","content":"/*Obfuscated by JShaman.com*/function demo(){alert(\"moc.namahsj.www olleh\".split(\"\").reverse().join(\"\"));}demo();"});
                    res.target.responseText = JSON.stringify({"status":0,"message":"恭喜,保护成功!","content":"/*Obfuscated by JShaman.com*/function demo(){alert(\"moc.namahsj.www olleh\".split(\"\").reverse().join(\"\"));}demo();"});

                    console.log("修改后的数据:",JSON.parse(res.target.response).content);

                    return true;
                }
            };

            send.apply(this, arguments);
        };
    })();
</script>

<html>
<head>
    <script src="http://www.jshaman.com/js/jquery-3.5.1.min.js"></script>
</head>
<body>
<h3>Ajax方法,调用JShaman接口混淆加密JS代码</h3>
JS代码:<br>
<textarea id="free_code_source" style="width: 550px; height:100px">
function get_copyright(){
    var domain = "jshaman.com";
    var from_year = 2017;
    var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
    return copyright;
}
console.log(get_copyright());
</textarea>
<br><br>
<input type="button" value="混淆加密" onclick="free_example()">
<br><br>
<script>
    function free_example(){
        $.ajax({
            url: "http://www.jshaman.com:800/submit_js_code/",
            dataType: "json",
            data : {
                //JS代码
                "js_code": document.getElementById("free_code_source").value,
                //VIP码,调用JSHaman免费接口,此处必须为"free"
                "vip_code": "free"
            },
            method: "POST"
        }).done(function (res) {
            //返回结果
            document.getElementById("free_code_result").value = JSON.stringify(res);
        }).fail(function(e){
            alert("发生了未知错误!");
            console.log(e)
        });
    }
</script>
混淆加密结果:<br>
<textarea id="free_code_result" style="width: 550px; height:100px">
</textarea>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Execute result:

Image description

Pay attention to the output in the console, as shown in the figure, both the sending and receiving data have been modified.

This technique can be applied to many scenarios. For example, it can be used to modify important Ajax data during interception: when calling an Ajax interface, the data written is A, but in the interception function, it is written as B to confuse others.

At the same time, the data returned by the server is C, but in the interception function, it is modified to D before being displayed or used.

Alternatively, if the service returns encrypted data (which can prevent data from being sniffed and leaked), it can be decrypted in the interception function.

In this process, the logic in the interception function is crucial. We can also encrypt the code of the interception function, for example, the send function modifies the returned data.

Image description

Using JShaman to encrypt and obfuscate this piece of code, the encrypted code can be:

Image description

This protects the important functional logic without any impact on its functionality.

Image description

Top comments (2)

Collapse
 
cyberfiducia profile image
CyberFiducia

Beautiful technical piece. Thanks!

Collapse
 
wangliwen profile image
WangLiwen
alert(":-D");
Enter fullscreen mode Exit fullscreen mode