php符号%3c%3e啥意思,[PHP防火墙]输入内容存在危险字符,安全起见,已被本站拦截...

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

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

0x01 安装

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

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

if(is_file($_SERVER['DOCUMENT_ROOT'].'/360safe/360webscan.php')){

require_once($_SERVER['DOCUMENT_ROOT'].'/360safe/360webscan.php');

} //注意文件路径

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

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

0x02 结构分析

在 webscan_cache.php 中

362ee210556dbcd769722087d2b6653c.png

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

同时还有白名单功能

//url白名单,可以自定义添加url白名单,默认是对phpcms的后台url放行

//写法:比如phpcms 后台操作url index.php?m=admin php168的文章提交链接post.php?job=postnew&step=post ,dedecms 空间设置edit_space_info.php

$webscan_white_url = array('index.php' => 'm=admin','post.php' => 'job=postnew&step=post','edit_space_info.php'=>'');

很清晰的解释了

再看 360webscan.php

8455561eb0b8c0a0b411bc37f91eb2f8.png

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

0x03 功能测试

在按照上述安装方法安装后,测试访问:http://www.test.com/index.php?test=

XSS拦截显示:

3a421f0c4967ea6549a3b8615958c28f.png

比如注入等都会被拦截

0x04 拦截规则//get拦截规则

$getfilter = "\\<.>|<.>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|load_file\s*?\\()|]*?\\bon([a-z]{4,})\s*?=|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|

//post拦截规则

$postfilter = "<.>|<.>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\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]+?|>|

//cookie拦截规则

$cookiefilter = "benchmark\s*?\(.*\)|sleep\s*?\(.*\)|load_file\s*?\\(|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|

//获取指令

$webscan_action = isset($_POST['webscan_act'])&&webscan_cheack() ? trim($_POST['webscan_act']) : '';

//referer获取

$webscan_referer = empty($_SERVER['HTTP_REFERER']) ? array() : array('HTTP_REFERER'=>$_SERVER['HTTP_REFERER']);

0x05 运行分析

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

e936e904637560623371311234ac9cc8.png

继续跟进:webscan_white()

/**

* 拦截目录白名单

*/

function webscan_white($webscan_white_name,$webscan_white_url=array()) {

$url_path=$_SERVER['SCRIPT_NAME']; //修复之前是PHP_SELF

$url_var=$_SERVER['QUERY_STRING'];

if (preg_match("/".$webscan_white_name."/is",$url_path)==1&&!empty($webscan_white_name)) {

return false;

}

foreach ($webscan_white_url as $key => $value) {

if(!empty($url_var)&&!empty($value)){

if (stristr($url_path,$key)&&stristr($url_var,$value)) {

return false;

}

}

elseif (empty($url_var)&&empty($value)) {

if (stristr($url_path,$key)) {

return false;

}

}

}

return true;

}

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给定的正则表达式的一个匹配.

reference: http://php.net/manual/zh/function.preg-match.php

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

翻译了一下

Regex quick reference

[abc] A single character: a, b or c 单独的字符

[^abc] Any single character but a, b, or c 匹配字符除了abc

[a-z] Any single character in the range a-z 匹配a到z的字符

[a-zA-Z] Any single character in the range a-z or A-Z 匹配a到z或A到Z的字符

^ Start of line 一行的开始

$ End of line 一行的结束

\A Start of string 字符串开头

\z End of string 字符串结尾

. Any single character 任何字符

\s Any whitespace character 任何空白字符

\S Any non-whitespace character 任何非空白字符

\d Any digit 任何数字

\D Any non-digit 任何非数字

\w Any word character (letter, number, underscore) 任何的单词字符(字母,数字,下划线)

\W Any non-word character 任何非单词字符

\b Any word boundary character 任何单词边界字符

(...) Capture everything enclosed 捕获所未包裹有内容

(a|b) a or b a或b

a? Zero or one of a 有0个或1个字符a

a* Zero or more of a 有0个或多个字符a

a+ One or more of a 有1个或多个字符a

a{3} Exactly 3 of a 有3个字符a

a{3,} 3 or more of a 有3个或多个字符a

a{3,6} Between 3 and 6 of a 有3到6个字符a

options: i case insensitive m make dot match newlines x ignore whitespace in regex o perform #{...} substitutions only once

可选设置:i不区分大小写,m使得.(点符号)匹配换行符,x忽略正则表达式中的空格,o只执行一次#{...}中内容替换

其中的\\等价于\

\\\\等价于\\等价于/

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

reference: http://php.net/manual/zh/function.stristr.php

string stristr ( string $haystack , mixed $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/index.php。

但有个小问题很多人没有注意到,当url是PATH_INFO的时候,比如

https://www.leavesongs.com/hehe/index.php/phithon

那么PHP_SELF就是/hehe/index.php/phithon

也就是说,其实PHP_SELF有一部分是我们可以控制的。

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

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

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

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

//get拦截规则

$getfilter = "\\<.>|<.>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|load_file\s*?\\()|]*?\\bon([a-z]{4,})\s*?=|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|

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

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

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

在上面我们看到iframe关键词没被过滤,那么改为如下的:

//添加一个iframe关键词 iframe|

$getfilter = "iframe|\\<.>|<.>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|load_file\s*?\\()|]*?\\bon([a-z]{4,})\s*?=|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|

7cfa73ab583b589d8bf44e1c2f0d42f1.png

这样就起到了拦截效果

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

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

0x06 总结

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值