利用autoDecoder工具在数据包加密+签名验证站点流畅测试

站点是个靶场
https://github.com/0ctDay/encrypt-decrypt-vuls

演示地址http://39.98.108.20:8085/

不是仅登录位置暴力破解的那种场景,使用autoDecoder(https://github.com/f0ng/autoDecoder)的好处就是每个请求自动加解密,测试起来比较流畅

如何查找js加密代码这里就不详细写了,网上很多文章,直接贴出关键部分信息

程序会校验三个header,timestamp、requestId、sign,每个都不能错

timestamp由Date.parse(new Date)生成

requestId由p函数生成

sign为MD5(明文参数的json串+requestId+timestamp)

p函数的代码为

关键的加密函数l(n),跟进看一下

用了AES_CBC加密,填充方式是Pkcs7,iv与key都是1234567891234567

明白了这些逻辑,参考https://github.com/f0ng/autoDecoder-usages/blob/main/加解密代码例子/aes_cbc_zeropadding.py

写出了本次的加解密逻辑代码,因为还有签名等逻辑,改动略大,不过后面遇到类似的照这个结构做些逻辑变更即可

from flask import Flask
import base64
import execjs
import time
import hashlib
import re
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from flask import request

# 密钥(key), 偏移量(vi)
app = Flask(__name__)
key = b'1234567891234567'  
iv = b'1234567891234567'

#从站点js文件中拷贝出来的一些函数,dtime生成时间戳,p函数生成requestID

ctx = execjs.compile("""
    function dtime() {
        return Date.parse(new Date)   
    }
    function p() {
        var t = "0123456789abcdef"
            , e = Array.from({
            length: 32
        }, (function() {
            return t.substr(Math.floor(16 * Math.random()), 1)
        }
        ));
        return e[14] = "4",
        e[19] = t.substr(3 & e[19] | 8, 1),
        e[8] = e[13] = e[18] = e[23],
        e.join("")
    }
""")

#生成md5,用于签名的生成
def md5_string(text):
    md5 = hashlib.md5()
    md5.update(text.encode('utf-8'))
    return md5.hexdigest()


def AES_Encrypt(data):
    # 定义加密算法为AES_CBC
    cipher = AES.new(key, AES.MODE_CBC, iv)
    # 字符串补位
    padded_data = pad(data.encode('utf-8'), AES.block_size)
    # 加密后得到的是bytes类型的数据
    encrypted = cipher.encrypt(padded_data)
    # 使用Base64进行编码,返回byte
    encodestrs = base64.b64encode(encrypted)
    # 对byte按utf-8进行解码转为字符串格式
    enctext = encodestrs.decode('utf8')
    return enctext
	
def AES_Decrypt(data):
    # base64解密
    encrypted_data = base64.b64decode(data)
    # 根据AES_CBC算法解密
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_padded = cipher.decrypt(encrypted_data)
    try:  
        #去除填充
        decrypted = unpad(decrypted_padded, AES.block_size)  
        # 返回字符串格式明文
        return decrypted.decode('utf-8')  
    except ValueError:  
        # 如果解密后数据格式不正确,比如填充错误,则抛出异常  
        raise ValueError("解密失败,可能密文已损坏或密钥/IV不正确")
	

@app.route('/encode',methods=["POST"])  #定义加密接口
def encrypt():
    param = request.form.get('dataBody')  # 获取body内容
    param_headers = request.form.get('dataHeaders')  # 获取headers内容
    request_id = ctx.call("p")     #调用js代码中的p函数生成requestId
    time_str = str(ctx.call("dtime"))  #调用js代码中的dtime函数生成过期时间戳
    json_body = param    #body内容为json串,如{"password":"123456789","username":"test","validCode":"d0f6"}
    #签名算法为MD5(参数信息+requestId+时间戳)
    sign_str = json_body + request_id + time_str
    sign_md5 = md5_string(sign_str)
    #获取的headers内容为字符串,这里替换header中timestamp、requestId、sign的值,否则校验不通过
    param_headers = re.sub(r'\btimestamp:\s*(.*?)(?=\s+)', f'timestamp: {time_str}', param_headers)
    param_headers = re.sub(r'\brequestId:\s*(.*?)(?=\s+)', f'requestId: {request_id}', param_headers)
    param_headers = re.sub(r'\bsign:\s*(.*?)(?=\s+)', f'sign: {sign_md5}', param_headers)

    #调用AES加密body数据
    encry_param = AES_Encrypt(param)
    #返回整个http包,headers与body中间通过多个换行分隔
    return param_headers.strip() + "\r\n\r\n\r\n\r\n" + encry_param.strip()

@app.route('/decode',methods=["POST"]) # 定义解密接口
def decrypt():
    param = request.form.get('dataBody')  # 获取body内容
    headers = request.form.get('dataHeaders')  # 获取headers内容
    # 如果body内容中有"存在,则表示数据包为明文,不需要解密,不包含则调用AES解密
    if '"' in param:
        return headers + "\r\n\r\n\r\n\r\n" + param
    else:
        decry_param = AES_Decrypt(param)
        return headers + "\r\n\r\n\r\n\r\n" + decry_param


if __name__ == '__main__':
    app.run(host="127.0.0.1",port="8888")   #接口地址为本地8888端口

autoDecoder配置如图

加解密接口配置

本地运行python启动接口

看下最终效果

实际数据包内容

在autoDecoder标签处可看到明文

在明文包中右键,选择"Send to Repeater"可以更改参数测试

把password值修改下提交,可看到返回包也会自动解密(注意要把明文包拷贝到Pretty或Raw下面才可以

暴力破解场景也是轻松拿捏,但需要限制为单个线程,否则验签会失败

成功获取密码

相关推荐
Spring_java_gg2 小时前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
独行soc3 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
newxtc3 小时前
【国内中间件厂商排名及四大中间件对比分析】
安全·web安全·网络安全·中间件·行为验证·国产中间件
mingzhi611 天前
渗透测试-快速获取目标中存在的漏洞(小白版)
安全·web安全·面试·职场和发展
安胜ANSCEN1 天前
加固筑牢安全防线:多源威胁检测响应在企业网络安全运营中的核心作用
网络·安全·web安全·威胁检测·自动化响应
超栈1 天前
蓝桥杯-网络安全比赛题目-遗漏的压缩包
前端·网络·sql·安全·web安全·职场和发展·蓝桥杯
黑龙江亿林等级保护测评1 天前
DDOS防护介绍
网络·人工智能·安全·web安全·智能路由器·ddos
kali-Myon1 天前
NewStarCTF2024-Week5-Web&Misc-WP
前端·python·学习·mysql·web安全·php·web
知孤云出岫1 天前
网络安全渗透实际案例
安全·web安全