Skip to content

Commit 46efe08

Browse files
committed
feat: 增加响应内容加密的靶场示例
1 parent 81941da commit 46efe08

File tree

6 files changed

+732
-110
lines changed

6 files changed

+732
-110
lines changed

goat/jsonp-response-encrypt/README.md

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
1-
# JSONP加密通信破解靶场
2-
3-
# 一、靶场简介
4-
这是一个靶场,用于演示一个页面,通过jsonp与后端通讯,并且通讯内容是加密的,这是请求:
5-
6-
![image-20250106023428688](./README.assets/image-20250106023428688.png)
7-
8-
响应:
9-
10-
![image-20250106023534246](./README.assets/image-20250106023534246.png)
11-
12-
而我们的目标就是借助js-script-hook来分析明白前后端通讯的逻辑。
13-
14-
# 二、启动靶场
15-
16-
启动server:
17-
18-
```bash
19-
node main.js
20-
```
21-
22-
打开前端页面:
23-
24-
```bash
25-
client.html
26-
```
27-
28-
# 三、分析
29-
30-
31-
32-
33-
34-
35-
36-
37-
38-
39-
40-
41-
42-
43-
44-
45-
46-
47-
1+
# JSONP 响应解密示例
2+
3+
## 简介
4+
演示前端通过 JSONP 发送明文请求,后端返回加密响应,前端解密后展示。
5+
6+
## 快速开始
7+
1. **克隆项目**:
8+
```bash
9+
git clone https://github.com/your-repo/jsonp-response-decryption-example.git
10+
cd jsonp-response-decryption-example
11+
```
12+
13+
2. **启动后端**:
14+
```bash
15+
cd backend
16+
npm install express crypto-js
17+
node server.js
18+
```
19+
20+
3. **运行前端**:
21+
打开 `frontend/index.html` 文件。
22+
23+
## 功能
24+
- **前端**: 发送明文请求,接收并解密加密响应。
25+
- **后端**: 接收明文请求,返回加密的 JSONP 响应。
26+
27+
## 代码结构
28+
- `frontend/index.html`: 前端页面。
29+
- `backend/server.js`: 后端服务器。
30+
31+
## 示例
32+
- **前端请求**:
33+
```javascript
34+
jsonpRequest("http://localhost:3000/api", "handleResponse", inputData);
35+
```
36+
- **后端响应**:
37+
```javascript
38+
res.jsonp(encryptedResponse);
39+
```
40+
41+
---
42+
43+
简洁明了,适合快速了解项目!

goat/jsonp-response-encrypt/client.html

Lines changed: 165 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,189 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>JSONP Example</title>
6+
<title>JSONP 响应解密示例</title>
7+
<!-- 引入 CryptoJS 库 -->
78
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
9+
<style>
10+
/* 全局样式 */
11+
body {
12+
margin: 0;
13+
height: 100vh;
14+
display: flex;
15+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16+
color: #333; /* 深色文字 */
17+
background: linear-gradient(135deg, #ff9a9e, #fad0c4); /* 亮色渐变背景 */
18+
overflow: hidden;
19+
}
20+
21+
/* 分屏布局 */
22+
.split-container {
23+
display: flex;
24+
width: 100%;
25+
height: 100%;
26+
}
27+
28+
/* 左侧操作区 */
29+
.left-pane {
30+
flex: 1;
31+
background: rgba(255, 255, 255, 0.3); /* 半透明白色背景 */
32+
backdrop-filter: blur(10px); /* 毛玻璃效果 */
33+
padding: 2rem;
34+
display: flex;
35+
flex-direction: column;
36+
justify-content: center;
37+
align-items: center;
38+
border-right: 1px solid rgba(255, 255, 255, 0.5); /* 浅色边框 */
39+
}
40+
41+
/* 右侧结果区 */
42+
.right-pane {
43+
flex: 1;
44+
background: rgba(255, 255, 255, 0.3); /* 半透明白色背景 */
45+
backdrop-filter: blur(10px); /* 毛玻璃效果 */
46+
padding: 2rem;
47+
display: flex;
48+
flex-direction: column;
49+
justify-content: center;
50+
align-items: center;
51+
}
52+
53+
/* 标题 */
54+
h1 {
55+
margin: 0 0 1.5rem;
56+
font-size: 1.8rem;
57+
font-weight: 600;
58+
color: #ff6f61; /* 亮色标题 */
59+
}
60+
61+
/* 输入框 */
62+
input {
63+
width: 100%;
64+
max-width: 300px;
65+
padding: 0.75rem;
66+
font-size: 1rem;
67+
border: none;
68+
border-radius: 8px;
69+
background: rgba(255, 255, 255, 0.8); /* 半透明白色背景 */
70+
color: #333; /* 深色文字 */
71+
outline: none;
72+
margin-bottom: 1rem;
73+
}
74+
75+
input::placeholder {
76+
color: rgba(51, 51, 51, 0.7); /* 深色占位符 */
77+
}
78+
79+
/* 按钮 */
80+
button {
81+
width: 100%;
82+
max-width: 300px;
83+
padding: 0.75rem;
84+
font-size: 1rem;
85+
border: none;
86+
border-radius: 8px;
87+
background: #ff6f61; /* 亮色按钮 */
88+
color: #fff; /* 白色文字 */
89+
cursor: pointer;
90+
transition: background 0.3s ease;
91+
}
92+
93+
button:hover {
94+
background: #ff4a3d; /* 悬停时稍暗的亮色 */
95+
}
96+
97+
/* 结果展示 */
98+
.result {
99+
width: 100%;
100+
max-width: 500px;
101+
height: 300px;
102+
padding: 1rem;
103+
background: rgba(255, 255, 255, 0.8); /* 半透明白色背景 */
104+
border-radius: 8px;
105+
font-size: 0.9rem;
106+
color: #333; /* 深色文字 */
107+
word-wrap: break-word;
108+
overflow-y: auto;
109+
border: 1px solid rgba(255, 255, 255, 0.5); /* 浅色边框 */
110+
}
111+
</style>
8112
</head>
9113
<body>
10-
<h1>JSONP Example</h1>
11-
<div id="result"></div>
114+
<div class="split-container">
115+
<!-- 左侧操作区 -->
116+
<div class="left-pane">
117+
<h1>JSONP 响应解密</h1>
118+
<input type="text" id="inputData" placeholder="请输入数据">
119+
<button id="sendRequest">发送请求</button>
120+
</div>
12121

13-
<script>
14-
15-
// 加密密钥(与后端一致)
16-
const SECRET_KEY = 'CC11001100';
122+
<!-- 右侧结果区 -->
123+
<div class="right-pane">
124+
<h1>解密结果</h1>
125+
<div class="result" id="resultContainer">结果将显示在这里...</div>
126+
</div>
127+
</div>
17128

18-
// 加密函数
19-
function encryptData(data) {
20-
return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString();
129+
<script>
130+
// 加密函数(使用 DES)
131+
function encryptData(data, secretKey) {
132+
return CryptoJS.DES.encrypt(data, secretKey).toString();
21133
}
22134

23-
// 解密函数
24-
function decryptData(encryptedData) {
25-
const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
135+
// 解密函数(使用 DES)
136+
function decryptData(encryptedData, secretKey) {
137+
const bytes = CryptoJS.DES.decrypt(encryptedData, secretKey);
26138
return bytes.toString(CryptoJS.enc.Utf8);
27139
}
28140

29-
// JSONP 请求
30-
function fetchData() {
31-
const data = { name: 'CC11001100' };
32-
const encryptedData = encryptData(data);
33-
141+
// JSONP 请求函数
142+
function jsonpRequest(url, callbackName, data) {
34143
const script = document.createElement('script');
35-
script.src = `http://localhost:3000/api/data?encryptedData=${encodeURIComponent(encryptedData)}&callback=handleResponse`;
144+
script.src = `${url}?callback=${callbackName}&data=${encodeURIComponent(data)}`;
36145
document.body.appendChild(script);
146+
147+
// 请求完成后移除 script 标签
148+
script.onload = function () {
149+
document.body.removeChild(script);
150+
};
37151
}
38152

39-
// 处理 JSONP 响应
153+
// 回调函数,用于处理服务器返回的加密数据
40154
function handleResponse(encryptedResponse) {
41-
const decryptedResponse = decryptData(encryptedResponse);
42-
const responseData = JSON.parse(decryptedResponse);
155+
const resultContainer = document.getElementById('resultContainer');
156+
const secretKey = "my-secret-key"; // 解密密钥(需要与服务器一致)
43157

44-
document.getElementById('result').innerText = responseData.message;
158+
try {
159+
// 解密数据
160+
const decryptedData = decryptData(encryptedResponse, secretKey);
161+
resultContainer.textContent = JSON.stringify(JSON.parse(decryptedData), null, 2);
162+
} catch (error) {
163+
resultContainer.textContent = "解密失败,请检查密钥或数据格式。";
164+
}
45165
}
46166

47-
// 发起请求
48-
fetchData();
167+
// 初始化随机值
168+
function generateRandomValue() {
169+
const randomData = {
170+
name: "User" + Math.floor(Math.random() * 1000),
171+
age: Math.floor(Math.random() * 100)
172+
};
173+
return JSON.stringify(randomData);
174+
}
175+
176+
// 页面加载时初始化输入框
177+
document.addEventListener('DOMContentLoaded', function () {
178+
const inputData = document.getElementById('inputData');
179+
inputData.value = generateRandomValue();
180+
});
181+
182+
// 绑定按钮点击事件
183+
document.getElementById('sendRequest').addEventListener('click', function () {
184+
const inputData = document.getElementById('inputData').value;
185+
186+
// 发送 JSONP 请求
187+
jsonpRequest("http://localhost:3000/api", "handleResponse", inputData);
188+
});
49189
</script>
50190
</body>
51191
</html>

goat/jsonp-response-encrypt/package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

goat/jsonp-response-encrypt/package.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,7 @@
33
"version": "1.0.0",
44
"main": "index.js",
55
"license": "MIT",
6-
"description": "这是一个jsonp请求的响应被加密的例子。",
7-
"scripts": {
8-
"test": "echo \"Error: no test specified\" && exit 1",
9-
"start": "node server.js"
10-
},
11-
"keywords": [],
12-
"author": "",
136
"dependencies": {
14-
"body-parser": "^1.20.3",
157
"crypto-js": "^4.2.0",
168
"express": "^4.21.2"
179
}

goat/jsonp-response-encrypt/server.js

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,35 @@
11
const express = require('express');
2-
const bodyParser = require('body-parser');
32
const CryptoJS = require('crypto-js');
4-
53
const app = express();
6-
const port = 3000;
7-
8-
// 加密密钥
9-
const SECRET_KEY = 'CC11001100';
104

11-
// 解密函数
12-
function decryptData(encryptedData) {
13-
const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
14-
return bytes.toString(CryptoJS.enc.Utf8);
5+
// 加密函数(使用 DES)
6+
function encryptData(data, secretKey) {
7+
return CryptoJS.DES.encrypt(JSON.stringify(data), secretKey).toString();
158
}
169

17-
// 加密函数
18-
function encryptData(data) {
19-
return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString();
20-
}
21-
22-
app.use(bodyParser.urlencoded({extended: true}));
23-
app.use(bodyParser.json());
24-
2510
// JSONP 接口
26-
app.get('/api/data', (req, res) => {
27-
const encryptedData = req.query.encryptedData;
28-
const decryptedData = decryptData(encryptedData);
11+
app.get('/api', (req, res) => {
12+
const callbackName = req.query.callback;
13+
const requestData = req.query.data;
2914

30-
console.log('Received decrypted data:', decryptedData);
15+
console.log("接收到的请求数据:", requestData);
3116

32-
// 处理数据(这里简单返回接收到的数据)
33-
const responseData = {message: `Hello, ${decryptedData}`};
17+
// 模拟响应数据
18+
const responseData = {
19+
status: "success",
20+
message: "请求成功!",
21+
requestData: requestData
22+
};
3423

3524
// 加密响应数据
36-
const encryptedResponse = encryptData(responseData);
25+
const secretKey = "my-secret-key"; // 加密密钥(需要与前端一致)
26+
const encryptedResponse = encryptData(responseData, secretKey);
3727

3828
// 返回 JSONP 响应
39-
const callback = req.query.callback;
40-
res.send(`${callback}('${encryptedResponse}')`);
29+
res.jsonp(encryptedResponse);
4130
});
4231

43-
app.listen(port, () => {
44-
console.log(`Server is running on http://localhost:${port}`);
32+
// 启动服务器
33+
app.listen(3000, () => {
34+
console.log('服务器运行在 http://localhost:3000');
4535
});

0 commit comments

Comments
 (0)