通过请求头对比,发现唯一加密参数为Sentry-Trace。
在js中 查找疑似定义位置如下
这一行将l赋给了Sentry-Trace ,故开始追踪l。
往上几行发现l是在此处被定义的
为js的三元表达式
l = i ? i.toTraceparent() : e4(o, void 0, s)
- 如果变量
i
为真(即存在且不为假值),则调用i.toTraceparent()
方法,并将该方法的返回值作为整个表达式的结果。 - 如果变量
i
为假(即不存在或为假值),则调用函数e4(o, void 0, s)
,并将该函数的返回值作为整个表达式的结果。
我们看到i是有被定义的,控制台也是真,那么暂时默认为真调用 i.toTraceparent()
控制台打印下型关信息
可以看出来i.toTraceparent()的值是由 traceid 与 spanid 与 一些-符号和数字0组成的,格式为
traceid-spanid-0
那么由请求头对比可以发现 tranceid是个固定值那么现在我们的目标锁定
即spanid 的 值为唯一加密参数
全局搜索js文件明显的发现spanid在此处被赋值
如果变量 e
存在且具有非假值的 spanId
属性,那么将当前对象(可能是某个类的实例)的 spanId
属性设置为与 e
的 spanId
属性相同的值,我们默认为真,那么现在任务切换为追踪 e.spanid
取消前面的断点给这个新的e.spanid打上断点, 刷新页面
发现在此处被定义
(0,y.DM)().substring(16) 在控制台把这个值打出来
每次都不一样,那就是我们需要的内容拉,参数一般都是根据时间戳加密的,所以比较明显。
我们解析下这个函数的意义 (0,y.DM)().substring(16) 可以理解成 返回了 y.DM(0)的值,返回值是一个字符串,然后以起始下标为0,截取16以后的切片。
那么现在我们直接点击此处跳转到 y.dm所载的函数,尝试还原本地代码
打上断点
可以发现赋值中调用了n()函数, 而n函数的定义在第一个箭头已经给出,没有用到时间戳之类的,只是单纯的随机值
那么我们对这行代码进行分析
let n = t && t.getRandomValues ? ()=>t.getRandomValues(new Uint8Array(1))[0] : ()=>16 * Math.random()
-
t && t.getRandomValues
:这部分代码检查变量t
是否存在,并且t
是否具有getRandomValues
方法。这可能是用于生成随机数的一个函数或 API。这里的t应该是为了辨别请求头的合法性,但是与加密无关。 -
() => t.getRandomValues(new Uint8Array(1))[0]
:如果t
存在且具有getRandomValues
方法,这部分代码定义了一个箭头函数,它会调用t.getRandomValues
来生成一个随机字节数组,然后提取该数组的第一个元素作为随机数。 -
() => 16 * Math.random()
:如果t
不存在或者不具有getRandomValues
方法,这部分代码定义了另一个箭头函数,它会使用Math.random()
来生成一个介于 0 到 16 之间的随机数。
综合起来,这段代码的作用是根据条件选择不同的方式来生成随机数。如果 t
存在且具有 getRandomValues
方法,它将使用这个方法生成一个更具随机性的随机数。否则,它将使用简单的 Math.random()
函数生成随机数。
不分析了,直接扣下来扔到node js里运行发现结果正确
到此Sentry-Trace 中的spanid 已经解决
测试时发现traceid 居然也有变化,那么继续挖出来。
全局搜索 tranceid 发现六处, 首先对疑似度最高的进行断点
发现断点失败,切换下一个
找的过程中发现traceid 是没从16位截断的完整字符串,那么traceid 不战而胜!
总js代码如下:
function traceid(){
const Crypto = require("crypto-js");
let n = Crypto && Crypto.getRandomValues ? ()=>Crypto.getRandomValues(new Uint8Array(1))[0] : ()=>16 * Math.random();
return "10000000100040008000100000000000".replace(/[018]/g, e=>(e ^ (15 & n()) >> e / 4).toString(16))}
// console.log(traceid(0))
function spanid(){
const Crypto = require("crypto-js");
let n = Crypto && Crypto.getRandomValues ? ()=>Crypto.getRandomValues(new Uint8Array(1))[0] : ()=>16 * Math.random();
return "10000000100040008000100000000000".replace(/[018]/g, e=>(e ^ (15 & n()) >> e / 4).toString(16)).substring(16)}
// console.log(spanid(0))
function Sentry_Trace(){
return traceid()+"-"+spanid()+"-0"
}
console.log(Sentry_Trace())
看上去正确
我们来使用postman 验证下 可行性
.............待更新