前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >有关于正则匹配的s和m修饰符的小Tip

有关于正则匹配的s和m修饰符的小Tip

作者头像
字节脉搏实验室
发布2020-04-14 17:03:23
6810
发布2020-04-14 17:03:23
举报

文章源自【字节脉搏社区】-字节脉搏实验室

作者-叶子

在基于PCRE实现的正则引擎中,我们常使用“m表示multi-line、s表示single-line”。

multi-line表示按行来匹配正则,可以理解为以换行符为切割,对每行进行正则匹配然后进行or运算出结果。 中single-line的意思是将待匹配的文本视为一行,换行符不再作为“换行”的标志。

这在日常使用中也经常会出现由首尾界定符产生的小bug,比如下面这一个。

代码语言:javascript
复制
<?php 
if(preg_match('/^a[a-z]+z$/m', $_GET['input'])) {
    echo $_GET['input']; 
}

正则匹配中我们常使用`^`和`$`来界定正则匹配的首尾,但这两个的符号本身的含义其实是代表了“行的开头和结尾”,也就意味着如果你输入一个%0a换行,后面就可以输入任何字符也能完成匹配。

比如上面的代码本身的含义可能是:用户输入一个以a开头,以z结尾的中间可以有若干字母的字符串。但因为指定了m修饰符,导致用户可以传入:

代码语言:javascript
复制
input=abcz%0a<svg%20onload=alert(1)>

来绕过检测。

但其实m修饰符的出现频率并不高,所以下面这个例子你有可能见过。

代码语言:javascript
复制
<?php 
if(preg_match('/SELECT.+FROM/i', $_GET['input'])) {
    echo 'SQL Injection: ' . $_GET['input']; 
} else {
   echo 'Bypass: ' . $_GET['input']; 
}

上面代码本身的含义可能是正则匹配SQL注入的payload,但同理可以用一个换行符绕过

代码语言:javascript
复制
input=SELECT%20password%0aFROM%20database

解决的办法也很简单,使用s修饰符即可,这样的话`.“可以匹配上所有字符,自然也就包含了换行符。

那如果我们不加修饰符,结果如何呢?

不加s或m -> single line,但 `.` 不能匹配换行符

加s -> single line,且 `.` 匹配包括换行符在内的所有字符

加m -> multi line

同时加s和m -> multi line,且 `.` 匹配包括换行符在内的所有字符

PS:在第一个代码中你也会发现如果input本身以`\n`结尾的话也是可以成功匹配的,所以严格来说也是可以算是一个漏洞,毕竟写代码的人本意是以z结尾的。导致这个结果的原因是,“行”这个事物本身就会存在两种情况:非最后一行的“行”,其结尾就是换行符或者最后一行,其结尾就是字符串结尾。 所以,`$`也就可以匹配两种情况:字符串结尾或换行符,即使在s模式下也是如此。这也就是”Apache HTTPd”。XD

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 字节脉搏实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档