webpack-js-前端签名(sign)算法实战分析

  • Comments Off on webpack-js-前端签名(sign)算法实战分析
  • 14 views
  • A+
所属分类:逆向工程

一、简介

目前许多网站前端源码都趋于模块化,参数值通过webpack的模块进行加解密,这对于爬虫和渗透都是一个拦路虎,因此写下该博客,记录自己的学习思路。


二、目标站点

这里分析的是某动某站前端的js代码

http://www.xxx.com/


三、算法分析


3.1 正常发送请求包

打开开发者工具,点击network,输入账号密码,点击登录。

webpack-js-前端签名(sign)算法实战分析

查看响应请求的内容,其中password的参数值被加密了,这里我输入的是123456,密文看着很像md5,但是通过解密发现,密文又似乎不是md5

webpack-js-前端签名(sign)算法实战分析

发送第二个登录包。

password的值没变,但是sign的值发生了变化,较大几率sign值在生成的时候,使用了时间戳

webpack-js-前端签名(sign)算法实战分析

此时寻找该参数加密点。

3.2 寻找password、sign加密相关的模块与函数

全局搜索该登录请求的接口

webpack-js-前端签名(sign)算法实战分析

并成功找到相关的参数。

webpack-js-前端签名(sign)算法实战分析

3.2.1 分析password

通过分析发现,password的值是由n决定的。

s = {
    phone: e.phone,
    password: n,
    type: t,
    sign: "",
    timestamp: d
}

并在第1886行,找到了有关n的声明

webpack-js-前端签名(sign)算法实战分析

此时发现password被md5加密后,与pwdkey的值,进行字符串拼接后,在进行一次md5加密。

直接搜索pwdkey,并在第27589行,找到了该值,发现该值是不变的。

webpack-js-前端签名(sign)算法实战分析

这里使用python3,写一个简单的password的加密demo

import hashlib

def md5Encode(str):
    m = hashlib.md5(str.encode(encoding='utf-8'))
    return m.hexdigest()

password = "123456"
pwdkey = "kla5ra8h9s"

encrypt_password = md5Encode(md5Encode(password)+pwdkey)
print(encrypt_password)   

webpack-js-前端签名(sign)算法实战分析


发现该值,与我在前端登录框处输入密码123456后,经前端webpack模块加密后的值是一样的,说明前面的分析思路是正确的。

webpack-js-前端签名(sign)算法实战分析


3.2.2 分析sign

sign的生成方式在第1866行进行的。

d.sign = this.$md5Sign(n)

webpack-js-前端签名(sign)算法实战分析

sign的值是通过md5Sign进行加密后得到的,因此这里需要分析两个点。分别是md5Sign的算法流程,以及l的值。

3.2.2.1 分析l

在第1858行发现

l = "" + e.phone + n + t + d

这里我下个断点,传值进来方便查看。

webpack-js-前端签名(sign)算法实战分析


l的值是由手机号+密码密文+1+时间戳生成的。

l=phone+md5(md5(password)+pwdkey)+1+时间戳

3.2.2.2 分析md5Sign

此时分析md5Sign的算法。

通过断点追踪发现,md5Sign和函数mn()有关。

webpack-js-前端签名(sign)算法实战分析

有点奇怪,为什么不应该是直接追到md5Sign的函数声明去吗?怎么会是mn()的声明。

此时我直接搜索了mn()


发送mn的值又赋值给了md5Sign

因此此处mnmd5Sign可以理解是等价的关系。


webpack-js-前端签名(sign)算法实战分析

此时来分析mn的函数流程。

sn = a("8237"),
cn = a.n(sn);
function mn(e) {
    var i = "",
    a = "6d9fkhj33rk8sa5fc";
    return i = e + a,
    i = cn()(i).toLowerCase(),
    i
}


webpack-js-前端签名(sign)算法实战分析


此处并设置断点传值。

webpack-js-前端签名(sign)算法实战分析

并连续调试到下一步

webpack-js-前端签名(sign)算法实战分析

此时分析可知

e = phone +password的密文+1+时间戳

e = 151123412349ac13f8bad58389388ecc1604eaed32011635925676

a = 6d9fkhj33rk8sa5fc

i = e + a

i = phone +password的密文 +1 + 时间戳 + 6d9fkhj33rk8sa5fc

i = 151123412349ac13f8bad58389388ecc1604eaed320116359256766d9fkhj33rk8sa5fc

这里为了方便查看看,就将i最后的值拆分一下

phone md5(md5(password)+pwdkey) 1
时间戳 a
15112341234 9ac13f8bad58389388ecc1604eaed320 1
1635925676 6d9fkhj33rk8sa5fc

i的值再被cn函数加密,加密后的值,全部通过toLowerCase()转换成小写字母。

sn = a("8237");

cn = a.n(sn);

为了方便调试,这里我打开了编辑器,准备扣前端js代码下来,本地执行调试了。

先把前面的流程进行整理,这里我把所有时间戳写死了,方便等下观察值是否一样。

当时间戳为1635925676时,sign的值为32138108f605a5122cc6f6c1bc54c7b3。(之前的截图)

var password = "9ac13f8bad58389388ecc1604eaed320"
var phone = "15112341234"
var timestamp = "1635925676"
var a = "6d9fkhj33rk8sa5fc"

var sn = a("8237");
var cn = a.n(sn);
var i  = phone + password + '1' + timestamp + a;
var sign = cn()(i).toLowerCase();

console.log(sign)


webpack-js-前端签名(sign)算法实战分析

此时只需要分析a

webpack-js-前端签名(sign)算法实战分析

断点跟进

在这里找到了a

webpack-js-前端签名(sign)算法实战分析


此时分析确定了分发器

webpack-js-前端签名(sign)算法实战分析


我们将这段代码全部扣下来。

声明一个flag,用于接收分发器模块的值。

webpack-js-前端签名(sign)算法实战分析

l赋值给flag,并要把原先的a("8237")a.n(sn)修改成flag("8237")flag.n(sn)

webpack-js-前端签名(sign)算法实战分析


运行之后,报错。

提示window没有被定义,这里就把window声明一下。

webpack-js-前端签名(sign)算法实战分析


var window = global;

将这个声明放在最上面,和flag的声明放在一起。

此时再次运行。报错,提示call没有被定义。原因是因此flag中的8237模块没有被调用。

webpack-js-前端签名(sign)算法实战分析


这里全局搜索8237

在此js文件中找到了有关8237的定义

webpack-js-前端签名(sign)算法实战分析

将这个js代码全部复制至本地的2.js中,并在1.js中进行调用。

并声明一下window

webpack-js-前端签名(sign)算法实战分析


并再次运行

webpack-js-前端签名(sign)算法实战分析

和预期值不一样?猜测时间戳填错了。

因此此处重新抓一个时间戳的数据包。

并修改timestamp的值

webpack-js-前端签名(sign)算法实战分析


此时本地调试的结果,与前端的结果一致,因此该sign的签名算法分析完成。

四、使用python3完成此次签名算法

import hashlib
import time

def md5Encode(str):
    m = hashlib.md5(str.encode(encoding='utf-8'))
    return m.hexdigest()

if __name__ == "__main__":
    phone = "15112341234"
    password = "123456"
    pwdkey = "kla5ra8h9s"
    #timestamp = "1635927403"
    timestamp = int(time.time())
    a = "6d9fkhj33rk8sa5fc"
    n = md5Encode(md5Encode(password)+pwdkey)
    i = phone + n + "1" + str(timestamp) + a 
   
    print("时间戳是:"+str(timestamp))
    print(md5Encode(i))



webpack-js-前端签名(sign)算法实战分析


使用系统时间戳

webpack-js-前端签名(sign)算法实战分析


五、总结

遇到前端加密不要慌,作为一个安服仔,应该直接干就完了,反正js代码已经默认开源给你了,慢慢调试分析算法逻辑,并调用相应的模块即可。

自主学习时,解决问题应有多样性,尽量还是多增加自己的知识层面。

实际解决问题时,应考虑效率。

所以此处我提供了javascript和python3的两种解决问题的方式方法。

相关推荐: 挖矿木马简要技术分析

点击上方"蓝字"关注我们吧!此文为哈工大安天联合CERT实验室发布的针对挖矿木马的简要技术分析,首发于”高校信息化应用“公众号,安天公众号现对其进行转载,以便读者进一步了解挖矿木马,同时为读者提供处置建议。挖矿木马概述互联网的虚拟货币,如比特币(BTC)、门罗…