JavaScript Magic Tricks: Ajax hacking
Tags: javascript, webdev, programming, security
Published: 2023-09-21 23:12:39

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>
```

Execute result:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/166pnsw22ctdkjjr9hwl.png)

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>

```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rchumip7nzmcxx4m2ixv.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6k2x9m9cftjabc7ejzbz.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nc4jh7dzl02ddp2sejvq.png)

Pay attention to these two important lines of code:

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

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>
```

Execute result:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gah05eddygqpqyzd77k3.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fk6a38jzhxq8apy2rcnm.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xt31ztue1cl6lkhjj4t.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txxd7qsh8willy4twubz.png)