[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中

默认拦截,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

所有的过滤规则以及函数实现都在此文件
0x03功能测试
在按照上述安装方法安装后,测试访问:http://www.test.com/index.php?test=<script>alert(1)</script>
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 )){ if (stristr ($ url_path ,$ key )&& stristr ($ url_var ,$ value ) ){ 返回false ; } }
elseif (空($ url_var )&& 空($ value )) { if (stristr ($ 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函数:搜索subject与pattern给定的正则表达式的一个匹配。
参考: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的过滤插件中,还是看到了函数封装的美感
[PHP防火墙]输入内容存在危险字符,安全起见,已被本站拦截的更多相关文章
- php中url传递中文字符,特殊危险字符的解决方法
php中的urldecode,base64_encode函数然后再结合自己写的替换函数来进行安全传递url中文字符,特殊危险字符. 需要在url中传递中文字符或是其它的html等特殊字符,似乎总会有各 ...
- Android 开发之拦截EditText的输入内容,定制输入内容
1.EditText作为一个比较成熟的View,在Android的应用开发中得到极为广泛的使用.在某些特殊情况下,我们可能需要定制EditText的输入内容, 只允许指定功能的输入,例如输入一个”dd ...
- salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现
项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...
- input长度随输入内容动态变化 input光标定位在最右侧
<input type="text" onkeydown="this.onkeyup();" onkeyup="this.size=(this. ...
- 实时监听input输入内容的N种方法
现在有一个需求,需要我们实时监听input输入框中的内容,从而带来更好的用户体验,而不是等我们全部输入完毕才告诉我们格式不对首先我们创建一个input输入框 <form name='loginF ...
- 正则表达式控制Input输入内容 ,js正则验证方法大全
https://blog.csdn.net/xushichang/article/details/4041507 //输入姓名的正则校验 e.currentTarget.value = e.curre ...
- asp.net提交危险字符处理方法之一
在form表单提交前,可以在web页面,submit按钮的click事件中,使用js函数对,可能有危险字符的内容进行编码. 有3个函数可用: encodeURI() 函数可把字符串作为 URI 进行编 ...
- 防止sql注入:替换危险字符
在用户名或者密码框中输入“11‘ or ’1‘ = '1”时,生成的sql语句将为“selec * from userInfo where name = '11' or '1' = '1' and p ...
- MySQL手工注入进阶篇——突破过滤危险字符问题
当我们在进行手工注入时,有时候会发现咱们构造的危险字符被过滤了,接下来,我就教大家如何解决这个问题.下面是我的实战过程.这里使用的是墨者学院的在线靶场.咱们直接开始. 第一步,判断注入点. 通过测试发 ...
随机推荐
- 七十四、SAP中内表的4中删除方法
一.代码如下 二.效果如下 *&---------------------------------------------------------------------* *& Re ...
- 三十四、在SAP的屏幕选择中,将英文替换成我们想要的文本内容
一.我们在代码中定义了一个选择屏幕,但是对应的显示界面为英文 界面如下 二.我们选择[转到]-[文本元素] 三.默认的文本内容是问号和三个点 四.我们修改成我们需要的,并激活这个文本,如果不激活会丢失 ...
- java开发 中台
中台就是接入层啊,一般有中台的都是比较大的项目,后台会分为很多模块,比如订单模块,比如会员模块,接入层需要做的就是对数据的封装,权限的过滤,以及各种安全什么的, 前台需要什么数据,接入层去对应的后台微 ...
- 记-OSPF学习
LSA Type 1:Router LSA1.传播范围 :只能在本区域2.通告者 :每台路由器 (router-id作为标识)3.内容 :路由和拓扑信息show ip ospf database ro ...
- stl 题目总结
stl 题目总结 一.圆桌问题 1 .问题: 圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第一个人开始数数,数到第m个人,则立即处死该人:然后从被处死的人之后开始数数,再将数到的第 ...
- webservice 的简单实现
1.什么是webservice: 服务端整出一些资源让客户端访问(获取数据) 一个跨语言.跨平台的规范2.作用:跨平台调用.跨语言调用.远程调用 3.什么时候使用webservice: 1.新旧系统之 ...
- win10安装centOS 失去win启动项
联网:执行以下三条命令 yum -y install epel-release yum -y install ntfs-3g grub2-mkconfig -o /boot/grub2/grub.cf ...
- UML-持久框架-目标&关键思想
1.目标 1).使用模板方法.状态模式.命令模式来设计部分框架 2).介绍对象-关系(O-R)映射中的一些问题 3).使用虚代理实现的滞后具体化 2.关键思想 1).映射(Mapping) 类--表 ...
- 关于构造函数中的this()和super()
今天看到一个这段代码 public DataSourcePool(String driver, String url, String user, String pwd) throws Exceptio ...
- PyMySQL学习笔记
一些常用函数及解释 db = pymysql.connect('host','user','password','database') # 连接数据库 cursor = db.cursor() # 创 ...