本文目录一览:
php配置文件是什么?
PHP 的配置文件一般是 php.ini 文件
php.ini 文件必须命名为'php.ini'并放置在httpd.conf中的PHPIniDir指令指定的目录中,使用phpinfo()函数可以查看。如果未作修改,windows平台下一般放在php安装目录中。
PHP还是一个不断发展的工具,其功能还在不断地删减
而php.ini的设置更改可以反映出相当的变化,
在使用新的PHP版本前,研究一下php.ini会有好处的
下面简单的介绍一下基本配置:
directive = value
; 指示标识符 是 *大小写敏感的* - foo=bar 不同于 FOO = bar。
engine = On
; 使 PHP scripting language engine(PHP 脚本语言引擎)在 Apache下有效。
short_open_tag = On
; 允许 tags 将被识别。
asp_tags = Off
; 允许ASP-style tags
precision = 14
; 浮点类型数显示时的有效位数
上面只是一个例子,其他详细的配置说明,可以参考一些资料。
php的类怎么读取到配置文件里面的配置项?
1、新建一个PHP文档,该文档的目的是检测PHP的环境配置,示例:?php phpinfo()。
2、保存以上内容,在浏览器查看输出信息。
3、以上信息便是PHP的配置信息了,在该页面查找:Loaded Configuration File,红色方框中便是php.ini的具体路径了。
4、打开CMD窗口,并输入:php -i | findstr php.ini。
5、按下回车键执行后,同样可以得到php.ini配置文件的路径。
在php.ini中如何配置安全的PHP环境参数
(1)
打开php的安全模式
php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),
同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,
但是默认的php.ini是没有打开安全模式的,我们把它打开:
safe_mode
=
on
(2)
用户组安全
当safe_mode打开时,safe_mode_gid被关闭,那么php脚本能够对文件进行访问,而且相同
组的用户也能够对文件进行访问。
建议设置为:
safe_mode_gid
=
off
如果不进行设置,可能我们无法对我们服务器网站目录下的文件进行操作了,比如我们需要
对文件进行操作的时候。
如何配置php服务器
1. 安装IIS
IIS是windows平台下比较成熟的web服务,安装方法也非常简单。
打开“开始”菜单,点击“管理您的服务器”,点击“添加或删除角色”(如图所示)。
2
进入预备步骤后直接点下一步。到达了选择角色的地方,选择“应用程序服务(IIS,ASP.net)”
3
之后点击下一步,出现附加组件的选择,一个是FrontPage Server Extentions,另外一个是ASP.net,这两项我们的环境中都不需要,不必选择,如果有需要,可以选择性安装。进入下一步,是选项总结,再下一步,进入安装过程,此时提示需要插入windows 2003(R2)的安装光盘,插入光盘后,选择光驱所在驱动器下的I386,点击确定,安装过程将会继续一直到结束,并且出现成功提示
4
完成后对IIS进行测试,打开“开始”菜单,点击“所有程序”,进入“管理工具”,点击“internet信息服务(IIS)管理器”
展开“网站”树型节点,删除默认网站,然后新建一个网站
5
进入向导后,进入下一步,为网站添加描述,也就是IIS中显示的网站标示,可以随便填写,再进入下一步,为网站配置主机头,我们是用来配置本地测试环境,所以把主机头配置为127.0.0.1
6
进入下一步,选择目录,目录需要提前建立好,然后选择即可。继续下一步,需要选择网站权限,这里只选择读取即可。之后便可完成网站新建向导了。
需要正常的浏览网站,还需要给网站的根目录文件夹指定相应的权限,首先在网站属性中查看网站的匿名访问账户是什么,然后将这个账户设置到网站的根目录文件夹,并设置相应的访问权限
7
网站的匿名访问账户是:IUSR_CBLH-DDEF00B671,为文件夹设置用户访问权限
8
权限配置好后,在目录中新建一个index.html文件,随意输入一些文字或者html代码即可。
在网站名称上右键,点击属性,进入“属性”后点击“文档”选项卡,在此添加一个index.html和index.php(index.php添加好是为了待会不必再做配置),然后点击“确定”或者“应用”保存配置。
然后在浏览器中的地址栏中输入“”或者“”,即可看到刚才我们建立的index.html中的内容。
9
安装fastcgi
IIS调试好后,就可以安装fastcgi了,首先需要下载IISfastcgi,下载地址是(),安装fastcgi非常简单,只需要同意协议后连续点击下一步即可,没有任何选项。
10
安装php
首先下载php在windows的安装包,下载地址,这里选用php-5.3.4-nts-Win32-VC9-x86.msi做例子。下载好php-5.3.4-nts-Win32-VC9-x86.msi后,双击文件安装,接受使用协议后,为php填写安装目录,这个目录是可以更换的,指向需要放置它的位置即可。之后需要选择web服务器的安装,这里选择我们先前安装的IIS fastcgi
11
下一步需要配置安装选项,这里我们除了默认的选项之外增加了pear install(如图所示)
12
再进入下一步,就可以确认安装了。
完成安装后,还需要测试一下php是否可用。
首先打开IIS管理器,然后在先前测试IIS的网站上右键,进入“属性”,点击主目录选项卡,然后将“执行权限”配置为“纯脚本”
13
然后点击旁边的“配置”,查看是否有.php扩展名,如果没有的话,需要添加一个新项,将可执行文件指向“C:WINDOWSsystem32inetsrvfcgiext.dll”,扩展名为“.php”(注意有个点),动作限制为“GET,HEAD,POST,TRACE”,点击确定即可
步骤阅读
14
做好了这些,就可以写个小脚本来测试了,在网站的目录中新建一个test.php文件,打开后输入,保存后退出。在浏览器地址栏中输入,即可看到php信息了。
4. 安装isapi_urlwriter ISAPI扩展组件
isapi_urlwriter ISAPI扩展组件主要用来做地址重写,重写后的虚拟静态地址对搜索引擎更友好。先将ISAPI_Rewrite3安装包解压到指定的文件目录中,然后进入网站属性窗口,选择窗口中的ISAPI筛选器选项卡,点击添加按钮,在弹出的窗口中选择ISAPI_Rewrite3解压目录中的ISAPI_Rewrite.dll文件为可执行文件并确定。
END
iis7.5 PHP环境配置
1
windows server 2008是基于NT6 平台的新型操作系统,其对硬件性能的发挥比起其它NT平台来说有了质的飞跃,已经开始普及到了广大用户中,而且操作较2003来说更为直观和简单,受到越来越多的好评。在这里我们要介绍windows server 2008中的php环境搭建。
安装IIS
windows server 2008的IIS版本为7.0,包括fastcgi,安装十分方便。
打开“开始”菜单→“服务器管理”,出现服务器管理界面
2
在图中黄色框中填入服务器ip,点击打开,之后提示输入用户名和密码,验证成功后完成登录服务器。
3
点击“下一步”之后,需要选择功能,这里需要比默认选项多增加一个“cgi”
4
点击“下一步”,将会需要确认一下安装的内容,此时点击安装,即可将IIS安装在操作系统中。
安装好IIS之后,需要进行一个测试,在浏览器地址栏中输入“”,如果出现IIS7的欢迎页则说明正常。接下来需要配置一个新网站,首先打开IIS管理器(“开始”→“所有程序”→“管理工具”→“internet 信息服务(IIS)管理器”)。
然后删除默认网站,在主菜单中,展开网站菜单,然后再网站名称上右键,点击删除即可
5
再新建一个网站,在“网站”上右击,点击添加网站,会出现信息网站添加的表单,首先输入网站名称,例如“stourwebcms”,路径选择为网站存放的路径,单IP的服务器可以不必选择IP,主机头填写为localhost,然后点击确定。
6
添加好网站后,需要为网站设置用户访问权限。在iis管理器左边的网站列表中选中网站,在右边的操作列表中点击“基本设置”,在弹出窗口中点击“连接为”,弹出的窗口中会出现网站的默认用户账户,也可以更改为其它的用户。确定网站的用户账户后,将此账户的访问权限设置到网站的根目录文件夹上
打开网站目录,新建一个index.html,然后用记事本打开,输入“hello stourweb”后保存,并访问本地地址“”进行测试,网页上显示出了“hello stourweb”,说明配置成功。
7
安装php
在前面已经提过,IIS7中不必单独安装fastcgi,所以,我们只需要下载php安装包进行安装即可,下载地址: 下载好后,打开安装程序,经过引导,配置好路径,来到选择“web server setup”的地方,在这里我们选择“IIS fastcgi”
8
然后点击“next”按钮,到了选择安装选项的步骤,一般安装默认的就可以了,如果要添加的话需要点击一下前面的磁盘小图标,然后选择安装,第一项是只安装选中的项目,第二项是安装所有该项目的子项目。配置好后进入下一步
9
配置好后,点击“next”然后点击“install”即可安装php。
当php安装完成后会自动在iis的处理程序映射中增加一条fastcgi到php的映射关系
安装完成后,我们还是需要测试一下,打开刚才新建的网站目录,新建一个test.php文件,用记事本打开,输入
?php
echo phpinfo();
?
保存退出,再从浏览器中访问
显示出php信息,说明php环境安装成功。
10
安装isapi_urlwriter ISAPI扩展组件
isapi_urlwriter ISAPI扩展组件主要用来做地址重写,重写后的虚拟静态地址对搜索引擎更友好。先将ISAPI_Rewrite3安装包解压到指定的文件目录中,然后双击iis的ISAPI筛选器配置项,进入网站ISAPI组件配置窗口,点击添加按钮,在弹出的窗口中选择ISAPI_Rewrite3解压目录中的ISAPI_Rewrite.dll文件为可执行文件并确定。
11
ISAPI_Rewrite3组件是一个32位的程序,因此在64位操作系统应用池进程下默认不工作,因此需要在网站所属应用进程池的高级设置中将进程池设置为32位兼容
END
Mysql数据库安装
1
下载mysql(),安装过程比较简单,首先配置路径,然后选择安装选项,一般采用默认安装的方式,之后会进入一个配置向导界面
步骤阅读
2
连续下一步,需要选择配置方式,这里选择配置方式,我们需要手动配置,所以选择detailed configuration,然后点击“下一步”
3
这里需要选择服务器类型,如果是开发用的测试环境,选择developer Machine ,如果是服务器用,则选择Server Machine,当然单一用途的服务器还可以选择dedicated mysql server machine。选择好后进入下一步
4
接下来是选择服务器使用,第一个是多功能数据库,可以使用 InnoDB engine和MyISAM engine。第二个选项,它的性能偏向于InnoDB,但是同时支持MyISAM engine。第三个选项是偏向于分析功能的MyISAM。至于这三个选项有什么区别,其实只要知道,MyISAM类型的数据库引擎可以为php提供强大的检索和分析功能。InnoDB的性能则偏重于存储。
所以如果只做web服务器的话选择第三项即可,如果是有其它用途,建议选择第一项。
5
下一步需要选择服务器上的连接数量,这里如果是测试用的小服务器可以选择最少的第一项,如果是流量巨大的网站,需要选择第二项,或者第三项自行填写。
之后是网络连接的选项,“enable TCP/IP Networking”可以按照需求来选择,如果不做集群的话可以把勾去掉,如果是在内网环境,不为mysql做路由规则是完全可以打开此项的。可以直接添加一个防火墙例外给3306端口。端口号可以选择,但是推荐默认的3306。还有一项是是否开启严谨模式,此项推荐勾选
6
点击下一步,选择默认字符集,这里选择自定义的utf8字符集
7
进入下一步,需要设定windows选项,这里推荐安装windows服务,并且自动启动。第二个选项,如果有必要,可以选择添加一个环境变量,可以方便命令行指向。
配置好后,进入下一步,需要为root用户设定密码,请设置一个比较复杂的密码以增加安全性,另外请牢记自己设置的密码,否则遗忘了后需要重置密码十分麻烦。还有一个是否允许root用户从远程登录的选项,此处最好不勾选,否则安全性将会降低。
到此配置就全部结束了,点击下一步,会出现安装总结,点击“execute”执行安装即可。
安装成功后,我们依然需要对此进行测试。
在网站中新建一个测试php文件test.php,我们使用pdo链接mysql作为测试。
输入
?php
$db=new PDO("mysql:host=localhost;dbname=test","root","刚才设置的密码");
if ($db)
{
echo "ok";
}
?
访问,如果屏幕上打印出了ok,表示mysql安装成功。
END
安全配置建议
1
安全软件
一款好的安全软件能有效防御来自计算机病毒、恶意软件和木马的威胁,但能用于服务器的安全软件并不多,其中大部分都是收费的,平常个人所用的金山毒霸和360等不能安装到windows server系列的服务器操作系统上,但他们都有相应的服务器版本并且提供免费升级,在他们的官网上面都能够找到。
2
防火墙
合理的配置好防火墙能有效的阻止各种恶意入侵,因为各种网络入侵都是通过相应的网络端口完成的。网络端口是服务器上的各种网络服务开启的,他们对外提供各种网络服务,如http、ftp、smtp等。自己的服务器上需要提供哪些网络服务就只开启这些服务的相应端口,如服务器上提供网站服务,就需要开启http的80端口,如需要提供ftp服务就要开启21端口;有些网络服务不需要对外提供服务就不应该开启,如sql server数据库不需要对外提供服务,就应该在防火墙中关闭掉1433端口。
Windows sever 2003和2008都自带防火墙,其实能简单有效的利用这些自带的防火墙就能有效的完成端口的开闭管理。
l Windows server 2003服务器防火墙配置
1) 鼠标右键单击“网上邻居”,选择“属性”。
2) 然后鼠标右键单击“本地连接”,选择“属性”。如图选择“高级”选项,选中“Internet连接防火墙”,确定后防火墙即起了作用。
点击“设置(G)...”按钮可进行高级设置。其中列出了可用的网络服务,选中后允许其打开网络端口并通信,反之则关闭其网络通信;单击“添加”则可以增加网络服务或打开指定的网络端口
3
Windows server 2008服务器防火墙配置
1) 在控制面板中打开网络和共享中心
2) 点击“windows防火墙”弹出防火墙配置窗口,在此窗口中要确认防火墙服务已经开启
3) 单击“允许程序或功能通过Windows防火墙”弹出网络服务端口配置窗口,在此窗口中可以选择允许打开端口并通信的网络服务,单击“允许运行另一程序”来自定义开启某一网络服务或端口
4
用户管理
系统中用户的数量能越少越好,并且每个用户都被用于特定的功能,如可以新建一个专门用于对网站进行匿名授权的账户(如条件允许,可以为每个网站新建一个独立的账户进行分别授权,这些能够隔离开各网站的授权,提高各网站的安全性,不至于一个网站被入侵后能够有权限访问到其它网站的文件目录)。另外最重要的一点是要为每个账户设置一个独立且复杂的密码,防止账户密码被猜解和穷举。
5
文件系统权限管理
l C盘只给administrators 和system权限,其他的权限不给,其他的盘也可以这样设置,这里给的system权限也不一定需要给,只是由于某些第三方应用程序是以服务形式启动的,需要加上这个用户,否则造成启动不了。
l Windows目录要加上给users的默认权限,否则ASP和ASPX等应用程序就无法运行。其实没有必要单独设置Instsrv和temp等目录权限。
l 另外在c:/Documents and Settings/这里相当重要,后面的目录里的权限根本不会继承从前的设置,如果仅仅只是设置了C盘给administrators权限,而在All Users/Application Data目录下会 出现everyone用户有完全控制权限,这样入侵这可以跳转到这个目录,写入脚本或只文件,再结合其他漏洞来提升权限;
譬如利用serv-u的本地溢出提升权限,或系统遗漏有补丁,数据库的弱点,甚至社会工程学等等N多方法,在用做web/ftp服务器的系统里,建议是将这些目录都设置的锁死。其他每个盘的目录都按照这样设置,每个盘都只给adinistrators权限。
另外,还将:
net.exe
cmd.exe
t
netstat.exe
regedit.exe
at.exe
attrib.exe
cacls.exe
format.exe
这些文件都设置只允许administrators访问。
l 网站的目录最好独立到一个磁盘中,新建一个为网站匿名访问而独立授权的账户,让此账户可以访问和编辑此目录,移除其它不必要的账户对此目录的访问权限,能有效防止网站被入侵后从而涉及到整个系统被控制
日常维护建议
1
定期运行安全软件进行快速扫描
定期运行一下安全软件,可以看到安全软件的引擎或病毒库是否已经更新到了最新版本,如果没有可以即时查找原因,看是否是安全软件未运行、升级端口被禁用或其它原因,虽然安全软件可以在后台即时扫描各种文件操作,以防止病毒入侵,但有些恶意软件、流氓软件或插件则不是实时防护的,虽然这些软件不会造成服务器宕机,但也会影响服务器性能。
2
定期检查防火墙端口配置
随着服务器上的网络服务越来越多,需要打开的网络端口也越来越多,但有些端口是不需要开放的,例如你安装了一个数据库软件(mysql、oracle等),这些数据库服务很可能只需要在你服务器的内部访问,就完全没有必要让其通过防火墙,这样能够提高服务器的安全,服务器对外提供的端口越少越好;
虽然在安装网络服务的过程中,防火墙会提示你有网络端口正在打开,是否允许通过防火墙,但有些管理员没有细心看提示,直接就同意了,造成了大量没有必要打开的网络端口被打开了,特别是一些木马或恶意软件会混水摸鱼,伪装提示信息来诱骗管理员打开网络端口,造成大量的安全隐患。进入防火墙配置界面,选择相应的端口或网络服务,点击“详细信息”则可以看到此项应用的详细信息,根据这些信息来判断其是否应该开启这个端口。
3
任务管理器中观察有无可疑进程,了解系统资源使用情况
任务管理器可以简单并快速的了解服务系统资源的使用情况,并即时查看系统运行的进程和他们占用的系统资源,根据服务器上已开启的各种应用的服务来判断哪些进程是非法的,哪些进程占用的系统资源过多。了解到这些信息后就可以即时的对服务器进行调整,特别是占用资源过多的进程进行分析,看是否有什么异常并即时进行调整。
l 观察系统进程,并自定义进程属性
4
查看网络使用情况
查看系统资源使用情况
检查IIS,了解网站安装情况
随时了解服务器上网站的安装状况,并做以下检查:
1、看各个网站定义的主机头是否异常
2、 绑定的域名是否完整
3、 主目录设置是正确
4、用户权限设置是否合理
5、 查看IIS的应用程序池设置是否合理,每个池下面托管的网站是否过多,是否需要设置新的应用池,是否有多余的应用池可以删除。
查看系统日志,仔细检查错误、警告日志发生的原因,并急时修复相应的问题。
检查系统用户,查看有无多余,可疑用户账户,查看每个账户所属的用户组,特别是administrators组下面的用户。服务器被入侵时会出现一些欺骗性的账户并被加入到administrators组中,特别留心新建的多余账户,弄清这些账户的用途,如果发现是入侵者建立的账户,要即时查找账户是被创建的原因,并修复相应的漏洞。
检查文件系统,确保磁盘被合理分区,各个分区应该有各自的功能,如系统、数据库、网站、备份等。各个分区的用户授权是不相同的,如系统、备份等不需要网站的专门授权账户访问,数据库分区需要对数据库账户进行单独的授权等。既然规划好了文件分区和功能,并进行了相应的授权,就要防止文件被乱放,以免造成安全隐患。
还要经常检查各种新建的文件夹和文件(特别是来历不明,名称畸形的隐藏文件夹和文件)这些都有可能是入侵者留下的入侵痕迹。
清除垃圾文件,随时系统运行时间的增加,会产生很多的临时文件和日志文件,占用宝贵的磁盘资源,如果磁盘的可用空间过小(特别是系统盘)还会影响服务器性能。
1、临时文件(安装程序、系统升级、应用程序等产生的)产生的,主要在系统盘,可以看哪些文件夹的体积异常大,可分析其内部文件,确认是临时文件后将其删除
2、 日志文件,主要是IIS产生的,这些日志文件对于查看网站运行状态、访问历史很有用,但日志有时效性,如果超过其三个月就没有什么用处了,但它会占用大量的磁盘空间,所以需要定期将其删除。
定期检查磁盘状态并进行碎片整理,随着系统运行时间的增长,特别是大量的IO操作后,磁盘上会产生大量的文件碎片,这些碎片过多则会严重影响服务器性能,所以定期(建议一个月)进行磁盘碎片检查,如果系统提醒需要进行碎片整理,则进行整理。
及时升级操作系统补丁,操作系统有各种大量的补丁,特别是一些重要的安全补丁需要即时升级,这样会有效防止黑客和病毒入侵。
及时备份重要的文件、应用、数据库。备份分为本地备份和异地备份,有条件的可以进行异地备份,备份是为了以防万一,当数据丢失或应用损坏时,备份就是救命稻草,因此合理的备份计划是非常有必要的。
不要随意下载安装来历不明的软件,特别是需要连接网络或需要打开端口的。现在网上许多的程序都内置有木马或恶意程序,所以不要下载和安装网上的不明软件,特别是一些小网站的。
END
php有什么安全规则,有哪些?
php安全篇值过滤用户输入的人参数
规则 1:绝不要信任外部数据或输入
关于Web应用程序安全性,必须认识到的第一件事是不应该信任外部数据。外部数据(outside data) 包括不是由程序员在PHP代码中直接输入的任何数据。在采取措施确保安全之前,来自任何其他来源(比如 GET 变量、表单 POST、数据库、配置文件、会话变量或 cookie)的任何数据都是不可信任的。
例如,下面的数据元素可以被认为是安全的,因为它们是在PHP中设置的。
复制代码 代码如下:
?php
$myUsername = 'tmyer';
$arrayUsers = array('tmyer', 'tom', 'tommy');define(”GREETING”, 'hello there' . $myUsername);?
但是,下面的数据元素都是有瑕疵的。
清单 2. 不安全、有瑕疵的代码
复制代码 代码如下:
?php
$myUsername = $_POST['username']; //tainted!
$arrayUsers = array($myUsername, 'tom', 'tommy'); //tainted!
define(”GREETING”, 'hello there' . $myUsername); //tainted!
?
为 什么第一个变量 $myUsername 是有瑕疵的?因为它直接来自表单 POST。用户可以在这个输入域中输入任何字符串,包括用来清除文件或运行以前上传的文件的恶意命令。您可能会问,“难道不能使用只接受字母 A-Z 的客户端(Javascrīpt)表单检验脚本来避免这种危险吗?”是的,这总是一个有好处的步骤,但是正如在后面会看到的,任何人都可以将任何表单下载 到自己的机器上,修改它,然后重新提交他们需要的任何内容。
解决方案很简单:必须对 $_POST['username'] 运行清理代码。如果不这么做,那么在使用 $myUsername 的任何其他时候(比如在数组或常量中),就可能污染这些对象。
对用户输入进行清理的一个简单方法是,使用正则表达式来处理它。在这个示例中,只希望接受字母。将字符串限制为特定数量的字符,或者要求所有字母都是小写的,这可能也是个好主意。
清单 3. 使用户输入变得安全
复制代码 代码如下:
?php
$myUsername = cleanInput($_POST['username']); //clean!
$arrayUsers = array($myUsername, 'tom', 'tommy'); //clean!
define(”GREETING”, 'hello there' . $myUsername); //clean!
function cleanInput($input){
$clean = strtolower($input);
$clean = preg_replace(”/[^a-z]/”, “”, $clean);$clean = substr($clean,0,12);
return $clean;
}
?
规则 2:禁用那些使安全性难以实施的 PHP 设置已经知道了不能信任用户输入,还应该知道不应该信任机器上配置 PHP 的方式。例如,要确保禁用 register_globals。如果启用了 register_globals,就可能做一些粗心的事情,比如使用 $variable 替换同名的 GET 或 POST 字符串。通过禁用这个设置,PHP 强迫您在正确的名称空间中引用正确的变量。要使用来自表单 POST 的变量,应该引用 $_POST['variable']。这样就不会将这个特定变量误会成 cookie、会话或 GET 变量。
规则 3:如果不能理解它,就不能保护它
一些开发人员使用奇怪的语法,或者将语句组织得很紧凑,形成简短但是含义模糊的代码。这种方式可能效率高,但是如果您不理解代码正在做什么,那么就无法决定如何保护它。
例如,您喜欢下面两段代码中的哪一段?
清单 4. 使代码容易得到保护
复制代码 代码如下:
?php
//obfuscated code
$input = (isset($_POST['username']) ? $_POST['username']:”);//unobfuscated code
$input = ”;
if (isset($_POST['username'])){
$input = $_POST['username'];
}else{
$input = ”;
}
?
在第二个比较清晰的代码段中,很容易看出 $input 是有瑕疵的,需要进行清理,然后才能安全地处理。
规则 4:“纵深防御” 是新的法宝
本教程将用示例来说明如何保护在线表单,同时在处理表单的 PHP 代码中采用必要的措施。同样,即使使用 PHP regex 来确保 GET 变量完全是数字的,仍然可以采取措施确保 SQL 查询使用转义的用户输入。
纵深防御不只是一种好思想,它可以确保您不会陷入严重的麻烦。
既然已经讨论了基本规则,现在就来研究第一种威胁:SQL 注入攻击。
防止 SQL 注入攻击
在 SQL 注入攻击 中,用户通过操纵表单或 GET 查询字符串,将信息添加到数据库查询中。例如,假设有一个简单的登录数据库。这个数据库中的每个记录都有一个用户名字段和一个密码字段。构建一个登录表单,让用户能够登录。
清单 5. 简单的登录表单
复制代码 代码如下:
html
head
titleLogin/title
/head
body
form action=”verify.php” method=”post”
plabel for='user'Username/label
input type='text' name='user' id='user'/
/p
plabel for='pw'Password/label
input type='password' name='pw' id='pw'/
/p
pinput type='submit' value='login'//p
/form
/body
/html
这个表单接受用户输入的用户名和密码,并将用户输入提交给名为 verify.php 的文件。在这个文件中,PHP 处理来自登录表单的数据,如下所示:
清单 6. 不安全的 PHP 表单处理代码
复制代码 代码如下:
?php
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = “select count(*) as ctr from users where username='”.$username.”' and password='”. $pw.”' limit 1″;$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){if ($data-ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php”);
}else{
header(”login.php”);
}
?
这 段代码看起来没问题,对吗?世界各地成百(甚至成千)的 PHP/MySQL 站点都在使用这样的代码。它错在哪里?好,记住 “不能信任用户输入”。这里没有对来自用户的任何信息进行转义,因此使应用程序容易受到攻击。具体来说,可能会出现任何类型的 SQL 注入攻击。
例如,如果用户输入 foo 作为用户名,输入 ' or '1′='1 作为密码,那么实际上会将以下字符串传递给 PHP,然后将查询传递给 MySQL:
复制代码 代码如下:
?php
$sql = “select count(*) as ctr from users where username='foo' and password=” or '1′='1′ limit 1″;?
这个查询总是返回计数值 1,因此 PHP 会允许进行访问。通过在密码字符串的末尾注入某些恶意 SQL,黑客就能装扮成合法的用户。
解 决这个问题的办法是,将 PHP 的内置 mysql_real_escape_string() 函数用作任何用户输入的包装器。这个函数对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让 MySQL 根据特殊字符进行操作。清单 7 展示了带转义处理的代码。
清单 7. 安全的 PHP 表单处理代码
复制代码 代码如下:
?php
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];
$sql = “select count(*) as ctr from users where username='”.mysql_real_escape_string($username).”' and password='”. mysql_real_escape_string($pw).”' limit 1″;$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){if ($data-ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header(”index.php”);
}else{
header(”login.php”);
}
?
使用 mysql_real_escape_string() 作为用户输入的包装器,就可以避免用户输入中的任何恶意 SQL 注入。如果用户尝试通过 SQL 注入传递畸形的密码,那么会将以下查询传递给数据库:
select count(*) as ctr from users where username='foo' and password='\' or \'1\'=\'1′ limit 1″数据库中没有任何东西与这样的密码匹配。仅仅采用一个简单的步骤,就堵住了 Web 应用程序中的一个大漏洞。这里得出的经验是,总是应该对 SQL 查询的用户输入进行转义。
但是,还有几个安全漏洞需要堵住。下一项是操纵 GET 变量。
防止用户操纵 GET 变量
在前一节中,防止了用户使用畸形的密码进行登录。如果您很聪明,应该应用您学到的方法,确保对 SQL 语句的所有用户输入进行转义。
但 是,用户现在已经安全地登录了。用户拥有有效的密码,并不意味着他将按照规则行事 —— 他有很多机会能够造成损害。例如,应用程序可能允许用户查看特殊的内容。所有链接指向 template.php?pid=33 或 template.php?pid=321 这样的位置。URL 中问号后面的部分称为查询字符串。因为查询字符串直接放在 URL 中,所以也称为 GET 查询字符串。
在 PHP 中,如果禁用了 register_globals,那么可以用 $_GET['pid'] 访问这个字符串。在 template.php 页面中,可能会执行与清单 8 相似的操作。
清单 8. 示例 template.php
复制代码 代码如下:
?php
$pid = $_GET['pid'];
//we create an object of a fictional class Page$obj = new Page;
$content = $obj-fetchPage($pid);
//and now we have a bunch of PHP that displays the page?
这 里有什么错吗?首先,这里隐含地相信来自浏览器的 GET 变量 pid 是安全的。这会怎么样呢?大多数用户没那么聪明,无法构造出语义攻击。但是,如果他们注意到浏览器的 URL 位置域中的 pid=33,就可能开始捣乱。如果他们输入另一个数字,那么可能没问题;但是如果输入别的东西,比如输入 SQL 命令或某个文件的名称(比如 /etc/passwd),或者搞别的恶作剧,比如输入长达 3,000 个字符的数值,那么会发生什么呢?
在这种情况下,要记住基本规则,不要信任用户输入。应用程序开发人员知道 template.php 接受的个人标识符(PID)应该是数字,所以可以使用 PHP 的 is_numeric()函数确保不接受非数字的 PID,如下所示:
清单 9. 使用 is_numeric() 来限制 GET 变量复制代码 代码如下:
?php
$pid = $_GET['pid'];
if (is_numeric($pid)){
//we create an object of a fictional class Page$obj = new Page;
$content = $obj-fetchPage($pid);
//and now we have a bunch of PHP that displays the page}else{
//didn't pass the is_numeric() test, do something else!
}
?
这个方法似乎是有效的,但是以下这些输入都能够轻松地通过 is_numeric() 的检查:
100 (有效)
100.1 (不应该有小数位)
+0123.45e6 (科学计数法 —— 不好)
0xff33669f (十六进制 —— 危险!危险!)那么,有安全意识的 PHP 开发人员应该怎么做呢?多年的经验表明,最好的做法是使用正则表达式来确保整个 GET 变量由数字组成,如下所示:
清单 10. 使用正则表达式限制 GET 变量
复制代码 代码如下:
?php
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid)){
//do something appropriate, like maybe logging them out or sending them back to home page}
}else{
//empty $pid, so send them back to the home page}
//we create an object of a fictional class Page, which is now//moderately protected from evil user input$obj = new Page;
$content = $obj-fetchPage($pid);
//and now we have a bunch of PHP that displays the page?
需 要做的只是使用 strlen() 检查变量的长度是否非零;如果是,就使用一个全数字正则表达式来确保数据元素是有效的。如果 PID 包含字母、斜线、点号或任何与十六进制相似的内容,那么这个例程捕获它并将页面从用户活动中屏蔽。如果看一下 Page 类幕后的情况,就会看到有安全意识的 PHP 开发人员已经对用户输入 $pid 进行了转义,从而保护了 fetchPage() 方法,如下所示:
清单 11. 对 fetchPage() 方法进行转义
复制代码 代码如下:
?php
class Page{
function fetchPage($pid){
$sql = “select pid,title,desc,kw,content,status from page where pid='”.mysql_real_escape_string($pid).”'”;}
}
?
您可能会问,“既然已经确保 PID 是数字,那么为什么还要进行转义?” 因为不知道在多少不同的上下文和情况中会使用 fetchPage() 方法。必须在调用这个方法的所有地方进行保护,而方法中的转义体现了纵深防御的意义。
如 果用户尝试输入非常长的数值,比如长达 1000 个字符,试图发起缓冲区溢出攻击,那么会发生什么呢?下一节更详细地讨论这个问题,但是目前可以添加另一个检查,确保输入的 PID 具有正确的长度。您知道数据库的 pid 字段的最大长度是 5 位,所以可以添加下面的检查。
清单 12. 使用正则表达式和长度检查来限制 GET 变量复制代码 代码如下:
?php
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid) strlen($pid) 5){//do something appropriate, like maybe logging them out or sending them back to home page}
} else {
//empty $pid, so send them back to the home page}
//we create an object of a fictional class Page, which is now//even more protected from evil user input$obj = new Page;
$content = $obj-fetchPage($pid);
//and now we have a bunch of PHP that displays the page?
现在,任何人都无法在数据库应用程序中塞进一个 5,000 位的数值 —— 至少在涉及 GET 字符串的地方不会有这种情况。想像一下黑客在试图突破您的应用程序而遭到挫折时咬牙切齿的样子吧!而且因为关闭了错误报告,黑客更难进行侦察。
缓冲区溢出攻击
缓冲区溢出攻击 试图使 PHP 应用程序中(或者更精确地说,在 Apache 或底层操作系统中)的内存分配缓冲区发生溢出。请记住,您可能是使用 PHP 这样的高级语言来编写 Web 应用程序,但是最终还是要调用 C(在 Apache 的情况下)。与大多数低级语言一样,C 对于内存分配有严格的规则。
缓冲区溢出攻击向缓冲区发送大量数据,使部分数据溢出到相邻的内存缓冲区,从而破坏缓冲区或者重写逻辑。这样就能够造成拒绝服务、破坏数据或者在远程服务器上执行恶意代码。
防止缓冲区溢出攻击的惟一方法是检查所有用户输入的长度。例如,如果有一个表单元素要求输入用户的名字,那么在这个域上添加值为 40 的 maxlength 属性,并在后端使用 substr() 进行检查。清单 13 给出表单和 PHP 代码的简短示例。