zoukankan      html  css  js  c++  java
  • 前端加密之使用firefox来解密

    前端加密之使用firefox来解密

     文本采用(CC-BY-NC-ND) 非商用可转载,不可修改本文内容

    随着等保2.0的实施,传输过程中加密变的必要了,很多APP或者手机浏览器端逐步加密了一些加密的措施来解决这个问题,比如以下这样的数据包

    一串乱码,什么是什么都看不懂别说修改数据了。。那咋办呢? 我们可以使用firefox,chrome之类的,我个人比较喜欢firefox,以下的都是基于firefox来讲解。

    1、触发button

     打开调试器ctrl+F12然后进入 调试器,刷新页面后会加载全部的js,根据习惯,一般login.js就看起来像是主要登录模块触发的函数的页面。

     我们回到页面来触发这个button。前端很都操作都是基于事件绑定的。js就是事件驱动的语言,会有大量的闭包,一旦写不好就浏览器内存++,当然这个是题外话。既然是事件驱动就会有很多function.on('click',callback(){})之类的操作来定义一些检测的逻辑。

    我们先对需要出发的那个button,比如“登录”,“发送”之类的button,点击他的右键,然后选择“查看元素”。 Firefox会快速定位到这个元素附近的HTML结构,当然也会因为CSS层叠的问题导致定位不准,不过这个不重要,多用几次就知道如何快速定位到关键元素,我们目前还是在讲解HTML,还没开始讲解JS部分。

    然后点击event,我们快速定位到这个button点击后的事件逻辑块代码,比如以下的图

    可以看到这个button绑定了2个click事件,下面那个事件为冒泡事件,即在上面的那个click的同时,下面那个click也会被触发。这个大概的触发代码应该是

    $('#buttion_id').click(function(){...}) ,其中,红色部分内容应该就是我们打开的这个click事件框框中的代码,我把代码全部贴出来。

    以下代码是基于jquery的,要看懂的话需要一些基础,我讲的尽可能简单,让大家都可以快速明白。

     1 function() {
     2   if (!$(this).prop('disabled')) {
     3     var mobilenum = /^(13[0-9]|15[0-9]|16[0-9]|17[013678]|18[0-9]|19[0-9]|14[57])[0-9]{8}$/;
     4     var mob = $('.row input').eq(3).val().replace(/s/g, '')
     5     if (!mobilenum.test(mob)) {
     6       $('#modal-error').modal('show').children('.error-content').children('.modal-body').html('请输入有效的手机号');
     7       return;
     8     }
     9     if (needImg) {
    10       $('#modal-input').modal('show');
    11       $('#modal-input .msg-code-img').eq(0).click();
    12       var $_input = $('#modal-input input')[0];
    13       setTimeout(function() {
    14         $_input.focus();
    15       }, 500);
    16     } else {
    17       var params = {
    18         'MOBILE': $('.row input').eq(3).val().replace(/s/g, '')
    19       };
    20       getPhoneCode(params);
    21     }
    22   }
    23 }

    最主要我们看17-20行的代码,构造了一个对象传入到getPhoneCode函数中,params的参数就是手机的参数 并且处理一定逻辑。

    2、调试JS,下断点

    接来下我们去搜索getPhoneCode(params)函数。

    我们通过全局查找快速定位到这个函数的位置。

     1 function getPhoneCode(params) {
     2     if (!$('#msg-btn').prop("disabled")) {
     3         $('#msg-btn').prop("disabled", true);
     4         params['ajaxUrl'] = "/user2/sendSmsCode";
     5         params['ajaxCallBack'] = function (data) {
     6             if (data.MSG_CODE == 0) {
     7                 if (data.MESSAGE_CODE) {
     8                     $('.msg-code-input').val(data.MESSAGE_CODE);
     9                     checkNull();
    10                 }
    11                 /*if (show_input) {
    12                  $('.tel-code-row').show();
    13                  }*/
    14                 $(".msg-code-img:not('#modal-input .msg-code-img'):last").click();
    15                 time($('#msg-btn'));
    16                 return;
    17             } else if (data.MSG_CODE == '102') {
    18                 if ($('.tel-code-row').css('display') == 'none') {
    19                     alerterror('您的失败次数过多<br/>请输入图片验证码');
    20                     $('.tel-code-row').show();
    21                 } else {
    22                     alerterror('图片验证码输入错误');
    23                 }
    24                 if (typeof show_input != 'undefined' && !show_input) {
    25                     show_input = true;
    26                 }
    27             } else {
    28                 alertfail();
    29             }
    30             $('#msg-btn').prop("disabled", false);
    31         }
    32         submitAjax(params);
    33     }
    34 }

    32行之前都是一些逻辑和判断的代码 和我们想要调试的没关系,4-5行是把一些信息包装进了params参数中,最终通过32行的submitAjax函数来执行,我们继续跟踪这个函数 ,方法和上面一样,全局搜索这个方法

    submitAjax函数的定义如下:

     1 //提交数据
     2 var submitAjax = function (dataObject) {
     3     var ajaxUrl = UC_URL + dataObject.ajaxUrl
     4     delete dataObject.ajaxUrl
     5     var ajaxCallBack = dataObject.ajaxCallBack;
     6     delete dataObject.ajaxCallBack;
     7     dataObject.CHNLID = dataStore.getItem("CHNLID");
     8     dataObject.BACKURL = unescape(Base64.decode(dataStore.getItem("backUrl")));
     9     dataObject.VERSION = "1.32";
    10     if (null != dataObject.BACKURL) {
    11         dataObject.BACKURL = getDomain(dataObject.BACKURL);
    12     }
    13     if (null == dataObject.CHNLID && null == dataObject.BACKURL) {
    14         dataObject.CHNLID = 'SF';
    15         dataObject.BACKURL = location.host;
    16     }
    17     var JsonParams = JSON.stringify(dataObject);
    18     var rsaCommit = function (JsonParams) {
    19         var RSAParams = RSAUtils.encryptedString(rsaKey, JsonParams);
    20         $.ajax({
    21             type: "POST",
    22             cache: false,
    23             dataType: "json",
    24             url: ajaxUrl,
    25             contentType: 'text/plain',
    26             data: RSAParams,
    27           ...82 }

    去掉了一些不重要的代码,我们主要来看dataObject参数。我们先对这个地方下个断点

     然后我们回到页面,填写好手机号,点击“获取验证码”,让代码跑起来。

    我们可以看到dataObject参数就2个属性,然后继续往下跟,在Json.stringfy之前下断点,因为最后加密的函数是第19行,RSAUtils.encryptedString(rsaKey, JsonParams);

    其实有经验的同学可以直接在这里下断点查看,这里的rasKey是没有定义的,只有这个JsonParams,而 JsonParams就是刚才的dataObject对象的json序列化。

    我们可以看到,在变成json格式之前,程序加入了一些其他的参数,这个不重要。接下来我们下断点到 RSAUtils.encryptedString函数。然后来看rsaKey参数是什么,鼠标移上去显示是undefined..

    因为代码只var rsaKey,并没赋值任何。。。不知道程序员在想什么,这个类的加密string方法显然是需要一个加密的key的,也就是私钥,其实这个程序有一个密钥,不过不是这个函数里的

    所以其实前端加密来阻止参数修改没意义的。。

    3、构造参数

    最后我们需要理解上面的流程和逻辑

    1. 获取需要的参数比如mobile,版本等信息
    2. json序列化
    3. 加密
    4. 发送至服务端

    最后的代码是

    1 var my = {MOBILE:"15*******",CHNLID:"SF",BACKURL:"*****.com.cn",VERSION:"1.32"};
    2 var data = JSON.stringify(my);
    3 var rsaKey;
    4 RSAUtils.encryptedString(rsaKey, data);

     最后得出的值是

    我们再和直接用burpsuite抓到的值对比下

     

    其他的一些思考

    基本上就结束了,接来下我们可以构造任何我们想要的值来替换掉传输,因为至此我们可以构造任何想要的参数来篡改。

    其实换个思路,我们可以编写一些插件(其实已经有类似的插件) ,例如早起的Tamper Data 插件之类的,或者自己写脚本引入,在一些关键代码之前反射出对象的全部属性.

    从程序员角度来看,我们可以看到他有好几个加密方法,有的传了密钥,有的没有。而且代码都是部分混淆,部分没有,其实提高一下门槛的话,应该把login.js之类的 也混淆了。虽然这种混淆对我这样的安全工程师没什么用,但是waf不也是这样的思路吗?

    把全部的js混淆了不仅可以压缩代码的字符数,减少服务器压力和带宽,还可以提高安全的门槛,增加破解难度,在交互中多次传输一些长度很高的token,迷惑安全人员,再使用一些js和浏览器的hack技术,使得门槛可以非常高。 比如这些js的奇怪特性。

    javascript中那些奇怪的特性

    JavaScript中的"奇奇怪怪"

  • 相关阅读:
    html基础教程2
    HTML的基础教程
    JS中响应函数和for循环执行问题
    Cookie显示上次访问时间出现错误的问题
    完全卸载VSCode--解决卸载重新安装后还有原来配置的问题
    servlet中输出HTML标签浏览器不能正常显示
    Java中Servlet输出中文乱码问题
    eclipse下配置Tomcat(没有Tomcat8及以上版本问题)
    Java多线程通信之wait()和notify()方法
    Java中synchronize关键字
  • 原文地址:https://www.cnblogs.com/xsserhaha/p/11246074.html
Copyright © 2011-2022 走看看