PHP利用PCRE回溯次数限制绕过某些安全限制
副问题[/!--empirenews.page--]
这次 Code-Breaking Puzzles 中我出了一道看似很简朴的标题pcrewaf,将其代码简化如下:
大意是判定一下用户输入的内容有没有 PHP 代码,假如没有,则写入文件。这种时辰,怎样绕过 is_php() 函数来写入 webshell 呢? 这道题看似简朴,穷究其道理,照旧值得写一篇文章的。 一、正则表达式是什么 正则表达式是一个可以被「有限状态自念头」接管的说话类。 「有限状态自念头」,其拥有有限数目的状态,每个状态可以迁徙到零个或多个状态,输入字串抉择执行哪个状态的迁徙。 而常见的正则引擎,又被细分为 DFA(确定性有限状态自念头)与 NFA(非确定性有限状态自念头)。他们匹配输入的进程别离是:
因为 NFA 的执行进程存在回溯,以是其机能会劣于 DFA,但它支持更多成果。大大都措施说话都行使了 NFA 作为正则引擎,个中也包罗 PHP 行使的 PCRE 库。 二、回溯的进程是奈何的 以是,我们标题中的正则 <?.*[(`;?>].*,假设匹配的输入是 见上图,可见第 4 步的时辰,由于第一个 .* 可以匹配任何字符,以是最终匹配到了输入串的末了,也就是 //aaaaa。但此时显然是差池的,由于正则表现.*后头还应该有一个字符 [(`;?>]。 以是 NFA 就开始回溯,先吐出一个 a,输入酿成第 5 步表现的 //aaaa,但如故匹配不上正则,继承吐出 a,酿成 //aaa,如故匹配不上…… 最终直到吐出;,输入酿成第 12 步表现的 ] ,这个功效满意正则表达式的要求,于是不再回溯。13 步开始向后匹配;,14 步匹配.*,第二个.*匹配到了字符串末端,最后竣事匹配。 在调试正则表达式的时辰,我们可以查察当前回溯的次数: 这里回溯了 8 次。 三、PHP 的 pcre.backtrack_limit 限定操作 PHP 为了防备正则表达式的拒绝处事进攻(reDOS),,给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit。我们可以通过 var_dump(ini_get(‘pcre.backtrack_limit’));的方法查察当前情形下的上限: 这里有个风趣的工作,就是 PHP 文档中,中英文版本的数值是纷歧样的: 我们应该以英文版为参考。 可见,回溯次数上限默认是 100 万。那么,假设我们的回溯次数高出了 100 万,会呈现什么征象呢?好比: 可见,preg_match 返回的非 1 和 0,而是 false。 preg_match 函数返回 false 暗示此次执行失败了,我们可以挪用 var_dump(preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR);,发明失败的缘故起因简直是回溯次数超出了限定: 以是,这道题的谜底就呼之欲出了。我们通过发送超长字符串的方法,使正则执行失败,最后绕过方针对 PHP 说话的限定。 对应的 POC 如下:
四、PCRE 另一种错误的用法 延长一下,许多基于 PHP 的 WAF,如:
均存在上述题目,通过大量回溯可以举办绕过。 其它,我碰着更常见的一种 WAF 是:
(编辑:河北网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |