热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

php表单提交程序的安全使用方法

是对一个接收自由提交表单数据的文件进行安全性分析,希望对各位有帮助。首先说明一下,代码中的error()和succeed()是我自定义的函数
是对一个接收自由提交表单数据的文件进行安全性分析,希望对各位有帮助。首先说明一下,代码中的error()和succeed()是我自定义的函数

用于显示错误信息和成功信息,其实也可以直接echo出错误信息,这里我只是想我的出错信息页面漂亮点,定义了一个页面输出的函数罢了。

// savecomment.php// 大家先不要看注释,看完本文后,再回过头来看
require ("config.php");
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
$name=$_POST['name'];
$cOntent=$_POST['content'];
$blogid=$_POST['blogid'];
$datearray=getdate(time());
$date=date("Y-m-d h:i:s",$datearray[0]);
if (!empty($name) && !empty($content)){
//用empty函数判断表单非空的话则往下。
if(strlen($name) > 20){
//通过非空判断则开始判断$name的长度。
error(“名字超过20个字节(20个英文或10个汉字)
”);
}
f(!is_numeric($_POST['blogid'])){
error(“隐藏数据被非法修改过,请返回
”);
}
//由于$blogid待会是要放进select的,此变量是用来标示评论是属于哪篇文章,它是int类型,虽说是隐藏变量,但攻击者也是可以在本地修改远程提交的,所以我们在放进select之前需要检查类型。
$blogsql = "Select * FROM $comment_table Where blogid=$blogid"
$blogresult = mysql_db_query($dbname, $blogsql);
$blog = mysql_fetch_array($blogresult);
if(strlen($name) == strlen($blog[name]) && strlen($content) == strlen($blog[content])){
//查询数据库的两个字段的长度,因为名字长度可能相同,但两个都相同正常情况下出现的几率就相当小了,所以用&&同时判断。
error(“你欲提交的内容评论里已存在,请返回
”);
}
//下面就开始判断时间间隔。更详细的说明请看文章后面内容。
session_start();
if(session_is_registered("time") && time()-$_SESSION[&#39;time&#39;]<60*2){ error(“对不起,你两次提交的时间间隔还不到2分钟
”);
} else {
$sql="Insert INTO $comment_table(date,name,content,blogid) VALUES(&#39;$date&#39;,&#39;$name&#39;,&#39;$content&#39;,&#39;$blogid&#39;)"
mysql_db_query($dbname,$sql);
mysql_close();
$time=time();
session_register("time");
succeed(“评论提交成功
”);
}}
//结束非空的判断
error(“你没有填写完所有表单
”);
?>


上面是一个记录评论数据的文件。表单如下:

代码如下:




您的名字:
评论内容:



一个学习过PHP的人很容易就能看懂上面的代码,但为什么我要拿来分析,因为在我学习PHP期间,看了不少程序的代码,发现有个很普遍的问题,那就是大多数程序对于接受来自于表单的数据做的检查还是不够严谨,这恐怕是程序员思维问题,因为这些安全措施都是很容易实现的。
对于一个简单的评论功能,我们假设它有两个地方是需要用户填写的:评论人的姓名和评论内容。那么,我们需要判断的地方如下:
l 表单是否为空
l 表单长度(该项和上面的项判断称为逻辑性判断,凡事都要符合逻辑)
l 表单内容(判断记录是否存在于数据库内,防止重复提交)
l 隐藏变量的过滤(如果有的话,注意上面表单有一个隐藏变量type="hidden",这往往容易让人忽略)
l 提交时间间隔(这个是最最容易被忽略的)
逻辑判断很多人都做了,但这仅仅只是解决了程序的逻辑问题,作为安全的程序,我们还要从安全的角度进行判断,一个没有做过安全检查的此类程序,最容易受到以下攻击:
l 修改隐藏变量进行非法提交(比如注入)
l 重复提交(对Web程序进行DoS攻击)
编者注:重复提交所形成的攻击的确是个非常烦人的问题,虽然这种方法没有什么技术性可言,但却会让管理员伤透脑筋,因此很有必要在写代码时就加以防范。
修改隐藏变量通常是在本地构造一个表单,然后指定隐藏变量,如果过滤不到位,直接构造:
1&#39; or 1=1 UNION Select * FROM any_table INTO OUTFILE &#39;c:/www/info.txt
然后提交,会有什么结果不用说了吧?
如果采用POST提交表单后刷新会出现提示,然后确定就可以反复提交,这样可以浪费服务器的资源,如果量大的话站点速度可能会受少许影响,特别是数据量大的搜索引擎。这就是小小表单未做安全过滤的结果,相信任何站点管理员也不想看到吧?所以我们就要进行防御。防御思路如下:
针对隐藏变量我们可以采用过滤,针对重复提交我们可以:
l 采用COOKIE/session进行提交时间间隔的判断;
l 提交前用strlen()函数判断欲提交的标题和内容是否和数据库里已有的一致;
l 完成提交后用Header("Location: url");跳转到其他页面
下面我们就对上面的savecomment.php的if代码段进行分析,关于针对修改变量攻击的防御代码大家可以看我在代码上的注释。对于采用COOKIE/session进行提交时间间隔的判断这两种方法,我有以下看法:
COOKIE:信息存在客户端,利用工具可以修改、删除使COOKIE失效,因为他是连续发送,中间的间隔时间很短,来不急去删除该COOKIE的。但也不排除自己编段小程序来删除COOKIE。如果对COOKIE不放心可以采用Session。
Session:信息存放在服务器,攻击者不可能修改,但会占用服务器一丁点资源。我的服务器好,我就用Session,放心:)。
下面来看看分别用这两种方式验证的代码:
COOKIE:

程序代码
if (isset($_COOKIE[&#39;beforeid&#39;])) {
error(“对不起,你两次提交的时间间隔还不到2分钟
”);
} else {
//先检查相关COOKIE是否存在,已存在则给出错误提示,不存在则正确执行的代码段,比如插入Insert语句。执行完毕以后设置一个COOKIE,表示已经提交过,60*2表示2分钟。
setCOOKIE("beforeid",$blogid,time()+60*2,"/","",0);
succeed(“评论提交成功
”); }
?>

Session:

程序代码
session_start();
if (session_is_registered("time") && time()-$_SESSION[&#39;time&#39;]<60*2) {
error(“对不起,你两次提交的时间间隔还不到2分钟
”);
//$time 前一次提交的时间
} else {
//先检查相关Session是否存在,已存在则给出错误提示,不存在则正确执行的代码段,比如插入Insert语句。执行完毕以后设置一个Session,表示已经提交过,60*2表示2分钟。
$time=time();
session_register("time");
succeed(“评论提交成功
”);
}
?>
这种时间间隔的方法可以用于各种表单,比如搜索、留言等,它可以有效地控制程序的有序运行。
至于第三个思路是用Header("Location: url");跳转页面,我想既然加入了COOKIE/session验证就不必贸然跳转了,毕竟大家还是想看看提交的相关信息的。
怎么样?想不到小小的表单验证有这么大的学问吧?简单几行代码就切断让攻击者的路子,其实这些都很容易的,重要的是开发人员验证的思路,我一个人只会加 COOKIE/session验证这个思路,结合Envymask的判断长度这条思路,我又掌握一点。其实开发安全的程序,安全措施的思路很重要,即使掌握各种防御代码,但如果考虑不严谨,照样有空子可钻。
鄙人刚学PHP不到半个月。写的代码不够规范、严谨,在各位高手面前班门弄斧了。
后记:一个小小的程序,已经折射出了一些普遍存在的安全问题。在安全代码的编写过程中,仅仅注意以上问题还是远远不够的,不过很多重大脚本漏洞的出现却都是因为这种小问题引起的。平时可以看到,在一个脚本程序出现漏洞之后,往往一两句代码就可以将相关漏洞补得很严实了。脚本攻防是智者之间的较量,但是智者千虑,必有一失,所以相对于攻击来说,防范要做到滴水不漏就显得尤为困难。

推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
author-avatar
as123466_866
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有