zoukankan      html  css  js  c++  java
  • [PHP防火墙]输入内容存在危险字符,安全起见,已被本站拦截

    之前在很多的网站都看到了360webscan的攻击拦截脚本,正好分析并学习一下。

    下载地址:http ://webscan.360.cn/protect/down?domain = blog.dyboy.cn

    最后一个domain参数更改自己的线上网站域名

    为了本地测试:我下载http://webscan.360.cn/protect/down?domain=www.test.com

    0x01安装

    将下载的360webscan.zip解压后,得到360safe文件夹,并上传至网站根目录

    在上方加载的文件中(示例网站根目录下:)index.php,加入如下代码:

    if(is_file($_SERVER['DOCUMENT_ROOT'].'/360safe/360webscan.php')){
        require_once($_SERVER['DOCUMENT_ROOT'].'/360safe/360webscan.php');
    } //注意文件路径

    访问:http : //www.test.com/360safe/360webscan.php后数据:webscan_act=ckinstall

    但是并没有出现安装信息,原因是:http : //safe.webscan.360.cn

    该域名已经无法访问(后面涉及到该网址的函数都不能够正常执行),因此着重分析拦截过滤的一个过程。

    看到这个脚本文件的最后编辑时间为2014年…

    0x02结构分析

    webscan_cache.php

    webscan_cache.php

    默认拦截,POST/GET/COOKIE/REFERER这四个参数

    同时还有白名单功能

    // url白名单,可以自定义添加url白名单,或者是对phpcms的后台URL放行//写法:phpphps后台操作url index.php?m = admin php168的文章提交链接post.php?job = postnew&step = post,dedecms空间设置edit_space_info.php 
    $ webscan_white_url = 数组('index.php' => 'm = admin' ,'post.php' => 'job = postnew&step = post' ,'edit_space_info.php' => ' ' );

    很清晰的解释了

    再看 360webscan.php

    360webscan.php

    所有的过滤规则以及函数实现都在此文件

    0x03功能测试

    在按照上述安装方法安装后,测试访问:http://www.test.com/index.php?test=<script>alert(1)</script>

    XSS拦截显示:

    XSS被拦截

    例如注入等都会被拦截


    0x04拦截规则

    // get拦截规则
    $ getfilter = “ \ <。+ javascript:window \ [。{1} \\ x | <。* =(&#\ d +?;?)+?> | <。 *(data | src)= data:text \ / html。*> | \ b(alert \(| confirm \(| expression \(| prompt \(| benchmark  s *?(。 * )| sleep  s *?(。* )| load_file  s *?\()| <[az] +?\ b [^>] *?\ bon([az] {4 ,}) s *?= | ^ \ + \ / v(8 | 9)| \ b(and | or)\ b \ s *?([\(\)'“ \ d] +?= [\(\)'“ \ d] +?| [\(\)'” a-zA-Z] +?= [\(\) '“ a-zA-Z] +?|> | <|  s +?[\ w] +?\ s +?\ bin \ b \ s *?(| \ blike \ b \ s +?[“'])| \ / \ *。* \ * \ / | <\ s *脚本\ b | \ bEXEC \ b | UNION。+?SELECT  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。*?(`|'| ” ) s *)| UPDATE  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。 *?(`|'| “) s *)SET | INSERT \ s + INTO。+?VALUES |(SELECT | DELETE)@ {0,2}(\(。+ \)| \ s +?。+?\ s +?|(`|'| “)。*?(`|'| “))FROM(\(。+ \)| \ s +?。+?|(`|'| ”)。*?(`|'| “))|(CREATE | ALTER | DROP | TRUNCATE)\ s +(TABLE | DATABASE)“ ; 
    // post拦截规则
    $ postfilter = “ <。* =(&#\ d +?;?)+?> | <。* data = data:text \ / html。*> | \ b(alert \ (|确认\(|表达式\(|提示\(|基准 s *?(。* )| sleep  s *?(。* )| load_file  s *?\() | <[^>] *?\ b(onerror | onmousemove | onload | onclick | onmouseover)\ b | \ b(and | or)\ b \ s *?([\(\) '“ \ d] +?= [\(\)'” \ d] +?| [\(\)'“ a-zA-Z] +?= [\( \)'“ a-zA-Z] +?|> | <|  s +?[\ w] +?\ s +?\ bin \ b \ s *?(| \ blike \ b \ s +?[“'])| \ / \ *。* \ * \ / | <\ s * script \ b | \ bEXEC \ b | UNION。+? SELECT  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。*?(`|' | “) s *)| UPDATE  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'|  “)。*?(`|'| ”) s *)SET | INSERT \ s + INTO。+?VALUES |(SELECT | DELETE)(\(。+ \)| \ s +?。 +?\ s +?|(`|'| “)。*?(`|'| ”))FROM(\(。+ \)| \ s +?。+?|(`|'| “)。*?(`|'| ”))|(CREATE | ALTER | DROP | TRUNCATE)\ s +(TABLE | DATABASE)“ ; // cookie拦截规则 
    
    $ cookiefilter = “基准 s *?(。* )| sleep  s *?(。* )| load_file  s *?\(| \ b(and | or)\ b \ s *?([[\(\)'“ \ d] +?= [\(\)'” \ d] +?| [\(\)'“ a- zA-Z] +?= [\(\)'“ a-zA-Z] +?|> | <|  s +?[\ w] +?\ s +?\ bin \ b \ s *?(||  blike \ b \ s +?[“'])| \ / \ *。* \ * \ / | <\ s * script \ b | \ bEXEC \ b | UNION。+?SELECT  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|' | “)。*?(`|'| ”) s *)| UPDATE  s *((。+ ) s * | @ {1,2}。+? s * |  s + ?。+?|(`|'| “)。*?(`|'| ”) s *)SET | INSERT \ s + INTO。+?VALUES |(SELECT | DELETE)@ {0, 2}(\(。+ \)| \ s +?。+?\ s +?|(`|'| “)。*?(`|'| ”))FROM(\(。 + \)| \ s +?。+?|(`|'| “)。*?(`|'| ”))|(CREATE | ALTER | DROP | TRUNCATE)\ s +(TABLE | DATABASE )“ ;//获取指令
    $ webscan_action   = isset ($ _POST [ 'webscan_act' ])&& webscan_cheack () 
     ?修剪($ _POST [ 'webscan_act' ]):'' ; // referer获取
    $ webscan_referer = 空($ _SERVER [ 'HTTP_REFERER' ])吗?array ():array ('HTTP_REFERER' => $ _SERVER [ 'HTTP_REFERER' ]);

    0x05运行分析

    在程序的底部初始化函数,过滤判断变量参数是否存在非法攻击字符串,如果是在白名单目录下(webscan_white()函数),就不会调用第二层的判断(替代拦截方式)

    拦截战术

    继续跟进:webscan_white()

    / **
     *拦截目录白名单
     * / 函数webscan_white ($ webscan_white_name ,$ webscan_white_url = array ()){ 
      $ url_path = $ _SERVER [ 'SCRIPT_NAME' ]; // 
      恢复之前是PHP_SELF $ url_var = $ _SERVER [ 'QUERY_STRING' ]; 如果(的preg_match (“/” 。$ webscan_white_name 。“/是” ,$ url_path )== 1 &&!空($ webscan_white_name )){ 返回假
       
        
         ; } foreach ($ webscan_white_url as $ key => $ value ){ if (!empty ($ url_var )&&!empty ($ value )){ ifstristr ($ url_path ,$ key )&& stristr ($ url_var ,$ value ) ){ 返回false ; } } 
        elseif (空($ url_var )&& 空($ value ))
      
        
        
            
             
          
         { ifstristr ($ url_path ,$ key )){ 返回false ; } } } 返回真; }

    1.如果你输入/test.php/123456的话$_SERVER['SCRIPT_NAME']结果是/test.php。所以为了安全起见,为了指向自身,应该用$_SERVER['SCRIPT_NAME']

    2. $_SERVER['QUERY_STRING']获取?后面的字符串,例如:index.php?action=login&username=123&pass=123,那么获取的结果就是:action=login&username=123&pass=123

    3. preg_mactch函数:搜索subjectpattern给定的正则表达式的一个匹配。

    参考http //php.net/manual/zh/function.preg-match.php int preg_match 字符串$ pattern 字符串$ subject [,array $ matches [,int $ flags = 0 [,int $ offset = 0 ]]] 

    正则语法:http : //php.net/manual/zh/reference.pcre.pattern.syntax.php

    翻译了一下

    正则表达式快速参考
     [ ABC ]      单个字符:一个,b 或c ^       单独的字符[^ ABC ] 的任何单个字符,但一个,b ,或c ^       匹配字符除了ABC
     [ 一- ž ] 的任何单个字符中的范围内的- ž         匹配a 到z 的字符[ a - zA - Z ] 任意
               
         单个字符在范围内的- ž 或甲- ž     匹配一个到ž 或阿到ž 的字符^ 开始线的             一行的开始
    $      结束线的             一行的结束
     A      开始的字符串字符串开头
    ž      结束的字符串字符串结尾。任何单个字符任何字符         
     s      任何空格字符任何空白字符             
     S     
                         
         任何非- 空白字符         任何非空白字符
     d      任何数字         任何数字
     d      任何非- 数字         任何非数字
     W      任何字字符(字母,数字,下划线)任何的单词字符(字母,数字,下划线)
     W      任何非- 单词字符             任何非单词字符
     b      的任何单词边界字符         任何单词边界字符(...)捕捉一切封闭     捕获所未包裹有内容(        
         
    一个| b )     a 或ba 或b
    一个?零或a           有0 个或1 个字符a      
    一个* 零或更多的         有0 个或多个字符一      
    a + 一个或多个a             有一个或多个字符a      
    一个{ 3 } 恰好3 的             有3 个字符一个      
    a { 3 ,} 3个或更多的a         有3 个或多个字符a      
    一个{ 3 ,6 } 间3 和6 的一个             有3 到6 个字符一个        
    
    选项:我的情况下不区分大小写M造成点匹配换行符X忽略空格的正则表达式。ο执行#{...}换人只有一次
    
    可选设置:i 不区分大小写,m ..(点符号)匹配换行符,x 忽略正则表达式中的空格,o 只执行一次#{...}中内容替换

    其中的\等价于

    \\等价于\等价于/

    4. strsti()函数:返回haystack字符串从needle第一次出现的位置开始到结尾的字符串。

    参考http //php.net/manual/zh/function.stristr.php 字符串stristr 字符串$ haystack 混合$ needle [,bool $ before_needle = FALSE ] 

    在整个白名单判断函数中,如果匹配上了,那么就返回false,就不做拦截检测,针对白名单这一点其实是有漏洞可绕过的,传递的第一个参数$webscan_white_name是一个参数参数在webscan_cache.php文件中

    //后台白名单,后台操作将不会被拦截,添加“ |”替换白名单目录下面的位置是网址带`admin``/ dede /`放行`$ webscan_white_directory ='admin |  / dede  /'` ;

    这样的话,那么我们只要在admin或者dede目录下的任何操作都不会被拦截。如果存在后台注入的话,同时在后台添加了白名单,那么拦截就不再有效果了。

    同时提一点:如上代码,注释了一下$url_path=$_SERVER['SCRIPT_NAME']; //修复之前是PHP_SELF,这里存在一个安全问题,直接引用一下离别歌大佬的博文:

    然后再给大家说明一下$ _SERVER [ 'PHP_SELF' ]是什么:
    PHP_SELF 指当前的页面绝对地址,此类我们的网站:
    https //www.leavesongs.com/hehe/index.php 那么PHP_SELF 就是/ hehe / 索引PHP的但有个小问题很多人没有注意到,当URL PATH_INFO 的时候,比如
    HTTPS //www.leavesongs.com/hehe/index.php/phithon 那么PHP_SELF 就是/ 嘿嘿/ 指数php / phithon 实际上,实际上
     PHP_SELF 有一部分是我们可以控制的。

    ok,那么如果目录不在白名单中,那么就会后续匹配参数是否在白名单中,如果能够匹配上也返回false

    进入过滤检测手中,例如xss过滤:

    这样的:http : //www.test.com/index.php?id= 123%3Ciframe%20src =http : //www.xxx.com/1.js%3E是不会被过滤的

    然后调用webscan_StopAttack()函数将拦截规则与当前的GET/POST/COOKIE/REFERER参数匹配!

    那么直接看GET请求中的过滤规则吧!

    // get拦截规则
    $ getfilter = “ \ <。+ javascript:window \ [。{1} \\ x | <。* =(&#\ d +?;?)+?> | <。 *(data | src)= data:text \ / html。*> | \ b(alert \(| confirm \(| expression \(| prompt \(| benchmark  s *?(。 * )| sleep  s *?(。* )| load_file  s *?\()| <[az] +?\ b [^>] *?\ bon([az] {4 ,}) s *?= | ^ \ + \ / v(8 | 9)| \ b(and | or)\ b \ s *?([\(\)'“ \ d] +?= [\(\)'“ \ d] +?| [\(\)'” a-zA-Z] +?= [\(\) '“ a-zA-Z] +?|> | <|  s +?[\ w] +?\ s +?\ bin \ b \ s *?(| \ blike \ b \ s +?[“'])| \ / \ *。* \ * \ / | <\ s *脚本\ b | \ bEXEC \ b | UNION。+?SELECT  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。*?(`|'| ” ) s *)| UPDATE  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。 *?(`|'| “) s *)SET | INSERT \ s + INTO。+?VALUES |(SELECT | DELETE)@ {0,2}(\(。+ \)| \ s +?。+?\ s +?|(`|'| “)。*?(`|'| “))FROM(\(。+ \)| \ s +?。+?|(`|'| ”)。*?(`|'| “))|(CREATE | ALTER | DROP | TRUNCATE)\ s +(TABLE | DATABASE)“ ;

    简单解释,只要规则中出现的单词或连续字符,那么在访问链接URL中就不能存在这些关键字,否则就会被拦截。

    为什么要简单解读呐?因为这TM的规则太复杂了...

    可以把|分割开的看成一个小规则,这样子来分别分析

    在上面我们看到关键字iframe没被过滤,那么替换如下的:

    
    
    //添加一个iframe关键字iframe |
    
    $ getfilter = “ iframe | \ <。+ javascript:window \ [。{1} \\ x | <。* =(&#\ d +?;?)+?> | <。*(data | src)= data:text \ / html。*> | \ b(alert \(| confirm \(| expression \(| prompt \(| benchmark  s *?(。* )) | sleep  s *?(。* )| load_file  s *?\()| <[az] +?\ b [^>] *?\ bon([az] {4,})  s *?= | ^ \ + \ / v(8 | 9)| \ b(and | or)\ b \ s *?([[\(\)'“ \ d ] +?= [\(\)'“ \ d] +?| [\(\)'” a-zA-Z] +?= [\(\)'“ a-zA-Z] +?|> | <|  s +?[\ w] +?\ s +?\ bin \ b \ s *?(||  blike \ b \ s + ?[“'])| \ / \ *。* \ * \ / | <\ s * script \ b | \ bEXEC \ b | UNION。+?SELECT  s *( (。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。*?(`|'| ”) s *)| UPDATE  s *((。+ ) s * | @ {1,2}。+? s * |  s +?。+?|(`|'| “)。*?( '|'| “) s *)SET | INSERT \ s + INTO。+?VALUES |(SELECT | DELETE)@ {0,2}(\(。+ \)| \ s +?。 +?\ s +?|(`|'| “)。*?(`|'| ”))FROM(\(。+ \)| \ s +?。+?|(`|'| “)。*?(`|'| ”))|(CREATE | ALTER | DROP | TRUNCATE )\ s +(TABLE | DATABASE)“ ;
    
    
    

    规则修改

    这样就罢了拦截效果

    其他的请求都是类似的,正则语法真难!真香!

    如果匹配到了需要拦截过滤的关键字,就会调用webscan_pape()函数,并调用拦截结果显示页面,如上图所示。

    0x06总结

    正则语法看得心力憔悴,更多的匹配规则得自己下来写一写,然后在本地环境输出查看!

    脚本防火墙真方便!正则匹配就好了,在这个360webscan的过滤插件中,还是看到了函数封装的美感

  • 相关阅读:
    最小的K个数
    CentOS 7 连接不到网络解决方法
    数组中超过一半的数字
    字符串的排列
    二叉搜索树与双向链表
    复杂链表的复制
    二叉树中和为某一数值的路径
    二叉搜索树的后序遍历序列
    从上到下打印二叉树
    java的图形文档
  • 原文地址:https://www.cnblogs.com/M0rta1s/p/11920939.html
Copyright © 2011-2022 走看看