乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JsRpc與Burp Suite聯(lián)動 自動化加解密的完整實戰(zhàn)指南(詳細版)|挖洞技巧

       zZ華 2025-06-16 發(fā)布于廣東

      0x01 前言 

             在滲透測試中,前端加密的請求數(shù)據(jù)常常增加分析難度,傳統(tǒng)的手動逆向加解密效率低下且耗時。JsRpc通過WebSocket與客戶端通信,結(jié)合Burp Suite的插件(如Galaxy)或代理工具(如mitmproxy),可實現(xiàn)請求與響應的自動加解密,極大提升測試效率。本文整合兩篇教程,詳細解析JsRpc與Burp Suite聯(lián)動的實現(xiàn)原理與步驟,涵蓋環(huán)境搭建、函數(shù)注冊、腳本配置及實戰(zhàn)效果展示,幫助安全從業(yè)者快速掌握自動化加解密技術(shù)。

      練手地址:

      https://github.com/0ctDay/encrypt-decrypt-vulsJsRpc:https://github.com/jxhczhl/JsRpc

      參考文章:https://xz.aliyun.com/news/16886

      https://xz.aliyun.com/news/14689

      現(xiàn)在只對常讀和星標的公眾號才展示大圖推送,建議大家把滲透安全HackTwo設為星標”,否則可能就看不到了啦!

      末尾可領(lǐng)取挖洞資料文件 #滲透安全HackTwo

      0x02 漏洞詳情

      JsRpc基本使用

      首先觀察一下原始的數(shù)據(jù)包

      圖片

      可以看到除了請求體需要解密,還有請求頭中的timestamp、requestId、sign 需要實時更新,所以請求包中總共有四個地方需要處理,由于是直接只用JsRpc,那么就只需要找到對應的處理位置然后調(diào)用即可,不需要弄清楚具體的處理邏輯

      圖片
      圖片

      可以看到就是圖中的幾個地方處理的,具體邏輯就不分析了,主要是學會使用jsrpc

      首先把這幾個函數(shù)先提升到全局,需要先斷點讓其加載到作用域

      圖片

      然后在控制臺執(zhí)行下面語句提升至全局作用域

      window.requestId=p//requestIdwindow.v1 = v//函數(shù)vwindow.sign=a.a.MD5//簽名signwindow.l=lwindow.d=d
      圖片

      然后注入jsrpc中的js文件JsEnv_Dev.js ,注意注js的時候斷點就得停止了

      圖片

      然后啟動jsrpc服務端

      圖片

      再客戶端連接

      var demo = new Hlclient('ws://127.0.0.1:12080/ws?group=zzz');
      圖片

      連接成功后服務端會提示新上線….然后就是將函數(shù)注冊進去,即我們要怎么處理值

      demo.regAction('encode',function (resolve,param) {    n=JSON.stringify(v1(param))    var request = l(n)    var time = Date.parse(new Date);    var id=requestId()    var sg = sign(n+id+time).toString()    var data={'time':'','id':'','sign':'','request':''}    data['time']=time.toString()    data['id']=id    data['sign']=sg    data['request'] = request    resolve(data);})

      上面是加密,下面是解密

      demo.regAction('decode'function (resolve,param) {    //這樣添加了一個param參數(shù),http接口帶上它,這里就能獲得    var response = d(param)    resolve(response);})
      圖片

      此時就可以測試一下jsrpc處理是否能成功

      圖片
      http://127.0.0.1:12080/go?group=zzz&action=encode&param={'password':'123123','username':'asd','validCode':'ycpa'}

      可以看到加密是沒有任何問題的,zzz就是加入的組和你一開始連接的時候相同即可,action 即你注冊的加密函數(shù),param 就是你要處理的參數(shù),看看解密

      圖片

      也是能夠正常處理的

      JsRpc聯(lián)動burp

      聯(lián)動burp需要借助mitmproxy寫腳本,或者借助其它一些burp插件也行,這里就用mitmproxy了,腳本借助gpt弄幾下即可

      import requestsimport jsonfrom mitmproxy import ctx
      def get_rpc(param):    url = 'http://127.0.0.1:12080/go'    params = {        'group''zzz',        'action''encode',        'param': param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)        # ctx.log.info(f'RPC Response: {result.text}')        # 第一次解析 JSON,獲取外層結(jié)構(gòu)        outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的內(nèi)層數(shù)據(jù)    except Exception as e:        ctx.log.error(f'Error in get_rpc: {str(e)}')        return None
      def get_responseRpc(param):    url = 'http://127.0.0.1:12080/go'    params = {        'group''zzz',        'action''decode',        'param': param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)
              outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的內(nèi)層數(shù)據(jù)    except Exception as e:        ctx.log.error(f'Error in get_rpc: {str(e)}')        return None
      def request(flow):    original_body = flow.request.content    ctx.log.info(f'原始請求體: {original_body}')
          result = get_rpc(original_body)    if result is None:        ctx.log.error('RPC failed, skipping request modification')        return
          try:        # 直接使用內(nèi)層數(shù)據(jù)        flow.request.headers['timestamp'] = result['time']        flow.request.headers['requestId'] = result['id']        flow.request.headers['sign'] = result['sign']        flow.request.content = result['request'].encode('utf-8')        flow.request.headers['Content-Length'] = str(len(flow.request.content))        ctx.log.info(f'加密后的請求體: {flow.request.content}')
          except Exception as e:        ctx.log.error(f'Error in request: {str(e)}')
      def response(flow):    response_body = flow.response.content    ctx.log.info(f'響應體: {response_body}')
          result = get_responseRpc(response_body)    if result is None:        ctx.log.error('Response RPC failed, keeping original response')        return
          try:        # 將解碼后的字典轉(zhuǎn)為 JSON 字符串并編碼為字節(jié)        decoded_json = json.dumps(result, ensure_ascii=False).encode('utf-8')        flow.response.content = decoded_json        flow.response.headers['Content-Length'] = str(len(flow.response.content))        # 可選:設置 Content-Type 為 JSON        flow.response.headers['Content-Type'] = 'application/json; charset=utf-8'        ctx.log.info(f'解碼后的響應體: {flow.response.content}')    except Exception as e:        ctx.log.error(f'Error in response: {str(e)}')

      然后設置burp的上游代理

      圖片

      運行腳本

      mitmdump -p 8081 -s .\JsPython.py 
      圖片

      這樣即可實現(xiàn)自動化加解密

      當密碼不正確時

      圖片

      當密碼正確時,這里請求頭中的三個值在burp雖然沒變但實際上是已經(jīng)改變了的,因為是在腳本中做的處理

      圖片

      還是非常方便滴,因為不需要去逆js了,接下來是

      JsRpc+Galaxy工具實現(xiàn)網(wǎng)站HTTP報文自動加解密+自動更新簽名

      Galaxy工具

      可以做到在請求/響應在客戶端/Burp/服務端流轉(zhuǎn)時加入自己的處理邏輯,這可以用來實現(xiàn)請求/響應自動解密。

      詳情見https://github.com/outlaws-bai/Galaxy

      JsRpc工具

      在網(wǎng)站的控制臺新建一個WebScoket客戶端鏈接到服務器通信,調(diào)用服務器的接口 > 服務器會發(fā)送信息給客戶端 > 客戶端接收到要執(zhí)行的方法執(zhí)行完js代碼后把獲得想要的內(nèi)容發(fā)回給服務器 > 服務器接收到后再顯示出來。

      詳情見https://github.com/jxhczhl/JsRpc

      環(huán)境靶場:

      http://39.98.108.20:8085/

      項目地址:

      https://github.com/0ctDay/encrypt-decrypt-vuls/

      JS逆向分析

      網(wǎng)站數(shù)據(jù)包如下,數(shù)據(jù)進行加密處理,請求包的請求頭內(nèi)三個參數(shù)requestId、timestamp、sign缺一不可,改動任何一個都失效,且無法使用repeater重放數(shù)據(jù)

      圖片

      瀏覽器控制臺定位相關(guān)js代碼,其中關(guān)于請求頭三個參數(shù)如下:

      圖片

      加密js代碼如下,采用AES CBC key和iv都寫在js內(nèi)

      圖片

      JS內(nèi)打上斷點

      圖片

      可以看到其中n為需要傳輸?shù)臄?shù)據(jù)、timestamp通過Date.parse(new Date)獲取、requestId通過函數(shù)p()獲取、sign為a.a.MD5函數(shù)對傳輸?shù)臄?shù)據(jù)n加上timestamp加上requestId做MD5處理。l(n)為加密函數(shù)對傳輸?shù)臄?shù)據(jù)n進行加密。

      控制臺調(diào)用函數(shù)打印相關(guān)數(shù)據(jù)

      圖片

      注入JsRpc客戶端及獲取簽名方法

      在這里使用jsrpc調(diào)用接口執(zhí)行js獲取timestamp、requestId、sign三個請求頭數(shù)據(jù),而加密采用Galaxy自帶加密模板。

      jsrpc連接成功后,在瀏覽器控制臺對相關(guān)函數(shù)進行注冊

      window.requestId=p//requestIdwindow.v1 = v//函數(shù)vwindow.sign=a.a.MD5//簽名sign
      圖片

      連接通信

      demo.regAction('hello',function (resolve,param) {    n=JSON.stringify(v1(param))    var time = Date.parse(new Date);    var id=requestId()    var sg = sign(n+id+time).toString()    var data={'time':'','id':'','sign':''}    data['time']=time.toString()    data['id']=id    data['sign']=sg    resolve(data);})
      圖片

      這里可以直接通過瀏覽器訪問查看對應結(jié)果

      圖片

      在Galaxy的hook腳本中調(diào)用JsRpc服務端

      加解密

      此處加密采用模板加解密python文件AES_CBC來實現(xiàn)

      腳本內(nèi)寫入key、iv和對應算法

      圖片

      該網(wǎng)站內(nèi)數(shù)據(jù)包采用GET和POST兩種方式進行請求,且只有POST請求的數(shù)據(jù)進行加密處理,因此請求數(shù)據(jù)發(fā)送到burp解密和burp明文數(shù)據(jù)到服務器加密需要區(qū)分開

      圖片
      圖片

      JsRpc引入

      引入jsrpc需要jython引入http客戶端

      from org.m2sec.core.outer import HttpClient

      按照格式構(gòu)建引入jsrpc和替換請求頭的代碼

      圖片
      burpRequestBody=request.getBody()            #獲取傳輸數(shù)據(jù),也就是上文中的nurl='http://127.0.0.1:12080/go?group=zzz&action=hello&param='jsrpcUrl=url+burpRequestBody                 #將n拼接urljsrpcRequest=request.of(jsrpcUrl)            #構(gòu)建request請求jsrpcRespone=HttpClient.send(jsrpcRequest)   #發(fā)送數(shù)據(jù)包jsrpcResponeJson=jsrpcRespone.getJson()      #獲取返回包內(nèi)數(shù)據(jù)headData=jsrpcResponeJson['data']            #提取data中內(nèi)容headData=json.loads(headData)                #將JSON數(shù)據(jù)的字符串轉(zhuǎn)換為Python中的數(shù)據(jù)類型time=headData['time']                        #提取時間requestId=headData['id']                     #提取requestIdsign=headData['sign']                        #提取簽名head=request.getHeaders()                    #提取原始數(shù)據(jù)包請求頭head.put('sign',sign)                        #替換signhead.put('requestId',requestId)              #替換requestIdhead.put('timestamp',time)                   #替換時間request.setHeaders(head)                     #替換請求頭

      將構(gòu)建好的代碼寫入到burp發(fā)送到服務器的函數(shù)zhong

      圖片

      效果圖

      自動加解密實現(xiàn)效果

      圖片

      重放數(shù)據(jù)實現(xiàn)效果

      圖片

      Galaxy完整的hook腳本

      import jsonimport base64from org.m2sec.core.utils import (    CodeUtil,    CryptoUtil,    HashUtil,    JsonUtil,    MacUtil,    FactorUtil,)from org.m2sec.core.models import Request, Responsefrom org.m2sec.core.outer import HttpClientfrom java.lang import String'''內(nèi)置示例,需要自定義代碼文件時查看該文檔:https://github.com/outlaws-bai/Galaxy/blob/main/docs/Custom.md按 Ctrl(control) + ` 可查看內(nèi)置函數(shù)'''ALGORITHM = 'AES/CBC/PKCS5Padding'secret = b'1234567891234567'iv = b'1234567891234567'paramMap = {'iv': iv}jsonKey = 'data'log = Nonedef hook_request_to_burp(request):    '''HTTP請求從客戶端到達Burp時被調(diào)用。在此處完成請求解密的代碼就可以在Burp中看到明文的請求報文。    Args:        request (Request): 請求對象    Returns:        Request: 經(jīng)過處理后的request對象,返回null代表從當前節(jié)點開始流量不再需要處理    '''    if(request.getMethod()=='GET'):        return request    else:    # 獲取需要解密的數(shù)據(jù)       encryptedData = CodeUtil.b64decode(request.getBody())    # 調(diào)用內(nèi)置函數(shù)解密       data = decrypt(encryptedData)    # 更新body為已加密的數(shù)據(jù)       request.setContent(data)       return requestdef hook_request_to_server(request):    '''HTTP請求從Burp將要發(fā)送到Server時被調(diào)用。在此處完成請求加密的代碼就可以將加密后的請求報文發(fā)送到Server。    Args:        request (Request): 請求對象    Returns:        Request: 經(jīng)過處理后的request對象,返回null代表從當前節(jié)點開始流量不再需要處理    '''    if(request.getMethod()=='GET'):        burpRequestBody=''        url='http://127.0.0.1:12080/go?group=zzz&action=hello&param='        jsrpcUrl=url+burpRequestBody        jsrpcRequest=request.of(jsrpcUrl)             jsrpcRespone=HttpClient.send(jsrpcRequest)        jsrpcResponeJson=jsrpcRespone.getJson()        headData=jsrpcResponeJson['data']        headData=json.loads(headData)        time=headData['time']        requestId=headData['id']        sign=headData['sign']        head=request.getHeaders()        head.put('sign',sign)        head.put('requestId',requestId)        head.put('timestamp',time)        request.setHeaders(head)        return request    # 獲取被解密的數(shù)據(jù)    else:        data = request.getContent()        burpRequestBody=request.getBody()        url='http://127.0.0.1:12080/go?group=zzz&action=hello&param='        jsrpcUrl=url+burpRequestBody        jsrpcRequest=request.of(jsrpcUrl)             jsrpcRespone=HttpClient.send(jsrpcRequest)        jsrpcResponeJson=jsrpcRespone.getJson()        headData=jsrpcResponeJson['data']        headData=json.loads(headData)        time=headData['time']        requestId=headData['id']        sign=headData['sign']        head=request.getHeaders()        head.put('sign',sign)        head.put('requestId',requestId)        head.put('timestamp',time)        request.setHeaders(head)    # 調(diào)用內(nèi)置函數(shù)加密回去        encryptedData = encrypt(data)    # 將已加密的數(shù)據(jù)轉(zhuǎn)換為Server可識別的格式        body = CodeUtil.b64encode(encryptedData)    # 更新body        request.setContent(body)        log.info('header2: {}',request)        return requestdef hook_response_to_burp(response):    '''HTTP請求從Server到達Burp時被調(diào)用。在此處完成響應解密的代碼就可以在Burp中看到明文的響應報文。    Args:        response (Response): 響應對象    Returns:        Response: 經(jīng)過處理后的response對象,返回null代表從當前節(jié)點開始流量不再需要處理    '''    # 獲取需要解密的數(shù)據(jù)    encryptedData = CodeUtil.b64decode(response.getBody())    # 調(diào)用內(nèi)置函數(shù)解密    data = decrypt(encryptedData)    # 更新body    response.setContent(data)    return responsedef hook_response_to_client(response):    '''HTTP請求從Burp將要發(fā)送到Client時被調(diào)用。在此處完成響應加密的代碼就可以將加密后的響應報文返回給Client。    Args:        response (Response): 響應對象    Returns:        Response: 經(jīng)過處理后的response對象,返回null代表從當前節(jié)點開始流量不再需要處理    '''    # 獲取被解密的數(shù)據(jù)    data = response.getContent()    # 調(diào)用內(nèi)置函數(shù)加密回去    encryptedData = encrypt(data)    # 更新body    # 將已加密的數(shù)據(jù)轉(zhuǎn)換為Server識別的格式    body = CodeUtil.b64encode(encryptedData)    # 更新body    response.setContent(body)    return responsedef decrypt(content):    return CryptoUtil.aesDecrypt(ALGORITHM, content, secret, paramMap)def encrypt(content):    return CryptoUtil.aesEncrypt(ALGORITHM, content, secret, paramMap)def set_log(log1):    '''程序在最開始會自動調(diào)用該函數(shù),在上方函數(shù)可以放心使用log對象'''    global log    log = log1

      0x03 總結(jié)

      通過JsRpc與Burp Suite(結(jié)合mitmproxy或Galaxy)的聯(lián)動,無需深入逆向JS加密邏輯即可實現(xiàn)自動化加解密,大幅提升滲透測試效率。JsRpc負責調(diào)用客戶端函數(shù),Galaxy或mitmproxy處理加密/解密與簽名更新,適用于復雜前端加密場景。喜歡的師傅可以點贊轉(zhuǎn)發(fā)支持一下謝謝!

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多