×

Javascript函数审计分析进阶版案例-二次函数绕过使用功能/间接跳过函数校检

0x_www 0x_www 发表于2022-05-30 11:55:25 浏览606 评论0

抢沙发发表评论

Javascript函数审计分析进阶版案例-二次函数绕过使用功能/间接跳过函数校检



漏洞成因:

由于前端BindUpdateUserClickEvent()函数代码段存在问题,导致二次函数绕过,

默认的AntiForgery也许是隐患



我们在分析JS函数的时候,需要注重全文通读,因为你只要通读了他的整个过程,代码事件

你才知道如何去利用薄弱环节,漏洞点,完成漏洞复现


案例1:间接跳过函数强校检

打开源代码进行分析

首先分析了一下函数

捕获.JPG




图片1.png


我们简单分析了一下

 var regex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,30}');

 

可以看到,这里取了一个正则

 if (regex.test(Pwd) != true) {                           // alert("你设置密码太简单,至少要包括大小写字母、数字、特殊字符,需要重新设置密码!");                            var temp = data.substring(3);                            //alert(temp);                            $("#ID").val(temp);

这里有有一个输入的判断

我们先来梳理一下登陆流程

首先是SmsSubmitLogin登陆函数,接着判断密码的复杂度

如果密码简单,则触发到BindGroupSelectButtonClickEvent

函数

强制修改密码,才能够登陆

然后这里有一个函数

BindUpdateUserClickEvent()

这个函数,相当于第二层验证,他这里,

/首先判断前台的验证是否通过                var valid = $('#UpdateUserInfo').form('validate');                if (valid == false) {                    return false;

 

有一个前台的验证,验证通过的UpdateUserInfo才能生效跳到下一步


图片2.png



也就是说不能通过前台的验证,则不能通过这一步

 

/UName1,Pwd1,PwdOK1,Phone1,Mail1

则是构造的所需参数

 //设置CSRF的AntiForgery的验证                if (postData != null) {                    postData.__RequestVerificationToken = $("input[name='__RequestVerificationToken']").val();                } else {                    postData = new Object;                    postData.__RequestVerificationToken = $("input[name='__RequestVerificationToken']").val();                }

这里有CSRF的AntiForgery验证

最后通过异步修改用户的密码


图片3.png



我们来到这里,前后对比一下


图片4.png


这里不就是前台取验证的吗

 

那么我们继续看


图片5.png



第一个函数是

BindGroupSelectButtonClickEvent

点击后,则触发修改密码

那么这个函数在

BindGroupSelectButtonClickEvent

在这里意义是什么呢



图片6.png



图片7.png

很明显了,他调用了

前面是调用这个函数

后面这个是具体调用的功能验证


图片8.png



可以看到这里 window.location.href = "/Home/Index";

 

他调到home/index,就是验证通过的意思了

那么在这里,

      else {                        alert(data);                        window.location.href = "/Login/Index/";                    }

 

否则跳转到首页

我们先来尝试一遍




QQ截图20220530120204.jpg



触发了登陆函数

随便提交错误数据


QQ截图22.jpg




QQ截图20220530120314.jpg

验证码没对,重新填入



这里提示用户密码错误,点击,就不能继续了



没通过验证

 

那么我们先来尝试一下修改密码的函数,我们是否能通过函数直接绕过他


图片9.png



按照思路,应该是直接选调这个函数

void 改成修改的函数



图片11.png


捕获890.JPG



注意,这是登陆的函数

那么修改的函数,点击确定后



捕获90.JPG



关键他这个函数调用,执行一次,这时候需要截取数据包,因为他是强验证,所以他会跳转到首页

这时候我们发点击确定的时候,自动跳出来一个窗口,证明函数调用成功,现ID是没有给值的,因为这里没有取到

//var val = sessionStorage.getItem("UserInfo");

所以ID是空

我们就简单填入

50asddzssda*)&

密码:50asddzssda*)&

50asddzssda*)18



这里我们说了

不能直接调用BindUpdateUserClickEvent()

函数

因为有前台验证

那我们来尝试

调用修改函数之后,再调用BindUpdateUserClickEvent()

函数,来试试


捕获891.JPG




我们可以发现这里,我们需要再次把BindUpdateUserClickEvent()

写入



QQ截图20220530120630.jpg



点击确定就会flase

flase是调到哪里呢?

图片10.png




那么没过前台验证嘛,所以直接flase

流程我们清楚了,那么我们回到前台验证代码段

注意这里



图片13.png




这是前台的验证阶段



图片14.png



那么这个函数我们能否调用呢

 BindGroupSelectButtonClickEvent()

那么这个函数,可以理解成什么呢

他间接了逃过了这个函数BindUpdateUserClickEvent()的校检

我们来试试,通过修改函数,换成

BindUpdateUserClickEvent()

看是否能逃到这一步


图片15.png


我们首先还是触发修改函数




捕获91.JPG





接着把密码填入

这里需要注意,修改成 BindGroupSelectButtonClickEvent()函数,

而不是

BindUpdateUserClickEvent()

 

我们这样做的目的,就是要看一看,是否真的能够通过BindGroupSelectButtonClickEvent()函数

间接逃过BindUpdateUserClickEvent()

的强校检

如果能逃过,那么就会直接带入到



图片12.png



当我们点了两次,第一次,触发错误的登陆函数信息,也就是这里


接着触发了BindGroupSelectButtonClickEvent()函数,点击确定

之后发现是过了

到了


QQ截图20220530120942.jpg




图片31.png



这里

那证明我们利用函数逃过了BindUpdateUserClickEvent()

函数强校检



==================================================


案例2:二次函数绕过使用功能

我们来看看其他的函数


图片41.png


注意这里,有一个函数

ShowSmsPhoneDialog()

这里提示输入手机号码

还有一个函数ShowSmsVerifyDialog()

这里提示手机号码输入判断

我们先看看能不能直接调用ShowSmsVerifyDialog()

函数



QQ截图20220530121205.jpg


QQ截图20220530121248.jpg



可以调用

那么我们就把用户名写成手机号码,1358888888

我们注意




默认是用户密码错误

 

我们现在做的就是函数调用他的原始功能

怎么调呢

首先

我们把用户名换成手机号了



换成13188888888

QQ截图20220530121342.jpg




默认是用户密码错误

 

我们现在做的就是函数调用他的原始功能

怎么调呢

首先

我们把用户名换成手机号了

换成13188888888


我们发现直接调是有误区的,为啥呢,直接调的话,手机号码参数就不对啊

怎么输入都是手机号码错误,弹回flase

虽然调了函数,但是用户名参数始终还是uname

没有变成Phone_NO嘛,所以他才会报错

也就证明不能直接调用,因为我们不可能让uname变成Phone_NO

那么我们先看看流程


图片51.png


我们发现其实ShowSmsVerifyDialog()函数和ShowSmsPhoneDialog()

是有依赖的,什么依赖呢,它们两个函数代表了一个流程

怎么走

比如说ShowSmsPhoneDialog()

可以理解成输入用户的手机号码:1388888888

接着,触发到ShowSmsVerifyDialog()进行发送验证码

是这么一个流程

那么我们既然知道了流程,就先调用ShowSmsPhoneDialog()

当我们点击确定的时候,发现直接把ShowSmsPhoneDialog()

函数的功能成功调取出来了,接着我们看看验证码这里,我们发现是void

这里是走不了下一步的,所以,我们得二次再去填入一个ShowSmsPhoneDialog()

让他走下去



QQ截图20220530121538.jpg



这里我们试试

修改函数


QQ截图20220530121611.jpg



我们这样做的目的就是让ShowSmsVerifyDialog()函数生效




QQ截图20220530121640.jpg


重放一下

再重放一次


QQ截图20220530121714.jpg

我们到这里可以发现&Phone_NO起作用了

成功带入了Phone_NO参数,也就是说流程是触发到ShowSmsVerifyDialog()函数


我们注意这里

__RequestVerificationToken=ywC7UQ3uABD6IG0NJBlu66AHA0xmoOEqIZPDzOcCQjE2hG1YzJOi3IV6bFPhweS3bxmGAAF7oxoGpVsiSc_K2_9tiuPzeyFSiGnaH3p5fxs1

这里是一个验证token



我们把它去掉后看看效果



QQ截图20220530121806.jpg



变成302状态了

原因是啥呢

这是一个重定向,代表对象被移动

所以还是需要__RequestVerificationToken

我们加入它

点击执行



QQ截图20220530121842.jpg



QQ截图20220530121907.jpg



我们发现功能就可以使用了

正确判断了

二次函数利用成功