深入理解正则表达式-----应用于检测csrf的正则表达式
如何写检测和防御csrf的规则?我们可以利用正则表达式进行匹配。对POST包进行正则匹配,这里只是提供了一个思路。
pcre:"
/POST \/(?P<uri>.*?) HTTP((?!\r\n\r\n).)*?
Host: (?P<host>[^\r\n]*?)((?!\r\n\r\n).)*?
Referer: https?:\/\/((?!(?P=host))|[^\/]*?\/(?!(?P=uri)))/ims";
如何理解该正则表达式?(我们尽量用大白话解释,要不扯那么多专业术语谁能看懂,哼,又不是写论文)
首先要说明的是此处检测的类型是 referer字段 由不同源的地址构造的情况。通俗的解释就是referer字段本来应该是指的你的该连接是从哪里指过来的,假如存在csrf,攻击者可以从其他的网站伪造请求,从而使得该网站执行攻击者的请求。
道理十分简单,大白话就是referer字段中要么包含post的字段,要么包含host字段。例如下图所示,referer字段就是host字段的内容。
只利用正则表达式如何进行检测?上述的正则表达式就是干的这个事情,同时也是比较巧妙的。
pcre:"
/POST \/(?P<uri>.*?) HTTP((?!\r\n\r\n).)*?
Host: (?P<host>[^\r\n]*?)((?!\r\n\r\n).)*?
Referer: https?:\/\/((?!(?P=host))|[^\/]*?\/(?!(?P=uri)))/ims";
我们对上面的正则表达式的各个点进行一下讲解。(本来计划只说一下比较难理解的,如果你会的话,请回答一下下面的问题,总有你不会的,哼,小样,就正则表达式这种非人类的东西,能天天都记住?!)推荐用kiki进行测试一下,如果遇到不懂的话。
1、/POST当中的 / 代表什么意思?
答:开头的 / 表示正则表达式要开始了,就是这么个意思,如果中间过程中还需要用到 / 的话就需要进行转义,使用 \/ 。同时POST呢,就是要匹配post字段,这条csrf检测规则主要是检测post包的么。
2、\/这个理解了吗?(要转义)
3、(?P<uri>.*?)这个玩意是个神马东西??
答:首先(1).*?是啥么意思? .* 是匹配多个非换行符外的字符串,那多一个?是不是就有点mengbility。这里的?是懒惰模式的意思,就是只要匹配到一次就停止的意思
(2)(?P<uri>.*?)这个应用叫做后向引用,大致的格式(?P<name>表达式),意思就是给此时表达式匹配到的内容起个名字叫做name。当你以后需要用到同样的内容的时候直接用name就可以了。举个例子就是妈妈生下了你,并给你取了个名字,以后直接用名字就可以代指你了,并不需要还是喊那个孩子。那在我们的这个例子中就是"POST /ajax/login_h.jsp?cmd=loginCorpNew&dogSrc=3"中匹配到ajax/login_h.jsp?cmd=loginCorpNew&dogSrc=3,并把这段命名为uri。以后再需要这段内容的时候,我们可以用uri这个名字进行检测。
4、HTTP((?!\r\n\r\n).)*?这个玩意是神马东西?
答:HTTP((?!\r\n\r\n).)*? 这个应用叫做负向零宽断言,大致的格式是(?!exp),意思就是在这个位置后面不能匹配到什么的意思。在这里就是匹配不是”\r\n\r\n“的任意元字符很多次,直到遇到下一个匹配单元,上面的例子就是Host:,也就说直到遇到Host:就停下来。上述的话(图片中)这段就匹配的是 HTTP /1.1。
5、Host: (?P<host>[^\r\n]*?)是什么,[^\r\n]*?到底干了啥?
答:首先Host:匹配到,同时 (?P<host>[^\r\n]*?)依旧是个后向引用,你不需要记住这个名词,反正知道就是给[^\r\n]*?取了个名字叫做host,那么问题来了,[^\r\n]*?到底匹配了个啥东西??
此处[^\r\n]就是不是换行的意思,那么不是换行的话是不是就把Host: 这一行给匹配上了。在此例子中就是www.faisco.com,一换行后面的东西就不属于[^\r\n]*?匹配到的东西了。
接下来的((?!\r\n\r\n).)*?就是像上面的解释一下,知道碰到Referer: 就停下了。仔细想想,不详细解释了。
6、Referer: https?:\/\/ 这个里面怎么跑出https了??
答:这里的https? ,后面这个?有学问,意思就是前面的这个s可以有,也可以没有。所以此时可以匹配http和https两种。
此处挖一个坑,假如是https??,有两个问号呢??又会是什么情况?
其实第一个问号和上述的方式是一样的,对‘s’进行0次或者多次匹配。第二个?是开启懒惰模式,那么在懒惰模式下,就只能匹配到http了。(懒惰模式,既然s可以有0次或者其他次,反正我懒,我就不匹配0次,所以此处只能有http)
那么\/\/ 呢?请看第二问,是不是一个转义啊,嗯,是的,很简单!
7、(?!(?P=host))是啥意思??
答:这里就是对负向零宽断言和后向引用的使用。意思就是这里不是上述我们命名为host的那个东西。(?!表达式)是负向零宽断言,表示这里不能是这个玩意。(?P=host)是我们在后向引用用到的,就是表示刚才我们刚才定义的host的那一串东西。
(?!(?P=uri))意思和上述是一样的。就不详细解释了。
8、((?!(?P=host))|[^\/]*?\/(?!(?P=uri))) 这里的 | 表示啥意思? [^\/]*?\/又是啥意思??
答:这里 (a|b)的形式意思就是不匹配a,那么就是b.用在检测csrf实际案例当中就是referfer要么是http://www.faisco.com,要么就是http://www.faisco.com/ajax/login_h.jsp?cmd=loginCorpNew&dogSrc=3(这里仅仅是举一个栗子,不要当真,这个栗子吃了会造成不消化)。
(?!(?P=host))的意思就是你这里不是www.faisco.com的话,你就是一个坏人,有可能是csrf攻击的流量。
[^\/]*?\/(?!(?P=uri))呢?
[^\/]*?\/意思是不是/的字符都给匹配上,在这里呢,就是把http://和第一个/之间的www.faisco.com匹配上,同时再加上\/,就是http://www.faisco.com/匹配上了。剩下一个(?!(?P=uri)),意思就是检测上述提到叫做uri的这一串东西是不是等于ajax/login_h.jsp?cmd=loginCorpNew&dogSrc=3,如果不等于,那么你就被抓住了,就被认为是csrf的恶意流量。
9、/ims
/i 忽略大小写
/m 将串视为多行
/s 将串视为单行
一堆修饰符,可以自行查找。
总结:
1、正则表达式很非人类,需要进行测试来进行理解。推荐kiki(我的机器是ubuntu,不知道windows下是什么工具)
2、csrf防御依旧可以用正则表达进行检测,并不是不能做检测的。但是仅仅能检测referfer字段的问题,是不是想一想id/ps可以写出针对token的规则。
3、耐心,耐性。很重要!