前端加密对抗——CDP远程调用Debug断点函数python代码实现

前端加密对抗——CDP远程调用Debug断点函数python代码实现

前几天看了看tools推送的前端加密的文章:前端加密对抗Part2-通过CDP远程调用Debug断点函数
觉得这个方法很方便,以前经常遇到开发自己改了加密代码导致同样是AES等加密算法,加密出来不一样,但是用CDP的话就能解决这个问题。上面那篇也没有具体实现的源码,于是自己研究了下,基本实现了,暂时没找到全流程加解密的站,找到了再把返回包解密的代码补上。

测试网址:某网站的登录接口。
首先设置中开启Protocol Monitor
图片.png添加协议监视器
图片.png

实现请求断点处函数

正常抓登录包,密码是加密的
图片.png在这里插入图片描述
找到加解密函数,打断点后控制台可以直接调用。
图片.png使用cdp调用加解密函数:
代码

import json
import requests
import websocket


def websocket_conn():
    # websocket_conn 连接
    resp = requests.get('http://127.0.0.1:9222/json')
    assert resp.status_code == 200
    ws_url = resp.json()[0].get('webSocketDebuggerUrl')
    return websocket.create_connection(ws_url)


def execute_cdp(conn: websocket, command: dict):
    # 执行  dp
    conn.send(json.dumps(command))
    # 接受websocket的响应,并将字符串转换为 dict()
    return json.loads(conn.recv())


def main():
    conn = websocket_conn()
    # js = "console.log('hello world')" # 控制台打印 hello world
    command = {
        'method': 'Debugger.evaluateOnCallFrame',  # 处理 传进去的 expression
        'id': int(), # id需要传一个整型,否则会报错
        'params': {
            'callFrameId': callFrameId,
            'expression': expression,
            'objectGroup': 'console',
            'includeCommandLineAPI': True,
        }
    }
    resp = execute_cdp(conn, command)
    print(resp["result"]["result"]['value'])


if __name__ == '__main__':
    callFrameId = "5889892333005756436.1.0"
    expression = 'Object(b[\"b\"])(\"123456\")'
    main()

运行发现调用加密函数加密成功!
图片.png

mitmproxy实现加解密

这里分为en_proxy.py和de_proxy.py两个文件
流程为:

浏览器数据包——>de_proxy.py(解密请求包)
——>burp(此时burp为解密的请求包)
——>en_proxy.py(burp再通过User options将请求包发给en_proxy加密,加密后发给服务器)
——>服务端(服务端返回加密的数据)
——>en_proxy.py(en_proxy还负责解密服务端发过来的数据)

首先实现de_proxy.py

from mitmproxy import http, ctx
import json
from tool.cdp3 import *


class DecryptPassword:
    # 解密请求包
    def request(self, flow: http.HTTPFlow) -> None:
        if flow.request.method == 'POST' and 'application/json' in flow.request.headers['Content-Type']:
            # 解析请求体中的JSON数据
            req_data = json.loads(flow.request.text)
            # 判断是否包含password参数
            if 'password' in req_data.keys():
                # 进行解密操作
                data = req_data['password']
                callFrameId = "5889892333005756436.1.0"
                de_expression = f'Object(b[\"a\"])(\"{data}\")'
                # 对参数进行解密
                decrypted_password = EZ_CDP(callFrameId, de_expression).encrypted()
                print(decrypted_password)
                # 修改JSON数据中的password参数值
                req_data['password'] = decrypted_password
                # 将修改后的JSON数据转换成字符串形式
                # 更新请求体中的数据
                flow.request.text = json.dumps(req_data)


addons = [
    DecryptPassword()
]

命令行执行

mitmproxy --mode upstream:http://127.0.0.1:8080 -s de_proxy.py --listen-port 8989 --ssl-insecure

--mode upstream:http://127.0.0.1:8080:设置二级代理,解密请求包后发给burp

此时,burp收到的请求包是解密的
查看经de_proxy.py处理的数据包:

在这里插入图片描述
此时,密码是解密的图片.pngburp也是收到解密包

在这里插入图片描述


BURP User options设置Upstream Proxy Serversen_proxy.py的地址,我这里是127.0.0.1:8990
图片.pngen_proxy.py实现,将burp发过来的请求包再加密发给服务端,这里其实还负责将服务端发过来的数据解密,但是由于这个网址这里只加密了密码,返回包没加密就没加这个功能,添加个response函数使用解密函数再解密一下返回包即可。

from mitmproxy import http, ctx
import json
from tool.cdp3 import *


class EncryptPassword:
    # 解密请求包
    def request(self, flow: http.HTTPFlow) -> None:
        if flow.request.method == 'POST' and 'application/json' in flow.request.headers['Content-Type']:
            # 解析请求体中的JSON数据
            req_data = json.loads(flow.request.text)
            # 判断是否包含password参数
            if 'password' in req_data.keys():
                # 进行加密操作
                data = req_data['password']
                callFrameId = "5889892333005756436.1.0"
                de_expression = f'Object(b[\"b\"])(\"{data}\")'
                # 对参数进行解密
                decrypted_password = EZ_CDP(callFrameId, de_expression).encrypted()
                print(decrypted_password)
                # 修改JSON数据中的password参数值
                req_data['password'] = decrypted_password
                # 将修改后的JSON数据转换成字符串形式
                # 更新请求体中的数据
                flow.request.text = json.dumps(req_data)


addons = [
    EncryptPassword()
]

命令行执行

mitmproxy -s en_proxy.py --listen-port 8990 --ssl-insecure

查看该数据包,可以发现发送给服务器的数据包加密了
图片.png此时发登录包
图片.png请求数据是解密的,返回内容也没问题。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
登录 CDP 集群需要使用 Kerberos 认证,可以使用 Java 的 Kerberos 相关类来实现。增删 Yarn 资源池队列可以使用 Cloudera Manager API 或者 Yarn REST API 来实现。 以下是一个简单的示例,实现登录 CDP 集群并添加 Yarn 资源池队列: ``` import java.io.File; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import org.apache.hadoop.security.UserGroupInformation; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class CdpYarnQueueExample { public static void main(String[] args) { String cdpPrincipal = "cdp-user@EXAMPLE.COM"; String cdpKeytab = "/path/to/cdp-user.keytab"; String cdpKrb5 = "/etc/krb5.conf"; String cmHost = "cm.host"; String cmUsername = "admin"; String cmPassword = "admin"; String yarnQueueName = "my_queue"; try { // Login to CDP using Kerberos authentication System.setProperty("java.security.krb5.conf", cdpKrb5); LoginContext lc = new LoginContext("CDPLogin", new CDPLoginCallbackHandler(cdpPrincipal, cdpKeytab)); lc.login(); Subject subject = lc.getSubject(); UserGroupInformation.setLoginUser(UserGroupInformation.getUGIFromSubject(subject)); // Create Yarn resource pool queue using Cloudera Manager API String cmApiUrl = "http://" + cmHost + ":7180/api/v19/clusters/my_cluster/services/yarn/yarnService"; String cmApiJson = "{\"yarnQueueConfigs\": [{\"name\": \"" + yarnQueueName + "\", \"capacity\": 10, \"maximumCapacity\": 20}]}"; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(cmApiUrl); httpPost.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType()); httpPost.setHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((cmUsername + ":" + cmPassword).getBytes())); httpPost.setEntity(new FileEntity(new File(cmApiJson), ContentType.APPLICATION_JSON)); CloseableHttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); if (entity != null) { String result = EntityUtils.toString(entity); System.out.println(result); } EntityUtils.consume(entity); response.close(); httpClient.close(); } catch (LoginException | IOException e) { e.printStackTrace(); } } } ``` 在上面的示例中,`CDPLoginCallbackHandler` 是一个自定义的回调处理器,用于加载 Kerberos keytab 并进行认证。`CDPLogin` 是一个自定义的 LoginModule,用于处理 Kerberos 认证流程。 注意,在使用 Cloudera Manager API 或者 Yarn REST API 时需要提供相应的认证信息。在示例中,使用了 Basic 认证方式,用户名和密码通过 Base64 编码后放在请求头中。具体实现可以根据自己的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值