【Web】Jsrpc+Mitmproxy+Burp通关encrypt-labs

目录

【第一关】AES固定key

【第二关】AES服务端获取key

【第三关】RSA加密

【第四关】AES+Rsa加密

【第五关】Des规律Key

【第六关】明文加签

【第七关】加签key在服务端

【第八关】禁止重放


encrypt-labs这种简单的场景本身用cloudx这些插件是很容易过的,但jsrpc会更通用,演示一下

首先注册全局函数

https://github.com/jxhczhl/JsRpc/blob/main/resouces/JsEnv_Dev.js

复制代码
var rpc_client_id, Hlclient = function (wsURL) {
    this.wsURL = wsURL;
    this.handlers = {
        _execjs: function (resolve, param) {
            var res = eval(param)
            if (!res) {
                resolve("没有返回值")
            } else {
                resolve(res)
            }
        }
    };
    this.socket = undefined;
    if (!wsURL) {
        throw new Error('wsURL can not be empty!!')
    }
    this.connect()
}
Hlclient.prototype.connect = function () {
    if (this.wsURL.indexOf("clientId=") === -1 && rpc_client_id) {
        this.wsURL += "&clientId=" + rpc_client_id
    }
    console.log('begin of connect to wsURL: ' + this.wsURL);
    var _this = this;
    try {
        this.socket = new WebSocket(this.wsURL);
        this.socket.onmessage = function (e) {
            _this.handlerRequest(e.data)
        }
    } catch (e) {
        console.log("connection failed,reconnect after 10s");
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.onclose = function () {
        console.log('rpc已关闭');
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.addEventListener('open', (event) => {
        console.log("rpc连接成功");
    });
    this.socket.addEventListener('error', (event) => {
        console.error('rpc连接出错,请检查是否打开服务端:', event.error);
    })
};
Hlclient.prototype.send = function (msg) {
    this.socket.send(msg)
}
Hlclient.prototype.regAction = function (func_name, func) {
    if (typeof func_name !== 'string') {
        throw new Error("an func_name must be string");
    }
    if (typeof func !== 'function') {
        throw new Error("must be function");
    }
    console.log("register func_name: " + func_name);
    this.handlers[func_name] = func;
    return true
}
Hlclient.prototype.handlerRequest = function (requestJson) {
    var _this = this;
    try {
        var result = JSON.parse(requestJson)
    } catch (error) {
        console.log("请求信息解析错误", requestJson);
        return
    }
    if (result["registerId"]) {
        rpc_client_id = result['registerId']
        return
    }
    if (!result['action'] || !result["message_id"]) {
        console.warn('没有方法或者消息id,不处理');
        return
    }
    var action = result["action"], message_id = result["message_id"]
    var theHandler = this.handlers[action];
    if (!theHandler) {
        this.sendResult(action, message_id, 'action没找到');
        return
    }
    try {
        if (!result["param"]) {
            const async_result = theHandler(function (response) {
                _this.sendResult(action, message_id, response);
            })
            if (async_result && typeof async_result.then === "function") {
                async_result.catch(e => {
                    _this.sendResult(action, message_id, "" + e);
                });
            }
            return
        }
        var param = result["param"]
        try {
            param = JSON.parse(param)
        } catch (e) {
        }
        theHandler(function (response) {
            _this.sendResult(action, message_id, response);
        }, param)
    } catch (e) {
        console.log("error: " + e);
        _this.sendResult(action, message_id, "" + e);
    }
}
Hlclient.prototype.sendResult = function (action, message_id, e) {
    if (typeof e === 'object' && e !== null) {
        try {
            e = JSON.stringify(e)
        } catch (v) {
            console.log(v)//不是json无需操作
        }
    }
    this.send(JSON.stringify({"action": action, "message_id": message_id, "response_data": e}));
}

启动jsrpc服务端

【第一关】AES固定key

注入,resolve里的部分照抄原js就行

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptaes");
demo.regAction("encryptest", function (resolve, param) {    
    // 先加密,然后对结果进行URL编码
    const encrypted = CryptoJS.AES.encrypt(param, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }).toString();
    
    const encodedResult = encodeURIComponent(encrypted);
    resolve(encodedResult);
});

注意一下传的参数

对应的去写一下mitmproxy的脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx
from urllib.parse import parse_qs


def encrypt(data):
    url = "http://127.0.0.1:12080/go"
    params = {
        "group": "encryptaes",
        "action": "encryptest",
        "param": data
    }
    response = requests.get(url, params=params)
    enctext = response.json()['data']
    return enctext


class dataencrypt:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        target_path = "/encrypt/aes.php"

        if (flow.request.method == "POST" and
                flow.request.path == target_path):

            try:
                if "encryptedData=" in flow.request.text:
                    body_params = parse_qs(flow.request.text)
                    encrypted_data_str = body_params.get('encryptedData', [''])[0]

                    json_with_quotes = json.dumps(encrypted_data_str)
                    encrypted_result = encrypt(json_with_quotes)

                    new_body = f"encryptedData={encrypted_result}"
                    flow.request.text = new_body

            except Exception:
                pass


addons = [dataencrypt()]

mitmproxy -p 9090 -s test1.py

设置bp上游代理

修改下前端发包逻辑

这样就可以抓到原始数据包

走的是全局的代理,直接赢了

也可以直接走intruder

【第二关】AES服务端获取key

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptaes2");
demo.regAction("encryptest2", function (resolve, param) {    
    const encrypted = CryptoJS.AES.encrypt(param, aesKey, {
			iv: aesIv,
			mode: CryptoJS.mode.CBC,
			padding: CryptoJS.pad.Pkcs7
		})
		.toString();
    resolve(encrypted);
});

稍微改下mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx
from urllib.parse import parse_qs

def encrypt(data):
    url = "http://127.0.0.1:12080/go"
    params = {
        "group": "encryptaes2",
        "action": "encryptest2",
        "param": data
    }
    response = requests.get(url, params=params)
    enctext = response.json()['data']
    return enctext

class dataencrypt:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        target_path = "/encrypt/aesserver.php"

        if (flow.request.method == "POST" and
                flow.request.path == target_path):

            try:
                try:
                    req_json = json.loads(flow.request.text)
                except Exception:
                    req_json = {}

                if "encryptedData" in req_json:
                    encrypted_data_str = req_json.get('encryptedData', '')
                    json_with_quotes = json.dumps(encrypted_data_str)
                    encrypted_result = encrypt(json_with_quotes)

                    req_json['encryptedData'] = encrypted_result
                    flow.request.text = json.dumps(req_json)

            except Exception:
                pass

addons = [dataencrypt()]

还是改下前端发包,直接bp拦截到明文

【第三关】RSA加密

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptrsa");
demo.regAction("encryptrsa", function (resolve, param) {    
    const encrypted = encryptor.encrypt(param);
    resolve(encrypted);
});

改下发包

改下mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt(data):
    url = "http://127.0.0.1:12080/go"
    params = {
        "group": "encryptrsa",
        "action": "encryptrsa",
        "param": data
    }
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                return res_json['data']
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_rsa:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        target_path = "/encrypt/rsa.php"
        
        if flow.request.path == target_path and flow.request.method == "POST":

            if "data" in flow.request.urlencoded_form:
                data_val = flow.request.urlencoded_form["data"]
                
                json_data = json.dumps(data_val)
                encrypted = encrypt(json_data)
                
                if encrypted:
                    flow.request.urlencoded_form["data"] = encrypted
                    ctx.log.info(f"Encrypted data for {target_path}")

addons = [encrypt_rsa()]

【第四关】AES+Rsa加密

插入hook

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptaesrsa");

demo.regAction("encryptaesrsa", function (resolve, param) {

    const jsonData = param;

    const key = CryptoJS.lib.WordArray.random(16);
    const iv = CryptoJS.lib.WordArray.random(16);

    const encryptedData = CryptoJS.AES.encrypt(jsonData, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }).toString();

    const rsa = new JSEncrypt();
    rsa.setPublicKey(`-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi 
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM 
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb 
ocDbsNeCwNpRxwjIdQIDAQAB 
-----END PUBLIC KEY-----`);

    const encryptedKey = rsa.encrypt(key.toString(CryptoJS.enc.Base64));
    const encryptedIv = rsa.encrypt(iv.toString(CryptoJS.enc.Base64));

    const result = {
        encryptedData: encryptedData,
        encryptedKey: encryptedKey,
        encryptedIv: encryptedIv
    };

    resolve(JSON.stringify(result));
});

mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt_aes_rsa(data_json_str):
    url = "http://127.0.0.1:12080/go"
    params = {
        "group": "encryptaesrsa",
        "action": "encryptaesrsa",
        "param": data_json_str
    }
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                return json.loads(res_json['data'])
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_aes_rsa_addon:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        if flow.request.method == "POST" and "encryptedKey" in flow.request.text:
            try:
                ctx.log.info("Detected AES+RSA encrypted request")
                try:
                    req_json = json.loads(flow.request.text)
                except Exception:
                    req_json = {}

                if "encryptedData" in req_json:
                    payload_to_encrypt = req_json['encryptedData']
                    if not isinstance(payload_to_encrypt, str):
                        payload_to_encrypt = json.dumps(payload_to_encrypt)
                    payload_with_quotes = json.dumps(payload_to_encrypt)

                    encrypted_package = encrypt_aes_rsa(payload_with_quotes)
  
                    if encrypted_package:
                        req_json['encryptedData'] = encrypted_package['encryptedData']
                        req_json['encryptedKey'] = encrypted_package['encryptedKey']
                        req_json['encryptedIv'] = encrypted_package['encryptedIv']
                        
                        flow.request.text = json.dumps(req_json)
                        ctx.log.info(f"Successfully re-encrypted data using payload: {payload_to_encrypt}")
                    
            except Exception as e:
                ctx.log.error(f"Error processing request: {e}")

addons = [encrypt_aes_rsa_addon()]

【第五关】Des规律Key

hook

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptdes");

demo.regAction("encryptdes", function (resolve, param) {
    var data = JSON.parse(param);
    var username = data.username;
    var password = data.password;

    const key = CryptoJS.enc.Utf8.parse(username.slice(0, 8)
        .padEnd(8, '6'));

    const iv = CryptoJS.enc.Utf8.parse('9999' + username.slice(0, 4)
        .padEnd(4, '9'));

    const encryptedPassword = CryptoJS.DES.encrypt(password, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });

    const encryptedHex = encryptedPassword.ciphertext.toString(CryptoJS.enc.Hex);

    resolve(encryptedHex);
});

改一下mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt_des(username, password):
    url = "http://127.0.0.1:12080/go"
    data = {
        "username": username,
        "password": password
    }
    
    params = {
        "group": "encryptdes",
        "action": "encryptdes",
        "param": json.dumps(json.dumps(data))
    }
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                return res_json['data']
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_des_addon:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        if flow.request.method == "POST":
            try:
                try:
                    req_json = json.loads(flow.request.text)
                except:
                    return

                if "username" in req_json and "password" in req_json:
                    username = req_json['username']
                    password = req_json['password']
                    
                    ctx.log.info(f"Intercepted plaintext password for user: {username}")
                    
                    encrypted_password = encrypt_des(username, password)
                    
                    if encrypted_password:
                        req_json['password'] = encrypted_password
                        
                        flow.request.text = json.dumps(req_json)
                        ctx.log.info(f"Replaced password with DES ciphertext: {encrypted_password}")
                        
            except Exception as e:
                ctx.log.error(f"Error processing request: {e}")

addons = [encrypt_des_addon()]

【第六关】明文加签

hook

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptsign");

demo.regAction("encryptsign", function (resolve, param) {
    var data = JSON.parse(param);
    var username = data.username;
    var password = data.password;
    const nonce = Math.random().toString(36).substring(2);
    const timestamp = Math.floor(Date.now() / 1000);

    const secretKey = "be56e057f20f883e";

    const dataToSign = username + password + nonce + timestamp;
    const signature = CryptoJS.HmacSHA256(dataToSign, secretKey).toString(CryptoJS.enc.Hex);

    const result = {
        username: username,
        password: password,
        nonce: nonce,
        timestamp: timestamp,
        signature: signature
    };

    resolve(JSON.stringify(result));
});

mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt_sign(username, password):
    url = "http://127.0.0.1:12080/go"
    data = {
        "username": username,
        "password": password
    }
    
    params = {
        "group": "encryptsign",
        "action": "encryptsign",
        "param": json.dumps(json.dumps(data))
    }
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                return json.loads(res_json['data'])
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_sign_addon:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        target_path = "/encrypt/signdata.php"
        
        if flow.request.path == target_path and flow.request.method == "POST":
            try:
                try:
                    req_json = json.loads(flow.request.text)
                except:
                    return
                if "username" in req_json and "password" in req_json and "signature" not in req_json:
                    username = req_json['username']
                    password = req_json['password']
                    
                    ctx.log.info(f"Intercepted unsigned request for user: {username}")
                    
                    signed_data = encrypt_sign(username, password)
                    
                    if signed_data:
                        flow.request.text = json.dumps(signed_data)
                        ctx.log.info(f"Replaced request with signed payload: {signed_data}")
                        
            except Exception as e:
                ctx.log.error(f"Error processing request: {e}")

addons = [encrypt_sign_addon()]

【第七关】加签key在服务端

hook

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptserver");

demo.regAction("encryptserver", function (resolve, param) {
    var data = JSON.parse(param);
    var username = data.username;
    var password = data.password;

    const timestamp = Math.floor(Date.now() / 1000);

    const signatureUrl = "/encrypt/get-signature.php"; 

    fetch(signatureUrl, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            username: username,
            password: password,
            timestamp: timestamp,
        }),
    })
    .then(response => response.json())
    .then(signData => {
        if (signData.signature) {
            const result = {
                username: username,
                password: password,
                timestamp: timestamp,
                signature: signData.signature
            };
            resolve(JSON.stringify(result));
        } else {
            resolve(JSON.stringify({ error: "Failed to get signature" }));
        }
    })
    .catch(error => {
        console.error("JSRPC signature fetch error:", error);
        resolve(JSON.stringify({ error: error.toString() }));
    });
});

mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt_server_sign(username, password):
    url = "http://127.0.0.1:12080/go"
    data = {
        "username": username,
        "password": password
    }
    
    params = {
        "group": "encryptserver",
        "action": "encryptserver",
        "param": json.dumps(json.dumps(data))
    }
    
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                return json.loads(res_json['data'])
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_server_addon:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        target_path = "/encrypt/signdataserver.php"
        
        if flow.request.path == target_path and flow.request.method == "POST":
            try:
                try:
                    req_json = json.loads(flow.request.text)
                except:
                    return

                if "username" in req_json and "password" in req_json and "signature" not in req_json:
                    username = req_json['username']
                    password = req_json['password']
                    
                    ctx.log.info(f"Intercepted unsigned request for user: {username}")
                    
                    signed_data = encrypt_server_sign(username, password)
                    
                    if signed_data:
                        if "error" in signed_data:
                            ctx.log.error(f"JSRPC Error: {signed_data['error']}")
                        else:
                            flow.request.text = json.dumps(signed_data)
                            ctx.log.info(f"Replaced request with server-side signed payload")
                        
            except Exception as e:
                ctx.log.error(f"Error processing request: {e}")

addons = [encrypt_server_addon()]

【第八关】禁止重放

hook

复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=encryptrandom");

demo.regAction("encryptrandom", function (resolve, param) {
    var data = JSON.parse(param);
    var username = data.username;
    var password = data.password;

    const timestamp = Date.now();

    const publicKey = `-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi 
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM 
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb 
ocDbsNeCwNpRxwjIdQIDAQAB 
-----END PUBLIC KEY-----`;

    function rsaEncrypt(data, key) {
        const jsEncrypt = new JSEncrypt();
        jsEncrypt.setPublicKey(key);
        const encrypted = jsEncrypt.encrypt(data.toString());
        return encrypted;
    }

    let encryptedTimestamp;
    try {
        encryptedTimestamp = rsaEncrypt(timestamp, publicKey);
        if (!encryptedTimestamp) {
            resolve(JSON.stringify({ error: "RSA encryption failed" }));
            return;
        }
    } catch (error) {
        resolve(JSON.stringify({ error: error.toString() }));
        return;
    }

    const result = {
        username: username,
        password: password,
        random: encryptedTimestamp
    };

    resolve(JSON.stringify(result));
});

mitmproxy脚本

复制代码
import mitmproxy
import requests
import json
from mitmproxy import ctx

def encrypt_random(username, password):
    url = "http://127.0.0.1:12080/go"
    data = {
        "username": username,
        "password": password
    }
    
    params = {
        "group": "encryptrandom",
        "action": "encryptrandom",
        "param": json.dumps(json.dumps(data))
    }
    
    try:
        response = requests.get(url, params=params, timeout=10)
        if response.status_code == 200:
            res_json = response.json()
            if 'data' in res_json:
                # JS 返回的是一个 JSON 字符串,需要解析为字典
                return json.loads(res_json['data'])
    except Exception as e:
        ctx.log.error(f"Encryption failed: {e}")
    return None

class encrypt_random_addon:
    def request(self, flow: mitmproxy.http.HTTPFlow):
        if flow.request.method == "POST":
            ctx.log.info(f"Checking request: {flow.request.path}")

        target_path = "/encrypt/norepeater.php"
        
        if flow.request.path == target_path and flow.request.method == "POST":
            ctx.log.info(f"Target matched: {target_path}")
            try:
                try:
                    req_json = json.loads(flow.request.text)
                    ctx.log.info(f"JSON parsed successfully: {req_json}")
                except Exception as e:
                    ctx.log.warn(f"JSON parse failed: {e}")
                    return

                has_username = "username" in req_json
                has_password = "password" in req_json
                no_random = "random" not in req_json
                
                ctx.log.info(f"Conditions - User: {has_username}, Pass: {has_password}, NoRandom: {no_random}")

                if has_username and has_password and no_random:
                    username = req_json['username']
                    password = req_json['password']
                    
                    ctx.log.info(f"Intercepted request without random field for user: {username}")
                    
                    encrypted_data = encrypt_random(username, password)
                    
                    if encrypted_data:
                        if "error" in encrypted_data:
                            ctx.log.error(f"JSRPC Error: {encrypted_data['error']}")
                        else:
                            flow.request.text = json.dumps(encrypted_data)
                            ctx.log.info(f"Replaced request with payload containing encrypted timestamp")
                        
            except Exception as e:
                ctx.log.error(f"Error processing request: {e}")

addons = [encrypt_random_addon()]
相关推荐
christine-rr5 小时前
【网络安全实验】IPSec的配置与实现
网络·计算机网络·安全·web安全·网络安全
是喵斯特ya6 小时前
常用的webshell工具流量分析
安全·web安全
pandarking6 小时前
[CTF]攻防世界:web-unfinish(sql二次注入)
前端·数据库·sql·web安全·ctf
小痞同学6 小时前
【网络安全】四、Sniffer网络安全检测
安全·web安全
儒道易行6 小时前
【钓鱼攻防】浅谈CobaltStrike钓鱼手法集锦
网络·安全·web安全·网络安全
白帽子凯哥哥18 小时前
如何从零开始搭建一个安全的渗透测试实验环境?
安全·web安全·网络安全·渗透测试·漏洞挖掘
独行soc19 小时前
2025年渗透测试面试题总结-280(题目+回答)
网络·python·安全·web安全·网络安全·渗透测试·安全狮
lifejump20 小时前
新版upload-labs报错:“Parse error...“(已解决)
web安全
Bruce_Liuxiaowei1 天前
Windows系统映像劫持:网络安全中的“李代桃僵”战术
windows·安全·web安全