一个长期贴(技术向)(3)

按理说,数据请求的基本要素都有了,就可以直接模拟请求了。但是这个app的接口有签名参数校验token。

简单来说。客户端和服务端会约定一套相同的加密算法(当然,实现的编程语言可能不同)。加密的参数由请求参数组成,通常还会算上一个实时变化的参数,如时间戳,和一个固定的混淆参数(一般称为盐),

举个例子,服务端和客户端实现一套相同的hash算法,比如说将请求参数先按键名排序 然后按 键=值&拼接成字符串,然后拼接上 timestamp=当前时间戳,再拼接上固定的盐,双md5,计算出一个32位的随机字符串作为token,一起发送给后端。后端对请求参数做相同处理,然后得出token,与前端发来的token对比,如果一致则放行,否则就拦截,下面看具体的例子:

<?php
$timestamp = time();  // 时间戳
$query_params = [ // 请求参数
    'a' => 1,
    'c' => 2,
    'b' => 'jons'
];
$salt = "this is the salt ,you cant guess it. right?"; // 盐
function signature($params, $timestamp, $salt){
    ksort($params, SORT_STRING); // 按键名升序排列
    $str = http_build_query($params); // a=1&b=jons&c=2
    $token = md5(md5($str . $salt . $timestamp));
    return $token;
}

function curl($url, $data){
    // 发起curl请求,这里忽略。
}

$token = signature($query_params, $timestamp, $salt); //3c70cacb73d99ad9ca1b682f33c341e1

$sign_params = [ 
    'timestamp' => $timestamp,
    'token' => $token
];
$url = 'https://image.baidu.com/api/login'; // 请求api
$real_params = array_merge($query_params, $sign_params); // 实际的请求参数
curl($url, $real_params); //发起请求

所以,我们可以从三方面考虑请求的合法性:

一,当客户端传过来的token与服务端计算出的token不一致时,必然是参数被人修改过,或加密规则不一致,或盐不一致,即不可被信任,需要拦截。

二,即使token一致,当传过来的时间戳与服务端时间戳相差太大的,可以认为是有人抓了包,但是没有修改,只是重复请求。也可以根据时间戳的实时性来拦截请求。

三,高手可以通过逆向反编译源码的方式获取apk客户端的源码,从而获取加密的规则,实时生成时间戳和请求参数,伪造加密过程。但是盐是前后端约定过的。这个如果被编译成二进制文件,则很难反汇编出来,从而无法从逆向的代码中获取。保证加密的最后一道防线的安全性。如果拿不到盐,一样无法获取最终的token。

现在,我就被卡在这一步加密算法。已经确定的加密方法是md5(不确定几次),加密参数中由时间戳timestamp这个参数,加密方法未知,是否有盐未知。而且加密方法不在安卓逆向的源码中,而是在被编译成so的二进制动态库中,无法反汇编

发表评论

邮箱地址不会被公开。 必填项已用*标注