Authorization参数

Authorization头部请求参数:Authorization的主要用作http协议的认证。Authorization的作用是当客户端访问受口令保护时,服务器端会发送401状态码和WWW-Authenticate响应头,要求客户机使用Authorization来应答。

Authorization格式

通常是一个固定字符串加上空格"XXXX " + JavaScript文件生成的一个token

config.headers['Authorization'] = 'Bearer ' + getToken()

例如:

  • Authorization:Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJUQ0JFNCIsImFjYyI6ImNmODI2NDRlLWIyOTYtNDZlYS1iMmUyLTRlOGVmMjZlNDE5ZiIsInN1YiI6IiIsImNoYWluIjoiIiwicGFydG5lciI6IldFQjQiLCJjaG4iOiIiLCJpc3MiOiJ0cmF2ZWxjbGljayIsImV4cCI6MTcxMDU2MDExMywianRpIjoiMmVkOWRmNzgtYTk0NS00N2U2LWIwMzgtNjFhYTUwNDA0Y2I3IiwibWVjaCI6IldFQjQifQ.cmMe9uoi6UKs6vXUftqRvRyIcZKRq0w1IbLBVMRvz8QC-gvpYN65jKUHBXj9tv3khAVtaB2L5hLMolFG8JxmFdwOk8Pubtb7Xq9oLmF8lPAr8O9hbTnZX2uoekyjfCjoYFAijx3jXEjugEeZK40aJrWcTUvl2qS-kXRyKofNETgsaY1lopO_3shjYtw0PIYc-ajkDn3nN9FHjRcCdlKh7CZMCjWmo-S74S6TS7cJK1Q72FrOcQ1KZFUCFtcjhZMPqfinkn2WTSoxwwmJqIzi7zqAlzEfPz3TxH-LjyyRqW4VKLdZFUjJpoM0_ZAyZsMMlNUXMa14gIs74gLwo0OhEg

练习目标地址

tips:仅供学习参考,分享技术心得
境外某酒店

逆向Authorization参数

tips:通过对Authorization的解析,我们可以通过快速定位到,本次案例Authorization的固定字符串'Bearer',通过该关键字参数全局搜索

在这里插入图片描述
搜索Bearer关键字出来的文件并不是特别多,给我们逆向简化了不少的工作,我们逐步分享一下存在Bearer关键字的文件,如果加密参数不是服务端返回来的,我们只需要关心js文件,其他的文件都是已经生成完成之后的Authorization,我们打开第一个js文件,文件内搜索Bearer,来找寻我们的加密参数的入口,只有找对了入口,才是我们逆向一个参数的开始
在这里插入图片描述
发现只有两次地方存在Bearer,第一处地方是字符串,相信各位大佬也是一眼就可以判断出不是我们要找的参数加密入口,我们继续研究第二处的位置,e.headers.Authorization= "Bearer " + C,是不是跟我们在前面了解到的Authorization格式很相似,我们也不知道C到底是不是我们要找的东西,不知道没关系,我们直接在这段代码前面打上一个断点看一下,然后刷新一下界面
在这里插入图片描述
我们把鼠标悬停在C变量上面看到,这跟我们要找的东西很像啊,然后看拼接上前面的"Bearer " + C,是不是就组成了我们的Authorization头部信息,但是为了不走冤枉路,我们先把当前拼接之后完整的Authorization头先拿到代码上测试一下看看是不是我们需要的值,这里就不带大佬们走代码测试部分了,因为小弟是做完了,开了上帝视角,直接跟各位大佬说结论,这里就是我们需要的参数信息,接下来我们继续往上找,C变量是怎么生成的呢
在这里插入图片描述
哎,我们看到在我们打断点的位置上方就存在一个变量C,而且在开发者工具也给我们显示了C变量的值,var C = d.getToken(); 而C变量的值就是是d.getToken()函数的返回值,我们直接鼠标悬停在d.getToken函数上面,就会显示函数的入口位置,我们点击跳转到该函数的位置
在这里插入图片描述
跳到了一个函数里面,我们先分析一下该函数,函数返回来的值是使用短路与运算,先判断一下o如果有值就为True,不会执行该(o = t(n, i))语句,如果o为False那就走(o = t(n, i)),最终的结果返回值都是o
tips: 小弟js基础一点薄弱,如果此处JavaScript语法分析有问题,请各位大佬多多担待

return o || (o = t(n, i)),
o

言归正传,我们继续,根据我们的分析函数返回值都是o,我们鼠标悬停到两个不同的o上面,发现两个o的值一模一样,那我们怎么找o的生成位置呢,既然我们鼠标悬停在2个不同的o上面时值是一模一样的,而后面的o的值是t(n, i) 函数的返回值,那有没有一种可能就是前面的o的值也是t(n, i) 的返回值呢,鼠标悬停在t函数上面,跳到该函数的位置观察一下
在这里插入图片描述
我们跳转到断点的位置,该函数在我们断点的上方一点,我们在t函数观察发现,函数内部逻辑实现的是加解密的逻辑,再结合函数的返回值
在这里插入图片描述
我们需要的加密参数是在t函数里面生成的,接下来我们把t函数扣下来

function t(a, t) {
		// 判断一下a与t是否都为True
        if (a && t)
        	// 异常捕获
            try {
                var o = "" + r.hotelCode
                  , n = a.substring(a.length - (16 - o.length)) + o
                  , i = aesjs.utils.utf8.toBytes(n)
                  , s = aesjs.utils.hex.toBytes(t)
                  , l = new aesjs.ModeOfOperation.ctr(i)
                  , c = l.decrypt(s);
                return aesjs.utils.utf8.fromBytes(c)
            // 出异常之后执行
            } catch (a) {
                a.stack && e.error(a.stack)
            }
    }

// 根据以上代码,我们稍微把代码简洁一下,删除掉一些不必要的代码
function t(a, t) {
                var o = "" + r.hotelCode
                  , n = a.substring(a.length - (16 - o.length)) + o
                  , i = aesjs.utils.utf8.toBytes(n)
                  , s = aesjs.utils.hex.toBytes(t)
                  , l = new aesjs.ModeOfOperation.ctr(i)
                  , c = l.decrypt(s);
                return aesjs.utils.utf8.fromBytes(c)
}

但是光有函数也不太行,函数里面要传入两个形参,我们可以先打印一下传入函数的实参是什么
在这里插入图片描述
参数n:是个13位的时间戳字符串,参数i:则是一段很长的密文
tips: 个人处理方式,先使用固定参数还原加密函数逻辑,再找参数位置,按照我个人的方式,我喜欢先处理一下加密的函数,至于参数等函数还原之后再解决

我们先使用现在手上已经有的参数调试一下我们刚才扣下来的t函数,在此之前,我们先分析一下t函数的结构和运行方式

function t(a, t) {
                var o = "" + r.hotelCode
                  , n = a.substring(a.length - (16 - o.length)) + o
                  , i = aesjs.utils.utf8.toBytes(n)
                  , s = aesjs.utils.hex.toBytes(t)
                  , l = new aesjs.ModeOfOperation.ctr(i)
                  , c = l.decrypt(s);
                return aesjs.utils.utf8.fromBytes(c)
}

function t(a, t) {
                var o = "" + 110437  // 酒店id可以写死
                  , n = a.substring(a.length - (16 - o.length)) + o    //参数a,o都有不用还原
                  , i = aesjs.utils.utf8.toBytes(n)    //这一步采用的是 JavaScript 中 AES 加密库 aes-js 中的一个函数,用于将 UTF-8 编码的字符串转换为字节数组(byte array)。
                
                  , s = aesjs.utils.hex.toBytes(t)    //在 JavaScript 中,aesjs.utils.hex.toBytes 函数用于将十六进制字符串转换为字节数组。
                  , l = new aesjs.ModeOfOperation.ctr(i)    //在 JavaScript 中,new aesjs.ModeOfOperation.ctr 是创建 AES 加密算法的计数器模式(CTR)的实例。CTR 模式是一种分组密码模式,它将加密器用作伪随机函数,并使用计数器值对明文进行加密以生成密文。
                  , c = l.decrypt(s);    //然后进行decrypt解码
                return aesjs.utils.utf8.fromBytes(c)    //aesjs.utils.utf8.fromBytes 是用于将字节数组转换为 UTF-8 编码的字符串的方法。在 aes-js 库中,这个方法可以用于将字节数组解码为 UTF-8 编码的字符串。
}

根据以上分析,得知加密算法为AES的CTR模式,我们假设使用的aes算法没有魔改,我们使用javascript中的aes密码学算法替代以上代码

const aesjs = require('aes-js');

function decryptText(a, t) {
        var r = { hotelCode: '110437' };
        var o = "" + r.hotelCode,
            n = a.substring(a.length - (16 - o.length)) + o,
            i = aesjs.utils.utf8.toBytes(n),
            s = aesjs.utils.hex.toBytes(t),
            l = new aesjs.ModeOfOperation.ctr(i),
            c = l.decrypt(s);
        return aesjs.utils.utf8.fromBytes(c);
}

const a = '1710565945657'; // 你提供的 a 值
// 你提供的 t 值
const t = '0e7271f907261a2a3cffdba790ab4dd68d65e349a646c33af75421fec2c20ad6ded3f2f40a46daf30bf8b725ec9bf27791aac17351e97179c67014d7078478d685110bf67e844d940eb46b33d1e2fa291c3302d44141048f5ad7223eb71cf90951a59005b7fceb678da9550d6820c487877465b37bb4137d5addc03c1ea9560c8818cf6e6f5e7b4773e738dbb89875d3b960e6bd62c0be42bfc56dd76cab4e28e1edba6925dff82808705c0062f419bc08c34385aab0ef367838bc6536e4856e75d033b555c3a9c11d00479b19659bfe91dc5323c5866dead8ffa0b8517efbd2a9c7ce1be4585fdc6e0b3779d6ce38b6d4dd0170acf7902a2bf47a62820512d4bdc8a54556fdf37d4a94cb57724a617b91e7d7f6da57556e8e4cec73314ec2eb564f00b7d1cbf0926e51f784663593063e73a2b1a90e4e75ae83db0f32951f5c2203af5b4960ca8df4d4b4cbdabc19ee90ba8e3a32ec072d9dda83725debc911773366e4042a5739b3fcc6122b00ca94b9c4160291e19c9cb301c942d2f6099bc8b60297657459c829e34252106028f681b871ce71556cb7aeb95ffbf1ce189eba8be8f7b285fa5026835d9cd4a96986529fab306b6e0fb7c4c31ed16ccb09db12c3ab04b5b8d2c194314151fc45b50021a85e4542eb54a7ae0cdb6508942ce3b97898dcaf592ba34d41d9fdb20353f01ba4da83322ff05a6a84418dfc87f9eeb10f83fe5d9106f85fdcc4b11e81b4929bd6fd0404e410fca99ede1769327a1b0d50724a314477f8387e4c4fe8dd745f9e0586dd0194fe0caad3180ef5eb5d5be360a538b9fa789558c292e95e3e7ece41555129082e4bdaf5f746333d746bd2fa12717fd32b55d0901697833c056f28337926e0fb422e0b51d1055680484287d0e988c34fb6348084e8';

console.log("Bearer " + CdecryptText(a, t));
// 得出密文结果跟网页结果一毛一样,说明使用的是原生算法,没有进行魔改eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJUQ0JFNCIsImFjYyI6ImNmODI2NDRlLWIyOTYtNDZlYS1iMmUyLTRlOGVmMjZlNDE5ZiIsInN1YiI6IiIsImNoYWluIjoiIiwicGFydG5lciI6IldFQjQiLCJjaG4iOiIiLCJpc3MiOiJ0cmF2ZWxjbGljayIsImV4cCI6MTcxMDU2NjA2NiwianRpIjoiNWY5NmUyNDItZWRhMy00YzJkLTgzMzctYjk1YTE2MjAzZDE5IiwibWVjaCI6IldFQjQifQ.a6iikxQz1kSuYJHXT-JPsX1eN1CAspOV6N2TI9WkWpXw6bxGLEwD2GtW1mV3vak93dNbEkQnF3EZ3M5HYyJESDM6vx7mfbaUg3m4ZL5MJBExW34K7lNJBdv9e5THRqpHlv1uS8SP5lDu9QEmxJKDUJ1bpZF88JTxV-xFUmOfe4V0Ab2vcwIv2ufkb-p7XIw0LT81TnmqT_9ZpZMImnD2Wt2GJK0KzygEZ9oUCu5fVSEzVm3FfrBbCNP8waZkPhM55OeU3YZt9H8JeovOz27TAnRJDN5pw-3m5EEKiGXxevz2AhhQmG4FbenrCDfYVe4g7CHXVrnR2Bu74ycAcn4TFg

接下来我们解决一下前面留下的坑,时间戳与密文实参怎么获得,经过我的研究,发现js文件中并没有发现参数密文的生成位置,那既然js文件中没有该参数的生成位置,那参数是从哪里来的呢,我们返回network界面,使用数据包检索一下密文,好家伙,原来是一条链接返回来的值,ts对应的参数就是13位的时间戳,tk对应的就是密文参数,至此我们所有的实参就拿到手了,只要请求链接取出对应的实参数据,再使用python调用js文件的时候传入参数给js文件的函数调用
在这里插入图片描述

使用python代码调用js文件,获取最终的Authorization头部参数,请求网站接口测试一下解密出来的Authorization是否是可用,我就不带各位大佬做测试了,结果肯定是可用的

小结

tips:本次就是Authorization请求头参数加密的逆向思路分享,本人新手写作,如果有那个地方有什么写的不对,讲的不够详细,欢迎大佬指点,小弟虚心学习,再接再厉

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值