漏洞描述:

扫描漏洞如下:

漏洞:Client ReDos From Regex Injection

代码:

// In IE6, the hash fragment and search params are incorrect if the

    // fragment contains `?`.

    getSearch: function() {

      var match = this.location.href.replace(/#.*/, '').match(/\?.+/);

      return match ? match[0] : '';

    },

// Update the hash location, either replacing the current entry, or adding

    // a new one to the browser history.

    _updateHash: function(location, fragment, replace) {

      if (replace) {

        var href = location.href.replace(/(javascript:|#).*$/, '');

        location.replace(href + '#' + fragment);

      } else {

        // Some browsers require that `hash` contains a leading #.

        location.hash = '#' + fragment;

      }

    }


ReDoS(Regularexpression Denial of Service)
正则表达式拒绝服务攻击。开发人员使用了正则表达式来对用户输入的数据进行有效性校验,当编写校验的正则表达式存在缺陷或者不严谨时, 攻击者可以构造特殊的字符串来大量消耗服务器的系统资源,造成服务器的服务中断或停止。

每个恶意的正则表达式模式应该包含:使用重复分组构造、在重复组内会出现、重复、交替重叠。

有缺陷的正则表达式会包含如下部分。

(a+)+
([a-zA-Z]+)*
(a|aa)+
(a|a?)+
(.*a){x} | for x > 10
注意: 这里的a是个泛指。

一些实际业务场景中会用到的缺陷正则:

英文的个人名字
Regex: ^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*$
Payload: aaaaaaaaaaaaaaaaaaaaaaaaaaaa!

Java类名
Regex: ^(([a-z])+.)+[A-Z]([a-z])+$
Payload: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!

Email格式验证
Regex: ^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$
Payload: [email protected]!

多个邮箱地址验证
Regex: ^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*\s+<(\w[-._\w]*\[email protected]\w[-._\w]*\w\.\w{2,3})>$|^(\w[-._\w]*\[email protected]\w[-._\w]*\w\.\w{2,3})$
Payload: aaaaaaaaaaaaaaaaaaaaaaaa!

复数验证
Regex: ^\d*[0-9](|.\d*[0-9]|)*$
Payload: 1111111111111111111111111!

模式匹配
Regex: ^([a-z0-9]+([\-a-z0-9]*[a-z0-9]+)?\.){0,}([a-z0-9]+([\-a-z0-9]*[a-z0-9]+)?){1,63}(\.[a-z0-9]{2,7})+$
Payload: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!

使用python来进行测试有缺陷的正则示例
$ python -c "import re;re.match('^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*$', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa!')"

 


解决方案:

防范手段只能降低风险而不能百分百消除ReDoS这种威胁。

1.  降低正则表达式的复杂度, 尽量少用分组;

2.  严格限制用户输入的字符串长度(特定情况下)。

    对本次测试漏洞进行分析,似乎并不存在重复分组或嵌套分组的正则表达式,为了应对安全测试,建议解决方案如下:

方案1

使用{m, n}替代“*”、“+”等,限制匹配的字符数量,如:

var href = location.href.replace(/(javascript:|#).*$/, '');

修改为

var href = location.href.replace(/(javascript:|#).{0, 1000}$/, '');

方案2

使用字符串截取函数slice()或substring(),替代replace()函数,如:

var href = location.href.replace(/(javascript:|#).*$/, '');

修改为

var lochref = location.href;

var idxnum = lochref.indexof(“javascript:”);

if(idxnum == -1) idxnum = lochref.indexof(“#”);

var href = idxnum == -1? lochref : lochref.slice(0, idxnum + 1);


参考资料:

Regular expression Denial of Service - ReDoS 

浅析ReDoS的原理与实践

Location 对象

正则表达式基础

js字符串截取函数slice()、substring()、substr()

相关文章:

  • 2021-07-16
  • 2021-06-29
  • 2021-12-04
  • 2022-02-23
  • 2021-09-20
  • 2022-12-23
  • 2021-11-19
猜你喜欢
  • 2021-05-08
  • 2022-12-23
  • 2022-12-23
  • 2021-11-12
  • 2021-06-28
  • 2022-12-23
  • 2021-10-10
相关资源
相似解决方案